aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rozman <simon@rozman.si>2021-07-28 20:20:09 +0200
committerSimon Rozman <simon@rozman.si>2021-07-28 20:25:27 +0200
commitd675646ab8df227ba39c9d0160d0ba77e8f85479 (patch)
treed6138df6a8b10083de89c644261116abd64b46d8
parentexample: resolve signed/unsigned code analysis warning (diff)
downloadwintun-d675646ab8df227ba39c9d0160d0ba77e8f85479.tar.xz
wintun-d675646ab8df227ba39c9d0160d0ba77e8f85479.zip
api: upgrade
Signed-off-by: Simon Rozman <simon@rozman.si>
-rw-r--r--api/adapter.c1129
-rw-r--r--api/adapter.h78
-rw-r--r--api/api.vcxproj4
-rw-r--r--api/logger.c51
-rw-r--r--api/logger.h123
-rw-r--r--api/main.c43
-rw-r--r--api/main.h27
-rw-r--r--api/namespace.c35
-rw-r--r--api/namespace.h25
-rw-r--r--api/nci.h16
-rw-r--r--api/ntdll.h8
-rw-r--r--api/registry.c160
-rw-r--r--api/registry.h57
-rw-r--r--api/resource.c53
-rw-r--r--api/resource.h31
-rw-r--r--api/rundll32.c544
-rw-r--r--api/rundll32.h29
-rw-r--r--api/rundll32_i.c352
-rw-r--r--api/session.c47
-rw-r--r--api/wintun.h110
20 files changed, 1539 insertions, 1383 deletions
diff --git a/api/adapter.c b/api/adapter.c
index 4d75351..2635a5c 100644
--- a/api/adapter.c
+++ b/api/adapter.c
@@ -28,38 +28,35 @@
#include "ntdll.h"
#include "registry.h"
#include "resource.h"
+#include "rundll32.h"
#include "wintun-inf.h"
#pragma warning(disable : 4221) /* nonstandard: address of automatic in initializer */
#define WAIT_FOR_REGISTRY_TIMEOUT 10000 /* ms */
#define MAX_POOL_DEVICE_TYPE (WINTUN_MAX_POOL + 8) /* Should accommodate a pool name with " Tunnel" appended */
-#if defined(_M_IX86)
-# define IMAGE_FILE_PROCESS IMAGE_FILE_MACHINE_I386
-#elif defined(_M_AMD64)
-# define IMAGE_FILE_PROCESS IMAGE_FILE_MACHINE_AMD64
-#elif defined(_M_ARM)
-# define IMAGE_FILE_PROCESS IMAGE_FILE_MACHINE_ARMNT
-#elif defined(_M_ARM64)
-# define IMAGE_FILE_PROCESS IMAGE_FILE_MACHINE_ARM64
-#else
-# error Unsupported architecture
-#endif
static const DEVPROPKEY DEVPKEY_Wintun_Pool = {
{ 0xaba51201, 0xdf7a, 0x3a38, { 0x0a, 0xd9, 0x90, 0x64, 0x42, 0xd2, 0x71, 0xae } },
DEVPROPID_FIRST_USABLE + 0
};
+static const DEVPROPKEY DEVPKEY_Wintun_Name = {
+ { 0x3361c968, 0x2f2e, 0x4660, { 0xb4, 0x7e, 0x69, 0x9c, 0xdc, 0x4c, 0x32, 0xb9 } },
+ DEVPROPID_FIRST_USABLE + 1
+};
+
typedef struct _SP_DEVINFO_DATA_LIST
{
SP_DEVINFO_DATA Data;
struct _SP_DEVINFO_DATA_LIST *Next;
} SP_DEVINFO_DATA_LIST;
-static USHORT NativeMachine = IMAGE_FILE_PROCESS;
-
-static _Return_type_success_(return != NULL) SP_DRVINFO_DETAIL_DATA_W *GetAdapterDrvInfoDetail(
+_Must_inspect_result_
+static _Return_type_success_(return != NULL)
+_Post_maybenull_
+SP_DRVINFO_DETAIL_DATA_W *
+GetAdapterDrvInfoDetail(
_In_ HDEVINFO DevInfo,
_In_opt_ SP_DEVINFO_DATA *DevInfoData,
_In_ SP_DRVINFO_DATA_W *DrvInfoData)
@@ -87,7 +84,12 @@ static _Return_type_success_(return != NULL) SP_DRVINFO_DETAIL_DATA_W *GetAdapte
}
}
-static _Return_type_success_(return != NULL) void *GetDeviceRegistryProperty(
+_Must_inspect_result_
+static _Return_type_success_(return != NULL)
+_Post_maybenull_
+_Post_writable_byte_size_(*BufLen)
+VOID *
+GetDeviceRegistryProperty(
_In_ HDEVINFO DevInfo,
_In_ SP_DEVINFO_DATA *DevInfoData,
_In_ DWORD Property,
@@ -106,17 +108,20 @@ static _Return_type_success_(return != NULL) void *GetDeviceRegistryProperty(
if (LastError != ERROR_INSUFFICIENT_BUFFER)
{
SetLastError(
- LOG_ERROR(LastError, L"Querying adapter %u property 0x%x failed", DevInfoData->DevInst, Property));
+ LOG_ERROR(LastError, L"Failed to query adapter %u property 0x%x", DevInfoData->DevInst, Property));
return NULL;
}
}
}
+_Must_inspect_result_
static _Return_type_success_(return != NULL)
- WCHAR *GetDeviceRegistryString(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData, _In_ DWORD Property)
+_Post_maybenull_
+LPWSTR
+GetDeviceRegistryString(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData, _In_ DWORD Property)
{
DWORD LastError, ValueType, Size = 256 * sizeof(WCHAR);
- WCHAR *Buf = GetDeviceRegistryProperty(DevInfo, DevInfoData, Property, &ValueType, &Size);
+ LPWSTR Buf = GetDeviceRegistryProperty(DevInfo, DevInfoData, Property, &ValueType, &Size);
if (!Buf)
return NULL;
switch (ValueType)
@@ -124,7 +129,7 @@ static _Return_type_success_(return != NULL)
case REG_SZ:
case REG_EXPAND_SZ:
case REG_MULTI_SZ:
- if (RegistryGetString(&Buf, Size / sizeof(WCHAR), ValueType))
+ if (RegistryGetString(&Buf, Size / sizeof(*Buf), ValueType))
return Buf;
LastError = GetLastError();
break;
@@ -141,11 +146,14 @@ static _Return_type_success_(return != NULL)
return NULL;
}
+_Must_inspect_result_
static _Return_type_success_(return != NULL)
- WCHAR *GetDeviceRegistryMultiString(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData, _In_ DWORD Property)
+_Post_maybenull_
+PZZWSTR
+GetDeviceRegistryMultiString(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData, _In_ DWORD Property)
{
DWORD LastError, ValueType, Size = 256 * sizeof(WCHAR);
- WCHAR *Buf = GetDeviceRegistryProperty(DevInfo, DevInfoData, Property, &ValueType, &Size);
+ PZZWSTR Buf = GetDeviceRegistryProperty(DevInfo, DevInfoData, Property, &ValueType, &Size);
if (!Buf)
return NULL;
switch (ValueType)
@@ -153,7 +161,7 @@ static _Return_type_success_(return != NULL)
case REG_SZ:
case REG_EXPAND_SZ:
case REG_MULTI_SZ:
- if (RegistryGetMultiString(&Buf, Size / sizeof(WCHAR), ValueType))
+ if (RegistryGetMultiString(&Buf, Size / sizeof(*Buf), ValueType))
return Buf;
LastError = GetLastError();
break;
@@ -171,7 +179,7 @@ static _Return_type_success_(return != NULL)
}
static BOOL
-IsOurHardwareID(_In_z_ const WCHAR *Hwids)
+IsOurHardwareID(_In_z_ PCZZWSTR Hwids)
{
for (; Hwids[0]; Hwids += wcslen(Hwids) + 1)
if (!_wcsicmp(Hwids, WINTUN_HWID))
@@ -182,7 +190,7 @@ IsOurHardwareID(_In_z_ const WCHAR *Hwids)
static BOOL
IsOurAdapter(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData)
{
- WCHAR *Hwids = GetDeviceRegistryMultiString(DevInfo, DevInfoData, SPDRP_HARDWAREID);
+ PZZWSTR Hwids = GetDeviceRegistryMultiString(DevInfo, DevInfoData, SPDRP_HARDWAREID);
if (!Hwids)
{
LOG_LAST_ERROR(L"Failed to get adapter %u hardware ID", DevInfoData->DevInst);
@@ -193,7 +201,11 @@ IsOurAdapter(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData)
return IsOurs;
}
-static _Return_type_success_(return != NULL) WCHAR *GetDeviceObjectFileName(_In_z_ const WCHAR *InstanceId)
+_Must_inspect_result_
+static _Return_type_success_(return != NULL)
+_Post_maybenull_
+LPWSTR
+GetDeviceObjectFileName(_In_z_ LPCWSTR InstanceId)
{
ULONG InterfacesLen;
DWORD LastError = CM_MapCrToWin32Err(
@@ -208,7 +220,7 @@ static _Return_type_success_(return != NULL) WCHAR *GetDeviceObjectFileName(_In_
SetLastError(LOG_ERROR(LastError, L"Failed to query adapter %s associated instances size", InstanceId));
return NULL;
}
- WCHAR *Interfaces = Alloc(InterfacesLen * sizeof(WCHAR));
+ LPWSTR Interfaces = AllocArray(InterfacesLen, sizeof(*Interfaces));
if (!Interfaces)
return NULL;
LastError = CM_MapCrToWin32Err(
@@ -228,7 +240,6 @@ static _Return_type_success_(return != NULL) WCHAR *GetDeviceObjectFileName(_In_
}
if (!Interfaces[0])
{
- LOG(WINTUN_LOG_ERR, L"Received empty adapter %s object file name", InstanceId);
Free(Interfaces);
SetLastError(ERROR_DEVICE_NOT_AVAILABLE);
return NULL;
@@ -236,9 +247,12 @@ static _Return_type_success_(return != NULL) WCHAR *GetDeviceObjectFileName(_In_
return Interfaces;
}
-static _Return_type_success_(return != INVALID_HANDLE_VALUE) HANDLE OpenDeviceObject(_In_z_ const WCHAR *InstanceId)
+_Must_inspect_result_
+static _Return_type_success_(return != INVALID_HANDLE_VALUE)
+HANDLE
+OpenDeviceObject(_In_z_ LPCWSTR InstanceId)
{
- WCHAR *Filename = GetDeviceObjectFileName(InstanceId);
+ LPWSTR Filename = GetDeviceObjectFileName(InstanceId);
if (!Filename)
return INVALID_HANDLE_VALUE;
HANDLE Handle = CreateFileW(
@@ -256,11 +270,14 @@ static _Return_type_success_(return != INVALID_HANDLE_VALUE) HANDLE OpenDeviceOb
}
static BOOL
-EnsureDeviceObject(_In_z_ const WCHAR *InstanceId)
+EnsureDeviceObject(_In_z_ LPCWSTR InstanceId)
{
- WCHAR *Filename = GetDeviceObjectFileName(InstanceId);
+ LPWSTR Filename = GetDeviceObjectFileName(InstanceId);
if (!Filename)
+ {
+ LOG_LAST_ERROR(L"Failed to determine adapter %s device object", InstanceId);
return FALSE;
+ }
BOOL Exists = TRUE;
const int Attempts = 100;
for (int i = 0; i < Attempts; ++i)
@@ -283,8 +300,9 @@ out:
#define TUN_IOCTL_FORCE_CLOSE_HANDLES CTL_CODE(51820U, 0x971U, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA)
-static _Return_type_success_(return != FALSE) BOOL
- ForceCloseWintunAdapterHandle(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData)
+static _Return_type_success_(return != FALSE)
+BOOL
+ForceCloseWintunAdapterHandle(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData)
{
DWORD LastError = ERROR_SUCCESS;
DWORD RequiredBytes;
@@ -294,7 +312,8 @@ static _Return_type_success_(return != FALSE) BOOL
LOG_ERROR(LastError, L"Failed to query adapter %u instance ID size", DevInfoData->DevInst);
return FALSE;
}
- WCHAR *InstanceId = Zalloc(sizeof(*InstanceId) * RequiredBytes);
+ LastError = ERROR_SUCCESS;
+ LPWSTR InstanceId = ZallocArray(RequiredBytes, sizeof(*InstanceId));
if (!InstanceId)
return FALSE;
if (!SetupDiGetDeviceInstanceIdW(DevInfo, DevInfoData, InstanceId, RequiredBytes, &RequiredBytes))
@@ -323,8 +342,9 @@ cleanupInstanceId:
return RET_ERROR(TRUE, LastError);
}
-static _Return_type_success_(return != FALSE) BOOL
- DisableAllOurAdapters(_In_ HDEVINFO DevInfo, _Inout_ SP_DEVINFO_DATA_LIST **DisabledAdapters)
+static _Return_type_success_(return != FALSE)
+BOOL
+DisableAllOurAdapters(_In_ HDEVINFO DevInfo, _Inout_ SP_DEVINFO_DATA_LIST **DisabledAdapters)
{
SP_PROPCHANGE_PARAMS Params = { .ClassInstallHeader = { .cbSize = sizeof(SP_CLASSINSTALL_HEADER),
.InstallFunction = DIF_PROPERTYCHANGE },
@@ -333,7 +353,7 @@ static _Return_type_success_(return != FALSE) BOOL
DWORD LastError = ERROR_SUCCESS;
for (DWORD EnumIndex = 0;; ++EnumIndex)
{
- SP_DEVINFO_DATA_LIST *DeviceNode = Alloc(sizeof(SP_DEVINFO_DATA_LIST));
+ SP_DEVINFO_DATA_LIST *DeviceNode = Zalloc(sizeof(*DeviceNode));
if (!DeviceNode)
return FALSE;
DeviceNode->Data.cbSize = sizeof(SP_DEVINFO_DATA);
@@ -377,8 +397,9 @@ static _Return_type_success_(return != FALSE) BOOL
return RET_ERROR(TRUE, LastError);
}
-static _Return_type_success_(return != FALSE) BOOL
- EnableAllOurAdapters(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA_LIST *AdaptersToEnable)
+static _Return_type_success_(return != FALSE)
+BOOL
+EnableAllOurAdapters(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA_LIST *AdaptersToEnable)
{
SP_PROPCHANGE_PARAMS Params = { .ClassInstallHeader = { .cbSize = sizeof(SP_CLASSINSTALL_HEADER),
.InstallFunction = DIF_PROPERTYCHANGE },
@@ -398,135 +419,23 @@ static _Return_type_success_(return != FALSE) BOOL
return RET_ERROR(TRUE, LastError);
}
-void
-AdapterInit(void)
-{
-#ifdef MAYBE_WOW64
- typedef BOOL(WINAPI * IsWow64Process2_t)(
- _In_ HANDLE hProcess, _Out_ USHORT * pProcessMachine, _Out_opt_ USHORT * pNativeMachine);
- HANDLE Kernel32;
- IsWow64Process2_t IsWow64Process2;
- USHORT ProcessMachine;
- if ((Kernel32 = GetModuleHandleW(L"kernel32.dll")) == NULL ||
- (IsWow64Process2 = (IsWow64Process2_t)GetProcAddress(Kernel32, "IsWow64Process2")) == NULL ||
- !IsWow64Process2(GetCurrentProcess(), &ProcessMachine, &NativeMachine))
- {
- BOOL IsWoW64;
- NativeMachine =
- IsWow64Process(GetCurrentProcess(), &IsWoW64) && IsWoW64 ? IMAGE_FILE_MACHINE_AMD64 : IMAGE_FILE_PROCESS;
- }
-#endif
-}
-
static BOOL
CheckReboot(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData)
{
SP_DEVINSTALL_PARAMS_W DevInstallParams = { .cbSize = sizeof(SP_DEVINSTALL_PARAMS_W) };
if (!SetupDiGetDeviceInstallParamsW(DevInfo, DevInfoData, &DevInstallParams))
{
- LOG_LAST_ERROR(L"Retrieving adapter %u device installation parameters failed", DevInfoData->DevInst);
+ LOG_LAST_ERROR(L"Failed to retrieve adapter %u device installation parameters", DevInfoData->DevInst);
return FALSE;
}
SetLastError(ERROR_SUCCESS);
return (DevInstallParams.Flags & (DI_NEEDREBOOT | DI_NEEDRESTART)) != 0;
}
-static _Return_type_success_(return != FALSE) BOOL
- SetQuietInstall(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData)
-{
- SP_DEVINSTALL_PARAMS_W DevInstallParams = { .cbSize = sizeof(SP_DEVINSTALL_PARAMS_W) };
- if (!SetupDiGetDeviceInstallParamsW(DevInfo, DevInfoData, &DevInstallParams))
- {
- LOG_LAST_ERROR(L"Retrieving adapter %u device installation parameters failed", DevInfoData->DevInst);
- return FALSE;
- }
- DevInstallParams.Flags |= DI_QUIETINSTALL;
- if (!SetupDiSetDeviceInstallParamsW(DevInfo, DevInfoData, &DevInstallParams))
- {
- LOG_LAST_ERROR(L"Setting adapter %u device installation parameters failed", DevInfoData->DevInst);
- return FALSE;
- }
- return TRUE;
-}
-
-static _Return_type_success_(return != FALSE) BOOL GetNetCfgInstanceIdFromHKEY(_In_ HKEY Key, _Out_ GUID *CfgInstanceID)
-{
- WCHAR *ValueStr = RegistryQueryString(Key, L"NetCfgInstanceId", TRUE);
- if (!ValueStr)
- {
- WCHAR RegPath[MAX_REG_PATH];
- LoggerGetRegistryKeyPath(Key, RegPath);
- return RET_ERROR(TRUE, LOG(WINTUN_LOG_ERR, L"Failed to get %.*s\\NetCfgInstanceId", MAX_REG_PATH, RegPath));
- }
- DWORD LastError = ERROR_SUCCESS;
- if (FAILED(CLSIDFromString(ValueStr, CfgInstanceID)))
- {
- WCHAR RegPath[MAX_REG_PATH];
- LoggerGetRegistryKeyPath(Key, RegPath);
- LOG(WINTUN_LOG_ERR, L"%.*s\\NetCfgInstanceId is not a GUID: %s", MAX_REG_PATH, RegPath, ValueStr);
- LastError = ERROR_INVALID_DATA;
- }
- Free(ValueStr);
- return RET_ERROR(TRUE, LastError);
-}
-
-static _Return_type_success_(return != FALSE) BOOL
- GetNetCfgInstanceIdFromDevInfo(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData, _Out_ GUID *CfgInstanceID)
-{
- HKEY Key = SetupDiOpenDevRegKey(DevInfo, DevInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
- if (Key == INVALID_HANDLE_VALUE)
- {
- LOG_LAST_ERROR(L"Opening adapter %u device registry key failed", DevInfoData->DevInst);
- return FALSE;
- }
- DWORD LastError = ERROR_SUCCESS;
- if (!GetNetCfgInstanceIdFromHKEY(Key, CfgInstanceID))
- LastError = GetLastError();
- RegCloseKey(Key);
- return RET_ERROR(TRUE, LastError);
-}
-
-static _Return_type_success_(return != FALSE) BOOL
- GetDevInfoData(_In_ const GUID *CfgInstanceID, _Out_ HDEVINFO *DevInfo, _Out_ SP_DEVINFO_DATA *DevInfoData)
-{
- *DevInfo = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL);
- if (!*DevInfo)
- {
- LOG_LAST_ERROR(L"Failed to get present adapters");
- return FALSE;
- }
- for (DWORD EnumIndex = 0;; ++EnumIndex)
- {
- DevInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
- if (!SetupDiEnumDeviceInfo(*DevInfo, EnumIndex, DevInfoData))
- {
- if (GetLastError() == ERROR_NO_MORE_ITEMS)
- break;
- continue;
- }
- GUID CfgInstanceID2;
- if (GetNetCfgInstanceIdFromDevInfo(*DevInfo, DevInfoData, &CfgInstanceID2) &&
- !memcmp(CfgInstanceID, &CfgInstanceID2, sizeof(GUID)))
- return TRUE;
- }
- SetupDiDestroyDeviceInfoList(*DevInfo);
- SetLastError(ERROR_FILE_NOT_FOUND);
- return FALSE;
-}
-
-static void
-RemoveNumberedSuffix(_Inout_z_ WCHAR *Name)
-{
- for (size_t i = wcslen(Name); i--;)
- {
- if ((Name[i] < L'0' || Name[i] > L'9') && !iswspace(Name[i]))
- return;
- Name[i] = 0;
- }
-}
-
-static _Return_type_success_(return != FALSE) BOOL
- GetPoolDeviceTypeName(_In_z_ const WCHAR *Pool, _Out_cap_c_(MAX_POOL_DEVICE_TYPE) WCHAR *Name)
+_Must_inspect_result_
+static _Return_type_success_(return != FALSE)
+BOOL
+GetPoolDeviceTypeName(_In_z_ LPCWSTR Pool, _Out_writes_z_(MAX_POOL_DEVICE_TYPE) LPWSTR Name)
{
if (_snwprintf_s(Name, MAX_POOL_DEVICE_TYPE, _TRUNCATE, L"%s Tunnel", Pool) == -1)
{
@@ -538,74 +447,62 @@ static _Return_type_success_(return != FALSE) BOOL
}
static BOOL
-IsPoolMember(_In_z_ const WCHAR *Pool, _In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData)
+IsPoolMember(_In_z_ LPCWSTR Pool, _In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData)
{
WCHAR PoolProp[MAX_POOL_DEVICE_TYPE];
DEVPROPTYPE PropType;
- if (SetupDiGetDevicePropertyW(
- DevInfo, DevInfoData, &DEVPKEY_Wintun_Pool, &PropType, (PBYTE)PoolProp, sizeof(PoolProp), NULL, 0) &&
- PropType == DEVPROP_TYPE_STRING)
- return !_wcsicmp(PoolProp, Pool);
-
- LOG_LAST_ERROR(L"Reading pool devpkey failed, falling back");
- DWORD LastError = ERROR_SUCCESS;
- BOOL Ret = FALSE;
- WCHAR *DeviceDesc = GetDeviceRegistryString(DevInfo, DevInfoData, SPDRP_DEVICEDESC);
- WCHAR *FriendlyName = GetDeviceRegistryString(DevInfo, DevInfoData, SPDRP_FRIENDLYNAME);
- WCHAR PoolDeviceTypeName[MAX_POOL_DEVICE_TYPE];
- if (!GetPoolDeviceTypeName(Pool, PoolDeviceTypeName))
+ if (!SetupDiGetDevicePropertyW(
+ DevInfo, DevInfoData, &DEVPKEY_Wintun_Pool, &PropType, (PBYTE)PoolProp, sizeof(PoolProp), NULL, 0))
+ return FALSE;
+ if (PropType != DEVPROP_TYPE_STRING)
{
- LastError = GetLastError();
- goto cleanupNames;
- }
- Ret = (FriendlyName && !_wcsicmp(FriendlyName, PoolDeviceTypeName)) ||
- (DeviceDesc && !_wcsicmp(DeviceDesc, PoolDeviceTypeName));
- if (Ret)
- goto cleanupNames;
- if (FriendlyName)
- RemoveNumberedSuffix(FriendlyName);
- if (DeviceDesc)
- RemoveNumberedSuffix(DeviceDesc);
- Ret = (FriendlyName && !_wcsicmp(FriendlyName, PoolDeviceTypeName)) ||
- (DeviceDesc && !_wcsicmp(DeviceDesc, PoolDeviceTypeName));
-cleanupNames:
- Free(FriendlyName);
- Free(DeviceDesc);
- SetLastError(LastError);
- return Ret;
+ SetLastError(ERROR_BAD_DEVICE);
+ return FALSE;
+ }
+ SetLastError(ERROR_SUCCESS);
+ return !_wcsicmp(PoolProp, Pool);
}
-static _Return_type_success_(return != NULL) WINTUN_ADAPTER
- *CreateAdapterData(_In_z_ const WCHAR *Pool, _In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData)
+_Must_inspect_result_
+static _Return_type_success_(return != FALSE)
+BOOL
+PopulateAdapterData(_Inout_ WINTUN_ADAPTER *Adapter, _In_z_ LPCWSTR Pool)
{
+ DWORD LastError = ERROR_SUCCESS;
+
/* Open HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\<class>\<id> registry key. */
- HKEY Key = SetupDiOpenDevRegKey(DevInfo, DevInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
+ HKEY Key =
+ SetupDiOpenDevRegKey(Adapter->DevInfo, &Adapter->DevInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
if (Key == INVALID_HANDLE_VALUE)
{
- LOG_LAST_ERROR(L"Opening adapter %u device registry key failed", DevInfoData->DevInst);
- return NULL;
+ LOG_LAST_ERROR(L"Failed to open adapter %u device registry key", Adapter->DevInfoData.DevInst);
+ return FALSE;
}
- DWORD LastError;
- WINTUN_ADAPTER *Adapter = Alloc(sizeof(WINTUN_ADAPTER));
- if (!Adapter)
+ LPWSTR ValueStr = RegistryQueryString(Key, L"NetCfgInstanceId", TRUE);
+ if (!ValueStr)
{
- LastError = GetLastError();
+ WCHAR RegPath[MAX_REG_PATH];
+ LoggerGetRegistryKeyPath(Key, RegPath);
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to get %.*s\\NetCfgInstanceId", MAX_REG_PATH, RegPath);
goto cleanupKey;
}
-
- if (!GetNetCfgInstanceIdFromHKEY(Key, &Adapter->CfgInstanceID))
+ if (FAILED(CLSIDFromString(ValueStr, &Adapter->CfgInstanceID)))
{
- LastError = GetLastError();
- goto cleanupAdapter;
+ WCHAR RegPath[MAX_REG_PATH];
+ LoggerGetRegistryKeyPath(Key, RegPath);
+ LastError = LOG(WINTUN_LOG_ERR, L"%.*s\\NetCfgInstanceId is not a GUID: %s", MAX_REG_PATH, RegPath, ValueStr);
+ Free(ValueStr);
+ goto cleanupKey;
}
+ Free(ValueStr);
if (!RegistryQueryDWORD(Key, L"NetLuidIndex", &Adapter->LuidIndex, TRUE))
{
WCHAR RegPath[MAX_REG_PATH];
LoggerGetRegistryKeyPath(Key, RegPath);
LastError = LOG(WINTUN_LOG_ERR, L"Failed to get %.*s\\NetLuidIndex", MAX_REG_PATH, RegPath);
- goto cleanupAdapter;
+ goto cleanupKey;
}
if (!RegistryQueryDWORD(Key, L"*IfType", &Adapter->IfType, TRUE))
@@ -613,166 +510,67 @@ static _Return_type_success_(return != NULL) WINTUN_ADAPTER
WCHAR RegPath[MAX_REG_PATH];
LoggerGetRegistryKeyPath(Key, RegPath);
LastError = LOG(WINTUN_LOG_ERR, L"Failed to get %.*s\\*IfType", MAX_REG_PATH, RegPath);
- goto cleanupAdapter;
+ goto cleanupKey;
}
DWORD Size;
if (!SetupDiGetDeviceInstanceIdW(
- DevInfo, DevInfoData, Adapter->DevInstanceID, _countof(Adapter->DevInstanceID), &Size))
+ Adapter->DevInfo, &Adapter->DevInfoData, Adapter->DevInstanceID, _countof(Adapter->DevInstanceID), &Size))
{
- LastError = LOG_LAST_ERROR(L"Failed to get adapter %u instance ID", DevInfoData->DevInst);
- goto cleanupAdapter;
+ LastError = LOG_LAST_ERROR(L"Failed to get adapter %u instance ID", Adapter->DevInfoData.DevInst);
+ goto cleanupKey;
}
if (wcsncpy_s(Adapter->Pool, _countof(Adapter->Pool), Pool, _TRUNCATE) == STRUNCATE)
{
LOG(WINTUN_LOG_ERR, L"Pool name too long: %s", Pool);
LastError = ERROR_INVALID_PARAMETER;
- goto cleanupAdapter;
+ goto cleanupKey;
}
- RegCloseKey(Key);
- return Adapter;
-cleanupAdapter:
- Free(Adapter);
cleanupKey:
RegCloseKey(Key);
- SetLastError(LastError);
- return NULL;
-}
-
-static _Return_type_success_(return != FALSE) BOOL
- GetDeviceRegPath(_In_ const WINTUN_ADAPTER *Adapter, _Out_cap_c_(MAX_REG_PATH) WCHAR *Path)
-{
- if (_snwprintf_s(
- Path,
- MAX_REG_PATH,
- _TRUNCATE,
- L"SYSTEM\\CurrentControlSet\\Enum\\%.*s",
- MAX_INSTANCE_ID,
- Adapter->DevInstanceID) == -1)
- {
- LOG(WINTUN_LOG_ERR, L"Registry path too long: %.*s", MAX_INSTANCE_ID, Adapter->DevInstanceID);
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- return TRUE;
+ return RET_ERROR(TRUE, LastError);
}
-void WINAPI
-WintunFreeAdapter(_In_ WINTUN_ADAPTER *Adapter)
+_Use_decl_annotations_
+VOID WINAPI
+WintunFreeAdapter(WINTUN_ADAPTER *Adapter)
{
+ if (!Adapter)
+ return;
+ if (Adapter->DevInfo)
+ SetupDiDestroyDeviceInfoList(Adapter->DevInfo);
Free(Adapter);
}
-_Return_type_success_(return != NULL) WINTUN_ADAPTER *WINAPI
- WintunOpenAdapter(_In_z_ const WCHAR *Pool, _In_z_ const WCHAR *Name)
+_Use_decl_annotations_
+BOOL WINAPI
+WintunGetAdapterName(WINTUN_ADAPTER *Adapter, LPWSTR Name)
{
- DWORD LastError;
- WINTUN_ADAPTER *Adapter = NULL;
- HANDLE Mutex = NamespaceTakePoolMutex(Pool);
- if (!Mutex)
- {
- LastError = LOG(WINTUN_LOG_ERR, L"Failed to take %s pool mutex", Pool);
- goto cleanup;
- }
-
- HDEVINFO DevInfo = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL);
- if (DevInfo == INVALID_HANDLE_VALUE)
- {
- LastError = LOG_LAST_ERROR(L"Failed to get present adapters");
- goto cleanupMutex;
- }
-
- for (DWORD EnumIndex = 0;; ++EnumIndex)
- {
- SP_DEVINFO_DATA DevInfoData = { .cbSize = sizeof(SP_DEVINFO_DATA) };
- if (!SetupDiEnumDeviceInfo(DevInfo, EnumIndex, &DevInfoData))
- {
- if (GetLastError() == ERROR_NO_MORE_ITEMS)
- break;
- continue;
- }
-
- GUID CfgInstanceID;
- if (!GetNetCfgInstanceIdFromDevInfo(DevInfo, &DevInfoData, &CfgInstanceID))
- continue;
-
- /* TODO: is there a better way than comparing ifnames? */
- WCHAR Name2[MAX_ADAPTER_NAME];
- if (NciGetConnectionName(&CfgInstanceID, Name2, sizeof(Name2), NULL) != ERROR_SUCCESS)
- continue;
- Name2[_countof(Name2) - 1] = 0;
- if (_wcsicmp(Name, Name2))
- {
- RemoveNumberedSuffix(Name2);
- if (_wcsicmp(Name, Name2))
- continue;
- }
-
- /* Check the Hardware ID to make sure it's a real Wintun device. */
- if (!IsOurAdapter(DevInfo, &DevInfoData))
- {
- LOG(WINTUN_LOG_ERR, L"Foreign adapter %u named %s exists", DevInfoData.DevInst, Name);
- LastError = ERROR_ALREADY_EXISTS;
- goto cleanupDevInfo;
- }
-
- if (!IsPoolMember(Pool, DevInfo, &DevInfoData))
- {
- if ((LastError = GetLastError()) == ERROR_SUCCESS)
- {
- LOG(WINTUN_LOG_ERR, L"Adapter %u named %s is not a member of %s pool", DevInfoData.DevInst, Name, Pool);
- LastError = ERROR_ALREADY_EXISTS;
- goto cleanupDevInfo;
- }
- else
- {
- LOG(WINTUN_LOG_ERR, L"Failed to get adapter %u pool membership", DevInfoData.DevInst);
- goto cleanupDevInfo;
- }
- }
-
- Adapter = CreateAdapterData(Pool, DevInfo, &DevInfoData);
- if (!Adapter)
- {
- LastError = LOG(WINTUN_LOG_ERR, L"Failed to create adapter %u data", DevInfoData.DevInst);
- goto cleanupDevInfo;
- }
-
- if (!EnsureDeviceObject(Adapter->DevInstanceID))
- {
- LastError = GetLastError();
- goto cleanupDevInfo;
- }
-
- LastError = ERROR_SUCCESS;
- goto cleanupDevInfo;
- }
- LastError = ERROR_FILE_NOT_FOUND;
-cleanupDevInfo:
- SetupDiDestroyDeviceInfoList(DevInfo);
-cleanupMutex:
- NamespaceReleaseMutex(Mutex);
-cleanup:
- SetLastError(LastError);
- return Adapter;
-}
-
-_Return_type_success_(return != FALSE) BOOL WINAPI
- WintunGetAdapterName(_In_ const WINTUN_ADAPTER *Adapter, _Out_cap_c_(MAX_ADAPTER_NAME) WCHAR *Name)
-{
- DWORD LastError = NciGetConnectionName(&Adapter->CfgInstanceID, Name, MAX_ADAPTER_NAME * sizeof(WCHAR), NULL);
- if (LastError != ERROR_SUCCESS)
+ DEVPROPTYPE PropType;
+ if (!SetupDiGetDevicePropertyW(
+ Adapter->DevInfo,
+ &Adapter->DevInfoData,
+ &DEVPKEY_Wintun_Name,
+ &PropType,
+ (PBYTE)Name,
+ MAX_ADAPTER_NAME * sizeof(*Name),
+ NULL,
+ 0))
+ return FALSE;
+ if (PropType != DEVPROP_TYPE_STRING || !*Name)
{
- SetLastError(LOG_ERROR(LastError, L"Failed to get name"));
+ SetLastError(ERROR_BAD_DEVICE);
return FALSE;
}
return TRUE;
}
-static _Return_type_success_(return != FALSE) BOOL
- ConvertInterfaceAliasToGuid(_In_z_ const WCHAR *Name, _Out_ GUID *Guid)
+_Must_inspect_result_
+static _Return_type_success_(return != FALSE)
+BOOL
+ConvertInterfaceAliasToGuid(_In_z_ LPCWSTR Name, _Out_ GUID *Guid)
{
NET_LUID Luid;
DWORD LastError = ConvertInterfaceAliasToLuid(Name, &Luid);
@@ -790,10 +588,10 @@ static _Return_type_success_(return != FALSE) BOOL
return TRUE;
}
-_Return_type_success_(return != FALSE) BOOL WINAPI
- WintunSetAdapterName(_In_ const WINTUN_ADAPTER *Adapter, _In_z_ const WCHAR *Name)
+_Use_decl_annotations_
+BOOL WINAPI
+WintunSetAdapterName(WINTUN_ADAPTER *Adapter, LPCWSTR Name)
{
- DWORD LastError;
const int MaxSuffix = 1000;
WCHAR AvailableName[MAX_ADAPTER_NAME];
if (wcsncpy_s(AvailableName, _countof(AvailableName), Name, _TRUNCATE) == STRUNCATE)
@@ -802,9 +600,24 @@ _Return_type_success_(return != FALSE) BOOL WINAPI
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
+
+ if (!SetupDiSetDevicePropertyW(
+ Adapter->DevInfo,
+ &Adapter->DevInfoData,
+ &DEVPKEY_Wintun_Name,
+ DEVPROP_TYPE_STRING,
+#pragma warning(suppress : 4090)
+ (const BYTE *)Name,
+ (DWORD)((wcslen(Name) + 1) * sizeof(*Name)),
+ 0))
+ {
+ LOG_LAST_ERROR(L"Failed to set adapter %u name", Adapter->DevInfoData.DevInst);
+ return FALSE;
+ }
+
for (int i = 0;; ++i)
{
- LastError = NciSetConnectionName(&Adapter->CfgInstanceID, AvailableName);
+ DWORD LastError = NciSetConnectionName(&Adapter->CfgInstanceID, AvailableName);
if (LastError == ERROR_DUP_NAME)
{
GUID Guid2;
@@ -838,7 +651,7 @@ _Return_type_success_(return != FALSE) BOOL WINAPI
break;
if (i >= MaxSuffix || LastError != ERROR_DUP_NAME)
{
- SetLastError(LOG_ERROR(LastError, L"Setting adapter name failed"));
+ SetLastError(LOG_ERROR(LastError, L"Failed to set adapter name"));
return FALSE;
}
if (_snwprintf_s(AvailableName, _countof(AvailableName), _TRUNCATE, L"%s %d", Name, i + 1) == -1)
@@ -849,74 +662,162 @@ _Return_type_success_(return != FALSE) BOOL WINAPI
}
}
- /* TODO: This should use NetSetup2 so that it doesn't get unset. */
- HKEY DeviceRegKey;
- WCHAR DeviceRegPath[MAX_REG_PATH];
- if (!GetDeviceRegPath(Adapter, DeviceRegPath))
- return FALSE;
- LastError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, DeviceRegPath, 0, KEY_SET_VALUE, &DeviceRegKey);
- if (LastError != ERROR_SUCCESS)
+ if (!SetupDiSetDevicePropertyW(
+ Adapter->DevInfo,
+ &Adapter->DevInfoData,
+ &DEVPKEY_Wintun_Pool,
+ DEVPROP_TYPE_STRING,
+#pragma warning(suppress : 4090)
+ (const BYTE *)Adapter->Pool,
+ (DWORD)((wcslen(Adapter->Pool) + 1) * sizeof(*Adapter->Pool)),
+ 0))
{
- SetLastError(LOG_ERROR(LastError, L"Failed to open registry key %s", DeviceRegPath));
+ LOG_LAST_ERROR(L"Failed to set adapter %u pool", Adapter->DevInfoData.DevInst);
return FALSE;
}
+
WCHAR PoolDeviceTypeName[MAX_POOL_DEVICE_TYPE];
if (!GetPoolDeviceTypeName(Adapter->Pool, PoolDeviceTypeName))
+ return FALSE;
+ if (!SetupDiSetDeviceRegistryPropertyW(
+ Adapter->DevInfo,
+ &Adapter->DevInfoData,
+ SPDRP_FRIENDLYNAME,
+ (const BYTE *)PoolDeviceTypeName,
+ (DWORD)((wcslen(PoolDeviceTypeName) + 1) * sizeof(*PoolDeviceTypeName))))
{
- LastError = GetLastError();
- goto cleanupDeviceRegKey;
+ LOG_LAST_ERROR(L"Failed to set adapter %u friendly name", Adapter->DevInfoData.DevInst);
+ return FALSE;
}
- LastError = RegSetKeyValueW(
- DeviceRegKey,
- NULL,
- L"FriendlyName",
- REG_SZ,
- PoolDeviceTypeName,
- (DWORD)((wcslen(PoolDeviceTypeName) + 1) * sizeof(WCHAR)));
+
+ return TRUE;
+}
+
+_Use_decl_annotations_
+WINTUN_ADAPTER_HANDLE WINAPI
+WintunOpenAdapter(LPCWSTR Pool, LPCWSTR Name)
+{
+ WINTUN_ADAPTER *Adapter = Zalloc(sizeof(*Adapter));
+ if (!Adapter)
+ return FALSE;
+
+ DWORD LastError = ERROR_SUCCESS;
+ HANDLE Mutex = NamespaceTakePoolMutex(Pool);
+ if (!Mutex)
+ {
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to take %s pool mutex", Pool);
+ goto cleanup;
+ }
+
+ Adapter->DevInfo = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL);
+ if (Adapter->DevInfo == INVALID_HANDLE_VALUE)
+ {
+ LastError = LOG_LAST_ERROR(L"Failed to get present adapters");
+ goto cleanupMutex;
+ }
+
+ Adapter->DevInfoData.cbSize = sizeof(Adapter->DevInfoData);
+ for (DWORD EnumIndex = 0;; ++EnumIndex)
+ {
+ if (!SetupDiEnumDeviceInfo(Adapter->DevInfo, EnumIndex, &Adapter->DevInfoData))
+ {
+ if (GetLastError() == ERROR_NO_MORE_ITEMS)
+ break;
+ continue;
+ }
+
+ WCHAR Name2[MAX_ADAPTER_NAME];
+ if (!WintunGetAdapterName(Adapter, Name2))
+ continue;
+ if (_wcsicmp(Name, Name2))
+ continue;
+
+ /* Check the Hardware ID to make sure it's a real Wintun device. */
+ if (!IsOurAdapter(Adapter->DevInfo, &Adapter->DevInfoData))
+ {
+ LOG(WINTUN_LOG_ERR, L"Foreign adapter %u named %s exists", Adapter->DevInfoData.DevInst, Name);
+ LastError = ERROR_ALREADY_EXISTS;
+ goto cleanupMutex;
+ }
+
+ if (!IsPoolMember(Pool, Adapter->DevInfo, &Adapter->DevInfoData))
+ {
+ if ((LastError = GetLastError()) == ERROR_SUCCESS)
+ {
+ LOG(WINTUN_LOG_ERR,
+ L"Adapter %u named %s is not a member of %s pool",
+ Adapter->DevInfoData.DevInst,
+ Name,
+ Pool);
+ LastError = ERROR_ALREADY_EXISTS;
+ goto cleanupMutex;
+ }
+ else
+ {
+ LOG(WINTUN_LOG_ERR, L"Failed to get adapter %u pool membership", Adapter->DevInfoData.DevInst);
+ goto cleanupMutex;
+ }
+ }
+
+ if (!PopulateAdapterData(Adapter, Pool))
+ {
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to populate adapter %u data", Adapter->DevInfoData.DevInst);
+ goto cleanupMutex;
+ }
+
+ if (!EnsureDeviceObject(Adapter->DevInstanceID))
+ {
+ LastError = GetLastError();
+ goto cleanupMutex;
+ }
+
+ /* Our comparison was case-insensitive, and we also might want to reenforce the NCI connection. */
+ WintunSetAdapterName(Adapter, Name);
+
+ LastError = ERROR_SUCCESS;
+ goto cleanupMutex;
+ }
+ LastError = ERROR_FILE_NOT_FOUND;
+cleanupMutex:
+ NamespaceReleaseMutex(Mutex);
+cleanup:
if (LastError != ERROR_SUCCESS)
- LOG_ERROR(LastError, L"Failed to set %s\\FriendlyName", DeviceRegPath);
-cleanupDeviceRegKey:
- RegCloseKey(DeviceRegKey);
- return RET_ERROR(TRUE, LastError);
+ WintunFreeAdapter(Adapter);
+ return RET_ERROR(Adapter, LastError);
}
-void WINAPI
-WintunGetAdapterLUID(_In_ const WINTUN_ADAPTER *Adapter, _Out_ NET_LUID *Luid)
+_Use_decl_annotations_
+VOID WINAPI
+WintunGetAdapterLUID(WINTUN_ADAPTER *Adapter, NET_LUID *Luid)
{
Luid->Info.Reserved = 0;
Luid->Info.NetLuidIndex = Adapter->LuidIndex;
Luid->Info.IfType = Adapter->IfType;
}
-_Return_type_success_(return != INVALID_HANDLE_VALUE) HANDLE WINAPI
- AdapterOpenDeviceObject(_In_ const WINTUN_ADAPTER *Adapter)
+_Use_decl_annotations_
+HANDLE WINAPI
+AdapterOpenDeviceObject(const WINTUN_ADAPTER *Adapter)
{
return OpenDeviceObject(Adapter->DevInstanceID);
}
-static BOOL
-IsWindows10(void)
-{
- DWORD MajorVersion;
- RtlGetNtVersionNumbers(&MajorVersion, NULL, NULL);
- return MajorVersion >= 10;
-}
-
-static BOOL
-HaveWHQL(void)
+static BOOL HaveWHQL(VOID)
{
#if defined(HAVE_WHQL)
- return IsWindows10();
+ return IsWindows10;
#else
return FALSE;
#endif
}
-static _Return_type_success_(return != FALSE) BOOL InstallCertificate(_In_z_ const WCHAR *SignedResource)
+static _Return_type_success_(return != FALSE)
+BOOL
+InstallCertificate(_In_z_ LPCWSTR SignedResource)
{
LOG(WINTUN_LOG_INFO, L"Trusting code signing certificate");
DWORD SizeResource;
- const void *LockedResource = ResourceGetAddress(SignedResource, &SizeResource);
+ const VOID *LockedResource = ResourceGetAddress(SignedResource, &SizeResource);
if (!LockedResource)
{
LOG(WINTUN_LOG_ERR, L"Failed to locate resource %s", SignedResource);
@@ -1021,8 +922,10 @@ IsNewer(
return FALSE;
}
-static _Return_type_success_(return != FALSE) BOOL
- GetTcpipAdapterRegPath(_In_ const WINTUN_ADAPTER *Adapter, _Out_cap_c_(MAX_REG_PATH) WCHAR *Path)
+_Must_inspect_result_
+static _Return_type_success_(return != FALSE)
+BOOL
+GetTcpipAdapterRegPath(_In_ const WINTUN_ADAPTER *Adapter, _Out_writes_z_(MAX_REG_PATH) LPWSTR Path)
{
WCHAR Guid[MAX_GUID_STRING_LEN];
if (_snwprintf_s(
@@ -1040,8 +943,10 @@ static _Return_type_success_(return != FALSE) BOOL
return TRUE;
}
-static _Return_type_success_(return != FALSE) BOOL
- GetTcpipInterfaceRegPath(_In_ const WINTUN_ADAPTER *Adapter, _Out_cap_c_(MAX_REG_PATH) WCHAR *Path)
+_Must_inspect_result_
+static _Return_type_success_(return != FALSE)
+BOOL
+GetTcpipInterfaceRegPath(_In_ const WINTUN_ADAPTER *Adapter, _Out_writes_z_(MAX_REG_PATH) LPWSTR Path)
{
HKEY TcpipAdapterRegKey;
WCHAR TcpipAdapterRegPath[MAX_REG_PATH];
@@ -1053,7 +958,7 @@ static _Return_type_success_(return != FALSE) BOOL
SetLastError(LOG_ERROR(LastError, L"Failed to open registry key %s", TcpipAdapterRegPath));
return FALSE;
}
- WCHAR *Paths = RegistryQueryString(TcpipAdapterRegKey, L"IpConfig", TRUE);
+ LPWSTR Paths = RegistryQueryString(TcpipAdapterRegKey, L"IpConfig", TRUE);
if (!Paths)
{
LastError = LOG(WINTUN_LOG_ERR, L"Failed to get %s\\IpConfig", TcpipAdapterRegPath);
@@ -1078,7 +983,9 @@ cleanupTcpipAdapterRegKey:
return RET_ERROR(TRUE, LastError);
}
-static _Return_type_success_(return != 0) DWORD VersionOfFile(_In_z_ const WCHAR *Filename)
+static _Return_type_success_(return != 0)
+DWORD
+VersionOfFile(_In_z_ LPCWSTR Filename)
{
DWORD Zero;
DWORD Len = GetFileVersionInfoSizeW(Filename, &Zero);
@@ -1114,45 +1021,6 @@ out:
return RET_ERROR(Version, LastError);
}
-static _Return_type_success_(return != FALSE) BOOL
- CreateTemporaryDirectory(_Out_cap_c_(MAX_PATH) WCHAR *RandomTempSubDirectory)
-{
- WCHAR WindowsDirectory[MAX_PATH];
- if (!GetWindowsDirectoryW(WindowsDirectory, _countof(WindowsDirectory)))
- {
- LOG_LAST_ERROR(L"Failed to get Windows folder");
- return FALSE;
- }
- WCHAR WindowsTempDirectory[MAX_PATH];
- if (!PathCombineW(WindowsTempDirectory, WindowsDirectory, L"Temp"))
- {
- SetLastError(ERROR_BUFFER_OVERFLOW);
- return FALSE;
- }
- UCHAR RandomBytes[32] = { 0 };
-#pragma warning(suppress : 6387)
- if (!RtlGenRandom(RandomBytes, sizeof(RandomBytes)))
- {
- LOG(WINTUN_LOG_ERR, L"Failed to generate random");
- SetLastError(ERROR_GEN_FAILURE);
- return FALSE;
- }
- WCHAR RandomSubDirectory[sizeof(RandomBytes) * 2 + 1];
- for (int i = 0; i < sizeof(RandomBytes); ++i)
- swprintf_s(&RandomSubDirectory[i * 2], 3, L"%02x", RandomBytes[i]);
- if (!PathCombineW(RandomTempSubDirectory, WindowsTempDirectory, RandomSubDirectory))
- {
- SetLastError(ERROR_BUFFER_OVERFLOW);
- return FALSE;
- }
- if (!CreateDirectoryW(RandomTempSubDirectory, &SecurityAttributes))
- {
- LOG_LAST_ERROR(L"Failed to create temporary folder %s", RandomTempSubDirectory);
- return FALSE;
- }
- return TRUE;
-}
-
static DWORD WINAPI
MaybeGetRunningDriverVersion(BOOL ReturnOneIfRunningInsteadOfVersion)
{
@@ -1176,7 +1044,7 @@ MaybeGetRunningDriverVersion(BOOL ReturnOneIfRunningInsteadOfVersion)
DWORD LastError = ERROR_SUCCESS, Version = 0;
for (ULONG i = Modules->NumberOfModules; i-- > 0;)
{
- const char *NtPath = (const char *)Modules->Modules[i].FullPathName;
+ LPCSTR NtPath = (LPCSTR)Modules->Modules[i].FullPathName;
if (!_stricmp(&NtPath[Modules->Modules[i].OffsetToFileName], "wintun.sys"))
{
if (ReturnOneIfRunningInsteadOfVersion)
@@ -1199,14 +1067,13 @@ cleanupModules:
return RET_ERROR(Version, LastError);
}
-DWORD WINAPI
-WintunGetRunningDriverVersion(void)
+_Use_decl_annotations_
+DWORD WINAPI WintunGetRunningDriverVersion(VOID)
{
return MaybeGetRunningDriverVersion(FALSE);
}
-static BOOL
-EnsureWintunUnloaded(void)
+static BOOL EnsureWintunUnloaded(VOID)
{
BOOL Loaded;
for (int i = 0; (Loaded = MaybeGetRunningDriverVersion(TRUE) != 0) != FALSE && i < 300; ++i)
@@ -1214,10 +1081,32 @@ EnsureWintunUnloaded(void)
return !Loaded;
}
-static _Return_type_success_(return != FALSE) BOOL SelectDriver(
+static VOID
+SelectDriverDeferredCleanup(_In_ HDEVINFO DevInfoExistingAdapters, _In_opt_ SP_DEVINFO_DATA_LIST *ExistingAdapters)
+{
+ if (ExistingAdapters)
+ {
+ EnableAllOurAdapters(DevInfoExistingAdapters, ExistingAdapters);
+ while (ExistingAdapters)
+ {
+ SP_DEVINFO_DATA_LIST *Next = ExistingAdapters->Next;
+ Free(ExistingAdapters);
+ ExistingAdapters = Next;
+ }
+ }
+ if (DevInfoExistingAdapters != INVALID_HANDLE_VALUE)
+ SetupDiDestroyDeviceInfoList(DevInfoExistingAdapters);
+}
+
+_Must_inspect_result_
+static _Return_type_success_(return != FALSE)
+BOOL
+SelectDriver(
_In_ HDEVINFO DevInfo,
_In_ SP_DEVINFO_DATA *DevInfoData,
- _Inout_ SP_DEVINSTALL_PARAMS_W *DevInstallParams)
+ _Inout_ SP_DEVINSTALL_PARAMS_W *DevInstallParams,
+ _Out_ HDEVINFO *DevInfoExistingAdaptersForCleanup,
+ _Out_ SP_DEVINFO_DATA_LIST **ExistingAdaptersForCleanup)
{
static const FILETIME OurDriverDate = WINTUN_INF_FILETIME;
static const DWORDLONG OurDriverVersion = WINTUN_INF_VERSION;
@@ -1313,7 +1202,7 @@ static _Return_type_success_(return != FALSE) BOOL SelectDriver(
(DWORD)((OurDriverVersion & 0xffff000000000000) >> 48),
(DWORD)((OurDriverVersion & 0x0000ffff00000000) >> 32));
WCHAR RandomTempSubDirectory[MAX_PATH];
- if (!CreateTemporaryDirectory(RandomTempSubDirectory))
+ if (!ResourceCreateTemporaryDirectory(RandomTempSubDirectory))
{
LastError = LOG_LAST_ERROR(L"Failed to create temporary folder %s", RandomTempSubDirectory);
goto cleanupExistingAdapters;
@@ -1363,7 +1252,7 @@ static _Return_type_success_(return != FALSE) BOOL SelectDriver(
}
if (!SetupDiSetDeviceInstallParamsW(DevInfo, DevInfoData, DevInstallParams))
{
- LastError = LOG_LAST_ERROR(L"Setting adapter %u device installation parameters failed", DevInfoData->DevInst);
+ LastError = LOG_LAST_ERROR(L"Failed to set adapter %u device installation parameters", DevInfoData->DevInst);
goto cleanupDelete;
}
if (!SetupDiBuildDriverInfoList(DevInfo, DevInfoData, SPDIT_COMPATDRIVER))
@@ -1393,18 +1282,13 @@ cleanupDelete:
cleanupDirectory:
RemoveDirectoryW(RandomTempSubDirectory);
cleanupExistingAdapters:
- if (ExistingAdapters)
+ if (LastError == ERROR_SUCCESS)
{
- EnableAllOurAdapters(DevInfoExistingAdapters, ExistingAdapters);
- while (ExistingAdapters)
- {
- SP_DEVINFO_DATA_LIST *Next = ExistingAdapters->Next;
- Free(ExistingAdapters);
- ExistingAdapters = Next;
- }
+ *DevInfoExistingAdaptersForCleanup = DevInfoExistingAdapters;
+ *ExistingAdaptersForCleanup = ExistingAdapters;
}
- if (DevInfoExistingAdapters != INVALID_HANDLE_VALUE)
- SetupDiDestroyDeviceInfoList(DevInfoExistingAdapters);
+ else
+ SelectDriverDeferredCleanup(DevInfoExistingAdapters, ExistingAdapters);
if (DestroyDriverInfoListOnCleanup)
SetupDiDestroyDriverInfoList(DevInfo, DevInfoData, SPDIT_COMPATDRIVER);
cleanupDriverInstallationLock:
@@ -1412,73 +1296,136 @@ cleanupDriverInstallationLock:
return RET_ERROR(TRUE, LastError);
}
-static _Return_type_success_(return != NULL) WINTUN_ADAPTER *CreateAdapter(
- _In_z_ const WCHAR *Pool,
- _In_z_ const WCHAR *Name,
- _In_opt_ const GUID *RequestedGUID,
- _Inout_ BOOL *RebootRequired)
+_Use_decl_annotations_
+WINTUN_ADAPTER *
+AdapterOpenFromDevInstanceId(LPCWSTR Pool, LPCWSTR DevInstanceID)
+{
+ WINTUN_ADAPTER *Adapter = Zalloc(sizeof(*Adapter));
+ if (!Adapter)
+ return FALSE;
+
+ DWORD LastError = ERROR_SUCCESS;
+ HANDLE Mutex = NamespaceTakePoolMutex(Pool);
+ if (!Mutex)
+ {
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to take %s pool mutex", Pool);
+ goto cleanup;
+ }
+ Adapter->DevInfo = SetupDiCreateDeviceInfoListExW(&GUID_DEVCLASS_NET, NULL, NULL, NULL);
+ if (Adapter->DevInfo == INVALID_HANDLE_VALUE)
+ {
+ LastError = LOG_LAST_ERROR(L"Failed to get present adapters");
+ goto cleanupMutex;
+ }
+ Adapter->DevInfoData.cbSize = sizeof(Adapter->DevInfoData);
+ if (!SetupDiOpenDeviceInfoW(Adapter->DevInfo, DevInstanceID, NULL, 0, &Adapter->DevInfoData))
+ {
+ LastError = LOG_LAST_ERROR(L"Failed to open device instance ID %s", DevInstanceID);
+ goto cleanupMutex;
+ }
+ if (!PopulateAdapterData(Adapter, Pool))
+ {
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to populate adapter %u data", Adapter->DevInfoData.DevInst);
+ goto cleanupMutex;
+ }
+cleanupMutex:
+ NamespaceReleaseMutex(Mutex);
+cleanup:
+ if (LastError != ERROR_SUCCESS)
+ WintunFreeAdapter(Adapter);
+ return RET_ERROR(Adapter, LastError);
+}
+
+_Use_decl_annotations_
+WINTUN_ADAPTER_HANDLE WINAPI
+WintunCreateAdapter(LPCWSTR Pool, LPCWSTR Name, const GUID *RequestedGUID, BOOL *RebootRequired)
{
+ BOOL DummyRebootRequired;
+ if (!RebootRequired)
+ RebootRequired = &DummyRebootRequired;
+ *RebootRequired = FALSE;
+
+#ifdef MAYBE_WOW64
+ if (NativeMachine != IMAGE_FILE_PROCESS)
+ return CreateAdapterViaRundll32(Pool, Name, RequestedGUID, RebootRequired);
+#endif
+
+ DWORD LastError = ERROR_SUCCESS;
LOG(WINTUN_LOG_INFO, L"Creating adapter");
- if (!IsWindows10())
+ if (!IsWindows10)
RequestedGUID = NULL;
- HDEVINFO DevInfo = SetupDiCreateDeviceInfoListExW(&GUID_DEVCLASS_NET, NULL, NULL, NULL);
- if (DevInfo == INVALID_HANDLE_VALUE)
- {
- LOG_LAST_ERROR(L"Creating empty device information set failed");
+ WINTUN_ADAPTER *Adapter = Zalloc(sizeof(*Adapter));
+ if (!Adapter)
return NULL;
+
+ Adapter->DevInfo = SetupDiCreateDeviceInfoListExW(&GUID_DEVCLASS_NET, NULL, NULL, NULL);
+ if (Adapter->DevInfo == INVALID_HANDLE_VALUE)
+ {
+ LastError = LOG_LAST_ERROR(L"Failed to create empty device information set");
+ goto cleanupAdapter;
}
- DWORD LastError;
- WINTUN_ADAPTER *Adapter = NULL;
WCHAR ClassName[MAX_CLASS_NAME_LEN];
if (!SetupDiClassNameFromGuidExW(&GUID_DEVCLASS_NET, ClassName, _countof(ClassName), NULL, NULL, NULL))
{
- LastError = LOG_LAST_ERROR(L"Retrieving class name associated with class GUID failed");
- goto cleanupDevInfo;
+ LastError = LOG_LAST_ERROR(L"Failed to retrieve class name associated with class GUID");
+ goto cleanupAdapter;
}
WCHAR PoolDeviceTypeName[MAX_POOL_DEVICE_TYPE];
if (!GetPoolDeviceTypeName(Pool, PoolDeviceTypeName))
{
LastError = GetLastError();
- goto cleanupDevInfo;
+ goto cleanupAdapter;
}
- SP_DEVINFO_DATA DevInfoData = { .cbSize = sizeof(SP_DEVINFO_DATA) };
+ Adapter->DevInfoData.cbSize = sizeof(Adapter->DevInfoData);
if (!SetupDiCreateDeviceInfoW(
- DevInfo, ClassName, &GUID_DEVCLASS_NET, PoolDeviceTypeName, NULL, DICD_GENERATE_ID, &DevInfoData))
+ Adapter->DevInfo,
+ ClassName,
+ &GUID_DEVCLASS_NET,
+ PoolDeviceTypeName,
+ NULL,
+ DICD_GENERATE_ID,
+ &Adapter->DevInfoData))
{
- LastError = LOG_LAST_ERROR(L"Creating new device information element failed");
- goto cleanupDevInfo;
+ LastError = LOG_LAST_ERROR(L"Failed to create new device information element");
+ goto cleanupAdapter;
}
- SP_DEVINSTALL_PARAMS_W DevInstallParams = { .cbSize = sizeof(SP_DEVINSTALL_PARAMS_W) };
- if (!SetupDiGetDeviceInstallParamsW(DevInfo, &DevInfoData, &DevInstallParams))
+ SP_DEVINSTALL_PARAMS_W DevInstallParams = { .cbSize = sizeof(DevInstallParams) };
+ if (!SetupDiGetDeviceInstallParamsW(Adapter->DevInfo, &Adapter->DevInfoData, &DevInstallParams))
{
- LastError = LOG_LAST_ERROR(L"Retrieving adapter %u device installation parameters failed", DevInfoData.DevInst);
- goto cleanupDevInfo;
+ LastError = LOG_LAST_ERROR(
+ L"Failed to retrieve adapter %u device installation parameters", Adapter->DevInfoData.DevInst);
+ goto cleanupAdapter;
}
DevInstallParams.Flags |= DI_QUIETINSTALL;
- if (!SetupDiSetDeviceInstallParamsW(DevInfo, &DevInfoData, &DevInstallParams))
+ if (!SetupDiSetDeviceInstallParamsW(Adapter->DevInfo, &Adapter->DevInfoData, &DevInstallParams))
{
- LastError = LOG_LAST_ERROR(L"Setting adapter %u device installation parameters failed", DevInfoData.DevInst);
- goto cleanupDevInfo;
+ LastError =
+ LOG_LAST_ERROR(L"Failed to set adapter %u device installation parameters", Adapter->DevInfoData.DevInst);
+ goto cleanupAdapter;
}
- if (!SetupDiSetSelectedDevice(DevInfo, &DevInfoData))
+ if (!SetupDiSetSelectedDevice(Adapter->DevInfo, &Adapter->DevInfoData))
{
- LastError = LOG_LAST_ERROR(L"Failed selecting adapter %u device", DevInfoData.DevInst);
- goto cleanupDevInfo;
+ LastError = LOG_LAST_ERROR(L"Failed to select adapter %u device", Adapter->DevInfoData.DevInst);
+ goto cleanupAdapter;
}
static const WCHAR Hwids[_countof(WINTUN_HWID) + 1 /*Multi-string terminator*/] = WINTUN_HWID;
- if (!SetupDiSetDeviceRegistryPropertyW(DevInfo, &DevInfoData, SPDRP_HARDWAREID, (const BYTE *)Hwids, sizeof(Hwids)))
+ if (!SetupDiSetDeviceRegistryPropertyW(
+ Adapter->DevInfo, &Adapter->DevInfoData, SPDRP_HARDWAREID, (const BYTE *)Hwids, sizeof(Hwids)))
{
- LastError = LOG_LAST_ERROR(L"Failed setting adapter %u hardware ID", DevInfoData.DevInst);
- goto cleanupDevInfo;
+ LastError = LOG_LAST_ERROR(L"Failed to set adapter %u hardware ID", Adapter->DevInfoData.DevInst);
+ goto cleanupAdapter;
}
- if (!SelectDriver(DevInfo, &DevInfoData, &DevInstallParams))
+ HDEVINFO DevInfoExistingAdapters;
+ SP_DEVINFO_DATA_LIST *ExistingAdapters;
+ if (!SelectDriver(
+ Adapter->DevInfo, &Adapter->DevInfoData, &DevInstallParams, &DevInfoExistingAdapters, &ExistingAdapters))
{
- LastError = LOG(WINTUN_LOG_ERR, L"Failed to select adapter %u driver", DevInfoData.DevInst);
- goto cleanupDevInfo;
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to select adapter %u driver", Adapter->DevInfoData.DevInst);
+ goto cleanupAdapter;
}
HANDLE Mutex = NamespaceTakePoolMutex(Pool);
@@ -1488,13 +1435,13 @@ static _Return_type_success_(return != NULL) WINTUN_ADAPTER *CreateAdapter(
goto cleanupDriverInfoList;
}
- if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, DevInfo, &DevInfoData))
+ if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, Adapter->DevInfo, &Adapter->DevInfoData))
{
- LastError = LOG_LAST_ERROR(L"Registering adapter %u device failed", DevInfoData.DevInst);
+ LastError = LOG_LAST_ERROR(L"Failed to register adapter %u device", Adapter->DevInfoData.DevInst);
goto cleanupDevice;
}
- if (!SetupDiCallClassInstaller(DIF_REGISTER_COINSTALLERS, DevInfo, &DevInfoData))
- LOG_LAST_ERROR(L"Registering adapter %u coinstallers failed", DevInfoData.DevInst);
+ if (!SetupDiCallClassInstaller(DIF_REGISTER_COINSTALLERS, Adapter->DevInfo, &Adapter->DevInfoData))
+ LOG_LAST_ERROR(L"Failed to register adapter %u coinstallers", Adapter->DevInfoData.DevInst);
HKEY NetDevRegKey = INVALID_HANDLE_VALUE;
const int PollTimeout = 50 /* ms */;
@@ -1503,11 +1450,17 @@ static _Return_type_success_(return != NULL) WINTUN_ADAPTER *CreateAdapter(
if (i)
Sleep(PollTimeout);
NetDevRegKey = SetupDiOpenDevRegKey(
- DevInfo, &DevInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_SET_VALUE | KEY_QUERY_VALUE | KEY_NOTIFY);
+ Adapter->DevInfo,
+ &Adapter->DevInfoData,
+ DICS_FLAG_GLOBAL,
+ 0,
+ DIREG_DRV,
+ KEY_SET_VALUE | KEY_QUERY_VALUE | KEY_NOTIFY);
}
if (NetDevRegKey == INVALID_HANDLE_VALUE)
{
- LastError = LOG_LAST_ERROR(L"Failed to open adapter %u device-specific registry key", DevInfoData.DevInst);
+ LastError =
+ LOG_LAST_ERROR(L"Failed to open adapter %u device-specific registry key", Adapter->DevInfoData.DevInst);
goto cleanupDevice;
}
if (RequestedGUID)
@@ -1523,43 +1476,43 @@ static _Return_type_success_(return != NULL) WINTUN_ADAPTER *CreateAdapter(
}
}
- if (!SetupDiCallClassInstaller(DIF_INSTALLINTERFACES, DevInfo, &DevInfoData))
- LOG_LAST_ERROR(L"Installing adapter %u interfaces failed", DevInfoData.DevInst);
+ if (!SetupDiCallClassInstaller(DIF_INSTALLINTERFACES, Adapter->DevInfo, &Adapter->DevInfoData))
+ LOG_LAST_ERROR(L"Failed to install adapter %u interfaces", Adapter->DevInfoData.DevInst);
- if (!SetupDiCallClassInstaller(DIF_INSTALLDEVICE, DevInfo, &DevInfoData))
+ if (!SetupDiCallClassInstaller(DIF_INSTALLDEVICE, Adapter->DevInfo, &Adapter->DevInfoData))
{
- LastError = LOG_LAST_ERROR(L"Installing adapter %u device failed", DevInfoData.DevInst);
+ LastError = LOG_LAST_ERROR(L"Failed to install adapter %u device", Adapter->DevInfoData.DevInst);
goto cleanupNetDevRegKey;
}
- *RebootRequired = *RebootRequired || CheckReboot(DevInfo, &DevInfoData);
+ *RebootRequired = *RebootRequired || CheckReboot(Adapter->DevInfo, &Adapter->DevInfoData);
if (!SetupDiSetDevicePropertyW(
- DevInfo,
- &DevInfoData,
+ Adapter->DevInfo,
+ &Adapter->DevInfoData,
&DEVPKEY_Wintun_Pool,
DEVPROP_TYPE_STRING,
#pragma warning(suppress : 4090)
(const BYTE *)Pool,
- (DWORD)((wcslen(Pool) + 1) * sizeof(WCHAR)),
+ (DWORD)((wcslen(Pool) + 1) * sizeof(*Pool)),
0))
{
- LastError = LOG_LAST_ERROR(L"Failed to set adapter %u pool", DevInfoData.DevInst);
+ LastError = LOG_LAST_ERROR(L"Failed to set adapter %u pool", Adapter->DevInfoData.DevInst);
goto cleanupNetDevRegKey;
}
if (!SetupDiSetDeviceRegistryPropertyW(
- DevInfo,
- &DevInfoData,
+ Adapter->DevInfo,
+ &Adapter->DevInfoData,
SPDRP_DEVICEDESC,
(const BYTE *)PoolDeviceTypeName,
- (DWORD)((wcslen(PoolDeviceTypeName) + 1) * sizeof(WCHAR))))
+ (DWORD)((wcslen(PoolDeviceTypeName) + 1) * sizeof(*PoolDeviceTypeName))))
{
- LastError = LOG_LAST_ERROR(L"Failed to set adapter %u description", DevInfoData.DevInst);
+ LastError = LOG_LAST_ERROR(L"Failed to set adapter %u description", Adapter->DevInfoData.DevInst);
goto cleanupNetDevRegKey;
}
/* DIF_INSTALLDEVICE returns almost immediately, while the device installation continues in the background. It might
* take a while, before all registry keys and values are populated. */
- WCHAR *DummyStr = RegistryQueryStringWait(NetDevRegKey, L"NetCfgInstanceId", WAIT_FOR_REGISTRY_TIMEOUT);
+ LPWSTR DummyStr = RegistryQueryStringWait(NetDevRegKey, L"NetCfgInstanceId", WAIT_FOR_REGISTRY_TIMEOUT);
if (!DummyStr)
{
WCHAR RegPath[MAX_REG_PATH];
@@ -1584,10 +1537,9 @@ static _Return_type_success_(return != NULL) WINTUN_ADAPTER *CreateAdapter(
goto cleanupNetDevRegKey;
}
- Adapter = CreateAdapterData(Pool, DevInfo, &DevInfoData);
- if (!Adapter)
+ if (!PopulateAdapterData(Adapter, Pool))
{
- LastError = LOG(WINTUN_LOG_ERR, L"Failed to create adapter %u data", DevInfoData.DevInst);
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to populate adapter %u data", Adapter->DevInfoData.DevInst);
goto cleanupNetDevRegKey;
}
@@ -1663,8 +1615,8 @@ static _Return_type_success_(return != NULL) WINTUN_ADAPTER *CreateAdapter(
DEVPROPTYPE PropertyType;
NTSTATUS ProblemStatus;
if (SetupDiGetDevicePropertyW(
- DevInfo,
- &DevInfoData,
+ Adapter->DevInfo,
+ &Adapter->DevInfoData,
&DEVPKEY_Device_ProblemStatus,
&PropertyType,
(PBYTE)&ProblemStatus,
@@ -1677,8 +1629,8 @@ static _Return_type_success_(return != NULL) WINTUN_ADAPTER *CreateAdapter(
{
INT32 ProblemCode;
if (!SetupDiGetDevicePropertyW(
- DevInfo,
- &DevInfoData,
+ Adapter->DevInfo,
+ &Adapter->DevInfoData,
&DEVPKEY_Device_ProblemCode,
&PropertyType,
(PBYTE)&ProblemCode,
@@ -1707,112 +1659,46 @@ static _Return_type_success_(return != NULL) WINTUN_ADAPTER *CreateAdapter(
cleanupTcpipAdapterRegKey:
RegCloseKey(TcpipAdapterRegKey);
-cleanupAdapter:
- if (LastError != ERROR_SUCCESS)
- {
- Free(Adapter);
- Adapter = NULL;
- }
cleanupNetDevRegKey:
RegCloseKey(NetDevRegKey);
cleanupDevice:
if (LastError != ERROR_SUCCESS)
{
- /* The adapter failed to install, or the adapter ID was unobtainable. Clean-up. */
SP_REMOVEDEVICE_PARAMS RemoveDeviceParams = { .ClassInstallHeader = { .cbSize = sizeof(SP_CLASSINSTALL_HEADER),
.InstallFunction = DIF_REMOVE },
.Scope = DI_REMOVEDEVICE_GLOBAL };
if (SetupDiSetClassInstallParamsW(
- DevInfo, &DevInfoData, &RemoveDeviceParams.ClassInstallHeader, sizeof(RemoveDeviceParams)) &&
- SetupDiCallClassInstaller(DIF_REMOVE, DevInfo, &DevInfoData))
- *RebootRequired = *RebootRequired || CheckReboot(DevInfo, &DevInfoData);
+ Adapter->DevInfo,
+ &Adapter->DevInfoData,
+ &RemoveDeviceParams.ClassInstallHeader,
+ sizeof(RemoveDeviceParams)) &&
+ SetupDiCallClassInstaller(DIF_REMOVE, Adapter->DevInfo, &Adapter->DevInfoData))
+ *RebootRequired = *RebootRequired || CheckReboot(Adapter->DevInfo, &Adapter->DevInfoData);
}
NamespaceReleaseMutex(Mutex);
cleanupDriverInfoList:
- SetupDiDestroyDriverInfoList(DevInfo, &DevInfoData, SPDIT_COMPATDRIVER);
-cleanupDevInfo:
- SetupDiDestroyDeviceInfoList(DevInfo);
- return RET_ERROR(Adapter, LastError);
-}
-
-static _Return_type_success_(return != NULL)
- WINTUN_ADAPTER *GetAdapter(_In_z_ const WCHAR *Pool, _In_ const GUID *CfgInstanceID)
-{
- HANDLE Mutex = NamespaceTakePoolMutex(Pool);
- if (!Mutex)
- {
- LOG(WINTUN_LOG_ERR, L"Failed to take %s pool mutex", Pool);
- return NULL;
- }
- DWORD LastError;
- WINTUN_ADAPTER *Adapter = NULL;
- HDEVINFO DevInfo;
- SP_DEVINFO_DATA DevInfoData;
- if (!GetDevInfoData(CfgInstanceID, &DevInfo, &DevInfoData))
- {
- WCHAR Guid[MAX_GUID_STRING_LEN];
- LastError =
- LOG(WINTUN_LOG_ERR,
- L"Failed to locate adapter %.*s",
- StringFromGUID2(CfgInstanceID, Guid, _countof(Guid)),
- Guid);
- goto cleanupMutex;
- }
- Adapter = CreateAdapterData(Pool, DevInfo, &DevInfoData);
- LastError = Adapter ? ERROR_SUCCESS : LOG(WINTUN_LOG_ERR, L"Failed to create adapter %u data", DevInfoData.DevInst);
- SetupDiDestroyDeviceInfoList(DevInfo);
-cleanupMutex:
- NamespaceReleaseMutex(Mutex);
- return RET_ERROR(Adapter, LastError);
-}
-
-#include "rundll32_i.c"
-
-_Return_type_success_(return != NULL) WINTUN_ADAPTER *WINAPI WintunCreateAdapter(
- _In_z_ const WCHAR *Pool,
- _In_z_ const WCHAR *Name,
- _In_opt_ const GUID *RequestedGUID,
- _Out_opt_ BOOL *RebootRequired)
-{
- BOOL DummyRebootRequired;
- if (!RebootRequired)
- RebootRequired = &DummyRebootRequired;
- *RebootRequired = FALSE;
- DWORD LastError;
- WINTUN_ADAPTER *Adapter;
-#ifdef MAYBE_WOW64
- if (NativeMachine != IMAGE_FILE_PROCESS)
- {
- Adapter = CreateAdapterViaRundll32(Pool, Name, RequestedGUID, RebootRequired);
- LastError = Adapter ? ERROR_SUCCESS : GetLastError();
- goto cleanup;
- }
-#endif
- Adapter = CreateAdapter(Pool, Name, RequestedGUID, RebootRequired);
- LastError = Adapter ? ERROR_SUCCESS : GetLastError();
-cleanup:
+ SelectDriverDeferredCleanup(DevInfoExistingAdapters, ExistingAdapters);
+ SetupDiDestroyDriverInfoList(Adapter->DevInfo, &Adapter->DevInfoData, SPDIT_COMPATDRIVER);
+cleanupAdapter:
+ if (LastError != ERROR_SUCCESS)
+ WintunFreeAdapter(Adapter);
return RET_ERROR(Adapter, LastError);
}
-_Return_type_success_(return != FALSE) BOOL WINAPI WintunDeleteAdapter(
- _In_ const WINTUN_ADAPTER *Adapter,
- _In_ BOOL ForceCloseSessions,
- _Out_opt_ BOOL *RebootRequired)
+_Use_decl_annotations_
+BOOL WINAPI
+WintunDeleteAdapter(WINTUN_ADAPTER *Adapter, BOOL ForceCloseSessions, BOOL *RebootRequired)
{
BOOL DummyRebootRequired;
if (!RebootRequired)
RebootRequired = &DummyRebootRequired;
*RebootRequired = FALSE;
- DWORD LastError;
#ifdef MAYBE_WOW64
if (NativeMachine != IMAGE_FILE_PROCESS)
- {
- LastError =
- DeleteAdapterViaRundll32(Adapter, ForceCloseSessions, RebootRequired) ? ERROR_SUCCESS : GetLastError();
- goto cleanup;
- }
+ return DeleteAdapterViaRundll32(Adapter, ForceCloseSessions, RebootRequired);
#endif
+ DWORD LastError = ERROR_SUCCESS;
HANDLE Mutex = NamespaceTakePoolMutex(Adapter->Pool);
if (!Mutex)
{
@@ -1820,49 +1706,44 @@ _Return_type_success_(return != FALSE) BOOL WINAPI WintunDeleteAdapter(
goto cleanup;
}
- HDEVINFO DevInfo;
- SP_DEVINFO_DATA DevInfoData;
- if (!GetDevInfoData(&Adapter->CfgInstanceID, &DevInfo, &DevInfoData))
+ SP_DEVINSTALL_PARAMS_W DevInstallParams = { .cbSize = sizeof(DevInstallParams) };
+ if (!SetupDiGetDeviceInstallParamsW(Adapter->DevInfo, &Adapter->DevInfoData, &DevInstallParams))
{
- if ((LastError = GetLastError()) == ERROR_FILE_NOT_FOUND)
- LastError = ERROR_SUCCESS;
- else
- {
- WCHAR Guid[MAX_GUID_STRING_LEN];
- LOG(WINTUN_LOG_ERR,
- L"Failed to get adapter %.*s info data",
- StringFromGUID2(&Adapter->CfgInstanceID, Guid, _countof(Guid)),
- Guid);
- }
+ LastError = LOG_LAST_ERROR(
+ L"Failed to retrieve adapter %u device installation parameters", Adapter->DevInfoData.DevInst);
+ goto cleanupMutex;
+ }
+ DevInstallParams.Flags |= DI_QUIETINSTALL;
+ if (!SetupDiSetDeviceInstallParamsW(Adapter->DevInfo, &Adapter->DevInfoData, &DevInstallParams))
+ {
+ LastError =
+ LOG_LAST_ERROR(L"Failed to set adapter %u device installation parameters", Adapter->DevInfoData.DevInst);
goto cleanupMutex;
}
- if (ForceCloseSessions && !ForceCloseWintunAdapterHandle(DevInfo, &DevInfoData))
- LOG(WINTUN_LOG_WARN, L"Failed to force close adapter %u handles", DevInfoData.DevInst);
+ if (ForceCloseSessions && !ForceCloseWintunAdapterHandle(Adapter->DevInfo, &Adapter->DevInfoData))
+ LOG(WINTUN_LOG_WARN, L"Failed to force close adapter %u handles", Adapter->DevInfoData.DevInst);
- SetQuietInstall(DevInfo, &DevInfoData);
SP_REMOVEDEVICE_PARAMS Params = { .ClassInstallHeader = { .cbSize = sizeof(SP_CLASSINSTALL_HEADER),
.InstallFunction = DIF_REMOVE },
.Scope = DI_REMOVEDEVICE_GLOBAL };
- if ((!SetupDiSetClassInstallParamsW(DevInfo, &DevInfoData, &Params.ClassInstallHeader, sizeof(Params)) ||
- !SetupDiCallClassInstaller(DIF_REMOVE, DevInfo, &DevInfoData)) &&
+ if ((!SetupDiSetClassInstallParamsW(
+ Adapter->DevInfo, &Adapter->DevInfoData, &Params.ClassInstallHeader, sizeof(Params)) ||
+ !SetupDiCallClassInstaller(DIF_REMOVE, Adapter->DevInfo, &Adapter->DevInfoData)) &&
GetLastError() != ERROR_NO_SUCH_DEVINST)
- {
- LastError = LOG_LAST_ERROR(L"Failed to remove adapter %u", DevInfoData.DevInst);
- goto cleanupDevInfo;
- }
- LastError = ERROR_SUCCESS;
-cleanupDevInfo:
- *RebootRequired = *RebootRequired || CheckReboot(DevInfo, &DevInfoData);
- SetupDiDestroyDeviceInfoList(DevInfo);
+ LastError = LOG_LAST_ERROR(L"Failed to remove adapter %u", Adapter->DevInfoData.DevInst);
+
+ *RebootRequired = *RebootRequired || CheckReboot(Adapter->DevInfo, &Adapter->DevInfoData);
+
cleanupMutex:
NamespaceReleaseMutex(Mutex);
cleanup:
return RET_ERROR(TRUE, LastError);
}
-static _Return_type_success_(return != FALSE) BOOL
- DeleteAllOurAdapters(_In_ const WCHAR Pool[WINTUN_MAX_POOL], _Inout_ BOOL *RebootRequired)
+static _Return_type_success_(return != FALSE)
+BOOL
+DeleteAllOurAdapters(_In_z_ LPCWSTR Pool, _Inout_ BOOL *RebootRequired)
{
HANDLE Mutex = NamespaceTakePoolMutex(Pool);
if (!Mutex)
@@ -1913,8 +1794,9 @@ cleanupMutex:
return RET_ERROR(TRUE, LastError);
}
-_Return_type_success_(return != FALSE) BOOL WINAPI
- WintunDeletePoolDriver(_In_z_ const WCHAR *Pool, _Out_opt_ BOOL *RebootRequired)
+_Use_decl_annotations_
+BOOL WINAPI
+WintunDeletePoolDriver(LPCWSTR Pool, BOOL *RebootRequired)
{
BOOL DummyRebootRequired;
if (!RebootRequired)
@@ -1986,8 +1868,9 @@ cleanup:
return RET_ERROR(TRUE, LastError);
}
-_Return_type_success_(return != FALSE) BOOL WINAPI
- WintunEnumAdapters(_In_z_ const WCHAR *Pool, _In_ WINTUN_ENUM_CALLBACK Func, _In_ LPARAM Param)
+_Use_decl_annotations_
+BOOL WINAPI
+WintunEnumAdapters(LPCWSTR Pool, WINTUN_ENUM_CALLBACK Func, LPARAM Param)
{
DWORD LastError = ERROR_SUCCESS;
HANDLE Mutex = NamespaceTakePoolMutex(Pool);
@@ -2005,25 +1888,23 @@ _Return_type_success_(return != FALSE) BOOL WINAPI
BOOL Continue = TRUE;
for (DWORD EnumIndex = 0; Continue; ++EnumIndex)
{
- SP_DEVINFO_DATA DevInfoData = { .cbSize = sizeof(SP_DEVINFO_DATA) };
- if (!SetupDiEnumDeviceInfo(DevInfo, EnumIndex, &DevInfoData))
+ WINTUN_ADAPTER Adapter = { .DevInfo = DevInfo, .DevInfoData.cbSize = sizeof(Adapter.DevInfoData) };
+ if (!SetupDiEnumDeviceInfo(DevInfo, EnumIndex, &Adapter.DevInfoData))
{
if (GetLastError() == ERROR_NO_MORE_ITEMS)
break;
continue;
}
- if (!IsOurAdapter(DevInfo, &DevInfoData) || !IsPoolMember(Pool, DevInfo, &DevInfoData))
+ if (!IsOurAdapter(DevInfo, &Adapter.DevInfoData) || !IsPoolMember(Pool, DevInfo, &Adapter.DevInfoData))
continue;
- WINTUN_ADAPTER *Adapter = CreateAdapterData(Pool, DevInfo, &DevInfoData);
- if (!Adapter)
+ if (!PopulateAdapterData(&Adapter, Pool))
{
- LastError = LOG(WINTUN_LOG_ERR, L"Failed to create adapter %u data", DevInfoData.DevInst);
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to populate adapter %u data", Adapter.DevInfoData.DevInst);
break;
}
- Continue = Func(Adapter, Param);
- Free(Adapter);
+ Continue = Func(&Adapter, Param);
}
SetupDiDestroyDeviceInfoList(DevInfo);
cleanupMutex:
diff --git a/api/adapter.h b/api/adapter.h
index 940330b..5f468b0 100644
--- a/api/adapter.h
+++ b/api/adapter.h
@@ -13,58 +13,96 @@
#define MAX_INSTANCE_ID MAX_PATH /* TODO: Is MAX_PATH always enough? */
#define WINTUN_HWID L"Wintun"
-void
-AdapterInit(void);
-
/**
* Wintun adapter descriptor.
*/
typedef struct _WINTUN_ADAPTER
{
+ HDEVINFO DevInfo;
+ SP_DEVINFO_DATA DevInfoData;
GUID CfgInstanceID;
WCHAR DevInstanceID[MAX_INSTANCE_ID];
DWORD LuidIndex;
DWORD IfType;
+ DWORD IfIndex;
WCHAR Pool[WINTUN_MAX_POOL];
} WINTUN_ADAPTER;
/**
* @copydoc WINTUN_FREE_ADAPTER_FUNC
*/
-void WINAPI
-WintunFreeAdapter(_In_ WINTUN_ADAPTER *Adapter);
+WINTUN_FREE_ADAPTER_FUNC_IMPL WintunFreeAdapter;
/**
* @copydoc WINTUN_CREATE_ADAPTER_FUNC
*/
-_Return_type_success_(return != NULL) WINTUN_ADAPTER *WINAPI WintunCreateAdapter(
- _In_z_ const WCHAR *Pool,
- _In_z_ const WCHAR *Name,
- _In_opt_ const GUID *RequestedGUID,
- _Out_opt_ BOOL *RebootRequired);
+WINTUN_CREATE_ADAPTER_FUNC_IMPL WintunCreateAdapter;
+
+/**
+ * @copydoc WINTUN_OPEN_ADAPTER_FUNC
+ */
+WINTUN_OPEN_ADAPTER_FUNC_IMPL WintunOpenAdapter;
/**
* @copydoc WINTUN_DELETE_ADAPTER_FUNC
*/
-_Return_type_success_(return != FALSE) BOOL WINAPI WintunDeleteAdapter(
- _In_ const WINTUN_ADAPTER *Adapter,
- _In_ BOOL ForceCloseSessions,
- _Out_opt_ BOOL *RebootRequired);
+WINTUN_DELETE_ADAPTER_FUNC_IMPL WintunDeleteAdapter;
+
+/**
+ * @copydoc WINTUN_ENUM_ADAPTERS_FUNC
+ */
+WINTUN_ENUM_ADAPTERS_FUNC_IMPL WintunEnumAdapters;
/**
* @copydoc WINTUN_DELETE_POOL_DRIVER_FUNC
*/
-_Return_type_success_(return != FALSE) BOOL WINAPI
- WintunDeletePoolDriver(_In_z_ const WCHAR *Pool, _Out_opt_ BOOL *RebootRequired);
+WINTUN_DELETE_POOL_DRIVER_FUNC_IMPL WintunDeletePoolDriver;
+
+/**
+ * @copydoc WINTUN_GET_ADAPTER_LUID_FUNC
+ */
+WINTUN_GET_ADAPTER_LUID_FUNC_IMPL WintunGetAdapterLUID;
+
+/**
+ * @copydoc WINTUN_GET_ADAPTER_NAME_FUNC
+ */
+WINTUN_GET_ADAPTER_NAME_FUNC_IMPL WintunGetAdapterName;
+
+/**
+ * @copydoc WINTUN_SET_ADAPTER_NAME_FUNC
+ */
+WINTUN_SET_ADAPTER_NAME_FUNC_IMPL WintunSetAdapterName;
+
+/**
+ * @copydoc WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC
+ */
+WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC_IMPL WintunGetRunningDriverVersion;
/**
* Returns a handle to the adapter device object.
*
* @param Adapter Adapter handle obtained with WintunOpenAdapter or WintunCreateAdapter.
*
- * @return If the function succeeds, the return value is adapter device object handle. Must be released with
- * CloseHandle. If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error
+ * @return If the function succeeds, the return value is adapter device object handle.
+ * If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error
+ * information, call GetLastError.
+ */
+_Return_type_success_(return != INVALID_HANDLE_VALUE)
+HANDLE WINAPI
+AdapterOpenDeviceObject(_In_ const WINTUN_ADAPTER *Adapter);
+/**
+ * Returns an adapter object based on a devnode instance ID.
+ *
+ * @param Pool Pool name of adapter object to be opened.
+ *
+ * @param DevInstanceID Instance ID of devnode for opening adapter.
+ *
+ * @return If the function succeeds, the return value is adapter object..
+ * If the function fails, the return value is NULL. To get extended error
* information, call GetLastError.
*/
-_Return_type_success_(return != INVALID_HANDLE_VALUE) HANDLE WINAPI
- AdapterOpenDeviceObject(_In_ const WINTUN_ADAPTER *Adapter); \ No newline at end of file
+_Must_inspect_result_
+_Return_type_success_(return != NULL)
+_Post_maybenull_
+WINTUN_ADAPTER *
+AdapterOpenFromDevInstanceId(_In_z_ LPCWSTR Pool, _In_z_ LPCWSTR DevInstanceID);
diff --git a/api/api.vcxproj b/api/api.vcxproj
index 00a6266..9c477cd 100644
--- a/api/api.vcxproj
+++ b/api/api.vcxproj
@@ -53,15 +53,13 @@
<ItemGroup>
<ClInclude Include="main.h" />
<ClInclude Include="adapter.h" />
- <ClInclude Include="rundll32_i.c">
- <ExcludedFromBuild>true</ExcludedFromBuild>
- </ClInclude>
<ClInclude Include="logger.h" />
<ClInclude Include="namespace.h" />
<ClInclude Include="nci.h" />
<ClInclude Include="ntdll.h" />
<ClInclude Include="registry.h" />
<ClInclude Include="resource.h" />
+ <ClInclude Include="rundll32.h" />
<ClInclude Include="wintun.h" />
</ItemGroup>
<ItemGroup>
diff --git a/api/logger.c b/api/logger.c
index 253d525..71dff5b 100644
--- a/api/logger.c
+++ b/api/logger.c
@@ -4,6 +4,7 @@
*/
#include "logger.h"
+#include "adapter.h"
#include "ntdll.h"
#include <Windows.h>
#include <winternl.h>
@@ -11,17 +12,16 @@
#include <stdlib.h>
static BOOL CALLBACK
-NopLogger(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ const WCHAR *LogLine)
+NopLogger(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ LPCWSTR LogLine)
{
- UNREFERENCED_PARAMETER(Level);
- UNREFERENCED_PARAMETER(LogLine);
return TRUE;
}
WINTUN_LOGGER_CALLBACK Logger = NopLogger;
-void CALLBACK
-WintunSetLogger(_In_ WINTUN_LOGGER_CALLBACK NewLogger)
+_Use_decl_annotations_
+VOID WINAPI
+WintunSetLogger(WINTUN_LOGGER_CALLBACK NewLogger)
{
if (!NewLogger)
NewLogger = NopLogger;
@@ -29,14 +29,15 @@ WintunSetLogger(_In_ WINTUN_LOGGER_CALLBACK NewLogger)
}
static VOID
-StrTruncate(_Inout_count_(StrChars) WCHAR *Str, _In_ SIZE_T StrChars)
+StrTruncate(_Inout_count_(StrChars) LPWSTR Str, _In_ SIZE_T StrChars)
{
Str[StrChars - 2] = L'\u2026'; /* Horizontal Ellipsis */
Str[StrChars - 1] = 0;
}
-_Post_equals_last_error_ DWORD
-LoggerLog(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ const WCHAR *Function, _In_z_ const WCHAR *LogLine)
+_Use_decl_annotations_
+DWORD
+LoggerLog(WINTUN_LOGGER_LEVEL Level, LPCWSTR Function, LPCWSTR LogLine)
{
DWORD LastError = GetLastError();
if (Function)
@@ -52,12 +53,9 @@ LoggerLog(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ const WCHAR *Function, _In_z_ c
return LastError;
}
-_Post_equals_last_error_ DWORD
-LoggerLogV(
- _In_ WINTUN_LOGGER_LEVEL Level,
- _In_z_ const WCHAR *Function,
- _In_z_ _Printf_format_string_ const WCHAR *Format,
- _In_ va_list Args)
+_Use_decl_annotations_
+DWORD
+LoggerLogV(WINTUN_LOGGER_LEVEL Level, LPCWSTR Function, LPCWSTR Format, va_list Args)
{
DWORD LastError = GetLastError();
WCHAR LogLine[0x400];
@@ -71,16 +69,17 @@ LoggerLogV(
return LastError;
}
-_Post_equals_last_error_ DWORD
-LoggerError(_In_ DWORD Error, _In_z_ const WCHAR *Function, _In_z_ const WCHAR *Prefix)
+_Use_decl_annotations_
+DWORD
+LoggerError(DWORD Error, LPCWSTR Function, LPCWSTR Prefix)
{
- WCHAR *SystemMessage = NULL, *FormattedMessage = NULL;
+ LPWSTR SystemMessage = NULL, FormattedMessage = NULL;
FormatMessageW(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_MAX_WIDTH_MASK,
NULL,
HRESULT_FROM_SETUPAPI(Error),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (void *)&SystemMessage,
+ (VOID *)&SystemMessage,
0,
NULL);
FormatMessageW(
@@ -89,7 +88,7 @@ LoggerError(_In_ DWORD Error, _In_z_ const WCHAR *Function, _In_z_ const WCHAR *
SystemMessage ? L"%4: %1: %3(Code 0x%2!08X!)" : L"%4: %1: Code 0x%2!08X!",
0,
0,
- (void *)&FormattedMessage,
+ (VOID *)&FormattedMessage,
0,
(va_list *)(DWORD_PTR[]){ (DWORD_PTR)Prefix, (DWORD_PTR)Error, (DWORD_PTR)SystemMessage, (DWORD_PTR)Function });
if (FormattedMessage)
@@ -99,12 +98,9 @@ LoggerError(_In_ DWORD Error, _In_z_ const WCHAR *Function, _In_z_ const WCHAR *
return Error;
}
-_Post_equals_last_error_ DWORD
-LoggerErrorV(
- _In_ DWORD Error,
- _In_z_ const WCHAR *Function,
- _In_z_ _Printf_format_string_ const WCHAR *Format,
- _In_ va_list Args)
+_Use_decl_annotations_
+DWORD
+LoggerErrorV(DWORD Error, LPCWSTR Function, LPCWSTR Format, va_list Args)
{
WCHAR Prefix[0x400];
if (_vsnwprintf_s(Prefix, _countof(Prefix), _TRUNCATE, Format, Args) == -1)
@@ -112,13 +108,14 @@ LoggerErrorV(
return LoggerError(Error, Function, Prefix);
}
+_Use_decl_annotations_
VOID
-LoggerGetRegistryKeyPath(_In_ HKEY Key, _Out_cap_c_(MAX_REG_PATH) WCHAR *Path)
+LoggerGetRegistryKeyPath(HKEY Key, LPWSTR Path)
{
DWORD LastError = GetLastError();
if (Key == NULL)
{
- wcscpy_s(Path, MAX_REG_PATH, L"<null>");
+ wcsncpy_s(Path, MAX_REG_PATH, L"<null>", _TRUNCATE);
goto out;
}
if (_snwprintf_s(Path, MAX_REG_PATH, _TRUNCATE, L"0x%p", Key) == -1)
diff --git a/api/logger.h b/api/logger.h
index 0ba4d55..72853cc 100644
--- a/api/logger.h
+++ b/api/logger.h
@@ -9,6 +9,7 @@
#include "main.h"
#include "registry.h"
#include <Windows.h>
+#include <intsafe.h>
#include <stdarg.h>
#include <wchar.h>
@@ -17,25 +18,23 @@ extern WINTUN_LOGGER_CALLBACK Logger;
/**
* @copydoc WINTUN_SET_LOGGER_FUNC
*/
-void WINAPI
-WintunSetLogger(_In_ WINTUN_LOGGER_CALLBACK NewLogger);
+WINTUN_SET_LOGGER_FUNC_IMPL WintunSetLogger;
-_Post_equals_last_error_ DWORD
-LoggerLog(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ const WCHAR *Function, _In_z_ const WCHAR *LogLine);
+_Post_equals_last_error_
+DWORD
+LoggerLog(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ LPCWSTR Function, _In_z_ LPCWSTR LogLine);
-_Post_equals_last_error_ DWORD
+_Post_equals_last_error_
+DWORD
LoggerLogV(
_In_ WINTUN_LOGGER_LEVEL Level,
- _In_z_ const WCHAR *Function,
- _In_z_ _Printf_format_string_ const WCHAR *Format,
+ _In_z_ LPCWSTR Function,
+ _In_z_ _Printf_format_string_ LPCWSTR Format,
_In_ va_list Args);
-static inline _Post_equals_last_error_ DWORD
-LoggerLogFmt(
- _In_ WINTUN_LOGGER_LEVEL Level,
- _In_z_ const WCHAR *Function,
- _In_z_ _Printf_format_string_ const WCHAR *Format,
- ...)
+_Post_equals_last_error_
+static inline DWORD
+LoggerLogFmt(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ LPCWSTR Function, _In_z_ _Printf_format_string_ LPCWSTR Format, ...)
{
va_list Args;
va_start(Args, Format);
@@ -44,18 +43,21 @@ LoggerLogFmt(
return LastError;
}
-_Post_equals_last_error_ DWORD
-LoggerError(_In_ DWORD Error, _In_z_ const WCHAR *Function, _In_z_ const WCHAR *Prefix);
+_Post_equals_last_error_
+DWORD
+LoggerError(_In_ DWORD Error, _In_z_ LPCWSTR Function, _In_z_ LPCWSTR Prefix);
-_Post_equals_last_error_ DWORD
+_Post_equals_last_error_
+DWORD
LoggerErrorV(
_In_ DWORD Error,
- _In_z_ const WCHAR *Function,
- _In_z_ _Printf_format_string_ const WCHAR *Format,
+ _In_z_ LPCWSTR Function,
+ _In_z_ _Printf_format_string_ LPCWSTR Format,
_In_ va_list Args);
-static inline _Post_equals_last_error_ DWORD
-LoggerErrorFmt(_In_ DWORD Error, _In_z_ const WCHAR *Function, _In_z_ _Printf_format_string_ const WCHAR *Format, ...)
+_Post_equals_last_error_
+static inline DWORD
+LoggerErrorFmt(_In_ DWORD Error, _In_z_ LPCWSTR Function, _In_z_ _Printf_format_string_ LPCWSTR Format, ...)
{
va_list Args;
va_start(Args, Format);
@@ -64,8 +66,9 @@ LoggerErrorFmt(_In_ DWORD Error, _In_z_ const WCHAR *Function, _In_z_ _Printf_fo
return LastError;
}
-static inline _Post_equals_last_error_ DWORD
-LoggerLastErrorV(_In_z_ const WCHAR *Function, _In_z_ _Printf_format_string_ const WCHAR *Format, _In_ va_list Args)
+_Post_equals_last_error_
+static inline DWORD
+LoggerLastErrorV(_In_z_ LPCWSTR Function, _In_z_ _Printf_format_string_ LPCWSTR Format, _In_ va_list Args)
{
DWORD LastError = GetLastError();
LoggerErrorV(LastError, Function, Format, Args);
@@ -73,8 +76,9 @@ LoggerLastErrorV(_In_z_ const WCHAR *Function, _In_z_ _Printf_format_string_ con
return LastError;
}
-static inline _Post_equals_last_error_ DWORD
-LoggerLastErrorFmt(_In_z_ const WCHAR *Function, _In_z_ _Printf_format_string_ const WCHAR *Format, ...)
+_Post_equals_last_error_
+static inline DWORD
+LoggerLastErrorFmt(_In_z_ LPCWSTR Function, _In_z_ _Printf_format_string_ LPCWSTR Format, ...)
{
va_list Args;
va_start(Args, Format);
@@ -84,7 +88,7 @@ LoggerLastErrorFmt(_In_z_ const WCHAR *Function, _In_z_ _Printf_format_string_ c
}
VOID
-LoggerGetRegistryKeyPath(_In_ HKEY Key, _Out_cap_c_(MAX_REG_PATH) WCHAR *Path);
+LoggerGetRegistryKeyPath(_In_ HKEY Key, _Out_writes_z_(MAX_REG_PATH) LPWSTR Path);
#define __L(x) L##x
#define _L(x) __L(x)
@@ -94,10 +98,31 @@ LoggerGetRegistryKeyPath(_In_ HKEY Key, _Out_cap_c_(MAX_REG_PATH) WCHAR *Path);
#define RET_ERROR(Ret, Error) ((Error) == ERROR_SUCCESS ? (Ret) : (SetLastError(Error), 0))
-static inline _Return_type_success_(return != NULL) _Ret_maybenull_
- _Post_writable_byte_size_(Size) void *LoggerAlloc(_In_z_ const WCHAR *Function, _In_ DWORD Flags, _In_ SIZE_T Size)
+_Must_inspect_result_
+DECLSPEC_ALLOCATOR
+static inline _Return_type_success_(return != NULL)
+_Post_maybenull_
+_Post_writable_byte_size_(Size)
+VOID *
+LoggerAlloc(_In_z_ LPCWSTR Function, _In_ DWORD Flags, _In_ SIZE_T Size)
{
- void *Data = HeapAlloc(ModuleHeap, Flags, Size);
+ VOID *Data = HeapAlloc(ModuleHeap, Flags, Size);
+ if (!Data)
+ {
+ LoggerLogFmt(WINTUN_LOG_ERR, Function, L"Out of memory (flags: 0x%x, requested size: 0x%zx)", Flags, Size);
+ SetLastError(ERROR_OUTOFMEMORY);
+ }
+ return Data;
+}
+_Must_inspect_result_
+DECLSPEC_ALLOCATOR
+static inline _Return_type_success_(return != NULL)
+_Post_maybenull_
+_Post_writable_byte_size_(Size)
+VOID *
+LoggerReAlloc(_In_z_ LPCWSTR Function, _In_ DWORD Flags, _Frees_ptr_opt_ LPVOID Mem, _In_ SIZE_T Size)
+{
+ VOID *Data = Mem ? HeapReAlloc(ModuleHeap, Flags, Mem, Size) : HeapAlloc(ModuleHeap, Flags, Size);
if (!Data)
{
LoggerLogFmt(WINTUN_LOG_ERR, Function, L"Out of memory (flags: 0x%x, requested size: 0x%zx)", Flags, Size);
@@ -106,10 +131,48 @@ static inline _Return_type_success_(return != NULL) _Ret_maybenull_
return Data;
}
#define Alloc(Size) LoggerAlloc(_L(__FUNCTION__), 0, Size)
+#define ReAlloc(Mem, Size) LoggerReAlloc(_L(__FUNCTION__), 0, Mem, Size)
#define Zalloc(Size) LoggerAlloc(_L(__FUNCTION__), HEAP_ZERO_MEMORY, Size)
+#define ReZalloc(Mem, Size) LoggerReAlloc(_L(__FUNCTION__), HEAP_ZERO_MEMORY, Mem, Size)
+
+_Must_inspect_result_
+DECLSPEC_ALLOCATOR
+static inline _Return_type_success_(return != NULL)
+_Post_maybenull_
+_Post_writable_byte_size_((NumberOfElements) * (SizeOfOneElement))
+VOID *
+LoggerAllocArray(_In_z_ LPCWSTR Function, _In_ DWORD Flags, _In_ SIZE_T NumberOfElements, _In_ SIZE_T SizeOfOneElement)
+{
+ SIZE_T Size;
+ if (FAILED(SIZETMult(NumberOfElements, SizeOfOneElement, &Size)))
+ return NULL;
+ return LoggerAlloc(Function, Flags, Size);
+}
+_Must_inspect_result_
+DECLSPEC_ALLOCATOR
+static inline _Return_type_success_(return != NULL)
+_Post_maybenull_
+_Post_writable_byte_size_((NumberOfElements) * (SizeOfOneElement))
+VOID *
+LoggerReAllocArray(
+ _In_z_ LPCWSTR Function,
+ _In_ DWORD Flags,
+ _Frees_ptr_opt_ LPVOID Mem,
+ _In_ SIZE_T NumberOfElements,
+ _In_ SIZE_T SizeOfOneElement)
+{
+ SIZE_T Size;
+ if (FAILED(SIZETMult(NumberOfElements, SizeOfOneElement, &Size)))
+ return NULL;
+ return LoggerReAlloc(Function, Flags, Mem, Size);
+}
+#define AllocArray(Count, Size) LoggerAllocArray(_L(__FUNCTION__), 0, Count, Size)
+#define ReAllocArray(Mem, Count, Size) LoggerReAllocArray(_L(__FUNCTION__), 0, Mem, Count, Size)
+#define ZallocArray(Count, Size) LoggerAllocArray(_L(__FUNCTION__), HEAP_ZERO_MEMORY, Count, Size)
+#define ReZallocArray(Mem, Count, Size) LoggerReAllocArray(_L(__FUNCTION__), HEAP_ZERO_MEMORY, Mem, Count, Size)
-static inline void
-Free(void *Ptr)
+static inline VOID
+Free(_Frees_ptr_opt_ VOID *Ptr)
{
if (!Ptr)
return;
diff --git a/api/main.c b/api/main.c
index 16d3b7c..294f35d 100644
--- a/api/main.c
+++ b/api/main.c
@@ -3,18 +3,15 @@
* Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved.
*/
-#include "adapter.h"
#include "logger.h"
-#include "registry.h"
+#include "adapter.h"
+#include "main.h"
#include "namespace.h"
-#include "wintun.h"
+#include "registry.h"
+#include "ntdll.h"
#include <Windows.h>
-#pragma warning(push)
-#pragma warning(disable : 4201)
-/* nonstandard extension used: nameless struct/union */
#include <delayimp.h>
-#pragma warning(pop)
#include <sddl.h>
#include <winefs.h>
#include <stdlib.h>
@@ -23,6 +20,8 @@ HINSTANCE ResourceModule;
HANDLE ModuleHeap;
SECURITY_ATTRIBUTES SecurityAttributes = { .nLength = sizeof(SECURITY_ATTRIBUTES) };
BOOL IsLocalSystem;
+USHORT NativeMachine = IMAGE_FILE_PROCESS;
+BOOL IsWindows10;
static FARPROC WINAPI
DelayedLoadLibraryHook(unsigned dliNotify, PDelayLoadInfo pdli)
@@ -37,8 +36,7 @@ DelayedLoadLibraryHook(unsigned dliNotify, PDelayLoadInfo pdli)
const PfnDliHook __pfnDliNotifyHook2 = DelayedLoadLibraryHook;
-static BOOL
-InitializeSecurityObjects(void)
+static BOOL InitializeSecurityObjects(VOID)
{
BYTE LocalSystemSid[MAX_SID_SIZE];
DWORD RequiredBytes = sizeof(LocalSystemSid);
@@ -72,11 +70,32 @@ cleanupProcessToken:
return Ret;
}
+static VOID EnvInit(VOID)
+{
+ DWORD MajorVersion;
+ RtlGetNtVersionNumbers(&MajorVersion, NULL, NULL);
+ IsWindows10 = MajorVersion >= 10;
+
+#ifdef MAYBE_WOW64
+ typedef BOOL(WINAPI * IsWow64Process2_t)(
+ _In_ HANDLE hProcess, _Out_ USHORT * pProcessMachine, _Out_opt_ USHORT * pNativeMachine);
+ HANDLE Kernel32;
+ IsWow64Process2_t IsWow64Process2;
+ USHORT ProcessMachine;
+ if ((Kernel32 = GetModuleHandleW(L"kernel32.dll")) == NULL ||
+ (IsWow64Process2 = (IsWow64Process2_t)GetProcAddress(Kernel32, "IsWow64Process2")) == NULL ||
+ !IsWow64Process2(GetCurrentProcess(), &ProcessMachine, &NativeMachine))
+ {
+ BOOL IsWoW64;
+ NativeMachine =
+ IsWow64Process(GetCurrentProcess(), &IsWoW64) && IsWoW64 ? IMAGE_FILE_MACHINE_AMD64 : IMAGE_FILE_PROCESS;
+ }
+#endif
+}
+
BOOL APIENTRY
DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved)
{
- UNREFERENCED_PARAMETER(lpvReserved);
-
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
@@ -89,7 +108,7 @@ DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved)
HeapDestroy(ModuleHeap);
return FALSE;
}
- AdapterInit();
+ EnvInit();
NamespaceInit();
break;
diff --git a/api/main.h b/api/main.h
index 9f6b0de..5d3ebb1 100644
--- a/api/main.h
+++ b/api/main.h
@@ -7,26 +7,21 @@
#include <Windows.h>
-/* TODO: Replace with is_defined. MSVC has issues with the linux kernel varadic macro trick for this. */
-#if defined(_M_IX86) || defined(_M_AMD64) || defined(_M_ARM)
-# define MAYBE_WOW64 1
+#if defined(_M_IX86)
+# define IMAGE_FILE_PROCESS IMAGE_FILE_MACHINE_I386
+#elif defined(_M_AMD64)
+# define IMAGE_FILE_PROCESS IMAGE_FILE_MACHINE_AMD64
+#elif defined(_M_ARM)
+# define IMAGE_FILE_PROCESS IMAGE_FILE_MACHINE_ARMNT
+#elif defined(_M_ARM64)
+# define IMAGE_FILE_PROCESS IMAGE_FILE_MACHINE_ARM64
#else
-# define MAYBE_WOW64 0
+# error Unsupported architecture
#endif
-#if defined(_M_AMD64) || defined(_M_ARM64)
-# define ACCEPT_WOW64 1
-#else
-# define ACCEPT_WOW64 0
-#endif
-#ifdef HAVE_WHQL
-# undef HAVE_WHQL
-# define HAVE_WHQL 1
-#else
-# define HAVE_WHQL 0
-#endif
-#pragma warning(disable : 4127) /* conditional expression is constant */
extern HINSTANCE ResourceModule;
extern HANDLE ModuleHeap;
extern SECURITY_ATTRIBUTES SecurityAttributes;
extern BOOL IsLocalSystem;
+extern USHORT NativeMachine;
+extern BOOL IsWindows10; \ No newline at end of file
diff --git a/api/namespace.c b/api/namespace.c
index 8f1449a..760dc6f 100644
--- a/api/namespace.c
+++ b/api/namespace.c
@@ -19,13 +19,16 @@ static HANDLE BoundaryDescriptor = NULL;
static CRITICAL_SECTION Initializing;
static BCRYPT_ALG_HANDLE AlgProvider;
-static _Return_type_success_(
- return != NULL) WCHAR *NormalizeStringAlloc(_In_ NORM_FORM NormForm, _In_z_ const WCHAR *Source)
+_Must_inspect_result_
+static _Return_type_success_(return != NULL)
+_Post_maybenull_
+LPWSTR
+NormalizeStringAlloc(_In_ NORM_FORM NormForm, _In_z_ LPCWSTR Source)
{
int Len = NormalizeString(NormForm, Source, -1, NULL, 0);
for (;;)
{
- WCHAR *Str = Alloc(sizeof(WCHAR) * Len);
+ LPWSTR Str = AllocArray(Len, sizeof(*Str));
if (!Str)
return NULL;
Len = NormalizeString(NormForm, Source, -1, Str, Len);
@@ -41,7 +44,8 @@ static _Return_type_success_(
}
}
-static _Return_type_success_(return != FALSE) BOOL NamespaceRuntimeInit(void)
+static _Return_type_success_(return != FALSE)
+BOOL NamespaceRuntimeInit(VOID)
{
DWORD LastError;
@@ -110,8 +114,9 @@ cleanupLeaveCriticalSection:
return FALSE;
}
-_Check_return_
-_Return_type_success_(return != NULL) HANDLE NamespaceTakePoolMutex(_In_z_ const WCHAR *Pool)
+_Use_decl_annotations_
+HANDLE
+NamespaceTakePoolMutex(LPCWSTR Pool)
{
if (!NamespaceRuntimeInit())
return NULL;
@@ -133,7 +138,7 @@ _Return_type_success_(return != NULL) HANDLE NamespaceTakePoolMutex(_In_z_ const
LastError = RtlNtStatusToDosError(Status);
goto cleanupSha256;
}
- WCHAR *PoolNorm = NormalizeStringAlloc(NormalizationC, Pool);
+ LPWSTR PoolNorm = NormalizeStringAlloc(NormalizationC, Pool);
if (!PoolNorm)
{
LastError = GetLastError();
@@ -184,8 +189,9 @@ cleanupSha256:
return NULL;
}
-_Check_return_
-_Return_type_success_(return != NULL) HANDLE NamespaceTakeDriverInstallationMutex(void)
+_Use_decl_annotations_
+HANDLE
+NamespaceTakeDriverInstallationMutex(VOID)
{
if (!NamespaceRuntimeInit())
return NULL;
@@ -208,21 +214,20 @@ _Return_type_success_(return != NULL) HANDLE NamespaceTakeDriverInstallationMute
return NULL;
}
-void
-NamespaceReleaseMutex(_In_ HANDLE Mutex)
+_Use_decl_annotations_
+VOID
+NamespaceReleaseMutex(HANDLE Mutex)
{
ReleaseMutex(Mutex);
CloseHandle(Mutex);
}
-void
-NamespaceInit(void)
+VOID NamespaceInit(VOID)
{
InitializeCriticalSection(&Initializing);
}
-void
-NamespaceDone(void)
+VOID NamespaceDone(VOID)
{
EnterCriticalSection(&Initializing);
if (PrivateNamespace)
diff --git a/api/namespace.h b/api/namespace.h
index 35d9930..cbd9100 100644
--- a/api/namespace.h
+++ b/api/namespace.h
@@ -7,17 +7,24 @@
#include <Windows.h>
-_Check_return_
-_Return_type_success_(return != NULL) HANDLE NamespaceTakePoolMutex(_In_z_ const WCHAR *Pool);
+_Must_inspect_result_
+_Return_type_success_(return != NULL)
+_Post_maybenull_
+_Acquires_lock_(_Curr_)
+HANDLE
+NamespaceTakePoolMutex(_In_z_ LPCWSTR Pool);
-_Check_return_
-_Return_type_success_(return != NULL) HANDLE NamespaceTakeDriverInstallationMutex(void);
+_Must_inspect_result_
+_Return_type_success_(return != NULL)
+_Post_maybenull_
+_Acquires_lock_(_Curr_)
+HANDLE
+NamespaceTakeDriverInstallationMutex(VOID);
-void
+_Releases_lock_(Mutex)
+VOID
NamespaceReleaseMutex(_In_ HANDLE Mutex);
-void
-NamespaceInit(void);
+VOID NamespaceInit(VOID);
-void
-NamespaceDone(void);
+VOID NamespaceDone(VOID);
diff --git a/api/nci.h b/api/nci.h
index 40e964e..ba99fa6 100644
--- a/api/nci.h
+++ b/api/nci.h
@@ -9,19 +9,23 @@
#ifdef GENERATE_LIB
# define DECLSPEC __declspec(dllexport)
-# define STUB { return 0; }
+# define STUB \
+ { \
+ return 0; \
+ }
#else
# define DECLSPEC __declspec(dllimport)
# define STUB ;
#endif
+EXTERN_C
+DECLSPEC DWORD WINAPI
+NciSetConnectionName(_In_ const GUID *Guid, _In_z_ LPCWSTR NewName) STUB
-EXTERN_C DECLSPEC DWORD WINAPI
-NciSetConnectionName(_In_ const GUID *Guid, _In_z_ const WCHAR *NewName) STUB
-
-EXTERN_C DECLSPEC DWORD WINAPI
+ EXTERN_C
+DECLSPEC DWORD WINAPI
NciGetConnectionName(
_In_ const GUID *Guid,
- _Out_z_bytecap_(InDestNameBytes) WCHAR *Name,
+ _Out_z_bytecap_(InDestNameBytes) LPWSTR Name,
_In_ DWORD InDestNameBytes,
_Out_opt_ DWORD *OutDestNameBytes) STUB \ No newline at end of file
diff --git a/api/ntdll.h b/api/ntdll.h
index 825119b..3782a30 100644
--- a/api/ntdll.h
+++ b/api/ntdll.h
@@ -45,7 +45,7 @@ typedef struct _KEY_NAME_INFORMATION
* when run from legacy contexts. So, we instead use the undocumented RtlGetNtVersionNumbers.
*
* Another way would be reading from the PEB directly:
- * ((DWORD *)NtCurrentTeb()->ProcessEnvironmentBlock)[sizeof(void *) == 8 ? 70 : 41]
+ * ((DWORD *)NtCurrentTeb()->ProcessEnvironmentBlock)[sizeof(VOID *) == 8 ? 70 : 41]
* Or just read from KUSER_SHARED_DATA the same way on 32-bit and 64-bit:
* *(DWORD *)0x7FFE026C
*/
@@ -61,9 +61,3 @@ NtQueryKey(
_Out_bytecap_post_bytecount_(Length, *ResultLength) PVOID KeyInformation,
_In_ ULONG Length,
_Out_ PULONG ResultLength);
-
-/* This is documented in NTSecAPI.h, which we can't include, due to header conflicts. It actually lives in advapi32.dll. */
-#define RtlGenRandom SystemFunction036
-BOOLEAN
-NTAPI
-RtlGenRandom(_Out_writes_bytes_all_(RandomBufferLength) PVOID RandomBuffer, _In_ ULONG RandomBufferLength); \ No newline at end of file
diff --git a/api/registry.c b/api/registry.c
index 5da05e7..d385d86 100644
--- a/api/registry.c
+++ b/api/registry.c
@@ -10,11 +10,14 @@
#include <stdlib.h>
#include <strsafe.h>
-static _Return_type_success_(return != NULL) HKEY
- OpenKeyWait(_In_ HKEY Key, _Inout_z_ WCHAR *Path, _In_ DWORD Access, _In_ ULONGLONG Deadline)
+_Must_inspect_result_
+static _Return_type_success_(return != NULL)
+_Post_maybenull_
+HKEY
+OpenKeyWait(_In_ HKEY Key, _Inout_z_ LPWSTR Path, _In_ DWORD Access, _In_ ULONGLONG Deadline)
{
DWORD LastError;
- WCHAR *PathNext = wcschr(Path, L'\\');
+ LPWSTR PathNext = wcschr(Path, L'\\');
if (PathNext)
*PathNext = 0;
@@ -87,8 +90,9 @@ static _Return_type_success_(return != NULL) HKEY
return NULL;
}
-_Return_type_success_(return != NULL) HKEY
- RegistryOpenKeyWait(_In_ HKEY Key, _In_z_ const WCHAR *Path, _In_ DWORD Access, _In_ DWORD Timeout)
+_Use_decl_annotations_
+HKEY
+RegistryOpenKeyWait(HKEY Key, LPCWSTR Path, DWORD Access, DWORD Timeout)
{
WCHAR Buf[MAX_REG_PATH];
if (wcsncpy_s(Buf, _countof(Buf), Path, _TRUNCATE) == STRUNCATE)
@@ -100,17 +104,17 @@ _Return_type_success_(return != NULL) HKEY
return OpenKeyWait(Key, Buf, Access, GetTickCount64() + Timeout);
}
-_Return_type_success_(return != FALSE) BOOL RegistryGetString(_Inout_ WCHAR **Buf, _In_ DWORD Len, _In_ DWORD ValueType)
+_Use_decl_annotations_
+BOOL
+RegistryGetString(LPWSTR *Buf, DWORD Len, DWORD ValueType)
{
if (wcsnlen(*Buf, Len) >= Len)
{
/* String is missing zero-terminator. */
- WCHAR *BufZ = Alloc(((size_t)Len + 1) * sizeof(WCHAR));
+ LPWSTR BufZ = ReZallocArray(*Buf, (SIZE_T)Len + 1, sizeof(*BufZ));
if (!BufZ)
return FALSE;
- wmemcpy(BufZ, *Buf, Len);
- BufZ[Len] = 0;
- Free(*Buf);
+ _Analysis_assume_((wmemset(BufZ, L'A', (SIZE_T)Len + 1), TRUE));
*Buf = BufZ;
}
@@ -122,10 +126,9 @@ _Return_type_success_(return != FALSE) BOOL RegistryGetString(_Inout_ WCHAR **Bu
if (!(*Buf)[0])
return TRUE;
- Len = Len * 2 + 64;
for (;;)
{
- WCHAR *Expanded = Alloc(Len * sizeof(WCHAR));
+ LPWSTR Expanded = AllocArray(Len, sizeof(*Expanded));
if (!Expanded)
return FALSE;
DWORD Result = ExpandEnvironmentStringsW(*Buf, Expanded, Len);
@@ -147,8 +150,9 @@ _Return_type_success_(return != FALSE) BOOL RegistryGetString(_Inout_ WCHAR **Bu
}
}
-_Return_type_success_(return != FALSE) BOOL
- RegistryGetMultiString(_Inout_ WCHAR **Buf, _In_ DWORD Len, _In_ DWORD ValueType)
+_Use_decl_annotations_
+BOOL
+RegistryGetMultiString(PZZWSTR *Buf, DWORD Len, DWORD ValueType)
{
if (ValueType == REG_MULTI_SZ)
{
@@ -157,25 +161,18 @@ _Return_type_success_(return != FALSE) BOOL
if (i > Len)
{
/* Missing string and list terminators. */
- WCHAR *BufZ = Alloc(((size_t)Len + 2) * sizeof(WCHAR));
+ PZZWSTR BufZ = ReZallocArray(*Buf, (SIZE_T)Len + 2, sizeof(*BufZ));
if (!BufZ)
return FALSE;
- wmemcpy(BufZ, *Buf, Len);
- BufZ[Len] = 0;
- BufZ[Len + 1] = 0;
- Free(*Buf);
*Buf = BufZ;
return TRUE;
}
if (i == Len)
{
/* Missing list terminator. */
- WCHAR *BufZ = Alloc(((size_t)Len + 1) * sizeof(WCHAR));
+ PZZWSTR BufZ = ReZallocArray(*Buf, (SIZE_T)Len + 1, sizeof(*BufZ));
if (!BufZ)
return FALSE;
- wmemcpy(BufZ, *Buf, Len);
- BufZ[Len] = 0;
- Free(*Buf);
*Buf = BufZ;
return TRUE;
}
@@ -188,22 +185,19 @@ _Return_type_success_(return != FALSE) BOOL
if (!RegistryGetString(Buf, Len, ValueType))
return FALSE;
Len = (DWORD)wcslen(*Buf) + 1;
- WCHAR *BufZ = Alloc(((size_t)Len + 1) * sizeof(WCHAR));
+ PZZWSTR BufZ = ReZallocArray(*Buf, (SIZE_T)Len + 1, sizeof(WCHAR));
if (!BufZ)
return FALSE;
- wmemcpy(BufZ, *Buf, Len);
- BufZ[Len] = 0;
- Free(*Buf);
*Buf = BufZ;
return TRUE;
}
-static _Return_type_success_(return != NULL) void *RegistryQuery(
- _In_ HKEY Key,
- _In_opt_z_ const WCHAR *Name,
- _Out_opt_ DWORD *ValueType,
- _Inout_ DWORD *BufLen,
- _In_ BOOL Log)
+_Must_inspect_result_
+static _Return_type_success_(return != NULL)
+_Post_maybenull_
+_Post_writable_byte_size_(*BufLen)
+VOID *
+RegistryQuery(_In_ HKEY Key, _In_opt_z_ LPCWSTR Name, _Out_opt_ DWORD *ValueType, _Inout_ DWORD *BufLen, _In_ BOOL Log)
{
for (;;)
{
@@ -220,7 +214,7 @@ static _Return_type_success_(return != NULL) void *RegistryQuery(
{
WCHAR RegPath[MAX_REG_PATH];
LoggerGetRegistryKeyPath(Key, RegPath);
- LOG_ERROR(LastError, L"Querying registry value %.*s\\%s failed", MAX_REG_PATH, RegPath, Name);
+ LOG_ERROR(LastError, L"Failed to query registry value %.*s\\%s", MAX_REG_PATH, RegPath, Name);
}
SetLastError(LastError);
return NULL;
@@ -228,11 +222,12 @@ static _Return_type_success_(return != NULL) void *RegistryQuery(
}
}
-_Return_type_success_(
- return != NULL) WCHAR *RegistryQueryString(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ BOOL Log)
+_Use_decl_annotations_
+LPWSTR
+RegistryQueryString(HKEY Key, LPCWSTR Name, BOOL Log)
{
DWORD LastError, ValueType, Size = 256 * sizeof(WCHAR);
- WCHAR *Value = RegistryQuery(Key, Name, &ValueType, &Size, Log);
+ LPWSTR Value = RegistryQuery(Key, Name, &ValueType, &Size, Log);
if (!Value)
return NULL;
switch (ValueType)
@@ -240,7 +235,7 @@ _Return_type_success_(
case REG_SZ:
case REG_EXPAND_SZ:
case REG_MULTI_SZ:
- if (RegistryGetString(&Value, Size / sizeof(WCHAR), ValueType))
+ if (RegistryGetString(&Value, Size / sizeof(*Value), ValueType))
return Value;
LastError = GetLastError();
break;
@@ -261,8 +256,9 @@ _Return_type_success_(
return NULL;
}
-_Return_type_success_(
- return != NULL) WCHAR *RegistryQueryStringWait(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ DWORD Timeout)
+_Use_decl_annotations_
+LPWSTR
+RegistryQueryStringWait(HKEY Key, LPCWSTR Name, DWORD Timeout)
{
DWORD LastError;
ULONGLONG Deadline = GetTickCount64() + Timeout;
@@ -282,7 +278,7 @@ _Return_type_success_(
LOG_ERROR(LastError, L"Failed to setup registry key %.*s notification", MAX_REG_PATH, RegPath);
break;
}
- WCHAR *Value = RegistryQueryString(Key, Name, FALSE);
+ LPWSTR Value = RegistryQueryString(Key, Name, FALSE);
if (Value)
{
CloseHandle(Event);
@@ -313,8 +309,9 @@ _Return_type_success_(
return NULL;
}
-_Return_type_success_(return != FALSE) BOOL
- RegistryQueryDWORD(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _Out_ DWORD *Value, _In_ BOOL Log)
+_Use_decl_annotations_
+BOOL
+RegistryQueryDWORD(HKEY Key, LPCWSTR Name, DWORD *Value, BOOL Log)
{
DWORD ValueType, Size = sizeof(DWORD);
DWORD LastError = RegQueryValueExW(Key, Name, NULL, &ValueType, (BYTE *)Value, &Size);
@@ -324,7 +321,7 @@ _Return_type_success_(return != FALSE) BOOL
{
WCHAR RegPath[MAX_REG_PATH];
LoggerGetRegistryKeyPath(Key, RegPath);
- LOG_ERROR(LastError, L"Querying registry value %.*s\\%s failed", MAX_REG_PATH, RegPath, Name);
+ LOG_ERROR(LastError, L"Failed to query registry value %.*s\\%s", MAX_REG_PATH, RegPath, Name);
}
SetLastError(LastError);
return FALSE;
@@ -348,8 +345,9 @@ _Return_type_success_(return != FALSE) BOOL
return TRUE;
}
-_Return_type_success_(return != FALSE) BOOL
- RegistryQueryDWORDWait(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ DWORD Timeout, _Out_ DWORD *Value)
+_Use_decl_annotations_
+BOOL
+RegistryQueryDWORDWait(HKEY Key, LPCWSTR Name, DWORD Timeout, DWORD *Value)
{
DWORD LastError;
ULONGLONG Deadline = GetTickCount64() + Timeout;
@@ -398,73 +396,3 @@ _Return_type_success_(return != FALSE) BOOL
SetLastError(LastError);
return FALSE;
}
-
-_Return_type_success_(return != FALSE) static BOOL
- DeleteNodeRecurse(_In_ HKEY Key, _In_z_ WCHAR *Name)
-{
- LSTATUS Ret;
- DWORD Size;
- SIZE_T Len;
- WCHAR SubName[MAX_REG_PATH], *End;
- HKEY SubKey;
-
- Len = wcslen(Name);
- if (Len >= MAX_REG_PATH || !Len)
- return TRUE;
-
- if (RegDeleteKeyW(Key, Name) == ERROR_SUCCESS)
- return TRUE;
-
- Ret = RegOpenKeyEx(Key, Name, 0, KEY_READ, &SubKey);
- if (Ret != ERROR_SUCCESS)
- {
- if (Ret == ERROR_FILE_NOT_FOUND)
- return TRUE;
- SetLastError(Ret);
- return FALSE;
- }
-
- End = Name + Len;
- if (End[-1] != L'\\')
- {
- *(End++) = L'\\';
- *End = L'\0';
- }
- Size = MAX_REG_PATH;
- Ret = RegEnumKeyEx(SubKey, 0, SubName, &Size, NULL, NULL, NULL, NULL);
- if (Ret == ERROR_SUCCESS)
- {
- do
- {
- End[0] = L'\0';
- StringCchCatW(Name, MAX_REG_PATH * 2, SubName);
- if (!DeleteNodeRecurse(Key, Name))
- break;
- Size = MAX_REG_PATH;
- Ret = RegEnumKeyEx(SubKey, 0, SubName, &Size, NULL, NULL, NULL, NULL);
- } while (Ret == ERROR_SUCCESS);
- }
- else
- {
- SetLastError(Ret);
- *(--End) = L'\0';
- RegCloseKey(SubKey);
- return FALSE;
- }
- *(--End) = L'\0';
- RegCloseKey(SubKey);
-
- Ret = RegDeleteKey(Key, Name);
- if (Ret == ERROR_SUCCESS)
- return TRUE;
- SetLastError(Ret);
- return FALSE;
-}
-
-_Return_type_success_(return != FALSE) BOOL
-RegistryDeleteKeyRecursive(_In_ HKEY Key, _In_z_ const WCHAR *Name)
-{
- WCHAR NameBuf[(MAX_REG_PATH + 2) * 2] = { 0 };
- StringCchCopyW(NameBuf, MAX_REG_PATH * 2, Name);
- return DeleteNodeRecurse(Key, NameBuf);
-} \ No newline at end of file
diff --git a/api/registry.h b/api/registry.h
index 106a79d..7a366b0 100644
--- a/api/registry.h
+++ b/api/registry.h
@@ -26,8 +26,11 @@
* @return Key handle on success. If the function fails, the return value is zero. To get extended error information,
* call GetLastError.
*/
-_Return_type_success_(return != NULL) HKEY
- RegistryOpenKeyWait(_In_ HKEY Key, _In_z_ const WCHAR *Path, _In_ DWORD Access, _In_ DWORD Timeout);
+_Must_inspect_result_
+_Return_type_success_(return != NULL)
+_Post_maybenull_
+HKEY
+RegistryOpenKeyWait(_In_ HKEY Key, _In_z_ LPCWSTR Path, _In_ DWORD Access, _In_ DWORD Timeout);
/**
* Validates and/or sanitizes string value read from registry.
@@ -44,8 +47,10 @@ _Return_type_success_(return != NULL) HKEY
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
* get extended error information, call GetLastError.
*/
-_Return_type_success_(return != FALSE) BOOL
- RegistryGetString(_Inout_ WCHAR **Buf, _In_ DWORD Len, _In_ DWORD ValueType);
+_Must_inspect_result_
+_Return_type_success_(return != FALSE)
+BOOL
+RegistryGetString(_Inout_ LPWSTR *Buf, _In_ DWORD Len, _In_ DWORD ValueType);
/**
* Validates and/or sanitizes multi-string value read from registry.
@@ -61,8 +66,10 @@ _Return_type_success_(return != FALSE) BOOL
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
* get extended error information, call GetLastError.
*/
-_Return_type_success_(return != FALSE) BOOL
- RegistryGetMultiString(_Inout_ WCHAR **Buf, _In_ DWORD Len, _In_ DWORD ValueType);
+_Must_inspect_result_
+_Return_type_success_(return != FALSE)
+BOOL
+RegistryGetMultiString(_Inout_ PZZWSTR *Buf, _In_ DWORD Len, _In_ DWORD ValueType);
/**
* Reads string value from registry key.
@@ -83,8 +90,11 @@ _Return_type_success_(return != FALSE) BOOL
* @return String with registry value on success; If the function fails, the return value is zero. To get extended error
* information, call GetLastError.
*/
-_Return_type_success_(
- return != NULL) WCHAR *RegistryQueryString(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ BOOL Log);
+_Must_inspect_result_
+_Return_type_success_(return != NULL)
+_Post_maybenull_
+LPWSTR
+RegistryQueryString(_In_ HKEY Key, _In_opt_z_ LPCWSTR Name, _In_ BOOL Log);
/**
* Reads string value from registry key. It waits for the registry value to become available.
@@ -101,8 +111,11 @@ _Return_type_success_(
* get extended error information, call GetLastError. Possible errors include the following:
* ERROR_INVALID_DATATYPE when the registry value is not a string
*/
-_Return_type_success_(
- return != NULL) WCHAR *RegistryQueryStringWait(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ DWORD Timeout);
+_Must_inspect_result_
+_Return_type_success_(return != NULL)
+_Post_maybenull_
+LPWSTR
+RegistryQueryStringWait(_In_ HKEY Key, _In_opt_z_ LPCWSTR Name, _In_ DWORD Timeout);
/**
* Reads a 32-bit DWORD value from registry key.
@@ -120,8 +133,10 @@ _Return_type_success_(
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
* get extended error information, call GetLastError.
*/
-_Return_type_success_(return != FALSE) BOOL
- RegistryQueryDWORD(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _Out_ DWORD *Value, _In_ BOOL Log);
+_Must_inspect_result_
+_Return_type_success_(return != FALSE)
+BOOL
+RegistryQueryDWORD(_In_ HKEY Key, _In_opt_z_ LPCWSTR Name, _Out_ DWORD *Value, _In_ BOOL Log);
/**
* Reads a 32-bit DWORD value from registry key. It waits for the registry value to become available.
@@ -139,17 +154,7 @@ _Return_type_success_(return != FALSE) BOOL
* ERROR_INVALID_DATATYPE when registry value exist but not REG_DWORD type;
* ERROR_INVALID_DATA when registry value size is not 4 bytes
*/
-_Return_type_success_(return != FALSE) BOOL
- RegistryQueryDWORDWait(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ DWORD Timeout, _Out_ DWORD *Value);
-
-/**
- * Deletes the entire registry key subtree recursively.
- *
- * @param Key Handle of the registry key to at which the subtree is rooted.
- *
- * @param Name Name of the subtree to delete.
- *
- * @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
- * get extended error information, call GetLastError.
- */
-_Return_type_success_(return != FALSE) BOOL RegistryDeleteKeyRecursive(_In_ HKEY Key, _In_z_ const WCHAR *Name);
+_Must_inspect_result_
+_Return_type_success_(return != FALSE)
+BOOL
+RegistryQueryDWORDWait(_In_ HKEY Key, _In_opt_z_ LPCWSTR Name, _In_ DWORD Timeout, _Out_ DWORD *Value);
diff --git a/api/resource.c b/api/resource.c
index ce590e1..648f568 100644
--- a/api/resource.c
+++ b/api/resource.c
@@ -7,9 +7,12 @@
#include "main.h"
#include "resource.h"
#include <Windows.h>
+#include <Shlwapi.h>
+#include <NTSecAPI.h>
-_Return_type_success_(return != NULL) _Ret_bytecount_(*Size) const
- void *ResourceGetAddress(_In_z_ const WCHAR *ResourceName, _Out_ DWORD *Size)
+_Use_decl_annotations_
+const VOID *
+ResourceGetAddress(LPCWSTR ResourceName, DWORD *Size)
{
HRSRC FoundResource = FindResourceW(ResourceModule, ResourceName, RT_RCDATA);
if (!FoundResource)
@@ -39,11 +42,12 @@ _Return_type_success_(return != NULL) _Ret_bytecount_(*Size) const
return Address;
}
-_Return_type_success_(return != FALSE) BOOL
- ResourceCopyToFile(_In_z_ const WCHAR *DestinationPath, _In_z_ const WCHAR *ResourceName)
+_Use_decl_annotations_
+BOOL
+ResourceCopyToFile(LPCWSTR DestinationPath, LPCWSTR ResourceName)
{
DWORD SizeResource;
- const void *LockedResource = ResourceGetAddress(ResourceName, &SizeResource);
+ const VOID *LockedResource = ResourceGetAddress(ResourceName, &SizeResource);
if (!LockedResource)
{
LOG(WINTUN_LOG_ERR, L"Failed to locate resource %s", ResourceName);
@@ -84,3 +88,42 @@ cleanupDestinationHandle:
CloseHandle(DestinationHandle);
return RET_ERROR(TRUE, LastError);
}
+
+_Return_type_success_(return != FALSE)
+BOOL
+ResourceCreateTemporaryDirectory(_Out_writes_z_(MAX_PATH) LPWSTR RandomTempSubDirectory)
+{
+ WCHAR WindowsDirectory[MAX_PATH];
+ if (!GetWindowsDirectoryW(WindowsDirectory, _countof(WindowsDirectory)))
+ {
+ LOG_LAST_ERROR(L"Failed to get Windows folder");
+ return FALSE;
+ }
+ WCHAR WindowsTempDirectory[MAX_PATH];
+ if (!PathCombineW(WindowsTempDirectory, WindowsDirectory, L"Temp"))
+ {
+ SetLastError(ERROR_BUFFER_OVERFLOW);
+ return FALSE;
+ }
+ UCHAR RandomBytes[32] = { 0 };
+ if (!RtlGenRandom(RandomBytes, sizeof(RandomBytes)))
+ {
+ LOG(WINTUN_LOG_ERR, L"Failed to generate random");
+ SetLastError(ERROR_GEN_FAILURE);
+ return FALSE;
+ }
+ WCHAR RandomSubDirectory[sizeof(RandomBytes) * 2 + 1];
+ for (int i = 0; i < sizeof(RandomBytes); ++i)
+ swprintf_s(&RandomSubDirectory[i * 2], 3, L"%02x", RandomBytes[i]);
+ if (!PathCombineW(RandomTempSubDirectory, WindowsTempDirectory, RandomSubDirectory))
+ {
+ SetLastError(ERROR_BUFFER_OVERFLOW);
+ return FALSE;
+ }
+ if (!CreateDirectoryW(RandomTempSubDirectory, &SecurityAttributes))
+ {
+ LOG_LAST_ERROR(L"Failed to create temporary folder %s", RandomTempSubDirectory);
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/api/resource.h b/api/resource.h
index 8938241..ae1210b 100644
--- a/api/resource.h
+++ b/api/resource.h
@@ -11,25 +11,40 @@
/**
* Locates RT_RCDATA resource memory address and size.
*
- * ResourceName Name of the RT_RCDATA resource. Use MAKEINTRESOURCEW to locate resource by ID.
+ * @param ResourceName Name of the RT_RCDATA resource. Use MAKEINTRESOURCEW to locate resource by ID.
*
- * Size Pointer to a variable to receive resource size.
+ * @param Size Pointer to a variable to receive resource size.
*
* @return Resource address on success. If the function fails, the return value is NULL. To get extended error
* information, call GetLastError.
*/
-_Return_type_success_(return != NULL) _Ret_bytecount_(*Size) const
- void *ResourceGetAddress(_In_z_ const WCHAR *ResourceName, _Out_ DWORD *Size);
+_Must_inspect_result_
+_Return_type_success_(return != NULL)
+_Post_maybenull_
+_Post_readable_byte_size_(*Size) const VOID *ResourceGetAddress(_In_z_ LPCWSTR ResourceName, _Out_ DWORD *Size);
/**
* Copies resource to a file.
*
- * DestinationPath File path
+ * @param DestinationPath File path
*
- * ResourceName Name of the RT_RCDATA resource. Use MAKEINTRESOURCEW to locate resource by ID.
+ * @param ResourceName Name of the RT_RCDATA resource. Use MAKEINTRESOURCEW to locate resource by ID.
*
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
* get extended error information, call GetLastError.
*/
-_Return_type_success_(return != FALSE) BOOL
- ResourceCopyToFile(_In_z_ const WCHAR *DestinationPath, _In_z_ const WCHAR *ResourceName);
+_Return_type_success_(return != FALSE)
+BOOL
+ResourceCopyToFile(_In_z_ LPCWSTR DestinationPath, _In_z_ LPCWSTR ResourceName);
+
+/**
+ * Creates a temporary directory.
+ *
+ * @param RandomTempSubDirectory Name of random temporary directory.
+ *
+ * @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
+ * get extended error information, call GetLastError.
+ */
+_Return_type_success_(return != FALSE)
+BOOL
+ResourceCreateTemporaryDirectory(_Out_writes_z_(MAX_PATH) LPWSTR RandomTempSubDirectory);
diff --git a/api/rundll32.c b/api/rundll32.c
index 99b1b26..77d7651 100644
--- a/api/rundll32.c
+++ b/api/rundll32.c
@@ -3,12 +3,14 @@
* Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved.
*/
+#include "rundll32.h"
#include "adapter.h"
+#include "main.h"
#include "logger.h"
-#include "wintun.h"
-
+#include "resource.h"
#include <Windows.h>
#include <shellapi.h>
+#include <Shlwapi.h>
#include <cfgmgr32.h>
#include <objbase.h>
#include <assert.h>
@@ -18,10 +20,10 @@
# define EXPORT comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__)
static DWORD
-WriteFormatted(_In_ DWORD StdHandle, _In_z_ const WCHAR *Template, ...)
+WriteFormatted(_In_ DWORD StdHandle, _In_z_ LPCWSTR Template, ...)
{
- WCHAR *FormattedMessage = NULL;
- DWORD SizeWritten;
+ LPWSTR FormattedMessage = NULL;
+ DWORD Size;
va_list Arguments;
va_start(Arguments, Template);
DWORD Len = FormatMessageW(
@@ -29,19 +31,22 @@ WriteFormatted(_In_ DWORD StdHandle, _In_z_ const WCHAR *Template, ...)
Template,
0,
0,
- (void *)&FormattedMessage,
+ (VOID *)&FormattedMessage,
0,
&Arguments);
- WriteFile(GetStdHandle(StdHandle), FormattedMessage, Len * sizeof(WCHAR), &SizeWritten, NULL);
+ if (SUCCEEDED(DWordMult(Len, sizeof(*FormattedMessage), &Size)))
+ WriteFile(GetStdHandle(StdHandle), FormattedMessage, Size, &Size, NULL);
+ else
+ Size = 0;
LocalFree(FormattedMessage);
va_end(Arguments);
- return SizeWritten / sizeof(WCHAR);
+ return Size / sizeof(*FormattedMessage);
}
-static void CALLBACK
-ConsoleLogger(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ const WCHAR *LogLine)
+static VOID CALLBACK
+ConsoleLogger(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ LPCWSTR LogLine)
{
- const WCHAR *Template;
+ LPCWSTR Template;
switch (Level)
{
case WINTUN_LOG_INFO:
@@ -59,29 +64,14 @@ ConsoleLogger(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ const WCHAR *LogLine)
WriteFormatted(STD_ERROR_HANDLE, Template, LogLine);
}
-static int Argc;
-static WCHAR **Argv;
-
-static void
-Init(void)
-{
- WintunSetLogger(ConsoleLogger);
- Argv = CommandLineToArgvW(GetCommandLineW(), &Argc);
-}
-
-static void
-Done(void)
-{
- LocalFree(Argv);
-}
-
-# pragma warning(disable : 4100) /* unreferenced formal parameter */
-
VOID __stdcall CreateAdapter(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
{
# pragma EXPORT
- Init();
+ int Argc;
+ LPWSTR *Argv = CommandLineToArgvW(GetCommandLineW(), &Argc);
+ WintunSetLogger(ConsoleLogger);
+
if (Argc < 4)
goto cleanup;
if (wcslen(Argv[2]) >= WINTUN_MAX_POOL)
@@ -95,47 +85,52 @@ VOID __stdcall CreateAdapter(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int
BOOL RebootRequired;
WINTUN_ADAPTER *Adapter = WintunCreateAdapter(Argv[2], Argv[3], Argc > 4 ? &RequestedGUID : NULL, &RebootRequired);
DWORD LastError = Adapter ? ERROR_SUCCESS : GetLastError();
- WCHAR GuidStr[MAX_GUID_STRING_LEN];
WriteFormatted(
- STD_OUTPUT_HANDLE,
- L"%1!X! %2!.*s! %3!X!",
- LastError,
- StringFromGUID2(Adapter ? &Adapter->CfgInstanceID : &GUID_NULL, GuidStr, _countof(GuidStr)),
- GuidStr,
- RebootRequired);
+ STD_OUTPUT_HANDLE, L"%1!X! %2!s! %3!X!", LastError, Adapter ? Adapter->DevInstanceID : L"", RebootRequired);
if (Adapter)
WintunFreeAdapter(Adapter);
cleanup:
- Done();
+ LocalFree(Argv);
}
VOID __stdcall DeleteAdapter(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
{
# pragma EXPORT
- Init();
- if (Argc < 3)
- goto cleanup;
+ int Argc;
+ LPWSTR *Argv = CommandLineToArgvW(GetCommandLineW(), &Argc);
+ WintunSetLogger(ConsoleLogger);
- WINTUN_ADAPTER Adapter = { 0 };
- BOOL ForceCloseSessions = wcstoul(Argv[2], NULL, 10);
- if (FAILED(CLSIDFromString(Argv[3], &Adapter.CfgInstanceID)))
+ if (Argc < 4)
goto cleanup;
- BOOL RebootRequired;
- DWORD LastError =
- WintunDeleteAdapter(&Adapter, ForceCloseSessions, &RebootRequired) ? ERROR_SUCCESS : GetLastError();
+
+ DWORD LastError;
+ BOOL RebootRequired = FALSE;
+ WINTUN_ADAPTER *Adapter = AdapterOpenFromDevInstanceId(Argv[2], Argv[3]);
+ if (!Adapter)
+ {
+ LastError = GetLastError();
+ goto write;
+ }
+ BOOL ForceCloseSessions = wcstoul(Argv[4], NULL, 10);
+ LastError = WintunDeleteAdapter(Adapter, ForceCloseSessions, &RebootRequired) ? ERROR_SUCCESS : GetLastError();
+ WintunFreeAdapter(Adapter);
+write:
WriteFormatted(STD_OUTPUT_HANDLE, L"%1!X! %2!X!", LastError, RebootRequired);
cleanup:
- Done();
+ LocalFree(Argv);
}
VOID __stdcall DeletePoolDriver(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
{
# pragma EXPORT
- Init();
+ int Argc;
+ LPWSTR *Argv = CommandLineToArgvW(GetCommandLineW(), &Argc);
+ WintunSetLogger(ConsoleLogger);
+
if (Argc < 2)
goto cleanup;
@@ -144,6 +139,455 @@ VOID __stdcall DeletePoolDriver(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, i
WriteFormatted(STD_OUTPUT_HANDLE, L"%1!X! %2!X!", LastError, RebootRequired);
cleanup:
- Done();
+ LocalFree(Argv);
+}
+#endif
+
+#ifdef MAYBE_WOW64
+
+_Return_type_success_(return != FALSE)
+static BOOL
+AppendToBuffer(_Inout_ LPWSTR *Buffer, _In_ CONST WCHAR Addition, _Inout_ SIZE_T *BufferPos, _Inout_ SIZE_T *BufferLen)
+{
+ SIZE_T NewPos;
+ if (FAILED(SIZETAdd(*BufferPos, sizeof(Addition), &NewPos)))
+ return FALSE;
+ if (NewPos >= *BufferLen)
+ {
+ SIZE_T NewLen;
+ if (FAILED(SIZETMult(NewPos, 3, &NewLen)))
+ return FALSE;
+ LPWSTR NewBuffer = ReZalloc(*Buffer, NewLen);
+ if (!NewBuffer)
+ return FALSE;
+ *Buffer = NewBuffer;
+ *BufferLen = NewLen;
+ }
+ SIZE_T NewIndex = *BufferPos / sizeof(**Buffer);
+ if (*Buffer + NewIndex < *Buffer)
+ return FALSE;
+ (*Buffer)[NewIndex] = Addition;
+ *BufferPos = NewPos;
+ return TRUE;
+}
+
+_Must_inspect_result_
+static _Return_type_success_(return != NULL)
+_Post_maybenull_
+LPWSTR
+ArgvToCommandLineW(_In_ SIZE_T ArgCount, ...)
+{
+ LPWSTR Output = NULL;
+ SIZE_T BufferPos = 0, BufferLen = 0;
+# define Append(Char) \
+ do \
+ { \
+ if (!AppendToBuffer(&Output, Char, &BufferPos, &BufferLen)) \
+ goto cleanupBuffer; \
+ } while (0)
+
+ va_list Args;
+ va_start(Args, ArgCount);
+ for (SIZE_T i = 0; i < ArgCount; ++i)
+ {
+ LPCWSTR Arg = va_arg(Args, LPCWSTR);
+ SIZE_T ArgLen = wcslen(Arg);
+ if (ArgLen >= DWORD_MAX >> 3)
+ goto cleanupBuffer;
+ if (i)
+ Append(L' ');
+ Append(L'"');
+ for (SIZE_T j = 0;; ++j)
+ {
+ SIZE_T NumberBackslashes = 0;
+
+ while (j < ArgLen && Arg[j] == L'\\')
+ {
+ ++j;
+ ++NumberBackslashes;
+ }
+ if (j >= ArgLen)
+ {
+ for (SIZE_T k = 0; k < NumberBackslashes * 2; ++k)
+ Append(L'\\');
+ break;
+ }
+ else if (Arg[j] == L'"')
+ {
+ for (SIZE_T k = 0; k < NumberBackslashes * 2 + 1; ++k)
+ Append(L'\\');
+ Append(Arg[j]);
+ }
+ else
+ {
+ for (SIZE_T k = 0; k < NumberBackslashes; ++k)
+ Append(L'\\');
+ Append(Arg[j]);
+ }
+ }
+ Append(L'"');
+ }
+ va_end(Args);
+ return Output;
+
+cleanupBuffer:
+ Free(Output);
+ return NULL;
+# undef Append
+}
+
+typedef struct _PROCESS_STDOUT_STATE
+{
+ HANDLE Stdout;
+ LPWSTR Response;
+ DWORD ResponseCapacity;
+} PROCESS_STDOUT_STATE;
+
+_Return_type_success_(return != ERROR_SUCCESS)
+static DWORD WINAPI
+ProcessStdout(_Inout_ PROCESS_STDOUT_STATE *State)
+{
+ for (DWORD Offset = 0, MaxLen = State->ResponseCapacity - 1; Offset < MaxLen;)
+ {
+ DWORD Size;
+ if (FAILED(DWordMult(MaxLen - Offset, sizeof(WCHAR), &Size)))
+ return ERROR_BUFFER_OVERFLOW;
+ if (!ReadFile(State->Stdout, State->Response + Offset, Size, &Size, NULL))
+ return ERROR_SUCCESS;
+ if (Size % sizeof(WCHAR))
+ return ERROR_INVALID_DATA;
+ Offset += Size / sizeof(WCHAR);
+ State->Response[Offset] = 0;
+ }
+ return ERROR_BUFFER_OVERFLOW;
+}
+
+static DWORD WINAPI
+ProcessStderr(_In_ HANDLE Stderr)
+{
+ enum
+ {
+ OnNone,
+ OnLevelStart,
+ OnLevel,
+ OnLevelEnd,
+ OnSpace,
+ OnMsg
+ } State = OnNone;
+ WCHAR Msg[0x200];
+ DWORD Count = 0;
+ WINTUN_LOGGER_LEVEL Level = WINTUN_LOG_INFO;
+ for (;;)
+ {
+ WCHAR Buf[0x200];
+ DWORD SizeRead;
+ if (!ReadFile(Stderr, Buf, sizeof(Buf), &SizeRead, NULL))
+ return ERROR_SUCCESS;
+ if (SizeRead % sizeof(*Buf))
+ return ERROR_INVALID_DATA;
+ SizeRead /= sizeof(*Buf);
+ for (DWORD i = 0; i < SizeRead; ++i)
+ {
+ WCHAR c = Buf[i];
+ if (State == OnNone && c == L'[')
+ State = OnLevelStart;
+ else if (
+ State == OnLevelStart && ((Level = WINTUN_LOG_INFO, c == L'+') ||
+ (Level = WINTUN_LOG_WARN, c == L'-') || (Level = WINTUN_LOG_ERR, c == L'!')))
+ State = OnLevelEnd;
+ else if (State == OnLevelEnd && c == L']')
+ State = OnSpace;
+ else if (State == OnSpace && !iswspace(c) || State == OnMsg && c != L'\r' && c != L'\n')
+ {
+ if (Count < _countof(Msg) - 1)
+ Msg[Count++] = c;
+ State = OnMsg;
+ }
+ else if (State == OnMsg && c == L'\n')
+ {
+ Msg[Count] = 0;
+ LoggerLog(Level, NULL, Msg);
+ State = OnNone;
+ Count = 0;
+ }
+ }
+ }
+}
+
+static _Return_type_success_(return != FALSE)
+BOOL
+ExecuteRunDll32(
+ _In_z_ LPCWSTR Function,
+ _In_z_ LPCWSTR Arguments,
+ _Out_z_cap_c_(ResponseCapacity) LPWSTR Response,
+ _In_ DWORD ResponseCapacity)
+{
+ WCHAR WindowsDirectory[MAX_PATH];
+ if (!GetWindowsDirectoryW(WindowsDirectory, _countof(WindowsDirectory)))
+ {
+ LOG_LAST_ERROR(L"Failed to get Windows folder");
+ return FALSE;
+ }
+ WCHAR RunDll32Path[MAX_PATH];
+ if (!PathCombineW(RunDll32Path, WindowsDirectory, L"Sysnative\\rundll32.exe"))
+ {
+ SetLastError(ERROR_BUFFER_OVERFLOW);
+ return FALSE;
+ }
+
+ DWORD LastError;
+ WCHAR RandomTempSubDirectory[MAX_PATH];
+ if (!ResourceCreateTemporaryDirectory(RandomTempSubDirectory))
+ {
+ LOG(WINTUN_LOG_ERR, L"Failed to create temporary folder");
+ return FALSE;
+ }
+ WCHAR DllPath[MAX_PATH] = { 0 };
+ if (!PathCombineW(DllPath, RandomTempSubDirectory, L"wintun.dll"))
+ {
+ LastError = ERROR_BUFFER_OVERFLOW;
+ goto cleanupDirectory;
+ }
+ LPCWSTR WintunDllResourceName;
+ switch (NativeMachine)
+ {
+ case IMAGE_FILE_MACHINE_AMD64:
+ WintunDllResourceName = L"wintun-amd64.dll";
+ break;
+ case IMAGE_FILE_MACHINE_ARM64:
+ WintunDllResourceName = L"wintun-arm64.dll";
+ break;
+ default:
+ LOG(WINTUN_LOG_ERR, L"Unsupported platform 0x%x", NativeMachine);
+ LastError = ERROR_NOT_SUPPORTED;
+ goto cleanupDirectory;
+ }
+ if (!ResourceCopyToFile(DllPath, WintunDllResourceName))
+ {
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to copy resource %s to %s", WintunDllResourceName, DllPath);
+ goto cleanupDelete;
+ }
+ size_t CommandLineLen = 10 + MAX_PATH + 2 + wcslen(Arguments) + 1 + wcslen(Function) + 1;
+ LPWSTR CommandLine = AllocArray(CommandLineLen, sizeof(*CommandLine));
+ if (!CommandLine)
+ {
+ LastError = GetLastError();
+ goto cleanupDelete;
+ }
+ if (_snwprintf_s(
+ CommandLine,
+ CommandLineLen,
+ _TRUNCATE,
+ L"rundll32 \"%.*s\",%s %s",
+ MAX_PATH,
+ DllPath,
+ Function,
+ Arguments) == -1)
+ {
+ LOG(WINTUN_LOG_ERR, L"Command line too long");
+ LastError = ERROR_INVALID_PARAMETER;
+ goto cleanupDelete;
+ }
+ HANDLE StreamRStdout = INVALID_HANDLE_VALUE, StreamRStderr = INVALID_HANDLE_VALUE,
+ StreamWStdout = INVALID_HANDLE_VALUE, StreamWStderr = INVALID_HANDLE_VALUE;
+ if (!CreatePipe(&StreamRStdout, &StreamWStdout, &SecurityAttributes, 0) ||
+ !CreatePipe(&StreamRStderr, &StreamWStderr, &SecurityAttributes, 0))
+ {
+ LastError = LOG_LAST_ERROR(L"Failed to create pipes");
+ goto cleanupPipes;
+ }
+ if (!SetHandleInformation(StreamWStdout, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT) ||
+ !SetHandleInformation(StreamWStderr, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
+ {
+ LastError = LOG_LAST_ERROR(L"Failed to set handle info");
+ goto cleanupPipes;
+ }
+ if (ResponseCapacity)
+ Response[0] = 0;
+ PROCESS_STDOUT_STATE ProcessStdoutState = { .Stdout = StreamRStdout,
+ .Response = Response,
+ .ResponseCapacity = ResponseCapacity };
+ HANDLE ThreadStdout = NULL, ThreadStderr = NULL;
+ if ((ThreadStdout = CreateThread(NULL, 0, ProcessStdout, &ProcessStdoutState, 0, NULL)) == NULL ||
+ (ThreadStderr = CreateThread(NULL, 0, ProcessStderr, StreamRStderr, 0, NULL)) == NULL)
+ {
+ LastError = LOG_LAST_ERROR(L"Failed to spawn readers");
+ goto cleanupThreads;
+ }
+ STARTUPINFOW si = { .cb = sizeof(STARTUPINFO),
+ .dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES,
+ .wShowWindow = SW_HIDE,
+ .hStdOutput = StreamWStdout,
+ .hStdError = StreamWStderr };
+ PROCESS_INFORMATION pi;
+ if (!CreateProcessW(RunDll32Path, CommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
+ {
+ LastError = LOG_LAST_ERROR(L"Failed to create process: %s", CommandLine);
+ goto cleanupThreads;
+ }
+ LastError = ERROR_SUCCESS;
+ WaitForSingleObject(pi.hProcess, INFINITE);
+ CloseHandle(pi.hProcess);
+ CloseHandle(pi.hThread);
+cleanupThreads:
+ if (ThreadStderr)
+ {
+ CloseHandle(StreamWStderr);
+ StreamWStderr = INVALID_HANDLE_VALUE;
+ WaitForSingleObject(ThreadStderr, INFINITE);
+ CloseHandle(ThreadStderr);
+ }
+ if (ThreadStdout)
+ {
+ CloseHandle(StreamWStdout);
+ StreamWStdout = INVALID_HANDLE_VALUE;
+ WaitForSingleObject(ThreadStdout, INFINITE);
+ DWORD ThreadResult;
+ if (!GetExitCodeThread(ThreadStdout, &ThreadResult))
+ LOG_LAST_ERROR(L"Failed to retrieve stdout reader result");
+ else if (ThreadResult != ERROR_SUCCESS)
+ LOG_ERROR(LastError, L"Failed to read process output");
+ CloseHandle(ThreadStdout);
+ }
+cleanupPipes:
+ CloseHandle(StreamRStderr);
+ CloseHandle(StreamWStderr);
+ CloseHandle(StreamRStdout);
+ CloseHandle(StreamWStdout);
+ Free(CommandLine);
+cleanupDelete:
+ DeleteFileW(DllPath);
+cleanupDirectory:
+ RemoveDirectoryW(RandomTempSubDirectory);
+ return RET_ERROR(TRUE, LastError);
+}
+
+_Use_decl_annotations_
+WINTUN_ADAPTER *
+CreateAdapterViaRundll32(LPCWSTR Pool, LPCWSTR Name, const GUID *RequestedGUID, BOOL *RebootRequired)
+{
+ LOG(WINTUN_LOG_INFO, L"Spawning native process");
+ LPWSTR Arguments = NULL;
+ if (RequestedGUID)
+ {
+ WCHAR RequestedGUIDStr[MAX_GUID_STRING_LEN];
+ if (StringFromGUID2(RequestedGUID, RequestedGUIDStr, _countof(RequestedGUIDStr)))
+ Arguments = ArgvToCommandLineW(3, Pool, Name, RequestedGUIDStr);
+ }
+ else
+ Arguments = ArgvToCommandLineW(2, Pool, Name);
+ if (!Arguments)
+ {
+ LOG(WINTUN_LOG_ERR, L"Command line too long");
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+ WINTUN_ADAPTER *Adapter = NULL;
+ DWORD LastError;
+ WCHAR Response[8 + 1 + MAX_GUID_STRING_LEN + 1 + 8 + 1];
+ if (!ExecuteRunDll32(L"CreateAdapter", Arguments, Response, _countof(Response)))
+ {
+ LastError = GetLastError();
+ LOG(WINTUN_LOG_ERR, L"Error executing worker process: %s", Arguments);
+ goto cleanupArguments;
+ }
+ int Argc;
+ LPWSTR *Argv = CommandLineToArgvW(Response, &Argc);
+ if (Argc < 3)
+ {
+ LOG(WINTUN_LOG_ERR, L"Incomplete response: %s", Response);
+ LastError = ERROR_INVALID_PARAMETER;
+ goto cleanupArgv;
+ }
+ LastError = wcstoul(Argv[0], NULL, 16);
+ if (LastError == ERROR_SUCCESS && (Adapter = AdapterOpenFromDevInstanceId(Pool, Argv[1])) == NULL)
+ {
+ LOG(WINTUN_LOG_ERR, L"Failed to get adapter %s", Argv[1]);
+ LastError = ERROR_FILE_NOT_FOUND;
+ }
+ if (wcstoul(Argv[2], NULL, 16))
+ *RebootRequired = TRUE;
+cleanupArgv:
+ LocalFree(Argv);
+cleanupArguments:
+ Free(Arguments);
+ SetLastError(LastError);
+ return Adapter;
+}
+
+_Use_decl_annotations_
+BOOL
+DeleteAdapterViaRundll32(const WINTUN_ADAPTER *Adapter, BOOL ForceCloseSessions, BOOL *RebootRequired)
+{
+ LOG(WINTUN_LOG_INFO, L"Spawning native process");
+ LPWSTR Arguments = ArgvToCommandLineW(3, Adapter->Pool, Adapter->DevInstanceID, ForceCloseSessions ? L"1" : L"0");
+ if (!Arguments)
+ {
+ LOG(WINTUN_LOG_ERR, L"Command line too long");
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ WCHAR Response[8 + 1 + 8 + 1];
+ DWORD LastError;
+ if (!ExecuteRunDll32(L"DeleteAdapter", Arguments, Response, _countof(Response)))
+ {
+ LastError = GetLastError();
+ LOG(WINTUN_LOG_ERR, L"Error executing worker process: %s", Arguments);
+ goto cleanupArguments;
+ }
+ int Argc;
+ LPWSTR *Argv = CommandLineToArgvW(Response, &Argc);
+ if (Argc < 2)
+ {
+ LOG(WINTUN_LOG_ERR, L"Incomplete response: %s", Response);
+ LastError = ERROR_INVALID_PARAMETER;
+ goto cleanupArgv;
+ }
+ LastError = wcstoul(Argv[0], NULL, 16);
+ if (wcstoul(Argv[1], NULL, 16))
+ *RebootRequired = TRUE;
+cleanupArgv:
+ LocalFree(Argv);
+cleanupArguments:
+ Free(Arguments);
+ return RET_ERROR(TRUE, LastError);
+}
+
+_Use_decl_annotations_
+BOOL
+DeletePoolDriverViaRundll32(LPCWSTR Pool, BOOL *RebootRequired)
+{
+ LOG(WINTUN_LOG_INFO, L"Spawning native process");
+ LPWSTR Arguments = ArgvToCommandLineW(1, Pool);
+ if (!Arguments)
+ {
+ LOG(WINTUN_LOG_ERR, L"Command line too long");
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ WCHAR Response[8 + 1 + 8 + 1];
+ DWORD LastError;
+ if (!ExecuteRunDll32(L"DeletePoolDriver", Arguments, Response, _countof(Response)))
+ {
+ LastError = GetLastError();
+ LOG(WINTUN_LOG_ERR, L"Error executing worker process: %s", Arguments);
+ goto cleanupArguments;
+ }
+ int Argc;
+ LPWSTR *Argv = CommandLineToArgvW(Response, &Argc);
+ if (Argc < 2)
+ {
+ LOG(WINTUN_LOG_ERR, L"Incomplete response: %s", Response);
+ LastError = ERROR_INVALID_PARAMETER;
+ goto cleanupArgv;
+ }
+ LastError = wcstoul(Argv[0], NULL, 16);
+ if (wcstoul(Argv[1], NULL, 16))
+ *RebootRequired = TRUE;
+cleanupArgv:
+ LocalFree(Argv);
+cleanupArguments:
+ Free(Arguments);
+ return RET_ERROR(TRUE, LastError);
}
#endif
diff --git a/api/rundll32.h b/api/rundll32.h
new file mode 100644
index 0000000..1cd3cae
--- /dev/null
+++ b/api/rundll32.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved.
+ */
+
+#pragma once
+
+#include "adapter.h"
+
+_Must_inspect_result_
+_Return_type_success_(return != NULL)
+_Post_maybenull_
+WINTUN_ADAPTER *
+CreateAdapterViaRundll32(
+ _In_z_ LPCWSTR Pool,
+ _In_z_ LPCWSTR Name,
+ _In_opt_ const GUID *RequestedGUID,
+ _Inout_ BOOL *RebootRequired);
+
+_Return_type_success_(return != FALSE)
+BOOL
+DeleteAdapterViaRundll32(
+ _In_ const WINTUN_ADAPTER *Adapter,
+ _In_ BOOL ForceCloseSessions,
+ _Inout_ BOOL *RebootRequired);
+
+_Return_type_success_(return != FALSE)
+BOOL
+DeletePoolDriverViaRundll32(_In_z_ LPCWSTR Pool, _Inout_ BOOL *RebootRequired);
diff --git a/api/rundll32_i.c b/api/rundll32_i.c
deleted file mode 100644
index 17598da..0000000
--- a/api/rundll32_i.c
+++ /dev/null
@@ -1,352 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0
- *
- * Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved.
- */
-
-/* TODO: This is currently #include'd in adapter.c. Move into rundll32.c properly. */
-
-typedef struct _PROCESS_STDOUT_STATE
-{
- HANDLE Stdout;
- WCHAR *Response;
- DWORD ResponseCapacity;
-} PROCESS_STDOUT_STATE;
-
-static DWORD WINAPI
-ProcessStdout(_Inout_ PROCESS_STDOUT_STATE *State)
-{
- for (DWORD Offset = 0, MaxLen = State->ResponseCapacity - 1; Offset < MaxLen;)
- {
- DWORD SizeRead;
- if (!ReadFile(State->Stdout, State->Response + Offset, sizeof(WCHAR) * (MaxLen - Offset), &SizeRead, NULL))
- return ERROR_SUCCESS;
- if (SizeRead % sizeof(WCHAR))
- return ERROR_INVALID_DATA;
- Offset += SizeRead / sizeof(WCHAR);
- State->Response[Offset] = 0;
- }
- return ERROR_BUFFER_OVERFLOW;
-}
-
-static DWORD WINAPI
-ProcessStderr(_In_ HANDLE Stderr)
-{
- enum
- {
- OnNone,
- OnLevelStart,
- OnLevel,
- OnLevelEnd,
- OnSpace,
- OnMsg
- } State = OnNone;
- WCHAR Msg[0x200];
- DWORD Count = 0;
- WINTUN_LOGGER_LEVEL Level = WINTUN_LOG_INFO;
- for (;;)
- {
- WCHAR Buf[0x200];
- DWORD SizeRead;
- if (!ReadFile(Stderr, Buf, sizeof(Buf), &SizeRead, NULL))
- return ERROR_SUCCESS;
- if (SizeRead % sizeof(WCHAR))
- return ERROR_INVALID_DATA;
- SizeRead /= sizeof(WCHAR);
- for (DWORD i = 0; i < SizeRead; ++i)
- {
- WCHAR c = Buf[i];
- if (State == OnNone && c == L'[')
- State = OnLevelStart;
- else if (
- State == OnLevelStart && ((Level = WINTUN_LOG_INFO, c == L'+') ||
- (Level = WINTUN_LOG_WARN, c == L'-') || (Level = WINTUN_LOG_ERR, c == L'!')))
- State = OnLevelEnd;
- else if (State == OnLevelEnd && c == L']')
- State = OnSpace;
- else if (State == OnSpace && !iswspace(c) || State == OnMsg && c != L'\r' && c != L'\n')
- {
- if (Count < _countof(Msg) - 1)
- Msg[Count++] = c;
- State = OnMsg;
- }
- else if (State == OnMsg && c == L'\n')
- {
- Msg[Count] = 0;
- LoggerLog(Level, NULL, Msg);
- State = OnNone;
- Count = 0;
- }
- }
- }
-}
-
-static _Return_type_success_(return != FALSE) BOOL ExecuteRunDll32(
- _In_z_ const WCHAR *Arguments,
- _Out_z_cap_c_(ResponseCapacity) WCHAR *Response,
- _In_ DWORD ResponseCapacity)
-{
- WCHAR WindowsDirectory[MAX_PATH];
- if (!GetWindowsDirectoryW(WindowsDirectory, _countof(WindowsDirectory)))
- {
- LOG_LAST_ERROR(L"Failed to get Windows folder");
- return FALSE;
- }
- WCHAR RunDll32Path[MAX_PATH];
- if (!PathCombineW(RunDll32Path, WindowsDirectory, L"Sysnative\\rundll32.exe"))
- {
- SetLastError(ERROR_BUFFER_OVERFLOW);
- return FALSE;
- }
-
- DWORD LastError;
- WCHAR RandomTempSubDirectory[MAX_PATH];
- if (!CreateTemporaryDirectory(RandomTempSubDirectory))
- {
- LOG(WINTUN_LOG_ERR, L"Failed to create temporary folder %s", RandomTempSubDirectory);
- return FALSE;
- }
- WCHAR DllPath[MAX_PATH] = { 0 };
- if (!PathCombineW(DllPath, RandomTempSubDirectory, L"wintun.dll"))
- {
- LastError = ERROR_BUFFER_OVERFLOW;
- goto cleanupDirectory;
- }
- const WCHAR *WintunDllResourceName;
- switch (NativeMachine)
- {
- case IMAGE_FILE_MACHINE_AMD64:
- WintunDllResourceName = L"wintun-amd64.dll";
- break;
- case IMAGE_FILE_MACHINE_ARM64:
- WintunDllResourceName = L"wintun-arm64.dll";
- break;
- default:
- LOG(WINTUN_LOG_ERR, L"Unsupported platform 0x%x", NativeMachine);
- LastError = ERROR_NOT_SUPPORTED;
- goto cleanupDirectory;
- }
- if (!ResourceCopyToFile(DllPath, WintunDllResourceName))
- {
- LastError = LOG(WINTUN_LOG_ERR, L"Failed to copy resource %s to %s", WintunDllResourceName, DllPath);
- goto cleanupDelete;
- }
- size_t CommandLineLen = 10 + MAX_PATH + 2 + wcslen(Arguments) + 1;
- WCHAR *CommandLine = Alloc(CommandLineLen * sizeof(WCHAR));
- if (!CommandLine)
- {
- LastError = GetLastError();
- goto cleanupDelete;
- }
- if (_snwprintf_s(CommandLine, CommandLineLen, _TRUNCATE, L"rundll32 \"%.*s\",%s", MAX_PATH, DllPath, Arguments) ==
- -1)
- {
- LOG(WINTUN_LOG_ERR, L"Command line too long");
- LastError = ERROR_INVALID_PARAMETER;
- goto cleanupDelete;
- }
- HANDLE StreamRStdout = INVALID_HANDLE_VALUE, StreamRStderr = INVALID_HANDLE_VALUE,
- StreamWStdout = INVALID_HANDLE_VALUE, StreamWStderr = INVALID_HANDLE_VALUE;
- if (!CreatePipe(&StreamRStdout, &StreamWStdout, &SecurityAttributes, 0) ||
- !CreatePipe(&StreamRStderr, &StreamWStderr, &SecurityAttributes, 0))
- {
- LastError = LOG_LAST_ERROR(L"Failed to create pipes");
- goto cleanupPipes;
- }
- if (!SetHandleInformation(StreamWStdout, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT) ||
- !SetHandleInformation(StreamWStderr, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
- {
- LastError = LOG_LAST_ERROR(L"Failed to set handle info");
- goto cleanupPipes;
- }
- if (ResponseCapacity)
- Response[0] = 0;
- PROCESS_STDOUT_STATE ProcessStdoutState = { .Stdout = StreamRStdout,
- .Response = Response,
- .ResponseCapacity = ResponseCapacity };
- HANDLE ThreadStdout = NULL, ThreadStderr = NULL;
- if ((ThreadStdout = CreateThread(NULL, 0, ProcessStdout, &ProcessStdoutState, 0, NULL)) == NULL ||
- (ThreadStderr = CreateThread(NULL, 0, ProcessStderr, StreamRStderr, 0, NULL)) == NULL)
- {
- LastError = LOG_LAST_ERROR(L"Failed to spawn readers");
- goto cleanupThreads;
- }
- STARTUPINFOW si = { .cb = sizeof(STARTUPINFO),
- .dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES,
- .wShowWindow = SW_HIDE,
- .hStdOutput = StreamWStdout,
- .hStdError = StreamWStderr };
- PROCESS_INFORMATION pi;
- if (!CreateProcessW(RunDll32Path, CommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
- {
- LastError = LOG_LAST_ERROR(L"Failed to create process: %s", CommandLine);
- goto cleanupThreads;
- }
- LastError = ERROR_SUCCESS;
- WaitForSingleObject(pi.hProcess, INFINITE);
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
-cleanupThreads:
- if (ThreadStderr)
- {
- CloseHandle(StreamWStderr);
- StreamWStderr = INVALID_HANDLE_VALUE;
- WaitForSingleObject(ThreadStderr, INFINITE);
- CloseHandle(ThreadStderr);
- }
- if (ThreadStdout)
- {
- CloseHandle(StreamWStdout);
- StreamWStdout = INVALID_HANDLE_VALUE;
- WaitForSingleObject(ThreadStdout, INFINITE);
- DWORD ThreadResult;
- if (!GetExitCodeThread(ThreadStdout, &ThreadResult))
- LOG_LAST_ERROR(L"Failed to retrieve stdout reader result");
- else if (ThreadResult != ERROR_SUCCESS)
- LOG_ERROR(LastError, L"Failed to read process output");
- CloseHandle(ThreadStdout);
- }
-cleanupPipes:
- CloseHandle(StreamRStderr);
- CloseHandle(StreamWStderr);
- CloseHandle(StreamRStdout);
- CloseHandle(StreamWStdout);
- Free(CommandLine);
-cleanupDelete:
- DeleteFileW(DllPath);
-cleanupDirectory:
- RemoveDirectoryW(RandomTempSubDirectory);
- return RET_ERROR(TRUE, LastError);
-}
-
-static _Return_type_success_(return != NULL) WINTUN_ADAPTER *CreateAdapterViaRundll32(
- _In_z_ const WCHAR *Pool,
- _In_z_ const WCHAR *Name,
- _In_opt_ const GUID *RequestedGUID,
- _Inout_ BOOL *RebootRequired)
-{
- LOG(WINTUN_LOG_INFO, L"Spawning native process");
- WCHAR RequestedGUIDStr[MAX_GUID_STRING_LEN];
- WCHAR Arguments[15 + WINTUN_MAX_POOL + 3 + MAX_ADAPTER_NAME + 2 + MAX_GUID_STRING_LEN + 1];
- if (_snwprintf_s(
- Arguments,
- _countof(Arguments),
- _TRUNCATE,
- RequestedGUID ? L"CreateAdapter \"%s\" \"%s\" %.*s" : L"CreateAdapter \"%s\" \"%s\"",
- Pool,
- Name,
- RequestedGUID ? StringFromGUID2(RequestedGUID, RequestedGUIDStr, _countof(RequestedGUIDStr)) : 0,
- RequestedGUIDStr) == -1)
- {
- LOG(WINTUN_LOG_ERR, L"Command line too long");
- SetLastError(ERROR_INVALID_PARAMETER);
- return NULL;
- }
- WCHAR Response[8 + 1 + MAX_GUID_STRING_LEN + 1 + 8 + 1];
- if (!ExecuteRunDll32(Arguments, Response, _countof(Response)))
- {
- LOG(WINTUN_LOG_ERR, L"Error executing worker process: %s", Arguments);
- return NULL;
- }
- DWORD LastError;
- WINTUN_ADAPTER *Adapter = NULL;
- int Argc;
- WCHAR **Argv = CommandLineToArgvW(Response, &Argc);
- GUID CfgInstanceID;
- if (Argc < 3 || FAILED(CLSIDFromString(Argv[1], &CfgInstanceID)))
- {
- LOG(WINTUN_LOG_ERR, L"Incomplete or invalid response: %s", Response);
- LastError = ERROR_INVALID_PARAMETER;
- goto cleanupArgv;
- }
- LastError = wcstoul(Argv[0], NULL, 16);
- if (LastError == ERROR_SUCCESS && (Adapter = GetAdapter(Pool, &CfgInstanceID)) == NULL)
- {
- LOG(WINTUN_LOG_ERR, L"Failed to get adapter %s", Argv[1]);
- LastError = ERROR_FILE_NOT_FOUND;
- }
- if (wcstoul(Argv[2], NULL, 16))
- *RebootRequired = TRUE;
-cleanupArgv:
- LocalFree(Argv);
- SetLastError(LastError);
- return Adapter;
-}
-
-static _Return_type_success_(return != FALSE) BOOL DeleteAdapterViaRundll32(
- _In_ const WINTUN_ADAPTER *Adapter,
- _In_ BOOL ForceCloseSessions,
- _Inout_ BOOL *RebootRequired)
-{
- LOG(WINTUN_LOG_INFO, L"Spawning native process");
- WCHAR GuidStr[MAX_GUID_STRING_LEN];
- WCHAR Arguments[16 + MAX_GUID_STRING_LEN + 1];
- if (_snwprintf_s(
- Arguments,
- _countof(Arguments),
- _TRUNCATE,
- L"DeleteAdapter %d %.*s",
- ForceCloseSessions ? 1 : 0,
- StringFromGUID2(&Adapter->CfgInstanceID, GuidStr, _countof(GuidStr)),
- GuidStr) == -1)
- {
- LOG(WINTUN_LOG_ERR, L"Command line too long");
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- WCHAR Response[8 + 1 + 8 + 1];
- DWORD LastError;
- if (!ExecuteRunDll32(Arguments, Response, _countof(Response)))
- {
- LOG(WINTUN_LOG_ERR, L"Error executing worker process: %s", Arguments);
- return FALSE;
- }
- int Argc;
- WCHAR **Argv = CommandLineToArgvW(Response, &Argc);
- if (Argc < 2)
- {
- LOG(WINTUN_LOG_ERR, L"Incomplete or invalid response: %s", Response);
- LastError = ERROR_INVALID_PARAMETER;
- goto cleanupArgv;
- }
- LastError = wcstoul(Argv[0], NULL, 16);
- if (wcstoul(Argv[1], NULL, 16))
- *RebootRequired = TRUE;
-cleanupArgv:
- LocalFree(Argv);
- return RET_ERROR(TRUE, LastError);
-}
-
-static _Return_type_success_(return != FALSE) BOOL
- DeletePoolDriverViaRundll32(_In_z_ const WCHAR Pool[WINTUN_MAX_POOL], _Inout_ BOOL *RebootRequired)
-{
- LOG(WINTUN_LOG_INFO, L"Spawning native process");
-
- WCHAR Arguments[17 + WINTUN_MAX_POOL + 1];
- if (_snwprintf_s(Arguments, _countof(Arguments), _TRUNCATE, L"DeletePoolDriver %s", Pool) == -1)
- {
- LOG(WINTUN_LOG_ERR, L"Command line too long");
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- WCHAR Response[8 + 1 + 8 + 1];
- DWORD LastError;
- if (!ExecuteRunDll32(Arguments, Response, _countof(Response)))
- {
- LOG(WINTUN_LOG_ERR, L"Error executing worker process: %s", Arguments);
- return FALSE;
- }
- int Argc;
- WCHAR **Argv = CommandLineToArgvW(Response, &Argc);
- if (Argc < 2)
- {
- LOG(WINTUN_LOG_ERR, L"Incomplete or invalid response: %s", Response);
- LastError = ERROR_INVALID_PARAMETER;
- goto cleanupArgv;
- }
- LastError = wcstoul(Argv[0], NULL, 16);
- if (wcstoul(Argv[1], NULL, 16))
- *RebootRequired = TRUE;
-cleanupArgv:
- LocalFree(Argv);
- return RET_ERROR(TRUE, LastError);
-}
diff --git a/api/session.c b/api/session.c
index ff158a8..d620411 100644
--- a/api/session.c
+++ b/api/session.c
@@ -70,8 +70,10 @@ typedef struct _TUN_SESSION
HANDLE Handle;
} TUN_SESSION;
-_Return_type_success_(return != NULL) TUN_SESSION *WINAPI
- WintunStartSession(_In_ const WINTUN_ADAPTER *Adapter, _In_ DWORD Capacity)
+WINTUN_START_SESSION_FUNC_IMPL WintunStartSession;
+_Use_decl_annotations_
+TUN_SESSION *WINAPI
+WintunStartSession(WINTUN_ADAPTER *Adapter, DWORD Capacity)
{
DWORD LastError;
TUN_SESSION *Session = Zalloc(sizeof(TUN_SESSION));
@@ -126,8 +128,8 @@ _Return_type_success_(return != NULL) TUN_SESSION *WINAPI
goto cleanupHandle;
}
Session->Capacity = Capacity;
- (void)InitializeCriticalSectionAndSpinCount(&Session->Receive.Lock, LOCK_SPIN_COUNT);
- (void)InitializeCriticalSectionAndSpinCount(&Session->Send.Lock, LOCK_SPIN_COUNT);
+ (VOID) InitializeCriticalSectionAndSpinCount(&Session->Receive.Lock, LOCK_SPIN_COUNT);
+ (VOID) InitializeCriticalSectionAndSpinCount(&Session->Send.Lock, LOCK_SPIN_COUNT);
return Session;
cleanupHandle:
CloseHandle(Session->Handle);
@@ -144,8 +146,10 @@ cleanup:
return NULL;
}
-void WINAPI
-WintunEndSession(_In_ TUN_SESSION *Session)
+WINTUN_END_SESSION_FUNC_IMPL WintunEndSession;
+_Use_decl_annotations_
+VOID WINAPI
+WintunEndSession(TUN_SESSION *Session)
{
DeleteCriticalSection(&Session->Send.Lock);
DeleteCriticalSection(&Session->Receive.Lock);
@@ -156,14 +160,18 @@ WintunEndSession(_In_ TUN_SESSION *Session)
Free(Session);
}
+WINTUN_GET_READ_WAIT_EVENT_FUNC_IMPL WintunGetReadWaitEvent;
+_Use_decl_annotations_
HANDLE WINAPI
-WintunGetReadWaitEvent(_In_ TUN_SESSION *Session)
+WintunGetReadWaitEvent(TUN_SESSION *Session)
{
return Session->Descriptor.Send.TailMoved;
}
-_Return_type_success_(return != NULL) _Ret_bytecount_(*PacketSize) BYTE *WINAPI
- WintunReceivePacket(_In_ TUN_SESSION *Session, _Out_ DWORD *PacketSize)
+WINTUN_RECEIVE_PACKET_FUNC_IMPL WintunReceivePacket;
+_Use_decl_annotations_
+BYTE *WINAPI
+WintunReceivePacket(TUN_SESSION *Session, DWORD *PacketSize)
{
DWORD LastError;
EnterCriticalSection(&Session->Send.Lock);
@@ -213,8 +221,10 @@ cleanup:
return NULL;
}
-void WINAPI
-WintunReleaseReceivePacket(_In_ TUN_SESSION *Session, _In_ const BYTE *Packet)
+WINTUN_RELEASE_RECEIVE_PACKET_FUNC_IMPL WintunReleaseReceivePacket;
+_Use_decl_annotations_
+VOID WINAPI
+WintunReleaseReceivePacket(TUN_SESSION *Session, const BYTE *Packet)
{
EnterCriticalSection(&Session->Send.Lock);
TUN_PACKET *ReleasedBuffPacket = (TUN_PACKET *)(Packet - offsetof(TUN_PACKET, Data));
@@ -232,8 +242,10 @@ WintunReleaseReceivePacket(_In_ TUN_SESSION *Session, _In_ const BYTE *Packet)
LeaveCriticalSection(&Session->Send.Lock);
}
-_Return_type_success_(return != NULL) _Ret_bytecount_(PacketSize) BYTE *WINAPI
- WintunAllocateSendPacket(_In_ TUN_SESSION *Session, _In_ DWORD PacketSize)
+WINTUN_ALLOCATE_SEND_PACKET_FUNC_IMPL WintunAllocateSendPacket;
+_Use_decl_annotations_
+BYTE *WINAPI
+WintunAllocateSendPacket(TUN_SESSION *Session, DWORD PacketSize)
{
DWORD LastError;
EnterCriticalSection(&Session->Receive.Lock);
@@ -268,8 +280,10 @@ cleanup:
return NULL;
}
-void WINAPI
-WintunSendPacket(_In_ TUN_SESSION *Session, _In_ const BYTE *Packet)
+WINTUN_SEND_PACKET_FUNC_IMPL WintunSendPacket;
+_Use_decl_annotations_
+VOID WINAPI
+WintunSendPacket(TUN_SESSION *Session, const BYTE *Packet)
{
EnterCriticalSection(&Session->Receive.Lock);
TUN_PACKET *ReleasedBuffPacket = (TUN_PACKET *)(Packet - offsetof(TUN_PACKET, Data));
@@ -285,7 +299,8 @@ WintunSendPacket(_In_ TUN_SESSION *Session, _In_ const BYTE *Packet)
TUN_RING_WRAP(Session->Receive.TailRelease + AlignedPacketSize, Session->Capacity);
Session->Receive.PacketsToRelease--;
}
- if (Session->Descriptor.Receive.Ring->Tail != Session->Receive.TailRelease) {
+ if (Session->Descriptor.Receive.Ring->Tail != Session->Receive.TailRelease)
+ {
WriteULongRelease(&Session->Descriptor.Receive.Ring->Tail, Session->Receive.TailRelease);
if (ReadAcquire(&Session->Descriptor.Receive.Ring->Alertable))
SetEvent(Session->Descriptor.Receive.TailMoved);
diff --git a/api/wintun.h b/api/wintun.h
index 2b03d33..9464a96 100644
--- a/api/wintun.h
+++ b/api/wintun.h
@@ -16,7 +16,7 @@ extern "C" {
/**
* A handle representing Wintun adapter
*/
-typedef void *WINTUN_ADAPTER_HANDLE;
+typedef struct _WINTUN_ADAPTER *WINTUN_ADAPTER_HANDLE;
/**
* Maximum pool name length including zero terminator
@@ -39,13 +39,14 @@ typedef void *WINTUN_ADAPTER_HANDLE;
* @param RebootRequired Optional pointer to a boolean flag to be set to TRUE in case SetupAPI suggests a reboot.
*
* @return If the function succeeds, the return value is the adapter handle. Must be released with WintunFreeAdapter. If
- * the function fails, the return value is NULL. To get extended error information, call GetLastError.
+ * the function fails, the return value is NULL. To get extended error information, call GetLastError.
*/
-typedef _Return_type_success_(return != NULL) WINTUN_ADAPTER_HANDLE(WINAPI *WINTUN_CREATE_ADAPTER_FUNC)(
- _In_z_ const WCHAR *Pool,
- _In_z_ const WCHAR *Name,
- _In_opt_ const GUID *RequestedGUID,
- _Out_opt_ BOOL *RebootRequired);
+typedef _Must_inspect_result_
+_Return_type_success_(return != NULL)
+_Post_maybenull_
+WINTUN_ADAPTER_HANDLE(WINAPI WINTUN_CREATE_ADAPTER_FUNC_IMPL)
+(_In_z_ LPCWSTR Pool, _In_z_ LPCWSTR Name, _In_opt_ const GUID *RequestedGUID, _Out_opt_ BOOL *RebootRequired);
+typedef WINTUN_CREATE_ADAPTER_FUNC_IMPL *WINTUN_CREATE_ADAPTER_FUNC;
/**
* Opens an existing Wintun adapter.
@@ -55,14 +56,15 @@ typedef _Return_type_success_(return != NULL) WINTUN_ADAPTER_HANDLE(WINAPI *WINT
* @param Name Adapter name. Zero-terminated string of up to MAX_ADAPTER_NAME-1 characters.
*
* @return If the function succeeds, the return value is adapter handle. Must be released with WintunFreeAdapter. If the
- * function fails, the return value is NULL. To get extended error information, call GetLastError. Possible
- * errors include the following:
- * ERROR_FILE_NOT_FOUND if adapter with given name is not found;
- * ERROR_ALREADY_EXISTS if adapter is found but not a Wintun-class or not a member of the pool
+ * function fails, the return value is NULL. To get extended error information, call GetLastError. Possible errors
+ * include the following: ERROR_FILE_NOT_FOUND if adapter with given name is not found; ERROR_ALREADY_EXISTS if adapter
+ * is found but not a Wintun-class or not a member of the pool
*/
-typedef _Return_type_success_(return != NULL)
- WINTUN_ADAPTER_HANDLE(WINAPI *WINTUN_OPEN_ADAPTER_FUNC)(_In_z_ const WCHAR *Pool, _In_z_ const WCHAR *Name);
-
+typedef _Must_inspect_result_
+_Return_type_success_(return != NULL)
+_Post_maybenull_
+WINTUN_ADAPTER_HANDLE(WINAPI WINTUN_OPEN_ADAPTER_FUNC_IMPL)(_In_z_ LPCWSTR Pool, _In_z_ LPCWSTR Name);
+typedef WINTUN_OPEN_ADAPTER_FUNC_IMPL *WINTUN_OPEN_ADAPTER_FUNC;
/**
* Deletes a Wintun adapter.
@@ -78,10 +80,10 @@ typedef _Return_type_success_(return != NULL)
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
* get extended error information, call GetLastError.
*/
-typedef _Return_type_success_(return != FALSE) BOOL(WINAPI *WINTUN_DELETE_ADAPTER_FUNC)(
- _In_ WINTUN_ADAPTER_HANDLE Adapter,
- _In_ BOOL ForceCloseSessions,
- _Out_opt_ BOOL *RebootRequired);
+typedef _Return_type_success_(return != FALSE)
+BOOL(WINAPI WINTUN_DELETE_ADAPTER_FUNC_IMPL)
+(_In_ WINTUN_ADAPTER_HANDLE Adapter, _In_ BOOL ForceCloseSessions, _Out_opt_ BOOL *RebootRequired);
+typedef WINTUN_DELETE_ADAPTER_FUNC_IMPL *WINTUN_DELETE_ADAPTER_FUNC;
/**
* Called by WintunEnumAdapters for each adapter in the pool.
@@ -107,15 +109,17 @@ typedef BOOL(CALLBACK *WINTUN_ENUM_CALLBACK)(_In_ WINTUN_ADAPTER_HANDLE Adapter,
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
* get extended error information, call GetLastError.
*/
-typedef _Return_type_success_(return != FALSE) BOOL(
- WINAPI *WINTUN_ENUM_ADAPTERS_FUNC)(_In_z_ const WCHAR *Pool, _In_ WINTUN_ENUM_CALLBACK Callback, _In_ LPARAM Param);
+typedef _Return_type_success_(return != FALSE)
+BOOL(WINAPI WINTUN_ENUM_ADAPTERS_FUNC_IMPL)(_In_z_ LPCWSTR Pool, _In_ WINTUN_ENUM_CALLBACK Callback, _In_ LPARAM Param);
+typedef WINTUN_ENUM_ADAPTERS_FUNC_IMPL *WINTUN_ENUM_ADAPTERS_FUNC;
/**
* Releases Wintun adapter resources.
*
* @param Adapter Adapter handle obtained with WintunOpenAdapter or WintunCreateAdapter.
*/
-typedef void(WINAPI *WINTUN_FREE_ADAPTER_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Adapter);
+typedef VOID(WINAPI WINTUN_FREE_ADAPTER_FUNC_IMPL)(_In_ WINTUN_ADAPTER_HANDLE Adapter);
+typedef WINTUN_FREE_ADAPTER_FUNC_IMPL *WINTUN_FREE_ADAPTER_FUNC;
/**
* Deletes all Wintun adapters in a pool and if there are no more adapters in any other pools, also removes Wintun
@@ -129,7 +133,8 @@ typedef void(WINAPI *WINTUN_FREE_ADAPTER_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Adapte
* get extended error information, call GetLastError.
*/
typedef _Return_type_success_(return != FALSE)
- BOOL(WINAPI *WINTUN_DELETE_POOL_DRIVER_FUNC)(_In_z_ const WCHAR *Pool, _Out_opt_ BOOL *RebootRequired);
+BOOL(WINAPI WINTUN_DELETE_POOL_DRIVER_FUNC_IMPL)(_In_z_ LPCWSTR Pool, _Out_opt_ BOOL *RebootRequired);
+typedef WINTUN_DELETE_POOL_DRIVER_FUNC_IMPL *WINTUN_DELETE_POOL_DRIVER_FUNC;
/**
* Returns the LUID of the adapter.
@@ -138,7 +143,8 @@ typedef _Return_type_success_(return != FALSE)
*
* @param Luid Pointer to LUID to receive adapter LUID.
*/
-typedef void(WINAPI *WINTUN_GET_ADAPTER_LUID_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Adapter, _Out_ NET_LUID *Luid);
+typedef VOID(WINAPI WINTUN_GET_ADAPTER_LUID_FUNC_IMPL)(_In_ WINTUN_ADAPTER_HANDLE Adapter, _Out_ NET_LUID *Luid);
+typedef WINTUN_GET_ADAPTER_LUID_FUNC_IMPL *WINTUN_GET_ADAPTER_LUID_FUNC;
/**
* Returns the name of the Wintun adapter.
@@ -150,9 +156,11 @@ typedef void(WINAPI *WINTUN_GET_ADAPTER_LUID_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Ad
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
* get extended error information, call GetLastError.
*/
-typedef _Return_type_success_(return != FALSE) BOOL(WINAPI *WINTUN_GET_ADAPTER_NAME_FUNC)(
- _In_ WINTUN_ADAPTER_HANDLE Adapter,
- _Out_cap_c_(MAX_ADAPTER_NAME) WCHAR *Name);
+typedef _Must_inspect_result_
+_Return_type_success_(return != FALSE)
+BOOL(WINAPI WINTUN_GET_ADAPTER_NAME_FUNC_IMPL)
+(_In_ WINTUN_ADAPTER_HANDLE Adapter, _Out_writes_z_(MAX_ADAPTER_NAME) LPWSTR Name);
+typedef WINTUN_GET_ADAPTER_NAME_FUNC_IMPL *WINTUN_GET_ADAPTER_NAME_FUNC;
/**
* Sets name of the Wintun adapter.
@@ -165,7 +173,8 @@ typedef _Return_type_success_(return != FALSE) BOOL(WINAPI *WINTUN_GET_ADAPTER_N
* get extended error information, call GetLastError.
*/
typedef _Return_type_success_(return != FALSE)
- BOOL(WINAPI *WINTUN_SET_ADAPTER_NAME_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Adapter, _In_z_ const WCHAR *Name);
+BOOL(WINAPI WINTUN_SET_ADAPTER_NAME_FUNC_IMPL)(_In_ WINTUN_ADAPTER_HANDLE Adapter, _In_z_ LPCWSTR Name);
+typedef WINTUN_SET_ADAPTER_NAME_FUNC_IMPL *WINTUN_SET_ADAPTER_NAME_FUNC;
/**
* Determines the version of the Wintun driver currently loaded.
@@ -174,7 +183,9 @@ typedef _Return_type_success_(return != FALSE)
* zero. To get extended error information, call GetLastError. Possible errors include the following:
* ERROR_FILE_NOT_FOUND Wintun not loaded
*/
-typedef DWORD(WINAPI *WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC)(void);
+typedef _Return_type_success_(return != 0)
+DWORD(WINAPI WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC_IMPL)(VOID);
+typedef WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC_IMPL *WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC;
/**
* Determines the level of logging, passed to WINTUN_LOGGER_CALLBACK.
@@ -193,7 +204,7 @@ typedef enum
*
* @param Message Message text.
*/
-typedef void(CALLBACK *WINTUN_LOGGER_CALLBACK)(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ const WCHAR *Message);
+typedef VOID(CALLBACK *WINTUN_LOGGER_CALLBACK)(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ LPCWSTR Message);
/**
* Sets logger callback function.
@@ -202,7 +213,8 @@ typedef void(CALLBACK *WINTUN_LOGGER_CALLBACK)(_In_ WINTUN_LOGGER_LEVEL Level, _
* threads concurrently. Should the logging require serialization, you must handle serialization in
* NewLogger. Set to NULL to disable.
*/
-typedef void(WINAPI *WINTUN_SET_LOGGER_FUNC)(_In_ WINTUN_LOGGER_CALLBACK NewLogger);
+typedef VOID(WINAPI WINTUN_SET_LOGGER_FUNC_IMPL)(_In_ WINTUN_LOGGER_CALLBACK NewLogger);
+typedef WINTUN_SET_LOGGER_FUNC_IMPL *WINTUN_SET_LOGGER_FUNC;
/**
* Minimum ring capacity.
@@ -217,7 +229,7 @@ typedef void(WINAPI *WINTUN_SET_LOGGER_FUNC)(_In_ WINTUN_LOGGER_CALLBACK NewLogg
/**
* A handle representing Wintun session
*/
-typedef void *WINTUN_SESSION_HANDLE;
+typedef struct _TUN_SESSION *WINTUN_SESSION_HANDLE;
/**
* Starts Wintun session.
@@ -230,15 +242,19 @@ typedef void *WINTUN_SESSION_HANDLE;
* @return Wintun session handle. Must be released with WintunEndSession. If the function fails, the return value is
* NULL. To get extended error information, call GetLastError.
*/
-typedef _Return_type_success_(return != NULL)
- WINTUN_SESSION_HANDLE(WINAPI *WINTUN_START_SESSION_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Adapter, _In_ DWORD Capacity);
+typedef _Must_inspect_result_
+_Return_type_success_(return != NULL)
+_Post_maybenull_
+WINTUN_SESSION_HANDLE(WINAPI WINTUN_START_SESSION_FUNC_IMPL)(_In_ WINTUN_ADAPTER_HANDLE Adapter, _In_ DWORD Capacity);
+typedef WINTUN_START_SESSION_FUNC_IMPL *WINTUN_START_SESSION_FUNC;
/**
* Ends Wintun session.
*
* @param Session Wintun session handle obtained with WintunStartSession
*/
-typedef void(WINAPI *WINTUN_END_SESSION_FUNC)(_In_ WINTUN_SESSION_HANDLE Session);
+typedef VOID(WINAPI WINTUN_END_SESSION_FUNC_IMPL)(_In_ WINTUN_SESSION_HANDLE Session);
+typedef WINTUN_END_SESSION_FUNC_IMPL *WINTUN_END_SESSION_FUNC;
/**
* Gets Wintun session's read-wait event handle.
@@ -250,7 +266,8 @@ typedef void(WINAPI *WINTUN_END_SESSION_FUNC)(_In_ WINTUN_SESSION_HANDLE Session
* load), wait for this event to become signaled before retrying WintunReceivePackets. Do not call
* CloseHandle on this event - it is managed by the session.
*/
-typedef HANDLE(WINAPI *WINTUN_GET_READ_WAIT_EVENT_FUNC)(_In_ WINTUN_SESSION_HANDLE Session);
+typedef HANDLE(WINAPI WINTUN_GET_READ_WAIT_EVENT_FUNC_IMPL)(_In_ WINTUN_SESSION_HANDLE Session);
+typedef WINTUN_GET_READ_WAIT_EVENT_FUNC_IMPL *WINTUN_GET_READ_WAIT_EVENT_FUNC;
/**
* Maximum IP packet size
@@ -272,8 +289,12 @@ typedef HANDLE(WINAPI *WINTUN_GET_READ_WAIT_EVENT_FUNC)(_In_ WINTUN_SESSION_HAND
* ERROR_NO_MORE_ITEMS Wintun buffer is exhausted;
* ERROR_INVALID_DATA Wintun buffer is corrupt
*/
-typedef _Return_type_success_(return != NULL) _Ret_bytecount_(*PacketSize) BYTE *(
- WINAPI *WINTUN_RECEIVE_PACKET_FUNC)(_In_ WINTUN_SESSION_HANDLE Session, _Out_ DWORD *PacketSize);
+typedef _Must_inspect_result_
+_Return_type_success_(return != NULL)
+_Post_maybenull_
+_Post_writable_byte_size_(*PacketSize)
+BYTE *(WINAPI WINTUN_RECEIVE_PACKET_FUNC_IMPL)(_In_ WINTUN_SESSION_HANDLE Session, _Out_ DWORD *PacketSize);
+typedef WINTUN_RECEIVE_PACKET_FUNC_IMPL *WINTUN_RECEIVE_PACKET_FUNC;
/**
* Releases internal buffer after the received packet has been processed by the client. This function is thread-safe.
@@ -282,7 +303,9 @@ typedef _Return_type_success_(return != NULL) _Ret_bytecount_(*PacketSize) BYTE
*
* @param Packet Packet obtained with WintunReceivePacket
*/
-typedef void(WINAPI *WINTUN_RELEASE_RECEIVE_PACKET_FUNC)(_In_ WINTUN_SESSION_HANDLE Session, _In_ const BYTE *Packet);
+typedef VOID(
+ WINAPI WINTUN_RELEASE_RECEIVE_PACKET_FUNC_IMPL)(_In_ WINTUN_SESSION_HANDLE Session, _In_ const BYTE *Packet);
+typedef WINTUN_RELEASE_RECEIVE_PACKET_FUNC_IMPL *WINTUN_RELEASE_RECEIVE_PACKET_FUNC;
/**
* Allocates memory for a packet to send. After the memory is filled with packet data, call WintunSendPacket to send
@@ -299,8 +322,12 @@ typedef void(WINAPI *WINTUN_RELEASE_RECEIVE_PACKET_FUNC)(_In_ WINTUN_SESSION_HAN
* ERROR_HANDLE_EOF Wintun adapter is terminating;
* ERROR_BUFFER_OVERFLOW Wintun buffer is full;
*/
-typedef _Return_type_success_(return != NULL) _Ret_bytecount_(PacketSize) BYTE *(
- WINAPI *WINTUN_ALLOCATE_SEND_PACKET_FUNC)(_In_ WINTUN_SESSION_HANDLE Session, _In_ DWORD PacketSize);
+typedef _Must_inspect_result_
+_Return_type_success_(return != NULL)
+_Post_maybenull_
+_Post_writable_byte_size_(PacketSize)
+BYTE *(WINAPI WINTUN_ALLOCATE_SEND_PACKET_FUNC_IMPL)(_In_ WINTUN_SESSION_HANDLE Session, _In_ DWORD PacketSize);
+typedef WINTUN_ALLOCATE_SEND_PACKET_FUNC_IMPL *WINTUN_ALLOCATE_SEND_PACKET_FUNC;
/**
* Sends the packet and releases internal buffer. WintunSendPacket is thread-safe, but the WintunAllocateSendPacket
@@ -311,7 +338,8 @@ typedef _Return_type_success_(return != NULL) _Ret_bytecount_(PacketSize) BYTE *
*
* @param Packet Packet obtained with WintunAllocateSendPacket
*/
-typedef void(WINAPI *WINTUN_SEND_PACKET_FUNC)(_In_ WINTUN_SESSION_HANDLE Session, _In_ const BYTE *Packet);
+typedef VOID(WINAPI WINTUN_SEND_PACKET_FUNC_IMPL)(_In_ WINTUN_SESSION_HANDLE Session, _In_ const BYTE *Packet);
+typedef WINTUN_SEND_PACKET_FUNC_IMPL *WINTUN_SEND_PACKET_FUNC;
#ifdef __cplusplus
}