diff options
author | Simon Rozman <simon@rozman.si> | 2020-10-19 22:23:09 +0200 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2020-10-30 16:51:01 +0100 |
commit | faf7d3771c9bd7b8b9a3ee20ceed2a432542c318 (patch) | |
tree | bad93f3e3406a5b57b51d9a2b61133e9f9dd49bd /api/rundll32.c | |
parent | api: installer: switch from MSM to ZIP distribution (diff) | |
download | wintun-faf7d3771c9bd7b8b9a3ee20ceed2a432542c318.tar.xz wintun-faf7d3771c9bd7b8b9a3ee20ceed2a432542c318.zip |
api: connect rundll32 child with parent using stdout and stderr
The WintunCreateAdapter()+CreateAdapter() and WintunDeleteAdapter()+
DeleteAdapter() communicate using Unicode anonymous pipes now. This
allows the WintunCreateAdapter() to exactly determine the adapter
CreateAdapter() just created by its GUID rather than its name - avoiding
the possible ambiguity caused by same-adapter-name ordinal suffixes.
This also allows exact retrieval of the result code and pending reboot
flag from the rundll32 child process.
Furthermore, CreateAdapter() and DeleteAdapter() are now available in
_DEBUG for all platforms to allow testing. It took a #pragma comment(
linker, "/EXPORT") trick to stop compiler from decorating function names
and exporting as _CreateAdapter@16() and _DeleteAdapter@16() in x86.
Signed-off-by: Simon Rozman <simon@rozman.si>
Diffstat (limited to 'api/rundll32.c')
-rw-r--r-- | api/rundll32.c | 64 |
1 files changed, 51 insertions, 13 deletions
diff --git a/api/rundll32.c b/api/rundll32.c index 77e4842..dcd6628 100644 --- a/api/rundll32.c +++ b/api/rundll32.c @@ -5,7 +5,34 @@ #include "pch.h" -#if defined(_M_AMD64) || defined(_M_ARM64) +#define EXPORT comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__) + +#if defined(_M_AMD64) || defined(_M_ARM64) || defined(_DEBUG) + +static DWORD +WriteFormatted(_In_ DWORD StdHandle, _In_z_ const WCHAR *Template, ...) +{ + WCHAR *FormattedMessage = NULL; + DWORD SizeWritten; + va_list Arguments; + va_start(Arguments, Template); + WriteFile( + GetStdHandle(StdHandle), + FormattedMessage, + sizeof(WCHAR) * FormatMessageW( + FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER, + Template, + 0, + 0, + (void *)&FormattedMessage, + 0, + &Arguments), + &SizeWritten, + NULL); + LocalFree(FormattedMessage); + va_end(Arguments); + return SizeWritten / sizeof(WCHAR); +} static BOOL CALLBACK ConsoleLogger(_In_ WINTUN_LOGGER_LEVEL Level, _In_ const WCHAR *LogLine) @@ -14,22 +41,23 @@ ConsoleLogger(_In_ WINTUN_LOGGER_LEVEL Level, _In_ const WCHAR *LogLine) switch (Level) { case WINTUN_LOG_INFO: - Template = L"[+] %s\n"; + Template = L"[+] %1\n"; break; case WINTUN_LOG_WARN: - Template = L"[-] %s\n"; + Template = L"[-] %1\n"; break; case WINTUN_LOG_ERR: - Template = L"[!] %s\n"; + Template = L"[!] %1\n"; break; default: return FALSE; } - fwprintf(stderr, Template, LogLine); + WriteFormatted(STD_ERROR_HANDLE, Template, LogLine); return TRUE; } -static BOOL ElevateToSystem(void) +static BOOL +ElevateToSystem(void) { HANDLE CurrentProcessToken, ThreadToken, ProcessSnapshot, WinlogonProcess, WinlogonToken, DuplicatedToken; PROCESSENTRY32W ProcessEntry = { .dwSize = sizeof(PROCESSENTRY32W) }; @@ -126,21 +154,24 @@ cleanup: static int Argc; static WCHAR **Argv; -static void Init(void) +static void +Init(void) { WintunSetLogger(ConsoleLogger); Argv = CommandLineToArgvW(GetCommandLineW(), &Argc); ElevateToSystem(); } -static void Done(void) +static void +Done(void) { RevertToSelf(); LocalFree(Argv); } -__declspec(dllexport) VOID __stdcall CreateAdapter(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) +VOID __stdcall CreateAdapter(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) { +# pragma EXPORT UNREFERENCED_PARAMETER(hwnd); UNREFERENCED_PARAMETER(hinst); UNREFERENCED_PARAMETER(lpszCmdLine); @@ -160,16 +191,23 @@ __declspec(dllexport) VOID __stdcall CreateAdapter(HWND hwnd, HINSTANCE hinst, L WINTUN_ADAPTER *Adapter; BOOL RebootRequired = FALSE; DWORD Result = WintunCreateAdapter(Argv[2], Argv[3], Argc > 4 ? &RequestedGUID : NULL, &Adapter, &RebootRequired); - if (Result != ERROR_SUCCESS) - goto cleanup; + WCHAR GuidStr[MAX_GUID_STRING_LEN]; + WriteFormatted( + STD_OUTPUT_HANDLE, + L"%1!X! %2!.*s! %3!X!", + Result, + StringFromGUID2(Result == ERROR_SUCCESS ? &Adapter->CfgInstanceID : &GUID_NULL, GuidStr, _countof(GuidStr)), + GuidStr, + RebootRequired); WintunFreeAdapter(Adapter); cleanup: Done(); } -__declspec(dllexport) VOID __stdcall DeleteAdapter(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) +VOID __stdcall DeleteAdapter(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) { +# pragma EXPORT UNREFERENCED_PARAMETER(hwnd); UNREFERENCED_PARAMETER(hinst); UNREFERENCED_PARAMETER(lpszCmdLine); @@ -183,7 +221,7 @@ __declspec(dllexport) VOID __stdcall DeleteAdapter(HWND hwnd, HINSTANCE hinst, L if (FAILED(CLSIDFromString(Argv[2], &Adapter.CfgInstanceID))) goto cleanup; BOOL RebootRequired = FALSE; - WintunDeleteAdapter(&Adapter, &RebootRequired); + WriteFormatted(STD_OUTPUT_HANDLE, L"%1!X! %2!X!", WintunDeleteAdapter(&Adapter, &RebootRequired), RebootRequired); cleanup: Done(); |