aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rozman <simon@rozman.si>2020-11-03 12:29:34 +0100
committerSimon Rozman <simon@rozman.si>2020-11-04 13:21:42 +0100
commitf657e6fd278732d054b064bb4836702d06e176f0 (patch)
tree3f113195349908e0390b1abc8f315619df4d598e
parentexample: account for adapter reuse (diff)
downloadwintun-f657e6fd278732d054b064bb4836702d06e176f0.tar.xz
wintun-f657e6fd278732d054b064bb4836702d06e176f0.zip
api: use GetLastError() to report failures like standard Win32
Signed-off-by: Simon Rozman <simon@rozman.si>
-rw-r--r--api/adapter.c1179
-rw-r--r--api/adapter.h18
-rw-r--r--api/elevate.c73
-rw-r--r--api/elevate.h6
-rw-r--r--api/entry.c5
-rw-r--r--api/entry.h2
-rw-r--r--api/logger.h19
-rw-r--r--api/namespace.c123
-rw-r--r--api/namespace.h8
-rw-r--r--api/registry.c248
-rw-r--r--api/registry.h65
-rw-r--r--api/resource.c60
-rw-r--r--api/resource.h16
-rw-r--r--api/rundll32.c38
-rw-r--r--api/rundll32.h133
-rw-r--r--api/session.c123
-rw-r--r--api/wintun.h131
-rw-r--r--example/example.c87
18 files changed, 1317 insertions, 1017 deletions
diff --git a/api/adapter.c b/api/adapter.c
index d87ed56..24626e8 100644
--- a/api/adapter.c
+++ b/api/adapter.c
@@ -53,110 +53,110 @@ typedef struct _SP_DEVINFO_DATA_LIST
static USHORT NativeMachine = IMAGE_FILE_PROCESS;
-static WINTUN_STATUS
-GetAdapterDrvInfoDetail(
+static _Return_type_success_(return != NULL) SP_DRVINFO_DETAIL_DATA_W *GetAdapterDrvInfoDetail(
_In_ HDEVINFO DevInfo,
_In_opt_ SP_DEVINFO_DATA *DevInfoData,
- _In_ SP_DRVINFO_DATA_W *DrvInfoData,
- _Out_ SP_DRVINFO_DETAIL_DATA_W **DrvInfoDetailData)
+ _In_ SP_DRVINFO_DATA_W *DrvInfoData)
{
DWORD Size = sizeof(SP_DRVINFO_DETAIL_DATA_W) + 0x100;
for (;;)
{
- SP_DRVINFO_DETAIL_DATA_W *p = HeapAlloc(ModuleHeap, 0, Size);
- if (!p)
- return LOG(WINTUN_LOG_ERR, L"Out of memory"), ERROR_OUTOFMEMORY;
- p->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W);
- if (SetupDiGetDriverInfoDetailW(DevInfo, DevInfoData, DrvInfoData, p, Size, &Size))
+ SP_DRVINFO_DETAIL_DATA_W *DrvInfoDetailData = HeapAlloc(ModuleHeap, 0, Size);
+ if (!DrvInfoDetailData)
{
- *DrvInfoDetailData = p;
- return ERROR_SUCCESS;
+ LOG(WINTUN_LOG_ERR, L"Out of memory");
+ SetLastError(ERROR_OUTOFMEMORY);
+ return NULL;
+ }
+ DrvInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W);
+ if (SetupDiGetDriverInfoDetailW(DevInfo, DevInfoData, DrvInfoData, DrvInfoDetailData, Size, &Size))
+ return DrvInfoDetailData;
+ DWORD LastError = GetLastError();
+ HeapFree(ModuleHeap, 0, DrvInfoDetailData);
+ if (LastError != ERROR_INSUFFICIENT_BUFFER)
+ {
+ SetLastError(LOG_ERROR(L"Failed", LastError));
+ return NULL;
}
- DWORD Result = GetLastError();
- HeapFree(ModuleHeap, 0, p);
- if (Result != ERROR_INSUFFICIENT_BUFFER)
- return LOG_ERROR(L"Failed", Result);
}
}
-static WINTUN_STATUS
-GetDeviceRegistryProperty(
+static _Return_type_success_(return != NULL) void *GetDeviceRegistryProperty(
_In_ HDEVINFO DevInfo,
_In_ SP_DEVINFO_DATA *DevInfoData,
_In_ DWORD Property,
_Out_opt_ DWORD *ValueType,
- _Out_ void **Buf,
_Inout_ DWORD *BufLen)
{
for (;;)
{
- BYTE *p = HeapAlloc(ModuleHeap, 0, *BufLen);
- if (!p)
- return LOG(WINTUN_LOG_ERR, L"Out of memory"), ERROR_OUTOFMEMORY;
- if (SetupDiGetDeviceRegistryPropertyW(DevInfo, DevInfoData, Property, ValueType, p, *BufLen, BufLen))
+ BYTE *Data = HeapAlloc(ModuleHeap, 0, *BufLen);
+ if (!Data)
+ {
+ LOG(WINTUN_LOG_ERR, L"Out of memory");
+ SetLastError(ERROR_OUTOFMEMORY);
+ return NULL;
+ }
+ if (SetupDiGetDeviceRegistryPropertyW(DevInfo, DevInfoData, Property, ValueType, Data, *BufLen, BufLen))
+ return Data;
+ DWORD LastError = GetLastError();
+ HeapFree(ModuleHeap, 0, Data);
+ if (LastError != ERROR_INSUFFICIENT_BUFFER)
{
- *Buf = p;
- return ERROR_SUCCESS;
+ SetLastError(LOG_ERROR(L"Querying property failed", LastError));
+ return NULL;
}
- DWORD Result = GetLastError();
- HeapFree(ModuleHeap, 0, p);
- if (Result != ERROR_INSUFFICIENT_BUFFER)
- return LOG_ERROR(L"Querying property failed", Result);
}
}
-static WINTUN_STATUS
-GetDeviceRegistryString(
- _In_ HDEVINFO DevInfo,
- _In_ SP_DEVINFO_DATA *DevInfoData,
- _In_ DWORD Property,
- _Out_ WCHAR **Buf)
+static _Return_type_success_(return != NULL)
+ WCHAR *GetDeviceRegistryString(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData, _In_ DWORD Property)
{
- DWORD Result, ValueType, Size = 256 * sizeof(WCHAR);
- Result = GetDeviceRegistryProperty(DevInfo, DevInfoData, Property, &ValueType, Buf, &Size);
- if (Result != ERROR_SUCCESS)
- return Result;
+ DWORD LastError, ValueType, Size = 256 * sizeof(WCHAR);
+ WCHAR *Buf = GetDeviceRegistryProperty(DevInfo, DevInfoData, Property, &ValueType, &Size);
+ if (!Buf)
+ return NULL;
switch (ValueType)
{
case REG_SZ:
case REG_EXPAND_SZ:
case REG_MULTI_SZ:
- Result = RegistryGetString(Buf, Size / sizeof(WCHAR), ValueType);
- if (Result != ERROR_SUCCESS)
- HeapFree(ModuleHeap, 0, *Buf);
- return Result;
+ if (RegistryGetString(&Buf, Size / sizeof(WCHAR), ValueType))
+ return Buf;
+ LastError = GetLastError();
+ break;
default:
LOG(WINTUN_LOG_ERR, L"Property is not a string");
- HeapFree(ModuleHeap, 0, *Buf);
- return ERROR_INVALID_DATATYPE;
+ LastError = ERROR_INVALID_DATATYPE;
}
+ HeapFree(ModuleHeap, 0, Buf);
+ SetLastError(LastError);
+ return NULL;
}
-static WINTUN_STATUS
-GetDeviceRegistryMultiString(
- _In_ HDEVINFO DevInfo,
- _In_ SP_DEVINFO_DATA *DevInfoData,
- _In_ DWORD Property,
- _Out_ WCHAR **Buf)
+static _Return_type_success_(return != NULL)
+ WCHAR *GetDeviceRegistryMultiString(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData, _In_ DWORD Property)
{
- DWORD Result, ValueType, Size = 256 * sizeof(WCHAR);
- Result = GetDeviceRegistryProperty(DevInfo, DevInfoData, Property, &ValueType, Buf, &Size);
- if (Result != ERROR_SUCCESS)
- return Result;
+ DWORD LastError, ValueType, Size = 256 * sizeof(WCHAR);
+ WCHAR *Buf = GetDeviceRegistryProperty(DevInfo, DevInfoData, Property, &ValueType, &Size);
+ if (!Buf)
+ return NULL;
switch (ValueType)
{
case REG_SZ:
case REG_EXPAND_SZ:
case REG_MULTI_SZ:
- Result = RegistryGetMultiString(Buf, Size / sizeof(WCHAR), ValueType);
- if (Result != ERROR_SUCCESS)
- HeapFree(ModuleHeap, 0, *Buf);
- return Result;
+ if (RegistryGetMultiString(&Buf, Size / sizeof(WCHAR), ValueType))
+ return Buf;
+ LastError = GetLastError();
+ break;
default:
LOG(WINTUN_LOG_ERR, L"Property is not a string");
- HeapFree(ModuleHeap, 0, *Buf);
- return ERROR_INVALID_DATATYPE;
+ LastError = ERROR_INVALID_DATATYPE;
}
+ HeapFree(ModuleHeap, 0, Buf);
+ SetLastError(LastError);
+ return NULL;
}
static BOOL
@@ -168,34 +168,44 @@ IsOurHardwareID(_In_z_ const WCHAR *Hwids)
return FALSE;
}
-static WINTUN_STATUS
-IsOurAdapter(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData, _Out_ BOOL *IsOurs)
+static BOOL
+IsOurAdapter(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData)
{
- WCHAR *Hwids;
- DWORD Result = GetDeviceRegistryMultiString(DevInfo, DevInfoData, SPDRP_HARDWAREID, &Hwids);
- if (Result != ERROR_SUCCESS)
- return LOG(WINTUN_LOG_ERR, L"Failed to get hardware ID"), Result;
- *IsOurs = IsOurHardwareID(Hwids);
- return ERROR_SUCCESS;
+ WCHAR *Hwids = GetDeviceRegistryMultiString(DevInfo, DevInfoData, SPDRP_HARDWAREID);
+ if (!Hwids)
+ {
+ LOG_LAST_ERROR(L"Failed to get hardware ID");
+ return FALSE;
+ }
+ BOOL IsOurs = IsOurHardwareID(Hwids);
+ HeapFree(ModuleHeap, 0, Hwids);
+ return IsOurs;
}
-static WINTUN_STATUS
-GetDeviceObject(_In_opt_z_ const WCHAR *InstanceId, _Out_ HANDLE *Handle)
+static _Return_type_success_(return != INVALID_HANDLE_VALUE) HANDLE OpenDeviceObject(_In_opt_z_ const WCHAR *InstanceId)
{
ULONG InterfacesLen;
- DWORD Result = CM_MapCrToWin32Err(
+ DWORD LastError = CM_MapCrToWin32Err(
CM_Get_Device_Interface_List_SizeW(
&InterfacesLen,
(GUID *)&GUID_DEVINTERFACE_NET,
(DEVINSTID_W)InstanceId,
CM_GET_DEVICE_INTERFACE_LIST_PRESENT),
ERROR_GEN_FAILURE);
- if (Result != ERROR_SUCCESS)
- return LOG_ERROR(L"Failed to query associated instances size", Result);
+ if (LastError != ERROR_SUCCESS)
+ {
+ SetLastError(LOG_ERROR(L"Failed to query associated instances size", LastError));
+ return INVALID_HANDLE_VALUE;
+ }
WCHAR *Interfaces = HeapAlloc(ModuleHeap, 0, InterfacesLen * sizeof(WCHAR));
if (!Interfaces)
- return LOG(WINTUN_LOG_ERR, L"Out of memory"), ERROR_OUTOFMEMORY;
- Result = CM_MapCrToWin32Err(
+ {
+ LOG(WINTUN_LOG_ERR, L"Out of memory");
+ SetLastError(ERROR_OUTOFMEMORY);
+ return INVALID_HANDLE_VALUE;
+ }
+ HANDLE Handle = INVALID_HANDLE_VALUE;
+ LastError = CM_MapCrToWin32Err(
CM_Get_Device_Interface_ListW(
(GUID *)&GUID_DEVINTERFACE_NET,
(DEVINSTID_W)InstanceId,
@@ -203,12 +213,12 @@ GetDeviceObject(_In_opt_z_ const WCHAR *InstanceId, _Out_ HANDLE *Handle)
InterfacesLen,
CM_GET_DEVICE_INTERFACE_LIST_PRESENT),
ERROR_GEN_FAILURE);
- if (Result != ERROR_SUCCESS)
+ if (LastError != ERROR_SUCCESS)
{
- LOG_ERROR(L"Failed to get associated instances", Result);
+ LOG_ERROR(L"Failed to get associated instances", LastError);
goto cleanupBuf;
}
- *Handle = CreateFileW(
+ Handle = CreateFileW(
Interfaces,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
@@ -216,65 +226,77 @@ GetDeviceObject(_In_opt_z_ const WCHAR *InstanceId, _Out_ HANDLE *Handle)
OPEN_EXISTING,
0,
NULL);
- Result = *Handle != INVALID_HANDLE_VALUE ? ERROR_SUCCESS : LOG_LAST_ERROR(L"Failed to connect to adapter");
+ LastError = Handle != INVALID_HANDLE_VALUE ? ERROR_SUCCESS : LOG_LAST_ERROR(L"Failed to connect to adapter");
cleanupBuf:
HeapFree(ModuleHeap, 0, Interfaces);
- return Result;
+ if (LastError != ERROR_SUCCESS)
+ SetLastError(LastError);
+ return Handle;
}
#define TUN_IOCTL_FORCE_CLOSE_HANDLES CTL_CODE(51820U, 0x971U, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA)
-static WINTUN_STATUS
-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 Result = ERROR_SUCCESS;
+ DWORD LastError = ERROR_SUCCESS;
DWORD RequiredBytes;
if (SetupDiGetDeviceInstanceIdW(DevInfo, DevInfoData, NULL, 0, &RequiredBytes) ||
- (Result = GetLastError()) != ERROR_INSUFFICIENT_BUFFER)
- return LOG_ERROR(L"Failed to query instance ID size", Result);
+ (LastError = GetLastError()) != ERROR_INSUFFICIENT_BUFFER)
+ {
+ LOG_ERROR(L"Failed to query instance ID size", LastError);
+ return FALSE;
+ }
WCHAR *InstanceId = HeapAlloc(ModuleHeap, HEAP_ZERO_MEMORY, sizeof(*InstanceId) * RequiredBytes);
if (!InstanceId)
- return LOG(WINTUN_LOG_ERR, L"Out of memory"), ERROR_OUTOFMEMORY;
+ {
+ LOG(WINTUN_LOG_ERR, L"Out of memory");
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
if (!SetupDiGetDeviceInstanceIdW(DevInfo, DevInfoData, InstanceId, RequiredBytes, &RequiredBytes))
{
- Result = LOG_LAST_ERROR(L"Failed to get instance ID");
- goto out;
+ LastError = LOG_LAST_ERROR(L"Failed to get instance ID");
+ goto cleanupInstanceId;
}
- HANDLE NdisHandle;
- Result = GetDeviceObject(InstanceId, &NdisHandle);
- if (Result != ERROR_SUCCESS)
+ HANDLE NdisHandle = OpenDeviceObject(InstanceId);
+ if (NdisHandle == INVALID_HANDLE_VALUE)
{
- LOG(WINTUN_LOG_ERR, L"Failed to get adapter object");
- goto out;
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to get adapter object");
+ goto cleanupInstanceId;
}
if (DeviceIoControl(NdisHandle, TUN_IOCTL_FORCE_CLOSE_HANDLES, NULL, 0, NULL, 0, &RequiredBytes, NULL))
{
- Result = ERROR_SUCCESS;
+ LastError = ERROR_SUCCESS;
Sleep(200);
}
else if (GetLastError() == ERROR_NOTHING_TO_TERMINATE)
- Result = ERROR_SUCCESS;
+ LastError = ERROR_SUCCESS;
else
- Result = LOG_LAST_ERROR(L"Failed to perform ioctl");
+ LastError = LOG_LAST_ERROR(L"Failed to perform ioctl");
CloseHandle(NdisHandle);
-out:
+cleanupInstanceId:
HeapFree(ModuleHeap, 0, InstanceId);
- return Result;
+ return RET_ERROR(TRUE, LastError);
}
-static WINTUN_STATUS
-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 },
.StateChange = DICS_DISABLE,
.Scope = DICS_FLAG_GLOBAL };
- DWORD Result = ERROR_SUCCESS;
+ DWORD LastError = ERROR_SUCCESS;
for (DWORD EnumIndex = 0;; ++EnumIndex)
{
SP_DEVINFO_DATA_LIST *DeviceNode = HeapAlloc(ModuleHeap, 0, sizeof(SP_DEVINFO_DATA_LIST));
if (!DeviceNode)
- return LOG(WINTUN_LOG_ERR, L"Out of memory"), ERROR_OUTOFMEMORY;
+ {
+ LOG(WINTUN_LOG_ERR, L"Out of memory");
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
DeviceNode->Data.cbSize = sizeof(SP_DEVINFO_DATA);
if (!SetupDiEnumDeviceInfo(DevInfo, EnumIndex, &DeviceNode->Data))
{
@@ -285,8 +307,7 @@ DisableAllOurAdapters(_In_ HDEVINFO DevInfo, _Inout_ SP_DEVINFO_DATA_LIST **Disa
}
goto cleanupDeviceNode;
}
- BOOL IsOurs;
- if (IsOurAdapter(DevInfo, &DeviceNode->Data, &IsOurs) != ERROR_SUCCESS || !IsOurs)
+ if (!IsOurAdapter(DevInfo, &DeviceNode->Data))
goto cleanupDeviceNode;
ULONG Status, ProblemCode;
@@ -295,7 +316,7 @@ DisableAllOurAdapters(_In_ HDEVINFO DevInfo, _Inout_ SP_DEVINFO_DATA_LIST **Disa
goto cleanupDeviceNode;
LOG(WINTUN_LOG_INFO, L"Force closing all open handles for existing adapter");
- if (ForceCloseWintunAdapterHandle(DevInfo, &DeviceNode->Data) != ERROR_SUCCESS)
+ if (!ForceCloseWintunAdapterHandle(DevInfo, &DeviceNode->Data))
LOG(WINTUN_LOG_WARN, L"Failed to force close adapter handles");
LOG(WINTUN_LOG_INFO, L"Disabling existing adapter");
@@ -303,7 +324,7 @@ DisableAllOurAdapters(_In_ HDEVINFO DevInfo, _Inout_ SP_DEVINFO_DATA_LIST **Disa
!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, DevInfo, &DeviceNode->Data))
{
LOG_LAST_ERROR(L"Failed to disable existing adapter");
- Result = Result != ERROR_SUCCESS ? Result : GetLastError();
+ LastError = LastError != ERROR_SUCCESS ? LastError : GetLastError();
goto cleanupDeviceNode;
}
@@ -314,17 +335,17 @@ DisableAllOurAdapters(_In_ HDEVINFO DevInfo, _Inout_ SP_DEVINFO_DATA_LIST **Disa
cleanupDeviceNode:
HeapFree(ModuleHeap, 0, DeviceNode);
}
- return Result;
+ return RET_ERROR(TRUE, LastError);
}
-static WINTUN_STATUS
-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 },
.StateChange = DICS_ENABLE,
.Scope = DICS_FLAG_GLOBAL };
- DWORD Result = ERROR_SUCCESS;
+ DWORD LastError = ERROR_SUCCESS;
for (SP_DEVINFO_DATA_LIST *DeviceNode = AdaptersToEnable; DeviceNode; DeviceNode = DeviceNode->Next)
{
LOG(WINTUN_LOG_INFO, L"Enabling existing adapter");
@@ -332,10 +353,10 @@ EnableAllOurAdapters(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA_LIST *AdaptersT
!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, DevInfo, &DeviceNode->Data))
{
LOG_LAST_ERROR(L"Failed to enable existing adapter");
- Result = Result != ERROR_SUCCESS ? Result : GetLastError();
+ LastError = LastError != ERROR_SUCCESS ? LastError : GetLastError();
}
}
- return Result;
+ return RET_ERROR(TRUE, LastError);
}
void
@@ -367,53 +388,64 @@ CheckReboot(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData)
LOG_LAST_ERROR(L"Retrieving device installation parameters failed");
return FALSE;
}
+ SetLastError(ERROR_SUCCESS);
return (DevInstallParams.Flags & (DI_NEEDREBOOT | DI_NEEDRESTART)) != 0;
}
-static WINTUN_STATUS
-SetQuietInstall(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData)
+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))
- return LOG_LAST_ERROR(L"Retrieving device installation parameters failed");
+ {
+ LOG_LAST_ERROR(L"Retrieving device installation parameters failed");
+ return FALSE;
+ }
DevInstallParams.Flags |= DI_QUIETINSTALL;
if (!SetupDiSetDeviceInstallParamsW(DevInfo, DevInfoData, &DevInstallParams))
- return LOG_LAST_ERROR(L"Setting device installation parameters failed");
- return ERROR_SUCCESS;
+ {
+ LOG_LAST_ERROR(L"Setting device installation parameters failed");
+ return FALSE;
+ }
+ return TRUE;
}
-static WINTUN_STATUS
-GetNetCfgInstanceId(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData, _Out_ GUID *CfgInstanceID)
+static _Return_type_success_(return != FALSE) BOOL
+ GetNetCfgInstanceId(_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)
- return LOG_LAST_ERROR(L"Opening device registry key failed");
- WCHAR *ValueStr;
- DWORD Result = RegistryQueryString(Key, L"NetCfgInstanceId", &ValueStr, TRUE);
- if (Result != ERROR_SUCCESS)
{
- LOG(WINTUN_LOG_ERR, L"Failed to get NetCfgInstanceId");
+ LOG_LAST_ERROR(L"Opening device registry key failed");
+ return FALSE;
+ }
+ DWORD LastError = ERROR_SUCCESS;
+ WCHAR *ValueStr = RegistryQueryString(Key, L"NetCfgInstanceId", TRUE);
+ if (!ValueStr)
+ {
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to get NetCfgInstanceId");
goto cleanupKey;
}
if (FAILED(CLSIDFromString(ValueStr, CfgInstanceID)))
{
LOG(WINTUN_LOG_ERR, L"NetCfgInstanceId is not a GUID");
- Result = ERROR_INVALID_DATA;
+ LastError = ERROR_INVALID_DATA;
}
- else
- Result = ERROR_SUCCESS;
HeapFree(ModuleHeap, 0, ValueStr);
cleanupKey:
RegCloseKey(Key);
- return Result;
+ return RET_ERROR(TRUE, LastError);
}
-static WINTUN_STATUS
-GetDevInfoData(_In_ const GUID *CfgInstanceID, _Out_ HDEVINFO *DevInfo, _Out_ SP_DEVINFO_DATA *DevInfoData)
+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)
- return LOG_LAST_ERROR(L"Failed to get present adapters");
+ {
+ LOG_LAST_ERROR(L"Failed to get present adapters");
+ return FALSE;
+ }
for (DWORD EnumIndex = 0;; ++EnumIndex)
{
DevInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
@@ -424,12 +456,13 @@ GetDevInfoData(_In_ const GUID *CfgInstanceID, _Out_ HDEVINFO *DevInfo, _Out_ SP
continue;
}
GUID CfgInstanceID2;
- if (GetNetCfgInstanceId(*DevInfo, DevInfoData, &CfgInstanceID2) == ERROR_SUCCESS &&
+ if (GetNetCfgInstanceId(*DevInfo, DevInfoData, &CfgInstanceID2) &&
!memcmp(CfgInstanceID, &CfgInstanceID2, sizeof(GUID)))
- return ERROR_SUCCESS;
+ return TRUE;
}
SetupDiDestroyDeviceInfoList(*DevInfo);
- return ERROR_FILE_NOT_FOUND;
+ SetLastError(ERROR_FILE_NOT_FOUND);
+ return FALSE;
}
static void
@@ -443,135 +476,135 @@ RemoveNumberedSuffix(_Inout_z_ WCHAR *Name)
}
}
-static WINTUN_STATUS
-GetPoolDeviceTypeName(_In_z_ const WCHAR *Pool, _Out_cap_c_(MAX_POOL_DEVICE_TYPE) WCHAR *Name)
+static _Return_type_success_(return != FALSE) BOOL
+ GetPoolDeviceTypeName(_In_z_ const WCHAR *Pool, _Out_cap_c_(MAX_POOL_DEVICE_TYPE) WCHAR *Name)
{
if (_snwprintf_s(Name, MAX_POOL_DEVICE_TYPE, _TRUNCATE, L"%s Tunnel", Pool) == -1)
- return LOG(WINTUN_LOG_ERR, L"Pool name too long"), ERROR_INVALID_PARAMETER;
- return ERROR_SUCCESS;
+ {
+ LOG(WINTUN_LOG_ERR, L"Pool name too long");
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ return TRUE;
}
-static WINTUN_STATUS
-IsPoolMember(_In_z_ const WCHAR *Pool, _In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData, _Out_ BOOL *IsMember)
+static BOOL
+IsPoolMember(_In_z_ const WCHAR *Pool, _In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData)
{
- WCHAR *DeviceDesc, *FriendlyName;
- DWORD Result = GetDeviceRegistryString(DevInfo, DevInfoData, SPDRP_DEVICEDESC, &DeviceDesc);
- if (Result != ERROR_SUCCESS)
+ WCHAR *DeviceDesc = GetDeviceRegistryString(DevInfo, DevInfoData, SPDRP_DEVICEDESC);
+ if (!DeviceDesc)
{
LOG(WINTUN_LOG_ERR, L"Failed to get adapter description");
- return Result;
+ return FALSE;
}
- Result = GetDeviceRegistryString(DevInfo, DevInfoData, SPDRP_FRIENDLYNAME, &FriendlyName);
- if (Result != ERROR_SUCCESS)
+ DWORD LastError = ERROR_SUCCESS;
+ BOOL Ret = FALSE;
+ WCHAR *FriendlyName = GetDeviceRegistryString(DevInfo, DevInfoData, SPDRP_FRIENDLYNAME);
+ if (!FriendlyName)
{
- LOG(WINTUN_LOG_ERR, L"Failed to get adapter friendly name");
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to get adapter friendly name");
goto cleanupDeviceDesc;
}
WCHAR PoolDeviceTypeName[MAX_POOL_DEVICE_TYPE];
- Result = GetPoolDeviceTypeName(Pool, PoolDeviceTypeName);
- if (Result != ERROR_SUCCESS)
+ if (!GetPoolDeviceTypeName(Pool, PoolDeviceTypeName))
+ {
+ LastError = GetLastError();
goto cleanupFriendlyName;
+ }
if (!_wcsicmp(FriendlyName, PoolDeviceTypeName) || !_wcsicmp(DeviceDesc, PoolDeviceTypeName))
{
- *IsMember = TRUE;
+ Ret = TRUE;
goto cleanupFriendlyName;
}
RemoveNumberedSuffix(FriendlyName);
RemoveNumberedSuffix(DeviceDesc);
if (!_wcsicmp(FriendlyName, PoolDeviceTypeName) || !_wcsicmp(DeviceDesc, PoolDeviceTypeName))
{
- *IsMember = TRUE;
+ Ret = TRUE;
goto cleanupFriendlyName;
}
- *IsMember = FALSE;
cleanupFriendlyName:
HeapFree(ModuleHeap, 0, FriendlyName);
cleanupDeviceDesc:
HeapFree(ModuleHeap, 0, DeviceDesc);
- return Result;
+ SetLastError(LastError);
+ return Ret;
}
-static WINTUN_STATUS
-CreateAdapterData(
- _In_z_ const WCHAR *Pool,
- _In_ HDEVINFO DevInfo,
- _In_ SP_DEVINFO_DATA *DevInfoData,
- _Out_ WINTUN_ADAPTER **Adapter)
+static _Return_type_success_(return != NULL) WINTUN_ADAPTER
+ *CreateAdapterData(_In_z_ const WCHAR *Pool, _In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData)
{
- DWORD Result;
-
/* 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);
if (Key == INVALID_HANDLE_VALUE)
- return LOG_LAST_ERROR(L"Opening device registry key failed");
+ {
+ LOG_LAST_ERROR(L"Opening device registry key failed");
+ return NULL;
+ }
- WINTUN_ADAPTER *a = HeapAlloc(ModuleHeap, 0, sizeof(WINTUN_ADAPTER));
- if (!a)
+ DWORD LastError;
+ WINTUN_ADAPTER *Adapter = HeapAlloc(ModuleHeap, 0, sizeof(WINTUN_ADAPTER));
+ if (!Adapter)
{
LOG(WINTUN_LOG_ERR, L"Out of memory");
- Result = ERROR_OUTOFMEMORY;
+ LastError = ERROR_OUTOFMEMORY;
goto cleanupKey;
}
- /* Read the NetCfgInstanceId value and convert to GUID. */
- WCHAR *ValueStr;
- Result = RegistryQueryString(Key, L"NetCfgInstanceId", &ValueStr, TRUE);
- if (Result != ERROR_SUCCESS)
+ WCHAR *ValueStr = RegistryQueryString(Key, L"NetCfgInstanceId", TRUE);
+ if (!ValueStr)
{
- LOG(WINTUN_LOG_ERR, L"Failed to get NetCfgInstanceId");
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to get NetCfgInstanceId");
goto cleanupAdapter;
}
- if (FAILED(CLSIDFromString(ValueStr, &a->CfgInstanceID)))
+ if (FAILED(CLSIDFromString(ValueStr, &Adapter->CfgInstanceID)))
{
- LOG(WINTUN_LOG_ERR, L"NetCfgInstanceId is not a GUID");
+ LOG(WINTUN_LOG_ERR, L"NetCfgInstanceId is not Adapter GUID");
HeapFree(ModuleHeap, 0, ValueStr);
- Result = ERROR_INVALID_DATA;
+ LastError = ERROR_INVALID_DATA;
goto cleanupAdapter;
}
HeapFree(ModuleHeap, 0, ValueStr);
- /* Read the NetLuidIndex value. */
- Result = RegistryQueryDWORD(Key, L"NetLuidIndex", &a->LuidIndex, TRUE);
- if (Result != ERROR_SUCCESS)
+ if (!RegistryQueryDWORD(Key, L"NetLuidIndex", &Adapter->LuidIndex, TRUE))
{
- LOG(WINTUN_LOG_ERR, L"Failed to get NetLuidIndex");
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to get NetLuidIndex");
goto cleanupAdapter;
}
- /* Read the NetLuidIndex value. */
- Result = RegistryQueryDWORD(Key, L"*IfType", &a->IfType, TRUE);
- if (Result != ERROR_SUCCESS)
+ if (!RegistryQueryDWORD(Key, L"*IfType", &Adapter->IfType, TRUE))
{
- LOG(WINTUN_LOG_ERR, L"Failed to get *IfType");
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to get *IfType");
goto cleanupAdapter;
}
DWORD Size;
- if (!SetupDiGetDeviceInstanceIdW(DevInfo, DevInfoData, a->DevInstanceID, _countof(a->DevInstanceID), &Size))
+ if (!SetupDiGetDeviceInstanceIdW(
+ DevInfo, DevInfoData, Adapter->DevInstanceID, _countof(Adapter->DevInstanceID), &Size))
{
- Result = LOG_LAST_ERROR(L"Failed to get instance ID");
+ LastError = LOG_LAST_ERROR(L"Failed to get instance ID");
goto cleanupAdapter;
}
- if (wcsncpy_s(a->Pool, _countof(a->Pool), Pool, _TRUNCATE) == STRUNCATE)
+ if (wcsncpy_s(Adapter->Pool, _countof(Adapter->Pool), Pool, _TRUNCATE) == STRUNCATE)
{
LOG(WINTUN_LOG_ERR, L"Pool name too long");
- Result = ERROR_INVALID_PARAMETER;
+ LastError = ERROR_INVALID_PARAMETER;
goto cleanupAdapter;
}
- *Adapter = a;
- Result = ERROR_SUCCESS;
+ RegCloseKey(Key);
+ return Adapter;
cleanupAdapter:
- if (Result != ERROR_SUCCESS)
- HeapFree(ModuleHeap, 0, a);
+ HeapFree(ModuleHeap, 0, Adapter);
cleanupKey:
RegCloseKey(Key);
- return Result;
+ SetLastError(LastError);
+ return NULL;
}
-static WINTUN_STATUS
-GetDeviceRegPath(_In_ const WINTUN_ADAPTER *Adapter, _Out_cap_c_(MAX_REG_PATH) WCHAR *Path)
+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,
@@ -580,8 +613,12 @@ GetDeviceRegPath(_In_ const WINTUN_ADAPTER *Adapter, _Out_cap_c_(MAX_REG_PATH) W
L"SYSTEM\\CurrentControlSet\\Enum\\%.*s",
MAX_INSTANCE_ID,
Adapter->DevInstanceID) == -1)
- return LOG(WINTUN_LOG_ERR, L"Registry path too long"), ERROR_INVALID_PARAMETER;
- return ERROR_SUCCESS;
+ {
+ LOG(WINTUN_LOG_ERR, L"Registry path too long");
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ return TRUE;
}
void WINAPI
@@ -590,23 +627,27 @@ WintunFreeAdapter(_In_ WINTUN_ADAPTER *Adapter)
HeapFree(ModuleHeap, 0, Adapter);
}
-WINTUN_STATUS WINAPI
-WintunGetAdapter(_In_z_ const WCHAR *Pool, _In_z_ const WCHAR *Name, _Out_ WINTUN_ADAPTER **Adapter)
+_Return_type_success_(return != NULL) WINTUN_ADAPTER *WINAPI
+ WintunGetAdapter(_In_z_ const WCHAR *Pool, _In_z_ const WCHAR *Name)
{
if (!ElevateToSystem())
- return LOG_LAST_ERROR(L"Failed to impersonate SYSTEM user");
- DWORD Result;
+ {
+ LOG(WINTUN_LOG_ERR, L"Failed to impersonate SYSTEM user");
+ return NULL;
+ }
+ DWORD LastError;
+ WINTUN_ADAPTER *Adapter = NULL;
HANDLE Mutex = NamespaceTakePoolMutex(Pool);
if (!Mutex)
{
- Result = ERROR_INVALID_HANDLE;
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to take pool mutex");
goto cleanupToken;
}
HDEVINFO DevInfo = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL);
if (DevInfo == INVALID_HANDLE_VALUE)
{
- Result = LOG_LAST_ERROR(L"Failed to get present adapters");
+ LastError = LOG_LAST_ERROR(L"Failed to get present adapters");
goto cleanupMutex;
}
@@ -621,7 +662,7 @@ WintunGetAdapter(_In_z_ const WCHAR *Pool, _In_z_ const WCHAR *Name, _Out_ WINTU
}
GUID CfgInstanceID;
- if (GetNetCfgInstanceId(DevInfo, &DevInfoData, &CfgInstanceID) != ERROR_SUCCESS)
+ if (!GetNetCfgInstanceId(DevInfo, &DevInfoData, &CfgInstanceID))
continue;
/* TODO: is there a better way than comparing ifnames? */
@@ -637,134 +678,162 @@ WintunGetAdapter(_In_z_ const WCHAR *Pool, _In_z_ const WCHAR *Name, _Out_ WINTU
}
/* Check the Hardware ID to make sure it's a real Wintun device. */
- BOOL IsOurs;
- Result = IsOurAdapter(DevInfo, &DevInfoData, &IsOurs);
- if (Result != ERROR_SUCCESS)
- {
- LOG(WINTUN_LOG_ERR, L"Failed to get hardware ID");
- goto cleanupDevInfo;
- }
- if (!IsOurs)
+ if (!IsOurAdapter(DevInfo, &DevInfoData))
{
LOG(WINTUN_LOG_ERR, L"Foreign adapter with the same name exists");
- Result = ERROR_ALREADY_EXISTS;
+ LastError = ERROR_ALREADY_EXISTS;
goto cleanupDevInfo;
}
- BOOL IsMember;
- Result = IsPoolMember(Pool, DevInfo, &DevInfoData, &IsMember);
- if (Result != ERROR_SUCCESS)
- {
- LOG(WINTUN_LOG_ERR, L"Failed to get pool membership");
- goto cleanupDevInfo;
- }
- if (!IsMember)
+ if (!IsPoolMember(Pool, DevInfo, &DevInfoData))
{
- LOG(WINTUN_LOG_ERR, L"Wintun adapter with the same name exists in another pool");
- Result = ERROR_ALREADY_EXISTS;
- goto cleanupDevInfo;
+ if ((LastError = GetLastError()) == ERROR_SUCCESS)
+ {
+ LOG(WINTUN_LOG_ERR, L"Wintun adapter with the same name exists in another pool");
+ LastError = ERROR_ALREADY_EXISTS;
+ goto cleanupDevInfo;
+ }
+ else
+ {
+ LOG(WINTUN_LOG_ERR, L"Failed to get pool membership");
+ goto cleanupDevInfo;
+ }
}
- Result = CreateAdapterData(Pool, DevInfo, &DevInfoData, Adapter);
- if (Result != ERROR_SUCCESS)
- LOG(WINTUN_LOG_ERR, L"Failed to create adapter data");
-
+ Adapter = CreateAdapterData(Pool, DevInfo, &DevInfoData);
+ LastError = Adapter ? ERROR_SUCCESS : LOG(WINTUN_LOG_ERR, L"Failed to create adapter data");
goto cleanupDevInfo;
}
- Result = ERROR_FILE_NOT_FOUND;
+ LastError = ERROR_FILE_NOT_FOUND;
cleanupDevInfo:
SetupDiDestroyDeviceInfoList(DevInfo);
cleanupMutex:
NamespaceReleaseMutex(Mutex);
cleanupToken:
RevertToSelf();
- return Result;
+ SetLastError(LastError);
+ return Adapter;
}
-WINTUN_STATUS WINAPI
-WintunGetAdapterName(_In_ const WINTUN_ADAPTER *Adapter, _Out_cap_c_(MAX_ADAPTER_NAME) WCHAR *Name)
+_Return_type_success_(return != FALSE) BOOL WINAPI
+ WintunGetAdapterName(_In_ const WINTUN_ADAPTER *Adapter, _Out_cap_c_(MAX_ADAPTER_NAME) WCHAR *Name)
{
- return NciGetConnectionName(&Adapter->CfgInstanceID, Name, MAX_ADAPTER_NAME * sizeof(WCHAR), NULL);
+ DWORD LastError = NciGetConnectionName(&Adapter->CfgInstanceID, Name, MAX_ADAPTER_NAME * sizeof(WCHAR), NULL);
+ if (LastError != ERROR_SUCCESS)
+ {
+ SetLastError(LOG_ERROR(L"Failed to get name", LastError));
+ return FALSE;
+ }
+ return TRUE;
}
-static WINTUN_STATUS
-ConvertInterfaceAliasToGuid(_In_z_ const WCHAR *Name, _Out_ GUID *Guid)
+static _Return_type_success_(return != FALSE) BOOL
+ ConvertInterfaceAliasToGuid(_In_z_ const WCHAR *Name, _Out_ GUID *Guid)
{
NET_LUID Luid;
- DWORD Result = ConvertInterfaceAliasToLuid(Name, &Luid);
- if (Result != NO_ERROR)
- return LOG_ERROR(L"Failed convert interface alias name to the locally unique identifier", Result);
- return ConvertInterfaceLuidToGuid(&Luid, Guid);
+ DWORD LastError = ConvertInterfaceAliasToLuid(Name, &Luid);
+ if (LastError != NO_ERROR)
+ {
+ SetLastError(LOG_ERROR(L"Failed convert interface alias name to the locally unique identifier", LastError));
+ return FALSE;
+ }
+ LastError = ConvertInterfaceLuidToGuid(&Luid, Guid);
+ if (LastError != NO_ERROR)
+ {
+ SetLastError(LOG_ERROR(L"Failed convert interface locally to globally unique identifier", LastError));
+ return FALSE;
+ }
+ return TRUE;
}
-WINTUN_STATUS WINAPI
-WintunSetAdapterName(_In_ const WINTUN_ADAPTER *Adapter, _In_z_ const WCHAR *Name)
+_Return_type_success_(return != FALSE) BOOL WINAPI
+ WintunSetAdapterName(_In_ const WINTUN_ADAPTER *Adapter, _In_z_ const WCHAR *Name)
{
- DWORD Result;
+ DWORD LastError;
const int MaxSuffix = 1000;
WCHAR AvailableName[MAX_ADAPTER_NAME];
if (wcsncpy_s(AvailableName, _countof(AvailableName), Name, _TRUNCATE) == STRUNCATE)
- return LOG(WINTUN_LOG_ERR, L"Adapter name too long"), ERROR_INVALID_PARAMETER;
+ {
+ LOG(WINTUN_LOG_ERR, L"Adapter name too long");
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
for (int i = 0;; ++i)
{
- Result = NciSetConnectionName(&Adapter->CfgInstanceID, AvailableName);
- if (Result == ERROR_DUP_NAME)
+ LastError = NciSetConnectionName(&Adapter->CfgInstanceID, AvailableName);
+ if (LastError == ERROR_DUP_NAME)
{
GUID Guid2;
- DWORD Result2 = ConvertInterfaceAliasToGuid(AvailableName, &Guid2);
- if (Result2 == ERROR_SUCCESS)
+ if (ConvertInterfaceAliasToGuid(AvailableName, &Guid2))
{
for (int j = 0; j < MaxSuffix; ++j)
{
WCHAR Proposal[MAX_ADAPTER_NAME];
if (_snwprintf_s(Proposal, _countof(Proposal), _TRUNCATE, L"%s %d", Name, j + 1) == -1)
- return LOG(WINTUN_LOG_ERR, L"Adapter name too long"), ERROR_INVALID_PARAMETER;
+ {
+ LOG(WINTUN_LOG_ERR, L"Adapter name too long");
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
if (_wcsnicmp(Proposal, AvailableName, MAX_ADAPTER_NAME) == 0)
continue;
- Result2 = NciSetConnectionName(&Guid2, Proposal);
- if (Result2 == ERROR_DUP_NAME)
+ DWORD LastError2 = NciSetConnectionName(&Guid2, Proposal);
+ if (LastError2 == ERROR_DUP_NAME)
continue;
- if (Result2 == ERROR_SUCCESS)
+ if (LastError2 == ERROR_SUCCESS)
{
- Result = NciSetConnectionName(&Adapter->CfgInstanceID, AvailableName);
- if (Result == ERROR_SUCCESS)
+ LastError = NciSetConnectionName(&Adapter->CfgInstanceID, AvailableName);
+ if (LastError == ERROR_SUCCESS)
break;
}
break;
}
}
}
- if (Result == ERROR_SUCCESS)
+ if (LastError == ERROR_SUCCESS)
break;
- if (i >= MaxSuffix || Result != ERROR_DUP_NAME)
- return LOG_ERROR(L"Setting adapter name failed", Result);
+ if (i >= MaxSuffix || LastError != ERROR_DUP_NAME)
+ {
+ SetLastError(LOG_ERROR(L"Setting adapter name failed", LastError));
+ return FALSE;
+ }
if (_snwprintf_s(AvailableName, _countof(AvailableName), _TRUNCATE, L"%s %d", Name, i + 1) == -1)
- return LOG(WINTUN_LOG_ERR, L"Adapter name too long"), ERROR_INVALID_PARAMETER;
+ {
+ LOG(WINTUN_LOG_ERR, L"Adapter name too long");
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
}
/* TODO: This should use NetSetup2 so that it doesn't get unset. */
HKEY DeviceRegKey;
WCHAR DeviceRegPath[MAX_REG_PATH];
- Result = GetDeviceRegPath(Adapter, DeviceRegPath);
- if (Result != ERROR_SUCCESS)
- return Result;
- Result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, DeviceRegPath, 0, KEY_SET_VALUE, &DeviceRegKey);
- if (Result != ERROR_SUCCESS)
- return LOG_ERROR(L"Failed to open registry key", Result);
+ if (!GetDeviceRegPath(Adapter, DeviceRegPath))
+ return FALSE;
+ LastError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, DeviceRegPath, 0, KEY_SET_VALUE, &DeviceRegKey);
+ if (LastError != ERROR_SUCCESS)
+ {
+ SetLastError(LOG_ERROR(L"Failed to open registry key", LastError));
+ return FALSE;
+ }
WCHAR PoolDeviceTypeName[MAX_POOL_DEVICE_TYPE];
- Result = GetPoolDeviceTypeName(Adapter->Pool, PoolDeviceTypeName);
- if (Result != ERROR_SUCCESS)
+ if (!GetPoolDeviceTypeName(Adapter->Pool, PoolDeviceTypeName))
+ {
+ LastError = GetLastError();
goto cleanupDeviceRegKey;
- Result = RegSetKeyValueW(
+ }
+ LastError = RegSetKeyValueW(
DeviceRegKey,
NULL,
L"FriendlyName",
REG_SZ,
PoolDeviceTypeName,
(DWORD)((wcslen(PoolDeviceTypeName) + 1) * sizeof(WCHAR)));
+ if (LastError != ERROR_SUCCESS)
+ LOG_ERROR(L"Failed to set FriendlyName", LastError);
cleanupDeviceRegKey:
RegCloseKey(DeviceRegKey);
- return Result;
+ return RET_ERROR(TRUE, LastError);
}
void WINAPI
@@ -775,10 +844,10 @@ WintunGetAdapterLUID(_In_ const WINTUN_ADAPTER *Adapter, _Out_ NET_LUID *Luid)
Luid->Info.IfType = Adapter->IfType;
}
-WINTUN_STATUS WINAPI
-WintunOpenAdapterDeviceObject(_In_ const WINTUN_ADAPTER *Adapter, _Out_ HANDLE *Handle)
+_Return_type_success_(return != INVALID_HANDLE_VALUE) HANDLE WINAPI
+ WintunOpenAdapterDeviceObject(_In_ const WINTUN_ADAPTER *Adapter)
{
- return GetDeviceObject(Adapter->DevInstanceID, Handle);
+ return OpenDeviceObject(Adapter->DevInstanceID);
}
static BOOL
@@ -793,15 +862,16 @@ HaveWHQL(void)
return FALSE;
}
-static WINTUN_STATUS
-InstallCertificate(_In_z_ const WCHAR *SignedResource)
+static _Return_type_success_(return != FALSE) BOOL InstallCertificate(_In_z_ const WCHAR *SignedResource)
{
LOG(WINTUN_LOG_INFO, L"Trusting code signing certificate");
- const void *LockedResource;
DWORD SizeResource;
- DWORD Result = ResourceGetAddress(SignedResource, &LockedResource, &SizeResource);
- if (Result != ERROR_SUCCESS)
- return LOG(WINTUN_LOG_ERR, L"Failed to locate resource"), Result;
+ const void *LockedResource = ResourceGetAddress(SignedResource, &SizeResource);
+ if (!LockedResource)
+ {
+ LOG(WINTUN_LOG_ERR, L"Failed to locate resource");
+ return FALSE;
+ }
const CERT_BLOB CertBlob = { .cbData = SizeResource, .pbData = (BYTE *)LockedResource };
HCERTSTORE QueriedStore;
if (!CryptQueryObject(
@@ -816,12 +886,16 @@ InstallCertificate(_In_z_ const WCHAR *SignedResource)
&QueriedStore,
0,
NULL))
- return LOG_LAST_ERROR(L"Failed to find certificate");
+ {
+ LOG_LAST_ERROR(L"Failed to find certificate");
+ return FALSE;
+ }
+ DWORD LastError = ERROR_SUCCESS;
HCERTSTORE TrustedStore =
CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"TrustedPublisher");
if (!TrustedStore)
{
- Result = LOG_LAST_ERROR(L"Failed to open store");
+ LastError = LOG_LAST_ERROR(L"Failed to open store");
goto cleanupQueriedStore;
}
LPSTR CodeSigningOid[] = { szOID_PKIX_KP_CODE_SIGNING };
@@ -852,13 +926,13 @@ InstallCertificate(_In_z_ const WCHAR *SignedResource)
if (!CertAddCertificateContextToStore(TrustedStore, CertContext, CERT_STORE_ADD_REPLACE_EXISTING, NULL))
{
LOG_LAST_ERROR(L"Failed to add certificate to store");
- Result = Result != ERROR_SUCCESS ? Result : GetLastError();
+ LastError = LastError != ERROR_SUCCESS ? LastError : GetLastError();
}
}
CertCloseStore(TrustedStore, 0);
cleanupQueriedStore:
CertCloseStore(QueriedStore, 0);
- return Result;
+ return RET_ERROR(TRUE, LastError);
}
static BOOL
@@ -897,8 +971,8 @@ IsNewer(
return FALSE;
}
-static DWORD
-GetTcpipAdapterRegPath(_In_ const WINTUN_ADAPTER *Adapter, _Out_cap_c_(MAX_REG_PATH) WCHAR *Path)
+static _Return_type_success_(return != FALSE) BOOL
+ GetTcpipAdapterRegPath(_In_ const WINTUN_ADAPTER *Adapter, _Out_cap_c_(MAX_REG_PATH) WCHAR *Path)
{
WCHAR Guid[MAX_GUID_STRING_LEN];
if (_snwprintf_s(
@@ -908,108 +982,134 @@ GetTcpipAdapterRegPath(_In_ const WINTUN_ADAPTER *Adapter, _Out_cap_c_(MAX_REG_P
L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Adapters\\%.*s",
StringFromGUID2(&Adapter->CfgInstanceID, Guid, _countof(Guid)),
Guid) == -1)
- return LOG(WINTUN_LOG_ERR, L"Registry path too long"), ERROR_INVALID_PARAMETER;
- return ERROR_SUCCESS;
+ {
+ LOG(WINTUN_LOG_ERR, L"Registry path too long");
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ return TRUE;
}
-static WINTUN_STATUS
-GetTcpipInterfaceRegPath(_In_ const WINTUN_ADAPTER *Adapter, _Out_cap_c_(MAX_REG_PATH) WCHAR *Path)
+static _Return_type_success_(return != FALSE) BOOL
+ GetTcpipInterfaceRegPath(_In_ const WINTUN_ADAPTER *Adapter, _Out_cap_c_(MAX_REG_PATH) WCHAR *Path)
{
- DWORD Result;
HKEY TcpipAdapterRegKey;
WCHAR TcpipAdapterRegPath[MAX_REG_PATH];
- Result = GetTcpipAdapterRegPath(Adapter, TcpipAdapterRegPath);
- if (Result != ERROR_SUCCESS)
- return Result;
- Result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, TcpipAdapterRegPath, 0, KEY_QUERY_VALUE, &TcpipAdapterRegKey);
- if (Result != ERROR_SUCCESS)
- return LOG_ERROR(L"Failed to open registry key", Result);
- WCHAR *Paths;
- Result = RegistryQueryString(TcpipAdapterRegKey, L"IpConfig", &Paths, TRUE);
- if (Result != ERROR_SUCCESS)
- {
- LOG(WINTUN_LOG_ERR, L"Failed to get IpConfig");
+ if (!GetTcpipAdapterRegPath(Adapter, TcpipAdapterRegPath))
+ return FALSE;
+ DWORD LastError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, TcpipAdapterRegPath, 0, KEY_QUERY_VALUE, &TcpipAdapterRegKey);
+ if (LastError != ERROR_SUCCESS)
+ {
+ SetLastError(LOG_ERROR(L"Failed to open registry key", LastError));
+ return FALSE;
+ }
+ WCHAR *Paths = RegistryQueryString(TcpipAdapterRegKey, L"IpConfig", TRUE);
+ if (!Paths)
+ {
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to get IpConfig");
goto cleanupTcpipAdapterRegKey;
}
if (!Paths[0])
{
LOG(WINTUN_LOG_ERR, L"IpConfig is empty");
- Result = ERROR_INVALID_DATA;
+ LastError = ERROR_INVALID_DATA;
goto cleanupPaths;
}
if (_snwprintf_s(Path, MAX_REG_PATH, _TRUNCATE, L"SYSTEM\\CurrentControlSet\\Services\\%s", Paths) == -1)
{
LOG(WINTUN_LOG_ERR, L"Registry path too long");
- Result = ERROR_INVALID_PARAMETER;
+ LastError = ERROR_INVALID_PARAMETER;
goto cleanupPaths;
}
- Result = ERROR_SUCCESS;
cleanupPaths:
HeapFree(ModuleHeap, 0, Paths);
cleanupTcpipAdapterRegKey:
RegCloseKey(TcpipAdapterRegKey);
- return Result;
+ return RET_ERROR(TRUE, LastError);
}
-static DWORD
-VersionOfFile(_In_z_ const WCHAR *Filename)
+static _Return_type_success_(return != 0) DWORD VersionOfFile(_In_z_ const WCHAR *Filename)
{
- DWORD Version = 0;
DWORD Zero;
DWORD Len = GetFileVersionInfoSizeW(Filename, &Zero);
if (!Len)
- return LOG_LAST_ERROR(L"Failed to query version info size"), Version;
+ {
+ LOG_LAST_ERROR(L"Failed to query version info size");
+ return 0;
+ }
VOID *VersionInfo = HeapAlloc(ModuleHeap, 0, Len);
if (!VersionInfo)
{
LOG(WINTUN_LOG_ERR, L"Out of memory");
- return Version;
+ SetLastError(ERROR_OUTOFMEMORY);
+ return 0;
}
+ DWORD LastError = ERROR_SUCCESS, Version = 0;
VS_FIXEDFILEINFO *FixedInfo;
UINT FixedInfoLen = sizeof(*FixedInfo);
if (!GetFileVersionInfoW(Filename, 0, Len, VersionInfo))
{
- LOG_LAST_ERROR(L"Failed to get version info");
+ LastError = LOG_LAST_ERROR(L"Failed to get version info");
goto out;
}
if (!VerQueryValueW(VersionInfo, L"\\", &FixedInfo, &FixedInfoLen))
{
- LOG_LAST_ERROR(L"Failed to get version info root");
+ LastError = LOG_LAST_ERROR(L"Failed to get version info root");
goto out;
}
Version = FixedInfo->dwFileVersionMS;
+ if (!Version)
+ {
+ LOG(WINTUN_LOG_WARN, L"Determined version of file, but was v0.0, so returning failure");
+ LastError = ERROR_VERSION_PARSE_ERROR;
+ }
out:
HeapFree(ModuleHeap, 0, VersionInfo);
- return Version;
+ return RET_ERROR(Version, LastError);
}
-static WINTUN_STATUS
-CreateTemporaryDirectory(_Out_cap_c_(MAX_PATH) WCHAR *RandomTempSubDirectory)
+static _Return_type_success_(return != FALSE) BOOL
+ CreateTemporaryDirectory(_Out_cap_c_(MAX_PATH) WCHAR *RandomTempSubDirectory)
{
WCHAR WindowsDirectory[MAX_PATH];
if (!GetWindowsDirectoryW(WindowsDirectory, _countof(WindowsDirectory)))
- return LOG_LAST_ERROR(L"Failed to get Windows folder");
+ {
+ LOG_LAST_ERROR(L"Failed to get Windows folder");
+ return FALSE;
+ }
WCHAR WindowsTempDirectory[MAX_PATH];
if (!PathCombineW(WindowsTempDirectory, WindowsDirectory, L"Temp"))
- return ERROR_BUFFER_OVERFLOW;
+ {
+ SetLastError(ERROR_BUFFER_OVERFLOW);
+ return FALSE;
+ }
UCHAR RandomBytes[32] = { 0 };
#pragma warning(suppress : 6387)
if (!RtlGenRandom(RandomBytes, sizeof(RandomBytes)))
- return LOG_LAST_ERROR(L"Failed to generate random");
+ {
+ 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))
- return ERROR_BUFFER_OVERFLOW;
+ {
+ SetLastError(ERROR_BUFFER_OVERFLOW);
+ return FALSE;
+ }
if (!CreateDirectoryW(RandomTempSubDirectory, &SecurityAttributes))
- return LOG_LAST_ERROR(L"Failed to create temporary folder");
- return ERROR_SUCCESS;
+ {
+ LOG_LAST_ERROR(L"Failed to create temporary folder");
+ return FALSE;
+ }
+ return TRUE;
}
-DWORD
+DWORD WINAPI
WintunGetVersion(void)
{
- DWORD Version = 0;
PRTL_PROCESS_MODULES Modules;
ULONG BufferSize = 128 * 1024;
for (;;)
@@ -1018,7 +1118,8 @@ WintunGetVersion(void)
if (!Modules)
{
LOG(WINTUN_LOG_ERR, L"Out of memory");
- return Version;
+ SetLastError(ERROR_OUTOFMEMORY);
+ return 0;
}
NTSTATUS Status = NtQuerySystemInformation(SystemModuleInformation, Modules, BufferSize, &BufferSize);
if (NT_SUCCESS(Status))
@@ -1027,8 +1128,10 @@ WintunGetVersion(void)
if (Status == STATUS_INFO_LENGTH_MISMATCH)
continue;
LOG(WINTUN_LOG_ERR, L"Failed to enumerate drivers");
- return Version;
+ SetLastError(ERROR_GEN_FAILURE);
+ return 0;
}
+ DWORD LastError = ERROR_SUCCESS, Version = 0;
for (ULONG i = Modules->NumberOfModules; i-- > 0;)
{
const char *NtPath = (const char *)Modules->Modules[i].FullPathName;
@@ -1038,12 +1141,15 @@ WintunGetVersion(void)
if (_snwprintf_s(FilePath, _countof(FilePath), _TRUNCATE, L"\\\\?\\GLOBALROOT%S", NtPath) == -1)
continue;
Version = VersionOfFile(FilePath);
- goto out;
+ if (!Version)
+ LastError = GetLastError();
+ goto cleanupModules;
}
}
-out:
+ LastError = ERROR_FILE_NOT_FOUND;
+cleanupModules:
HeapFree(ModuleHeap, 0, Modules);
- return Version;
+ return RET_ERROR(Version, LastError);
}
static BOOL
@@ -1055,8 +1161,7 @@ EnsureWintunUnloaded(void)
return !Loaded;
}
-static WINTUN_STATUS
-SelectDriver(
+static _Return_type_success_(return != FALSE) BOOL SelectDriver(
_In_ HDEVINFO DevInfo,
_In_opt_ SP_DEVINFO_DATA *DevInfoData,
_Inout_ SP_DEVINSTALL_PARAMS_W *DevInstallParams,
@@ -1066,11 +1171,14 @@ SelectDriver(
static const DWORDLONG OurDriverVersion = WINTUN_INF_VERSION;
HANDLE DriverInstallationLock = NamespaceTakeDriverInstallationMutex();
if (!DriverInstallationLock)
- return LOG_LAST_ERROR(L"Failed to take driver installation mutex");
- DWORD Result = ERROR_SUCCESS;
+ {
+ LOG(WINTUN_LOG_ERR, L"Failed to take driver installation mutex");
+ return FALSE;
+ }
+ DWORD LastError;
if (!SetupDiBuildDriverInfoList(DevInfo, DevInfoData, SPDIT_COMPATDRIVER))
{
- Result = LOG_LAST_ERROR(L"Failed building driver info list");
+ LastError = LOG_LAST_ERROR(L"Failed building driver info list");
goto cleanupDriverInstallationLock;
}
BOOL DestroyDriverInfoListOnCleanup = TRUE;
@@ -1087,8 +1195,8 @@ SelectDriver(
break;
continue;
}
- SP_DRVINFO_DETAIL_DATA_W *DrvInfoDetailData;
- if (GetAdapterDrvInfoDetail(DevInfo, DevInfoData, &DrvInfoData, &DrvInfoDetailData) != ERROR_SUCCESS)
+ SP_DRVINFO_DETAIL_DATA_W *DrvInfoDetailData = GetAdapterDrvInfoDetail(DevInfo, DevInfoData, &DrvInfoData);
+ if (!DrvInfoDetailData)
{
LOG(WINTUN_LOG_WARN, L"Failed getting driver info detail");
continue;
@@ -1103,7 +1211,7 @@ SelectDriver(
SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL);
if (DevInfoExistingAdapters == INVALID_HANDLE_VALUE)
{
- Result = LOG_LAST_ERROR(L"Failed to get present adapters");
+ LastError = LOG_LAST_ERROR(L"Failed to get present adapters");
HeapFree(ModuleHeap, 0, DrvInfoDetailData);
goto cleanupExistingAdapters;
}
@@ -1114,16 +1222,16 @@ SelectDriver(
LOG(WINTUN_LOG_WARN,
L"Failed to unload existing driver, which means a reboot will likely be required");
}
- LOG(WINTUN_LOG_INFO, TEXT("Removing existing driver"));
+ LOG(WINTUN_LOG_INFO, L"Removing existing driver");
if (!SetupUninstallOEMInfW(PathFindFileNameW(DrvInfoDetailData->InfFileName), SUOI_FORCEDELETE, NULL))
- LOG_LAST_ERROR(TEXT("Unable to remove existing driver"));
+ LOG_LAST_ERROR(L"Unable to remove existing driver");
goto next;
}
if (!IsNewer(&DrvInfoData.DriverDate, DrvInfoData.DriverVersion, &DriverDate, DriverVersion))
goto next;
if (!SetupDiSetSelectedDriverW(DevInfo, DevInfoData, &DrvInfoData))
{
- LOG_ERROR(L"Failed to select driver", GetLastError());
+ LOG_LAST_ERROR(L"Failed to select driver");
goto next;
}
DriverDate = DrvInfoData.DriverDate;
@@ -1134,14 +1242,15 @@ SelectDriver(
if (DriverVersion)
{
+ LastError = ERROR_SUCCESS;
DestroyDriverInfoListOnCleanup = FALSE;
goto cleanupExistingAdapters;
}
WCHAR RandomTempSubDirectory[MAX_PATH];
- if ((Result = CreateTemporaryDirectory(RandomTempSubDirectory)) != ERROR_SUCCESS)
+ if (!CreateTemporaryDirectory(RandomTempSubDirectory))
{
- LOG(WINTUN_LOG_ERR, L"Failed to create temporary folder");
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to create temporary folder");
goto cleanupExistingAdapters;
}
@@ -1152,27 +1261,27 @@ SelectDriver(
!PathCombineW(SysPath, RandomTempSubDirectory, L"wintun.sys") ||
!PathCombineW(InfPath, RandomTempSubDirectory, L"wintun.inf"))
{
- Result = ERROR_BUFFER_OVERFLOW;
+ LastError = ERROR_BUFFER_OVERFLOW;
goto cleanupDirectory;
}
BOOL UseWHQL = HaveWHQL();
- if (!UseWHQL && (Result = InstallCertificate(L"wintun.cat")) != ERROR_SUCCESS)
+ if (!UseWHQL && !InstallCertificate(L"wintun.cat"))
LOG(WINTUN_LOG_WARN, L"Failed to install code signing certificate");
LOG(WINTUN_LOG_INFO, L"Extracting driver");
- if ((Result = ResourceCopyToFile(CatPath, UseWHQL ? L"wintun-whql.cat" : L"wintun.cat")) != ERROR_SUCCESS ||
- (Result = ResourceCopyToFile(SysPath, UseWHQL ? L"wintun-whql.sys" : L"wintun.sys")) != ERROR_SUCCESS ||
- (Result = ResourceCopyToFile(InfPath, UseWHQL ? L"wintun-whql.inf" : L"wintun.inf")) != ERROR_SUCCESS)
+ if (!ResourceCopyToFile(CatPath, UseWHQL ? L"wintun-whql.cat" : L"wintun.cat") ||
+ !ResourceCopyToFile(SysPath, UseWHQL ? L"wintun-whql.sys" : L"wintun.sys") ||
+ !ResourceCopyToFile(InfPath, UseWHQL ? L"wintun-whql.inf" : L"wintun.inf"))
{
- LOG(WINTUN_LOG_ERR, L"Failed to extract driver");
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to extract driver");
goto cleanupDelete;
}
LOG(WINTUN_LOG_INFO, L"Installing driver");
WCHAR InfStorePath[MAX_PATH];
if (!SetupCopyOEMInfW(InfPath, NULL, SPOST_NONE, 0, InfStorePath, MAX_PATH, NULL, NULL))
{
- Result = LOG_LAST_ERROR(L"Could not install driver to store");
+ LastError = LOG_LAST_ERROR(L"Could not install driver to store");
goto cleanupDelete;
}
_Analysis_assume_nullterminated_(InfStorePath);
@@ -1190,32 +1299,32 @@ SelectDriver(
STRUNCATE)
{
LOG(WINTUN_LOG_ERR, L"Inf path too long");
- Result = ERROR_INVALID_PARAMETER;
+ LastError = ERROR_INVALID_PARAMETER;
goto cleanupDelete;
}
if (!SetupDiSetDeviceInstallParamsW(DevInfo, DevInfoData, DevInstallParams))
{
- Result = LOG_LAST_ERROR(L"Setting device installation parameters failed");
+ LastError = LOG_LAST_ERROR(L"Setting device installation parameters failed");
goto cleanupDelete;
}
if (!SetupDiBuildDriverInfoList(DevInfo, DevInfoData, SPDIT_COMPATDRIVER))
{
- Result = LOG_LAST_ERROR(L"Failed rebuilding driver info list");
+ LastError = LOG_LAST_ERROR(L"Failed rebuilding driver info list");
goto cleanupDelete;
}
DestroyDriverInfoListOnCleanup = TRUE;
SP_DRVINFO_DATA_W DrvInfoData = { .cbSize = sizeof(SP_DRVINFO_DATA_W) };
if (!SetupDiEnumDriverInfoW(DevInfo, DevInfoData, SPDIT_COMPATDRIVER, 0, &DrvInfoData))
{
- Result = LOG_LAST_ERROR(L"Failed to get driver");
+ LastError = LOG_LAST_ERROR(L"Failed to get driver");
goto cleanupDelete;
}
if (!SetupDiSetSelectedDriverW(DevInfo, DevInfoData, &DrvInfoData))
{
- Result = LOG_LAST_ERROR(L"Failed to set driver");
+ LastError = LOG_LAST_ERROR(L"Failed to set driver");
goto cleanupDelete;
}
- Result = ERROR_SUCCESS;
+ LastError = ERROR_SUCCESS;
DestroyDriverInfoListOnCleanup = FALSE;
cleanupDelete:
@@ -1241,82 +1350,85 @@ cleanupExistingAdapters:
SetupDiDestroyDriverInfoList(DevInfo, DevInfoData, SPDIT_COMPATDRIVER);
cleanupDriverInstallationLock:
NamespaceReleaseMutex(DriverInstallationLock);
- return Result;
+ return RET_ERROR(TRUE, LastError);
}
-static WINTUN_STATUS
-CreateAdapter(
+static _Return_type_success_(return != NULL) WINTUN_ADAPTER *CreateAdapter(
_In_z_ const WCHAR *Pool,
_In_z_ const WCHAR *Name,
_In_opt_ const GUID *RequestedGUID,
- _Out_ WINTUN_ADAPTER **Adapter,
_Inout_ BOOL *RebootRequired)
{
LOG(WINTUN_LOG_INFO, L"Creating adapter");
HDEVINFO DevInfo = SetupDiCreateDeviceInfoListExW(&GUID_DEVCLASS_NET, NULL, NULL, NULL);
if (DevInfo == INVALID_HANDLE_VALUE)
- return LOG_LAST_ERROR(L"Creating empty device information set failed");
- DWORD Result;
+ {
+ LOG_LAST_ERROR(L"Creating empty device information set failed");
+ return NULL;
+ }
+ DWORD LastError;
+ WINTUN_ADAPTER *Adapter = NULL;
WCHAR ClassName[MAX_CLASS_NAME_LEN];
if (!SetupDiClassNameFromGuidExW(&GUID_DEVCLASS_NET, ClassName, _countof(ClassName), NULL, NULL, NULL))
{
- Result = LOG_LAST_ERROR(L"Retrieving class name associated with class GUID failed");
+ LastError = LOG_LAST_ERROR(L"Retrieving class name associated with class GUID failed");
goto cleanupDevInfo;
}
WCHAR PoolDeviceTypeName[MAX_POOL_DEVICE_TYPE];
- Result = GetPoolDeviceTypeName(Pool, PoolDeviceTypeName);
- if (Result != ERROR_SUCCESS)
+ if (!GetPoolDeviceTypeName(Pool, PoolDeviceTypeName))
+ {
+ LastError = GetLastError();
goto cleanupDevInfo;
+ }
SP_DEVINFO_DATA DevInfoData = { .cbSize = sizeof(SP_DEVINFO_DATA) };
if (!SetupDiCreateDeviceInfoW(
DevInfo, ClassName, &GUID_DEVCLASS_NET, PoolDeviceTypeName, NULL, DICD_GENERATE_ID, &DevInfoData))
{
- Result = LOG_LAST_ERROR(L"Creating new device information element failed");
+ LastError = LOG_LAST_ERROR(L"Creating new device information element failed");
goto cleanupDevInfo;
}
SP_DEVINSTALL_PARAMS_W DevInstallParams = { .cbSize = sizeof(SP_DEVINSTALL_PARAMS_W) };
if (!SetupDiGetDeviceInstallParamsW(DevInfo, &DevInfoData, &DevInstallParams))
{
- Result = LOG_LAST_ERROR(L"Retrieving device installation parameters failed");
+ LastError = LOG_LAST_ERROR(L"Retrieving device installation parameters failed");
goto cleanupDevInfo;
}
DevInstallParams.Flags |= DI_QUIETINSTALL;
if (!SetupDiSetDeviceInstallParamsW(DevInfo, &DevInfoData, &DevInstallParams))
{
- Result = LOG_LAST_ERROR(L"Setting device installation parameters failed");
+ LastError = LOG_LAST_ERROR(L"Setting device installation parameters failed");
goto cleanupDevInfo;
}
if (!SetupDiSetSelectedDevice(DevInfo, &DevInfoData))
{
- Result = LOG_LAST_ERROR(L"Failed selecting device");
+ LastError = LOG_LAST_ERROR(L"Failed selecting device");
goto cleanupDevInfo;
}
static const WCHAR Hwids[_countof(WINTUN_HWID) + 1 /*Multi-string terminator*/] = WINTUN_HWID;
if (!SetupDiSetDeviceRegistryPropertyW(DevInfo, &DevInfoData, SPDRP_HARDWAREID, (const BYTE *)Hwids, sizeof(Hwids)))
{
- Result = LOG_LAST_ERROR(L"Failed setting hardware ID");
+ LastError = LOG_LAST_ERROR(L"Failed setting hardware ID");
goto cleanupDevInfo;
}
- Result = SelectDriver(DevInfo, &DevInfoData, &DevInstallParams, RebootRequired);
- if (Result != ERROR_SUCCESS)
+ if (!SelectDriver(DevInfo, &DevInfoData, &DevInstallParams, RebootRequired))
{
- LOG(WINTUN_LOG_ERR, L"Failed to select driver");
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to select driver");
goto cleanupDevInfo;
}
HANDLE Mutex = NamespaceTakePoolMutex(Pool);
if (!Mutex)
{
- Result = LOG_LAST_ERROR(L"Failed to take pool mutex");
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to take pool mutex");
goto cleanupDriverInfoList;
}
if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, DevInfo, &DevInfoData))
{
- Result = LOG_LAST_ERROR(L"Registering device failed");
+ LastError = LOG_LAST_ERROR(L"Registering device failed");
goto cleanupDevice;
}
if (!SetupDiCallClassInstaller(DIF_REGISTER_COINSTALLERS, DevInfo, &DevInfoData))
@@ -1333,22 +1445,22 @@ CreateAdapter(
}
if (NetDevRegKey == INVALID_HANDLE_VALUE)
{
- Result = LOG_LAST_ERROR(L"Failed to open device-specific registry key");
+ LastError = LOG_LAST_ERROR(L"Failed to open device-specific registry key");
goto cleanupDevice;
}
if (RequestedGUID)
{
WCHAR RequestedGUIDStr[MAX_GUID_STRING_LEN];
- Result = RegSetValueExW(
+ LastError = RegSetValueExW(
NetDevRegKey,
L"NetSetupAnticipatedInstanceId",
0,
REG_SZ,
(const BYTE *)RequestedGUIDStr,
StringFromGUID2(RequestedGUID, RequestedGUIDStr, _countof(RequestedGUIDStr)) * sizeof(WCHAR));
- if (Result != ERROR_SUCCESS)
+ if (LastError != ERROR_SUCCESS)
{
- LOG_LAST_ERROR(L"Failed to set NetSetupAnticipatedInstanceId");
+ LOG_ERROR(L"Failed to set NetSetupAnticipatedInstanceId", LastError);
goto cleanupNetDevRegKey;
}
}
@@ -1358,7 +1470,7 @@ CreateAdapter(
if (!SetupDiCallClassInstaller(DIF_INSTALLDEVICE, DevInfo, &DevInfoData))
{
- Result = LOG_LAST_ERROR(L"Installing device failed");
+ LastError = LOG_LAST_ERROR(L"Installing device failed");
goto cleanupNetDevRegKey;
}
*RebootRequired = *RebootRequired || CheckReboot(DevInfo, &DevInfoData);
@@ -1370,99 +1482,87 @@ CreateAdapter(
(const BYTE *)PoolDeviceTypeName,
(DWORD)((wcslen(PoolDeviceTypeName) + 1) * sizeof(WCHAR))))
{
- Result = LOG_LAST_ERROR(L"Failed to set adapter description");
+ LastError = LOG_LAST_ERROR(L"Failed to set adapter description");
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;
- Result = RegistryQueryStringWait(NetDevRegKey, L"NetCfgInstanceId", WAIT_FOR_REGISTRY_TIMEOUT, &DummyStr);
- if (Result != ERROR_SUCCESS)
+ WCHAR *DummyStr = RegistryQueryStringWait(NetDevRegKey, L"NetCfgInstanceId", WAIT_FOR_REGISTRY_TIMEOUT);
+ if (!DummyStr)
{
- LOG(WINTUN_LOG_ERR, L"Failed to get NetCfgInstanceId");
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to get NetCfgInstanceId");
goto cleanupNetDevRegKey;
}
HeapFree(ModuleHeap, 0, DummyStr);
DWORD DummyDWORD;
- Result = RegistryQueryDWORDWait(NetDevRegKey, L"NetLuidIndex", WAIT_FOR_REGISTRY_TIMEOUT, &DummyDWORD);
- if (Result != ERROR_SUCCESS)
+ if (!RegistryQueryDWORDWait(NetDevRegKey, L"NetLuidIndex", WAIT_FOR_REGISTRY_TIMEOUT, &DummyDWORD))
{
- LOG(WINTUN_LOG_ERR, L"Failed to get NetLuidIndex");
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to get NetLuidIndex");
goto cleanupNetDevRegKey;
}
- Result = RegistryQueryDWORDWait(NetDevRegKey, L"*IfType", WAIT_FOR_REGISTRY_TIMEOUT, &DummyDWORD);
- if (Result != ERROR_SUCCESS)
+ if (!RegistryQueryDWORDWait(NetDevRegKey, L"*IfType", WAIT_FOR_REGISTRY_TIMEOUT, &DummyDWORD))
{
- LOG(WINTUN_LOG_ERR, L"Failed to get *IfType");
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to get *IfType");
goto cleanupNetDevRegKey;
}
- WINTUN_ADAPTER *a;
- Result = CreateAdapterData(Pool, DevInfo, &DevInfoData, &a);
- if (Result != ERROR_SUCCESS)
+ Adapter = CreateAdapterData(Pool, DevInfo, &DevInfoData);
+ if (!Adapter)
{
- LOG(WINTUN_LOG_ERR, L"Failed to create adapter data");
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to create adapter data");
goto cleanupNetDevRegKey;
}
HKEY TcpipAdapterRegKey;
WCHAR TcpipAdapterRegPath[MAX_REG_PATH];
- Result = GetTcpipAdapterRegPath(a, TcpipAdapterRegPath);
- if (Result != ERROR_SUCCESS)
+ if (!GetTcpipAdapterRegPath(Adapter, TcpipAdapterRegPath))
+ {
+ LastError = GetLastError();
goto cleanupAdapter;
- Result = RegistryOpenKeyWait(
- HKEY_LOCAL_MACHINE,
- TcpipAdapterRegPath,
- KEY_QUERY_VALUE | KEY_NOTIFY,
- WAIT_FOR_REGISTRY_TIMEOUT,
- &TcpipAdapterRegKey);
- if (Result != ERROR_SUCCESS)
- {
- LOG(WINTUN_LOG_ERR, L"Failed to open adapter-specific TCP/IP interface registry key");
+ }
+ TcpipAdapterRegKey = RegistryOpenKeyWait(
+ HKEY_LOCAL_MACHINE, TcpipAdapterRegPath, KEY_QUERY_VALUE | KEY_NOTIFY, WAIT_FOR_REGISTRY_TIMEOUT);
+ if (!TcpipAdapterRegKey)
+ {
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to open adapter-specific TCP/IP interface registry key");
goto cleanupAdapter;
}
- Result = RegistryQueryStringWait(TcpipAdapterRegKey, L"IpConfig", WAIT_FOR_REGISTRY_TIMEOUT, &DummyStr);
- if (Result != ERROR_SUCCESS)
+ DummyStr = RegistryQueryStringWait(TcpipAdapterRegKey, L"IpConfig", WAIT_FOR_REGISTRY_TIMEOUT);
+ if (!DummyStr)
{
- LOG(WINTUN_LOG_ERR, L"Failed to get IpConfig");
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to get IpConfig");
goto cleanupTcpipAdapterRegKey;
}
HeapFree(ModuleHeap, 0, DummyStr);
HKEY TcpipInterfaceRegKey;
WCHAR TcpipInterfaceRegPath[MAX_REG_PATH];
- Result = GetTcpipInterfaceRegPath(a, TcpipInterfaceRegPath);
- if (Result != ERROR_SUCCESS)
+ if (!GetTcpipInterfaceRegPath(Adapter, TcpipInterfaceRegPath))
{
- LOG(WINTUN_LOG_ERR, L"Failed to determine interface-specific TCP/IP network registry key path");
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to determine interface-specific TCP/IP network registry key path");
goto cleanupTcpipAdapterRegKey;
}
- Result = RegistryOpenKeyWait(
- HKEY_LOCAL_MACHINE,
- TcpipInterfaceRegPath,
- KEY_QUERY_VALUE | KEY_SET_VALUE,
- WAIT_FOR_REGISTRY_TIMEOUT,
- &TcpipInterfaceRegKey);
- if (Result != ERROR_SUCCESS)
+ TcpipInterfaceRegKey = RegistryOpenKeyWait(
+ HKEY_LOCAL_MACHINE, TcpipInterfaceRegPath, KEY_QUERY_VALUE | KEY_SET_VALUE, WAIT_FOR_REGISTRY_TIMEOUT);
+ if (!TcpipInterfaceRegKey)
{
- LOG(WINTUN_LOG_ERR, L"Failed to open interface-specific TCP/IP network registry key");
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to open interface-specific TCP/IP network registry key");
goto cleanupTcpipAdapterRegKey;
}
static const DWORD EnableDeadGWDetect = 0;
- Result = RegSetKeyValueW(
+ LastError = RegSetKeyValueW(
TcpipInterfaceRegKey, NULL, L"EnableDeadGWDetect", REG_DWORD, &EnableDeadGWDetect, sizeof(EnableDeadGWDetect));
- if (Result != ERROR_SUCCESS)
+ if (LastError != ERROR_SUCCESS)
{
- LOG_ERROR(L"Failed to set EnableDeadGWDetect", Result);
+ LOG_ERROR(L"Failed to set EnableDeadGWDetect", LastError);
goto cleanupTcpipInterfaceRegKey;
}
- Result = WintunSetAdapterName(a, Name);
- if (Result != ERROR_SUCCESS)
+ if (!WintunSetAdapterName(Adapter, Name))
{
- LOG_ERROR(L"Failed to set adapter name", Result);
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to set adapter name");
goto cleanupTcpipInterfaceRegKey;
}
@@ -1481,11 +1581,11 @@ CreateAdapter(
0) &&
PropertyType == DEVPROP_TYPE_NTSTATUS)
{
- Result = RtlNtStatusToDosError(ProblemStatus);
- _Analysis_assume_(Result != ERROR_SUCCESS);
+ LastError = RtlNtStatusToDosError(ProblemStatus);
+ _Analysis_assume_(LastError != ERROR_SUCCESS);
if (ProblemStatus != STATUS_PNP_DEVICE_CONFIGURATION_PENDING || Tries == 999)
{
- LOG_ERROR(L"Failed to setup adapter", Result);
+ LOG_ERROR(L"Failed to setup adapter", LastError);
goto cleanupTcpipInterfaceRegKey;
}
Sleep(10);
@@ -1493,21 +1593,22 @@ CreateAdapter(
else
break;
}
- Result = ERROR_SUCCESS;
-
- *Adapter = a;
+ LastError = ERROR_SUCCESS;
cleanupTcpipInterfaceRegKey:
RegCloseKey(TcpipInterfaceRegKey);
cleanupTcpipAdapterRegKey:
RegCloseKey(TcpipAdapterRegKey);
cleanupAdapter:
- if (Result != ERROR_SUCCESS)
- HeapFree(ModuleHeap, 0, a);
+ if (LastError != ERROR_SUCCESS)
+ {
+ HeapFree(ModuleHeap, 0, Adapter);
+ Adapter = NULL;
+ }
cleanupNetDevRegKey:
RegCloseKey(NetDevRegKey);
cleanupDevice:
- if (Result != ERROR_SUCCESS)
+ 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),
@@ -1523,120 +1624,137 @@ cleanupDriverInfoList:
SetupDiDestroyDriverInfoList(DevInfo, &DevInfoData, SPDIT_COMPATDRIVER);
cleanupDevInfo:
SetupDiDestroyDeviceInfoList(DevInfo);
- return Result;
+ return RET_ERROR(Adapter, LastError);
}
-static WINTUN_STATUS
-GetAdapter(_In_z_ const WCHAR *Pool, _In_ const GUID *CfgInstanceID, _Out_ WINTUN_ADAPTER **Adapter)
+static _Return_type_success_(return != NULL)
+ WINTUN_ADAPTER *GetAdapter(_In_z_ const WCHAR *Pool, _In_ const GUID *CfgInstanceID)
{
HANDLE Mutex = NamespaceTakePoolMutex(Pool);
if (!Mutex)
- return ERROR_INVALID_HANDLE;
+ {
+ LOG(WINTUN_LOG_ERR, L"Failed to take pool mutex");
+ return NULL;
+ }
+ DWORD LastError;
+ WINTUN_ADAPTER *Adapter = NULL;
HDEVINFO DevInfo;
SP_DEVINFO_DATA DevInfoData;
- DWORD Result = GetDevInfoData(CfgInstanceID, &DevInfo, &DevInfoData);
- if (Result != ERROR_SUCCESS)
+ if (!GetDevInfoData(CfgInstanceID, &DevInfo, &DevInfoData))
{
- LOG(WINTUN_LOG_ERR, L"Failed to locate adapter");
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to locate adapter");
goto cleanupMutex;
}
- Result = CreateAdapterData(Pool, DevInfo, &DevInfoData, Adapter);
- if (Result != ERROR_SUCCESS)
- LOG(WINTUN_LOG_ERR, L"Failed to create adapter data");
+ Adapter = CreateAdapterData(Pool, DevInfo, &DevInfoData);
+ LastError = Adapter ? ERROR_SUCCESS : LOG(WINTUN_LOG_ERR, L"Failed to create adapter data");
SetupDiDestroyDeviceInfoList(DevInfo);
cleanupMutex:
NamespaceReleaseMutex(Mutex);
- return Result;
+ return RET_ERROR(Adapter, LastError);
}
#include "rundll32.h"
-WINTUN_STATUS WINAPI
-WintunCreateAdapter(
+_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_ WINTUN_ADAPTER **Adapter,
_Out_opt_ BOOL *RebootRequired)
{
if (!ElevateToSystem())
- return LOG_LAST_ERROR(L"Failed to impersonate SYSTEM user");
+ {
+ LOG(WINTUN_LOG_ERR, L"Failed to impersonate SYSTEM user");
+ return NULL;
+ }
BOOL DummyRebootRequired;
if (!RebootRequired)
RebootRequired = &DummyRebootRequired;
*RebootRequired = FALSE;
- DWORD Result;
+ DWORD LastError;
+ WINTUN_ADAPTER *Adapter;
if (MAYBE_WOW64 && NativeMachine != IMAGE_FILE_PROCESS)
- Result = CreateAdapterViaRundll32(Pool, Name, RequestedGUID, Adapter, RebootRequired);
- else
- Result = CreateAdapter(Pool, Name, RequestedGUID, Adapter, RebootRequired);
+ {
+ Adapter = CreateAdapterViaRundll32(Pool, Name, RequestedGUID, RebootRequired);
+ LastError = Adapter ? ERROR_SUCCESS : GetLastError();
+ goto cleanupToken;
+ }
+ Adapter = CreateAdapter(Pool, Name, RequestedGUID, RebootRequired);
+ LastError = Adapter ? ERROR_SUCCESS : GetLastError();
+cleanupToken:
RevertToSelf();
- return Result;
+ return RET_ERROR(Adapter, LastError);
}
-WINTUN_STATUS WINAPI
-WintunDeleteAdapter(_In_ const WINTUN_ADAPTER *Adapter, _In_ BOOL ForceCloseSessions, _Out_opt_ BOOL *RebootRequired)
+_Return_type_success_(return != FALSE) BOOL WINAPI WintunDeleteAdapter(
+ _In_ const WINTUN_ADAPTER *Adapter,
+ _In_ BOOL ForceCloseSessions,
+ _Out_opt_ BOOL *RebootRequired)
{
if (!ElevateToSystem())
- return LOG_LAST_ERROR(L"Failed to impersonate SYSTEM user");
-
+ {
+ LOG(WINTUN_LOG_ERR, L"Failed to impersonate SYSTEM user");
+ return FALSE;
+ }
BOOL DummyRebootRequired;
if (!RebootRequired)
RebootRequired = &DummyRebootRequired;
*RebootRequired = FALSE;
- DWORD Result;
+ DWORD LastError;
if (MAYBE_WOW64 && NativeMachine != IMAGE_FILE_PROCESS)
{
- Result = DeleteAdapterViaRundll32(Adapter, ForceCloseSessions, RebootRequired);
- RevertToSelf();
- return Result;
+ LastError =
+ DeleteAdapterViaRundll32(Adapter, ForceCloseSessions, RebootRequired) ? ERROR_SUCCESS : GetLastError();
+ goto cleanupToken;
}
HDEVINFO DevInfo;
SP_DEVINFO_DATA DevInfoData;
- Result = GetDevInfoData(&Adapter->CfgInstanceID, &DevInfo, &DevInfoData);
- if (Result == ERROR_FILE_NOT_FOUND)
+ if (!GetDevInfoData(&Adapter->CfgInstanceID, &DevInfo, &DevInfoData))
{
- Result = ERROR_SUCCESS;
- goto cleanupToken;
- }
- else if (Result != ERROR_SUCCESS)
- {
- LOG(WINTUN_LOG_ERR, L"Failed to get adapter info data");
+ if ((LastError = GetLastError()) == ERROR_FILE_NOT_FOUND)
+ LastError = ERROR_SUCCESS;
+ else
+ LOG(WINTUN_LOG_ERR, L"Failed to get adapter info data");
goto cleanupToken;
}
- if (ForceCloseSessions && ForceCloseWintunAdapterHandle(DevInfo, &DevInfoData) != ERROR_SUCCESS)
+ if (ForceCloseSessions && !ForceCloseWintunAdapterHandle(DevInfo, &DevInfoData))
LOG(WINTUN_LOG_WARN, L"Failed to force close adapter handles");
SetQuietInstall(DevInfo, &DevInfoData);
- 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);
- else
- Result = LOG_LAST_ERROR(L"Failed to remove existing adapter");
+ 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))
+ {
+ LastError = LOG_LAST_ERROR(L"Failed to remove existing adapter");
+ goto cleanupDevInfo;
+ }
+ LastError = ERROR_SUCCESS;
+cleanupDevInfo:
+ *RebootRequired = *RebootRequired || CheckReboot(DevInfo, &DevInfoData);
SetupDiDestroyDeviceInfoList(DevInfo);
cleanupToken:
RevertToSelf();
- return Result;
+ return RET_ERROR(TRUE, LastError);
}
-static WINTUN_STATUS
-DeleteAllOurAdapters(_In_ const WCHAR Pool[WINTUN_MAX_POOL], _Inout_ BOOL *RebootRequired)
+static _Return_type_success_(return != FALSE) BOOL
+ DeleteAllOurAdapters(_In_ const WCHAR Pool[WINTUN_MAX_POOL], _Inout_ BOOL *RebootRequired)
{
HANDLE Mutex = NamespaceTakePoolMutex(Pool);
if (!Mutex)
- return ERROR_INVALID_HANDLE;
- DWORD Result = ERROR_SUCCESS;
+ {
+ LOG(WINTUN_LOG_ERR, L"Failed to take pool mutex");
+ return FALSE;
+ }
+ DWORD LastError = ERROR_SUCCESS;
HDEVINFO DevInfo = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL);
if (DevInfo == INVALID_HANDLE_VALUE)
{
- NamespaceReleaseMutex(Mutex);
- return LOG_LAST_ERROR(L"Failed to get present adapters");
+ LastError = LOG_LAST_ERROR(L"Failed to get present adapters");
+ goto cleanupMutex;
}
SP_REMOVEDEVICE_PARAMS Params = { .ClassInstallHeader = { .cbSize = sizeof(SP_CLASSINSTALL_HEADER),
.InstallFunction = DIF_REMOVE },
@@ -1651,76 +1769,70 @@ DeleteAllOurAdapters(_In_ const WCHAR Pool[WINTUN_MAX_POOL], _Inout_ BOOL *Reboo
continue;
}
- BOOL IsOurs;
- if (IsOurAdapter(DevInfo, &DevInfoData, &IsOurs) != ERROR_SUCCESS || !IsOurs)
- continue;
- BOOL IsMember;
- Result = IsPoolMember(Pool, DevInfo, &DevInfoData, &IsMember);
- if (Result != ERROR_SUCCESS)
- {
- LOG(WINTUN_LOG_ERR, L"Failed to get pool membership");
- break;
- }
- if (!IsMember)
+ if (!IsOurAdapter(DevInfo, &DevInfoData) || !IsPoolMember(Pool, DevInfo, &DevInfoData))
continue;
LOG(WINTUN_LOG_INFO, L"Force closing all open handles for existing adapter");
- if (ForceCloseWintunAdapterHandle(DevInfo, &DevInfoData) != ERROR_SUCCESS)
+ if (!ForceCloseWintunAdapterHandle(DevInfo, &DevInfoData))
LOG(WINTUN_LOG_WARN, L"Failed to force close adapter handles");
LOG(WINTUN_LOG_INFO, L"Removing existing adapter");
- if (SetupDiSetClassInstallParamsW(DevInfo, &DevInfoData, &Params.ClassInstallHeader, sizeof(Params)) &&
- SetupDiCallClassInstaller(DIF_REMOVE, DevInfo, &DevInfoData))
- *RebootRequired = *RebootRequired || CheckReboot(DevInfo, &DevInfoData);
- else
+ if (!SetupDiSetClassInstallParamsW(DevInfo, &DevInfoData, &Params.ClassInstallHeader, sizeof(Params)) ||
+ !SetupDiCallClassInstaller(DIF_REMOVE, DevInfo, &DevInfoData))
{
LOG_LAST_ERROR(L"Failed to remove existing adapter");
- Result = Result != ERROR_SUCCESS ? Result : GetLastError();
+ LastError = LastError != ERROR_SUCCESS ? LastError : GetLastError();
}
+ *RebootRequired = *RebootRequired || CheckReboot(DevInfo, &DevInfoData);
}
SetupDiDestroyDeviceInfoList(DevInfo);
+cleanupMutex:
NamespaceReleaseMutex(Mutex);
- return Result;
+ return RET_ERROR(TRUE, LastError);
}
-WINTUN_STATUS WINAPI
-WintunDeletePoolDriver(_In_z_ const WCHAR Pool[WINTUN_MAX_POOL], _Out_opt_ BOOL *RebootRequired)
+_Return_type_success_(return != FALSE) BOOL WINAPI
+ WintunDeletePoolDriver(_In_z_ const WCHAR *Pool, _Out_opt_ BOOL *RebootRequired)
{
if (!ElevateToSystem())
- return LOG_LAST_ERROR(L"Failed to impersonate SYSTEM user");
+ {
+ LOG(WINTUN_LOG_ERR, L"Failed to impersonate SYSTEM user");
+ return FALSE;
+ }
BOOL DummyRebootRequired;
if (!RebootRequired)
RebootRequired = &DummyRebootRequired;
*RebootRequired = FALSE;
- DWORD Result;
+ DWORD LastError = ERROR_SUCCESS;
if (MAYBE_WOW64 && NativeMachine != IMAGE_FILE_PROCESS)
{
- Result = DeletePoolDriverViaRundll32(Pool, RebootRequired);
- RevertToSelf();
- return Result;
+ LastError = DeletePoolDriverViaRundll32(Pool, RebootRequired) ? ERROR_SUCCESS : GetLastError();
+ goto cleanupToken;
}
- Result = DeleteAllOurAdapters(Pool, RebootRequired);
- if (Result != ERROR_SUCCESS)
+ if (!DeleteAllOurAdapters(Pool, RebootRequired))
+ {
+ LastError = GetLastError();
goto cleanupToken;
+ }
HANDLE DriverInstallationLock = NamespaceTakeDriverInstallationMutex();
if (!DriverInstallationLock)
{
- Result = LOG_LAST_ERROR(L"Failed to take driver installation mutex");
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to take driver installation mutex");
goto cleanupToken;
}
HDEVINFO DeviceInfoSet = SetupDiGetClassDevsW(&GUID_DEVCLASS_NET, NULL, NULL, 0);
if (!DeviceInfoSet)
{
- Result = LOG_LAST_ERROR(L"Failed to get adapter information");
+ LastError = LOG_LAST_ERROR(L"Failed to get adapter information");
goto cleanupDriverInstallationLock;
}
if (!SetupDiBuildDriverInfoList(DeviceInfoSet, NULL, SPDIT_CLASSDRIVER))
{
- Result = LOG_LAST_ERROR(L"Failed building driver info list");
+ LastError = LOG_LAST_ERROR(L"Failed building driver info list");
goto cleanupDeviceInfoSet;
}
for (DWORD EnumIndex = 0;; ++EnumIndex)
@@ -1732,16 +1844,16 @@ WintunDeletePoolDriver(_In_z_ const WCHAR Pool[WINTUN_MAX_POOL], _Out_opt_ BOOL
break;
continue;
}
- SP_DRVINFO_DETAIL_DATA_W *DriverDetail;
- if (GetAdapterDrvInfoDetail(DeviceInfoSet, NULL, &DriverInfo, &DriverDetail) != ERROR_SUCCESS)
+ SP_DRVINFO_DETAIL_DATA_W *DriverDetail = GetAdapterDrvInfoDetail(DeviceInfoSet, NULL, &DriverInfo);
+ if (!DriverDetail)
continue;
if (!_wcsicmp(DriverDetail->HardwareID, WINTUN_HWID))
{
- LOG(WINTUN_LOG_INFO, TEXT("Removing existing driver"));
+ LOG(WINTUN_LOG_INFO, L"Removing existing driver");
if (!SetupUninstallOEMInfW(PathFindFileNameW(DriverDetail->InfFileName), 0, NULL))
{
- LOG_LAST_ERROR(TEXT("Unable to remove existing driver"));
- Result = Result != ERROR_SUCCESS ? Result : GetLastError();
+ LOG_LAST_ERROR(L"Unable to remove existing driver");
+ LastError = LastError != ERROR_SUCCESS ? LastError : GetLastError();
}
}
HeapFree(ModuleHeap, 0, DriverDetail);
@@ -1753,20 +1865,23 @@ cleanupDriverInstallationLock:
NamespaceReleaseMutex(DriverInstallationLock);
cleanupToken:
RevertToSelf();
- return Result;
+ return RET_ERROR(TRUE, LastError);
}
-WINTUN_STATUS WINAPI
-WintunEnumAdapters(_In_z_ const WCHAR *Pool, _In_ WINTUN_ENUM_CALLBACK_FUNC Func, _In_ LPARAM Param)
+_Return_type_success_(return != FALSE) BOOL WINAPI
+ WintunEnumAdapters(_In_z_ const WCHAR *Pool, _In_ WINTUN_ENUM_CALLBACK_FUNC Func, _In_ LPARAM Param)
{
HANDLE Mutex = NamespaceTakePoolMutex(Pool);
if (!Mutex)
- return ERROR_INVALID_HANDLE;
- DWORD Result = ERROR_SUCCESS;
+ {
+ LOG(WINTUN_LOG_ERR, L"Failed to take pool mutex");
+ return FALSE;
+ }
+ DWORD LastError = ERROR_SUCCESS;
HDEVINFO DevInfo = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL);
if (DevInfo == INVALID_HANDLE_VALUE)
{
- Result = LOG_LAST_ERROR(L"Failed to get present adapters");
+ LastError = LOG_LAST_ERROR(L"Failed to get present adapters");
goto cleanupMutex;
}
BOOL Continue = TRUE;
@@ -1780,25 +1895,13 @@ WintunEnumAdapters(_In_z_ const WCHAR *Pool, _In_ WINTUN_ENUM_CALLBACK_FUNC Func
continue;
}
- BOOL IsOurs;
- if (IsOurAdapter(DevInfo, &DevInfoData, &IsOurs) != ERROR_SUCCESS || !IsOurs)
- continue;
-
- BOOL IsMember;
- Result = IsPoolMember(Pool, DevInfo, &DevInfoData, &IsMember);
- if (Result != ERROR_SUCCESS)
- {
- LOG(WINTUN_LOG_ERR, L"Failed to get pool membership");
- break;
- }
- if (!IsMember)
+ if (!IsOurAdapter(DevInfo, &DevInfoData) || !IsPoolMember(Pool, DevInfo, &DevInfoData))
continue;
- WINTUN_ADAPTER *Adapter;
- Result = CreateAdapterData(Pool, DevInfo, &DevInfoData, &Adapter);
- if (Result != ERROR_SUCCESS)
+ WINTUN_ADAPTER *Adapter = CreateAdapterData(Pool, DevInfo, &DevInfoData);
+ if (!Adapter)
{
- LOG(WINTUN_LOG_ERR, L"Failed to create adapter data");
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to create adapter data");
break;
}
Continue = Func(Adapter, Param);
@@ -1807,5 +1910,5 @@ WintunEnumAdapters(_In_z_ const WCHAR *Pool, _In_ WINTUN_ENUM_CALLBACK_FUNC Func
SetupDiDestroyDeviceInfoList(DevInfo);
cleanupMutex:
NamespaceReleaseMutex(Mutex);
- return Result;
+ return RET_ERROR(TRUE, LastError);
}
diff --git a/api/adapter.h b/api/adapter.h
index cd890ab..3f4532a 100644
--- a/api/adapter.h
+++ b/api/adapter.h
@@ -37,28 +37,28 @@ WintunFreeAdapter(_In_ WINTUN_ADAPTER *Adapter);
/**
* @copydoc WINTUN_OPEN_ADAPTER_DEVICE_OBJECT_FUNC
*/
-WINTUN_STATUS WINAPI
-WintunOpenAdapterDeviceObject(_In_ const WINTUN_ADAPTER *Adapter, _Out_ HANDLE *Handle);
+_Return_type_success_(return != INVALID_HANDLE_VALUE) HANDLE WINAPI
+ WintunOpenAdapterDeviceObject(_In_ const WINTUN_ADAPTER *Adapter);
/**
* @copydoc WINTUN_CREATE_ADAPTER_FUNC
*/
-WINTUN_STATUS WINAPI
-WintunCreateAdapter(
+_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_ WINTUN_ADAPTER **Adapter,
_Out_opt_ BOOL *RebootRequired);
/**
* @copydoc WINTUN_DELETE_ADAPTER_FUNC
*/
-WINTUN_STATUS WINAPI
-WintunDeleteAdapter(_In_ const WINTUN_ADAPTER *Adapter, _In_ BOOL ForceCloseSessions, _Out_opt_ BOOL *RebootRequired);
+_Return_type_success_(return != FALSE) BOOL WINAPI WintunDeleteAdapter(
+ _In_ const WINTUN_ADAPTER *Adapter,
+ _In_ BOOL ForceCloseSessions,
+ _Out_opt_ BOOL *RebootRequired);
/**
* @copydoc WINTUN_DELETE_POOL_DRIVER_FUNC
*/
-WINTUN_STATUS WINAPI
-WintunDeletePoolDriver(_In_z_ const WCHAR Pool[WINTUN_MAX_POOL], _Out_opt_ BOOL *RebootRequired);
+_Return_type_success_(return != FALSE) BOOL WINAPI
+ WintunDeletePoolDriver(_In_z_ const WCHAR *Pool, _Out_opt_ BOOL *RebootRequired);
diff --git a/api/elevate.c b/api/elevate.c
index e89a54c..57bafbf 100644
--- a/api/elevate.c
+++ b/api/elevate.c
@@ -4,12 +4,12 @@
*/
#include "elevate.h"
+#include "logger.h"
#include <Windows.h>
#include <TlHelp32.h>
-BOOL
-ElevateToSystem(void)
+_Return_type_success_(return != FALSE) BOOL ElevateToSystem(void)
{
HANDLE CurrentProcessToken, ThreadToken, ProcessSnapshot, WinlogonProcess, WinlogonToken, DuplicatedToken;
PROCESSENTRY32W ProcessEntry = { .dwSize = sizeof(PROCESSENTRY32W) };
@@ -25,29 +25,40 @@ ElevateToSystem(void)
} TokenUserBuffer;
Ret = CreateWellKnownSid(WinLocalSystemSid, NULL, &LocalSystemSid, &RequiredBytes);
- LastError = GetLastError();
if (!Ret)
+ {
+ LastError = LOG_LAST_ERROR(L"Failed to create SID");
goto cleanup;
+ }
Ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &CurrentProcessToken);
- LastError = GetLastError();
if (!Ret)
+ {
+ LastError = LOG_LAST_ERROR(L"Failed to open process token");
goto cleanup;
+ }
Ret =
GetTokenInformation(CurrentProcessToken, TokenUser, &TokenUserBuffer, sizeof(TokenUserBuffer), &RequiredBytes);
LastError = GetLastError();
CloseHandle(CurrentProcessToken);
if (!Ret)
+ {
+ LOG_ERROR(L"Failed to get token information", LastError);
goto cleanup;
+ }
if (EqualSid(TokenUserBuffer.MaybeLocalSystem.User.Sid, LocalSystemSid))
return TRUE;
Ret = LookupPrivilegeValueW(NULL, SE_DEBUG_NAME, &Privileges.Privileges[0].Luid);
- LastError = GetLastError();
if (!Ret)
+ {
+ LastError = LOG_LAST_ERROR(L"Failed to lookup privilege value");
goto cleanup;
+ }
ProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
- LastError = GetLastError();
if (ProcessSnapshot == INVALID_HANDLE_VALUE)
+ {
+ LastError = LOG_LAST_ERROR(L"Failed to create toolhelp snapshot");
goto cleanup;
+ }
for (Ret = Process32FirstW(ProcessSnapshot, &ProcessEntry); Ret;
Ret = Process32NextW(ProcessSnapshot, &ProcessEntry))
{
@@ -55,13 +66,17 @@ ElevateToSystem(void)
continue;
RevertToSelf();
Ret = ImpersonateSelf(SecurityImpersonation);
- LastError = GetLastError();
if (!Ret)
+ {
+ LastError = GetLastError();
continue;
+ }
Ret = OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, FALSE, &ThreadToken);
- LastError = GetLastError();
if (!Ret)
+ {
+ LastError = GetLastError();
continue;
+ }
Ret = AdjustTokenPrivileges(ThreadToken, FALSE, &Privileges, sizeof(Privileges), NULL, NULL);
LastError = GetLastError();
CloseHandle(ThreadToken);
@@ -69,9 +84,11 @@ ElevateToSystem(void)
continue;
WinlogonProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, ProcessEntry.th32ProcessID);
- LastError = GetLastError();
if (!WinlogonProcess)
+ {
+ LastError = GetLastError();
continue;
+ }
Ret = OpenProcessToken(WinlogonProcess, TOKEN_IMPERSONATE | TOKEN_DUPLICATE, &WinlogonToken);
LastError = GetLastError();
CloseHandle(WinlogonProcess);
@@ -84,13 +101,15 @@ ElevateToSystem(void)
continue;
if (!GetTokenInformation(DuplicatedToken, TokenUser, &TokenUserBuffer, sizeof(TokenUserBuffer), &RequiredBytes))
goto next;
- if (SetLastError(ERROR_ACCESS_DENIED), !EqualSid(TokenUserBuffer.MaybeLocalSystem.User.Sid, LocalSystemSid))
+ if (!EqualSid(TokenUserBuffer.MaybeLocalSystem.User.Sid, LocalSystemSid))
+ {
+ SetLastError(ERROR_ACCESS_DENIED);
goto next;
+ }
if (!SetThreadToken(NULL, DuplicatedToken))
goto next;
CloseHandle(DuplicatedToken);
CloseHandle(ProcessSnapshot);
- SetLastError(ERROR_SUCCESS);
return TRUE;
next:
LastError = GetLastError();
@@ -103,8 +122,7 @@ cleanup:
return FALSE;
}
-HANDLE
-GetPrimarySystemTokenFromThread(void)
+_Return_type_success_(return != NULL) HANDLE GetPrimarySystemTokenFromThread(void)
{
HANDLE CurrentThreadToken, DuplicatedToken;
BOOL Ret;
@@ -120,26 +138,41 @@ GetPrimarySystemTokenFromThread(void)
Ret = CreateWellKnownSid(WinLocalSystemSid, NULL, &LocalSystemSid, &RequiredBytes);
if (!Ret)
+ {
+ LastError = LOG_LAST_ERROR(L"Failed to create SID");
return NULL;
+ }
Ret = OpenThreadToken(
GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES | TOKEN_DUPLICATE, FALSE, &CurrentThreadToken);
if (!Ret)
+ {
+ LastError = LOG_LAST_ERROR(L"Failed to open thread token");
return NULL;
+ }
Ret = GetTokenInformation(CurrentThreadToken, TokenUser, &TokenUserBuffer, sizeof(TokenUserBuffer), &RequiredBytes);
- LastError = GetLastError();
if (!Ret)
+ {
+ LastError = LOG_LAST_ERROR(L"Failed to get token information");
goto cleanup;
- LastError = ERROR_ACCESS_DENIED;
+ }
if (!EqualSid(TokenUserBuffer.MaybeLocalSystem.User.Sid, LocalSystemSid))
+ {
+ LOG(WINTUN_LOG_ERR, L"Not SYSTEM");
+ LastError = ERROR_ACCESS_DENIED;
goto cleanup;
+ }
Ret = LookupPrivilegeValueW(NULL, SE_ASSIGNPRIMARYTOKEN_NAME, &Privileges.Privileges[0].Luid);
- LastError = GetLastError();
if (!Ret)
+ {
+ LastError = LOG_LAST_ERROR(L"Failed to lookup privilege value");
goto cleanup;
+ }
Ret = AdjustTokenPrivileges(CurrentThreadToken, FALSE, &Privileges, sizeof(Privileges), NULL, NULL);
- LastError = GetLastError();
if (!Ret)
+ {
+ LastError = LOG_LAST_ERROR(L"Failed to adjust token privileges");
goto cleanup;
+ }
Ret = DuplicateTokenEx(
CurrentThreadToken,
TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY,
@@ -147,14 +180,16 @@ GetPrimarySystemTokenFromThread(void)
SecurityImpersonation,
TokenPrimary,
&DuplicatedToken);
- LastError = GetLastError();
if (!Ret)
+ {
+ LastError = LOG_LAST_ERROR(L"Failed to duplicate token");
goto cleanup;
+ }
CloseHandle(CurrentThreadToken);
return DuplicatedToken;
cleanup:
CloseHandle(CurrentThreadToken);
SetLastError(LastError);
- return FALSE;
+ return NULL;
}
diff --git a/api/elevate.h b/api/elevate.h
index 5f2cbbd..aa0fc60 100644
--- a/api/elevate.h
+++ b/api/elevate.h
@@ -7,8 +7,6 @@
#include <Windows.h>
-BOOL
-ElevateToSystem(void);
+_Return_type_success_(return != FALSE) BOOL ElevateToSystem(void);
-HANDLE
-GetPrimarySystemTokenFromThread(void); \ No newline at end of file
+_Return_type_success_(return != NULL) HANDLE GetPrimarySystemTokenFromThread(void);
diff --git a/api/entry.c b/api/entry.c
index 4b56a12..6afccbc 100644
--- a/api/entry.c
+++ b/api/entry.c
@@ -22,7 +22,8 @@ HINSTANCE ResourceModule;
HANDLE ModuleHeap;
SECURITY_ATTRIBUTES SecurityAttributes = { .nLength = sizeof(SECURITY_ATTRIBUTES) };
-static FARPROC WINAPI DelayedLoadLibraryHook(unsigned dliNotify, PDelayLoadInfo pdli)
+static FARPROC WINAPI
+DelayedLoadLibraryHook(unsigned dliNotify, PDelayLoadInfo pdli)
{
if (dliNotify != dliNotePreLoadLibrary)
return NULL;
@@ -53,7 +54,7 @@ DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved)
break;
case DLL_PROCESS_DETACH:
- NamespaceCleanup();
+ NamespaceDone();
LocalFree(SecurityAttributes.lpSecurityDescriptor);
HeapDestroy(ModuleHeap);
break;
diff --git a/api/entry.h b/api/entry.h
index ac37680..4f925b1 100644
--- a/api/entry.h
+++ b/api/entry.h
@@ -26,6 +26,8 @@
#endif
#pragma warning(disable : 4127) /* conditional expression is constant */
+#define RET_ERROR(Ret, Error) ((Error) == ERROR_SUCCESS ? (Ret) : (SetLastError(Error), 0))
+
extern HINSTANCE ResourceModule;
extern HANDLE ModuleHeap;
extern SECURITY_ATTRIBUTES SecurityAttributes;
diff --git a/api/logger.h b/api/logger.h
index 5e26de3..0affdc3 100644
--- a/api/logger.h
+++ b/api/logger.h
@@ -16,20 +16,29 @@ extern WINTUN_LOGGER_CALLBACK_FUNC Logger;
void WINAPI
WintunSetLogger(_In_ WINTUN_LOGGER_CALLBACK_FUNC NewLogger);
+static inline _Post_equals_last_error_ DWORD
+LoggerLog(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ const WCHAR *LogLine)
+{
+ DWORD LastError = GetLastError();
+ Logger(Level, LogLine);
+ SetLastError(LastError);
+ return LastError;
+}
+
_Post_equals_last_error_ DWORD
LoggerError(_In_z_ const WCHAR *Prefix, _In_ DWORD Error);
static inline _Post_equals_last_error_ DWORD
LoggerLastError(_In_z_ const WCHAR *Prefix)
{
- DWORD Error = GetLastError();
- LoggerError(Prefix, Error);
- SetLastError(Error);
- return Error;
+ DWORD LastError = GetLastError();
+ LoggerError(Prefix, LastError);
+ SetLastError(LastError);
+ return LastError;
}
#define __L(x) L##x
#define _L(x) __L(x)
-#define LOG(lvl, msg) (Logger((lvl), _L(__FUNCTION__) L": " msg))
+#define LOG(lvl, msg) (LoggerLog((lvl), _L(__FUNCTION__) L": " msg))
#define LOG_ERROR(msg, err) (LoggerError(_L(__FUNCTION__) L": " msg, (err)))
#define LOG_LAST_ERROR(msg) (LoggerLastError(_L(__FUNCTION__) L": " msg))
diff --git a/api/namespace.c b/api/namespace.c
index 7f6959b..883a1a7 100644
--- a/api/namespace.c
+++ b/api/namespace.c
@@ -15,41 +15,48 @@ static BOOL HasInitialized = FALSE;
static CRITICAL_SECTION Initializing;
static BCRYPT_ALG_HANDLE AlgProvider;
-static WCHAR *
-NormalizeStringAlloc(_In_ NORM_FORM NormForm, _In_z_ const WCHAR *Source)
+static _Return_type_success_(
+ return != NULL) WCHAR *NormalizeStringAlloc(_In_ NORM_FORM NormForm, _In_z_ const WCHAR *Source)
{
int Len = NormalizeString(NormForm, Source, -1, NULL, 0);
for (;;)
{
WCHAR *Str = HeapAlloc(ModuleHeap, 0, sizeof(WCHAR) * Len);
if (!Str)
- return LOG(WINTUN_LOG_ERR, L"Out of memory"), NULL;
+ {
+ LOG(WINTUN_LOG_ERR, L"Out of memory");
+ SetLastError(ERROR_OUTOFMEMORY);
+ return NULL;
+ }
Len = NormalizeString(NormForm, Source, -1, Str, Len);
if (Len > 0)
return Str;
- DWORD Result = GetLastError();
+ DWORD LastError = GetLastError();
HeapFree(ModuleHeap, 0, Str);
- if (Result != ERROR_INSUFFICIENT_BUFFER)
- return LOG_ERROR(L"Failed", Result), NULL;
+ if (LastError != ERROR_INSUFFICIENT_BUFFER)
+ {
+ SetLastError(LOG_ERROR(L"Failed", LastError));
+ return NULL;
+ }
Len = -Len;
}
}
-static WINTUN_STATUS
-NamespaceRuntimeInit(void)
+static _Return_type_success_(return != FALSE) BOOL NamespaceRuntimeInit(void)
{
- DWORD Result;
+ DWORD LastError;
EnterCriticalSection(&Initializing);
if (HasInitialized)
{
LeaveCriticalSection(&Initializing);
- return ERROR_SUCCESS;
+ return TRUE;
}
if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&AlgProvider, BCRYPT_SHA256_ALGORITHM, NULL, 0)))
{
- Result = ERROR_GEN_FAILURE;
+ LOG(WINTUN_LOG_ERR, L"Failed to open algorithm provider");
+ LastError = ERROR_GEN_FAILURE;
goto cleanupLeaveCriticalSection;
}
@@ -57,19 +64,19 @@ NamespaceRuntimeInit(void)
DWORD SidSize = MAX_SID_SIZE;
if (!CreateWellKnownSid(WinLocalSystemSid, NULL, Sid, &SidSize))
{
- Result = GetLastError();
+ LastError = LOG_LAST_ERROR(L"Failed to create SID");
goto cleanupBCryptCloseAlgorithmProvider;
}
HANDLE Boundary = CreateBoundaryDescriptorW(L"Wintun", 0);
if (!Boundary)
{
- Result = GetLastError();
+ LastError = LOG_LAST_ERROR(L"Failed to create boundary descriptor");
goto cleanupBCryptCloseAlgorithmProvider;
}
if (!AddSIDToBoundaryDescriptor(&Boundary, Sid))
{
- Result = GetLastError();
+ LastError = LOG_LAST_ERROR(L"Failed to add SID to boundary descriptor");
goto cleanupBCryptCloseAlgorithmProvider;
}
@@ -77,98 +84,124 @@ NamespaceRuntimeInit(void)
{
if (CreatePrivateNamespaceW(&SecurityAttributes, Boundary, L"Wintun"))
break;
- Result = GetLastError();
- if (Result == ERROR_ALREADY_EXISTS)
+ if ((LastError = GetLastError()) == ERROR_ALREADY_EXISTS)
{
if (OpenPrivateNamespaceW(Boundary, L"Wintun"))
break;
- Result = GetLastError();
- if (Result == ERROR_PATH_NOT_FOUND)
+ if ((LastError = GetLastError()) == ERROR_PATH_NOT_FOUND)
continue;
+ LOG_ERROR(L"Failed to open private namespace", LastError);
}
+ else
+ LOG_ERROR(L"Failed to create private namespace", LastError);
goto cleanupBCryptCloseAlgorithmProvider;
}
HasInitialized = TRUE;
- Result = ERROR_SUCCESS;
- goto cleanupLeaveCriticalSection;
+ LeaveCriticalSection(&Initializing);
+ return TRUE;
cleanupBCryptCloseAlgorithmProvider:
BCryptCloseAlgorithmProvider(AlgProvider, 0);
cleanupLeaveCriticalSection:
LeaveCriticalSection(&Initializing);
- return Result;
+ SetLastError(LastError);
+ return FALSE;
}
_Check_return_
-HANDLE
-NamespaceTakePoolMutex(_In_z_ const WCHAR *Pool)
+_Return_type_success_(return != NULL) HANDLE NamespaceTakePoolMutex(_In_z_ const WCHAR *Pool)
{
- HANDLE Mutex = NULL;
-
- if (NamespaceRuntimeInit() != ERROR_SUCCESS)
+ if (!NamespaceRuntimeInit())
return NULL;
BCRYPT_HASH_HANDLE Sha256 = NULL;
if (!BCRYPT_SUCCESS(BCryptCreateHash(AlgProvider, &Sha256, NULL, 0, NULL, 0, 0)))
+ {
+ LOG(WINTUN_LOG_ERR, L"Failed to create hash");
+ SetLastError(ERROR_GEN_FAILURE);
return NULL;
+ }
+ DWORD LastError;
static const WCHAR mutex_label[] = L"Wintun Adapter Name Mutex Stable Suffix v1 jason@zx2c4.com";
- if (!BCRYPT_SUCCESS(BCryptHashData(Sha256, (PUCHAR)mutex_label, sizeof(mutex_label) /* Including NULL 2 bytes */, 0)))
+ if (!BCRYPT_SUCCESS(
+ BCryptHashData(Sha256, (PUCHAR)mutex_label, sizeof(mutex_label) /* Including NULL 2 bytes */, 0)))
+ {
+ LOG(WINTUN_LOG_ERR, L"Failed to hash data");
+ LastError = ERROR_GEN_FAILURE;
goto cleanupSha256;
+ }
WCHAR *PoolNorm = NormalizeStringAlloc(NormalizationC, Pool);
if (!PoolNorm)
+ {
+ LastError = GetLastError();
goto cleanupSha256;
- if (!BCRYPT_SUCCESS(BCryptHashData(Sha256, (PUCHAR)PoolNorm, (int)wcslen(PoolNorm) + 2 /* Add in NULL 2 bytes */, 0)))
+ }
+ if (!BCRYPT_SUCCESS(
+ BCryptHashData(Sha256, (PUCHAR)PoolNorm, (int)wcslen(PoolNorm) + 2 /* Add in NULL 2 bytes */, 0)))
+ {
+ LOG(WINTUN_LOG_ERR, L"Failed to hash data");
+ LastError = ERROR_GEN_FAILURE;
goto cleanupPoolNorm;
+ }
BYTE Hash[32];
if (!BCRYPT_SUCCESS(BCryptFinishHash(Sha256, Hash, sizeof(Hash), 0)))
+ {
+ LOG(WINTUN_LOG_ERR, L"Failed to calculate hash");
+ LastError = ERROR_GEN_FAILURE;
goto cleanupPoolNorm;
+ }
static const WCHAR MutexNamePrefix[] = L"Wintun\\Wintun-Name-Mutex-";
WCHAR MutexName[_countof(MutexNamePrefix) + sizeof(Hash) * 2];
memcpy(MutexName, MutexNamePrefix, sizeof(MutexNamePrefix));
for (size_t i = 0; i < sizeof(Hash); ++i)
swprintf_s(&MutexName[_countof(MutexNamePrefix) - 1 + i * 2], 3, L"%02x", Hash[i]);
- Mutex = CreateMutexW(&SecurityAttributes, FALSE, MutexName);
+ HANDLE Mutex = CreateMutexW(&SecurityAttributes, FALSE, MutexName);
if (!Mutex)
+ {
+ LastError = LOG_LAST_ERROR(L"Failed to create mutex");
goto cleanupPoolNorm;
+ }
switch (WaitForSingleObject(Mutex, INFINITE))
{
case WAIT_OBJECT_0:
case WAIT_ABANDONED:
- goto cleanupPoolNorm;
+ HeapFree(ModuleHeap, 0, PoolNorm);
+ BCryptDestroyHash(Sha256);
+ return Mutex;
}
-
+ LOG(WINTUN_LOG_ERR, L"Failed to get mutex");
+ LastError = ERROR_GEN_FAILURE;
CloseHandle(Mutex);
- Mutex = NULL;
cleanupPoolNorm:
HeapFree(ModuleHeap, 0, PoolNorm);
cleanupSha256:
BCryptDestroyHash(Sha256);
- return Mutex;
+ SetLastError(LastError);
+ return NULL;
}
_Check_return_
-HANDLE
-NamespaceTakeDriverInstallationMutex(void)
+_Return_type_success_(return != NULL) HANDLE NamespaceTakeDriverInstallationMutex(void)
{
- HANDLE Mutex = NULL;
-
- if (NamespaceRuntimeInit() != ERROR_SUCCESS)
+ if (!NamespaceRuntimeInit())
return NULL;
- Mutex = CreateMutexW(&SecurityAttributes, FALSE, L"Wintun\\Wintun-Driver-Installation-Mutex");
+ HANDLE Mutex = CreateMutexW(&SecurityAttributes, FALSE, L"Wintun\\Wintun-Driver-Installation-Mutex");
if (!Mutex)
+ {
+ LOG_LAST_ERROR(L"Failed to create mutex");
return NULL;
+ }
switch (WaitForSingleObject(Mutex, INFINITE))
{
case WAIT_OBJECT_0:
case WAIT_ABANDONED:
- goto out;
+ return Mutex;
}
-
+ LOG(WINTUN_LOG_ERR, L"Failed to get mutex");
CloseHandle(Mutex);
- Mutex = NULL;
-out:
- return Mutex;
+ SetLastError(ERROR_GEN_FAILURE);
+ return NULL;
}
void
@@ -185,7 +218,7 @@ NamespaceInit(void)
}
void
-NamespaceCleanup(void)
+NamespaceDone(void)
{
EnterCriticalSection(&Initializing);
if (HasInitialized)
diff --git a/api/namespace.h b/api/namespace.h
index 0f2598a..d0f83a1 100644
--- a/api/namespace.h
+++ b/api/namespace.h
@@ -8,12 +8,10 @@
#include <Windows.h>
_Check_return_
-HANDLE
-NamespaceTakePoolMutex(_In_z_ const WCHAR *Pool);
+_Return_type_success_(return != NULL) HANDLE NamespaceTakePoolMutex(_In_z_ const WCHAR *Pool);
_Check_return_
-HANDLE
-NamespaceTakeDriverInstallationMutex(void);
+_Return_type_success_(return != NULL) HANDLE NamespaceTakeDriverInstallationMutex(void);
void
NamespaceReleaseMutex(_In_ HANDLE Mutex);
@@ -22,4 +20,4 @@ void
NamespaceInit(void);
void
-NamespaceCleanup(void);
+NamespaceDone(void);
diff --git a/api/registry.c b/api/registry.c
index 82e3020..523016e 100644
--- a/api/registry.c
+++ b/api/registry.c
@@ -9,42 +9,54 @@
#include <Windows.h>
#include <wchar.h>
-static WINTUN_STATUS
-OpenKeyWait(_In_ HKEY Key, _Inout_z_ WCHAR *Path, _In_ DWORD Access, _In_ ULONGLONG Deadline, _Out_ HKEY *KeyOut)
+static _Return_type_success_(return != NULL) HKEY
+ OpenKeyWait(_In_ HKEY Key, _Inout_z_ WCHAR *Path, _In_ DWORD Access, _In_ ULONGLONG Deadline)
{
- DWORD Result;
+ DWORD LastError;
WCHAR *PathNext = wcschr(Path, L'\\');
if (PathNext)
*PathNext = 0;
HANDLE Event = CreateEventW(NULL, FALSE, FALSE, NULL);
if (!Event)
- return LOG_LAST_ERROR(L"Failed to create event");
+ {
+ LOG_LAST_ERROR(L"Failed to create event");
+ return NULL;
+ }
for (;;)
{
- Result = RegNotifyChangeKeyValue(Key, FALSE, REG_NOTIFY_CHANGE_NAME, Event, TRUE);
- if (Result != ERROR_SUCCESS)
+ LastError = RegNotifyChangeKeyValue(Key, FALSE, REG_NOTIFY_CHANGE_NAME, Event, TRUE);
+ if (LastError != ERROR_SUCCESS)
{
- LOG_ERROR(L"Failed to setup notification", Result);
+ LOG_ERROR(L"Failed to setup notification", LastError);
break;
}
HKEY Subkey;
- Result = RegOpenKeyExW(Key, Path, 0, PathNext ? KEY_NOTIFY : Access, &Subkey);
- if (Result == ERROR_SUCCESS)
+ LastError = RegOpenKeyExW(Key, Path, 0, PathNext ? KEY_NOTIFY : Access, &Subkey);
+ if (LastError == ERROR_SUCCESS)
{
if (PathNext)
{
- Result = OpenKeyWait(Subkey, PathNext + 1, Access, Deadline, KeyOut);
- RegCloseKey(Subkey);
+ HKEY KeyOut = OpenKeyWait(Subkey, PathNext + 1, Access, Deadline);
+ if (KeyOut)
+ {
+ RegCloseKey(Subkey);
+ CloseHandle(Event);
+ return KeyOut;
+ }
+ LastError = GetLastError();
+ break;
}
else
- *KeyOut = Subkey;
- break;
+ {
+ CloseHandle(Event);
+ return Subkey;
+ }
}
- if (Result != ERROR_FILE_NOT_FOUND && Result != ERROR_PATH_NOT_FOUND)
+ if (LastError != ERROR_FILE_NOT_FOUND && LastError != ERROR_PATH_NOT_FOUND)
{
- LOG_ERROR(L"Failed to open", Result);
+ LOG_ERROR(L"Failed to open", LastError);
break;
}
@@ -58,27 +70,35 @@ OpenKeyWait(_In_ HKEY Key, _Inout_z_ WCHAR *Path, _In_ DWORD Access, _In_ ULONGL
}
}
CloseHandle(Event);
- return Result;
+ SetLastError(LastError);
+ return NULL;
}
-WINTUN_STATUS
-RegistryOpenKeyWait(_In_ HKEY Key, _In_z_ const WCHAR *Path, _In_ DWORD Access, _In_ DWORD Timeout, _Out_ HKEY *KeyOut)
+_Return_type_success_(return != NULL) HKEY
+ RegistryOpenKeyWait(_In_ HKEY Key, _In_z_ const WCHAR *Path, _In_ DWORD Access, _In_ DWORD Timeout)
{
WCHAR Buf[MAX_REG_PATH];
if (wcsncpy_s(Buf, _countof(Buf), Path, _TRUNCATE) == STRUNCATE)
- return LOG(WINTUN_LOG_ERR, L"Registry path too long"), ERROR_INVALID_PARAMETER;
- return OpenKeyWait(Key, Buf, Access, GetTickCount64() + Timeout, KeyOut);
+ {
+ LOG(WINTUN_LOG_ERR, L"Registry path too long");
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+ return OpenKeyWait(Key, Buf, Access, GetTickCount64() + Timeout);
}
-WINTUN_STATUS
-RegistryGetString(_Inout_ WCHAR **Buf, _In_ DWORD Len, _In_ DWORD ValueType)
+_Return_type_success_(return != FALSE) BOOL RegistryGetString(_Inout_ WCHAR **Buf, _In_ DWORD Len, _In_ DWORD ValueType)
{
if (wcsnlen(*Buf, Len) >= Len)
{
/* String is missing zero-terminator. */
WCHAR *BufZ = HeapAlloc(ModuleHeap, 0, ((size_t)Len + 1) * sizeof(WCHAR));
if (!BufZ)
- return LOG(WINTUN_LOG_ERR, L"Out of memory"), ERROR_OUTOFMEMORY;
+ {
+ LOG(WINTUN_LOG_ERR, L"Out of memory");
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
wmemcpy(BufZ, *Buf, Len);
BufZ[Len] = 0;
HeapFree(ModuleHeap, 0, *Buf);
@@ -86,25 +106,30 @@ RegistryGetString(_Inout_ WCHAR **Buf, _In_ DWORD Len, _In_ DWORD ValueType)
}
if (ValueType != REG_EXPAND_SZ)
- return ERROR_SUCCESS;
+ return TRUE;
/* ExpandEnvironmentStringsW() returns strlen on success or 0 on error. Bail out on empty input strings to
* disambiguate. */
if (!(*Buf)[0])
- return ERROR_SUCCESS;
+ return TRUE;
Len = Len * 2 + 64;
for (;;)
{
WCHAR *Expanded = HeapAlloc(ModuleHeap, 0, Len * sizeof(WCHAR));
if (!Expanded)
- return LOG(WINTUN_LOG_ERR, L"Out of memory"), ERROR_OUTOFMEMORY;
+ {
+ LOG(WINTUN_LOG_ERR, L"Out of memory");
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
DWORD Result = ExpandEnvironmentStringsW(*Buf, Expanded, Len);
if (!Result)
{
- Result = LOG_LAST_ERROR(L"Failed to expand environment variables");
+ DWORD LastError = LOG_LAST_ERROR(L"Failed to expand environment variables");
HeapFree(ModuleHeap, 0, Expanded);
- return Result;
+ SetLastError(LastError);
+ return FALSE;
}
if (Result > Len)
{
@@ -114,12 +139,12 @@ RegistryGetString(_Inout_ WCHAR **Buf, _In_ DWORD Len, _In_ DWORD ValueType)
}
HeapFree(ModuleHeap, 0, *Buf);
*Buf = Expanded;
- return ERROR_SUCCESS;
+ return TRUE;
}
}
-WINTUN_STATUS
-RegistryGetMultiString(_Inout_ WCHAR **Buf, _In_ DWORD Len, _In_ DWORD ValueType)
+_Return_type_success_(return != FALSE) BOOL
+ RegistryGetMultiString(_Inout_ WCHAR **Buf, _In_ DWORD Len, _In_ DWORD ValueType)
{
if (ValueType == REG_MULTI_SZ)
{
@@ -130,52 +155,61 @@ RegistryGetMultiString(_Inout_ WCHAR **Buf, _In_ DWORD Len, _In_ DWORD ValueType
/* Missing string and list terminators. */
WCHAR *BufZ = HeapAlloc(ModuleHeap, 0, ((size_t)Len + 2) * sizeof(WCHAR));
if (!BufZ)
- return LOG(WINTUN_LOG_ERR, L"Out of memory"), ERROR_OUTOFMEMORY;
+ {
+ LOG(WINTUN_LOG_ERR, L"Out of memory");
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
wmemcpy(BufZ, *Buf, Len);
BufZ[Len] = 0;
BufZ[Len + 1] = 0;
HeapFree(ModuleHeap, 0, *Buf);
*Buf = BufZ;
- return ERROR_SUCCESS;
+ return TRUE;
}
if (i == Len)
{
/* Missing list terminator. */
WCHAR *BufZ = HeapAlloc(ModuleHeap, 0, ((size_t)Len + 1) * sizeof(WCHAR));
if (!BufZ)
- return LOG(WINTUN_LOG_ERR, L"Out of memory"), ERROR_OUTOFMEMORY;
+ {
+ LOG(WINTUN_LOG_ERR, L"Out of memory");
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
wmemcpy(BufZ, *Buf, Len);
BufZ[Len] = 0;
HeapFree(ModuleHeap, 0, *Buf);
*Buf = BufZ;
- return ERROR_SUCCESS;
+ return TRUE;
}
if (!(*Buf)[i])
- return ERROR_SUCCESS;
+ return TRUE;
}
}
/* Sanitize REG_SZ/REG_EXPAND_SZ and append a list terminator to make a multi-string. */
- DWORD Result = RegistryGetString(Buf, Len, ValueType);
- if (Result != ERROR_SUCCESS)
- return Result;
+ if (!RegistryGetString(Buf, Len, ValueType))
+ return FALSE;
Len = (DWORD)wcslen(*Buf) + 1;
WCHAR *BufZ = HeapAlloc(ModuleHeap, 0, ((size_t)Len + 1) * sizeof(WCHAR));
if (!BufZ)
- return LOG(WINTUN_LOG_ERR, L"Out of memory"), ERROR_OUTOFMEMORY;
+ {
+ LOG(WINTUN_LOG_ERR, L"Out of memory");
+ SetLastError(ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
wmemcpy(BufZ, *Buf, Len);
BufZ[Len] = 0;
HeapFree(ModuleHeap, 0, *Buf);
*Buf = BufZ;
- return ERROR_SUCCESS;
+ return TRUE;
}
-static WINTUN_STATUS
-RegistryQuery(
+static _Return_type_success_(return != NULL) void *RegistryQuery(
_In_ HKEY Key,
_In_opt_z_ const WCHAR *Name,
_Out_opt_ DWORD *ValueType,
- _Out_ void **Buf,
_Inout_ DWORD *BufLen,
_In_ BOOL Log)
{
@@ -183,60 +217,77 @@ RegistryQuery(
{
BYTE *p = HeapAlloc(ModuleHeap, 0, *BufLen);
if (!p)
- return LOG(WINTUN_LOG_ERR, L"Out of memory"), ERROR_OUTOFMEMORY;
- LSTATUS Result = RegQueryValueExW(Key, Name, NULL, ValueType, p, BufLen);
- if (Result == ERROR_SUCCESS)
{
- *Buf = p;
- return ERROR_SUCCESS;
+ LOG(WINTUN_LOG_ERR, L"Out of memory");
+ SetLastError(ERROR_OUTOFMEMORY);
+ return NULL;
}
+ LSTATUS LastError = RegQueryValueExW(Key, Name, NULL, ValueType, p, BufLen);
+ if (LastError == ERROR_SUCCESS)
+ return p;
HeapFree(ModuleHeap, 0, p);
- if (Result != ERROR_MORE_DATA)
- return Log ? LOG_ERROR(L"Querying value failed", Result) : Result;
+ if (LastError != ERROR_MORE_DATA)
+ {
+ if (Log)
+ LOG_ERROR(L"Querying value failed", LastError);
+ SetLastError(LastError);
+ return NULL;
+ }
}
}
-WINTUN_STATUS
-RegistryQueryString(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _Out_ WCHAR **Value, _In_ BOOL Log)
+_Return_type_success_(
+ return != NULL) WCHAR *RegistryQueryString(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ BOOL Log)
{
- DWORD ValueType, Size = 256 * sizeof(WCHAR);
- DWORD Result = RegistryQuery(Key, Name, &ValueType, Value, &Size, Log);
- if (Result != ERROR_SUCCESS)
- return Result;
+ DWORD LastError, ValueType, Size = 256 * sizeof(WCHAR);
+ WCHAR *Value = RegistryQuery(Key, Name, &ValueType, &Size, Log);
+ if (!Value)
+ return NULL;
switch (ValueType)
{
case REG_SZ:
case REG_EXPAND_SZ:
case REG_MULTI_SZ:
- Result = RegistryGetString(Value, Size / sizeof(WCHAR), ValueType);
- if (Result != ERROR_SUCCESS)
- HeapFree(ModuleHeap, 0, *Value);
- return Result;
+ if (RegistryGetString(&Value, Size / sizeof(WCHAR), ValueType))
+ return Value;
+ LastError = GetLastError();
+ break;
default:
LOG(WINTUN_LOG_ERR, L"Value is not a string");
- HeapFree(ModuleHeap, 0, *Value);
- return ERROR_INVALID_DATATYPE;
+ LastError = ERROR_INVALID_DATATYPE;
}
+ HeapFree(ModuleHeap, 0, Value);
+ SetLastError(LastError);
+ return NULL;
}
-WINTUN_STATUS
-RegistryQueryStringWait(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ DWORD Timeout, _Out_ WCHAR **Value)
+_Return_type_success_(
+ return != NULL) WCHAR *RegistryQueryStringWait(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ DWORD Timeout)
{
- DWORD Result;
+ DWORD LastError;
ULONGLONG Deadline = GetTickCount64() + Timeout;
HANDLE Event = CreateEventW(NULL, FALSE, FALSE, NULL);
if (!Event)
- return LOG_LAST_ERROR(L"Failed to create event");
+ {
+ LOG_LAST_ERROR(L"Failed to create event");
+ return NULL;
+ }
for (;;)
{
- Result = RegNotifyChangeKeyValue(Key, FALSE, REG_NOTIFY_CHANGE_LAST_SET, Event, TRUE);
- if (Result != ERROR_SUCCESS)
+ LastError = RegNotifyChangeKeyValue(Key, FALSE, REG_NOTIFY_CHANGE_LAST_SET, Event, TRUE);
+ if (LastError != ERROR_SUCCESS)
{
- LOG_ERROR(L"Failed to setup notification", Result);
+ LOG_ERROR(L"Failed to setup notification", LastError);
break;
}
- Result = RegistryQueryString(Key, Name, Value, FALSE);
- if (Result != ERROR_FILE_NOT_FOUND && Result != ERROR_PATH_NOT_FOUND)
+ WCHAR *Value = RegistryQueryString(Key, Name, FALSE);
+ if (Value)
+ {
+ CloseHandle(Event);
+ return Value;
+ }
+ LastError = GetLastError();
+ if (LastError != ERROR_FILE_NOT_FOUND && LastError != ERROR_PATH_NOT_FOUND)
break;
LONGLONG TimeLeft = Deadline - GetTickCount64();
if (TimeLeft < 0)
@@ -248,51 +299,63 @@ RegistryQueryStringWait(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ DWORD
}
}
CloseHandle(Event);
- return Result;
+ SetLastError(LastError);
+ return NULL;
}
-WINTUN_STATUS
-RegistryQueryDWORD(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _Out_ DWORD *Value, _In_ BOOL Log)
+_Return_type_success_(return != FALSE) BOOL
+ RegistryQueryDWORD(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _Out_ DWORD *Value, _In_ BOOL Log)
{
DWORD ValueType, Size = sizeof(DWORD);
- DWORD Result = RegQueryValueExW(Key, Name, NULL, &ValueType, (BYTE *)Value, &Size);
- if (Result != ERROR_SUCCESS)
+ DWORD LastError = RegQueryValueExW(Key, Name, NULL, &ValueType, (BYTE *)Value, &Size);
+ if (LastError != ERROR_SUCCESS)
{
if (Log)
- LOG_ERROR(L"Querying failed", Result);
- return Result;
+ LOG_ERROR(L"Querying failed", LastError);
+ SetLastError(LastError);
+ return FALSE;
}
if (ValueType != REG_DWORD)
{
LOG(WINTUN_LOG_ERR, L"Value is not a DWORD");
- return ERROR_INVALID_DATATYPE;
+ SetLastError(ERROR_INVALID_DATATYPE);
+ return FALSE;
}
if (Size != sizeof(DWORD))
{
LOG(WINTUN_LOG_ERR, L"Value size is not 4 bytes");
- return ERROR_INVALID_DATA;
+ SetLastError(ERROR_INVALID_DATA);
+ return FALSE;
}
- return ERROR_SUCCESS;
+ return TRUE;
}
-WINTUN_STATUS
-RegistryQueryDWORDWait(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ DWORD Timeout, _Out_ DWORD *Value)
+_Return_type_success_(return != FALSE) BOOL
+ RegistryQueryDWORDWait(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ DWORD Timeout, _Out_ DWORD *Value)
{
- DWORD Result;
+ DWORD LastError;
ULONGLONG Deadline = GetTickCount64() + Timeout;
HANDLE Event = CreateEventW(NULL, FALSE, FALSE, NULL);
if (!Event)
- return LOG_LAST_ERROR(L"Failed to create event");
+ {
+ LOG_LAST_ERROR(L"Failed to create event");
+ return FALSE;
+ }
for (;;)
{
- Result = RegNotifyChangeKeyValue(Key, FALSE, REG_NOTIFY_CHANGE_LAST_SET, Event, TRUE);
- if (Result != ERROR_SUCCESS)
+ LastError = RegNotifyChangeKeyValue(Key, FALSE, REG_NOTIFY_CHANGE_LAST_SET, Event, TRUE);
+ if (LastError != ERROR_SUCCESS)
{
- LOG_ERROR(L"Failed to setup notification", Result);
+ LOG_ERROR(L"Failed to setup notification", LastError);
break;
}
- Result = RegistryQueryDWORD(Key, Name, Value, FALSE);
- if (Result != ERROR_FILE_NOT_FOUND && Result != ERROR_PATH_NOT_FOUND)
+ if (RegistryQueryDWORD(Key, Name, Value, FALSE))
+ {
+ CloseHandle(Event);
+ return TRUE;
+ }
+ LastError = GetLastError();
+ if (LastError != ERROR_FILE_NOT_FOUND && LastError != ERROR_PATH_NOT_FOUND)
break;
LONGLONG TimeLeft = Deadline - GetTickCount64();
if (TimeLeft < 0)
@@ -304,5 +367,6 @@ RegistryQueryDWORDWait(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ DWORD T
}
}
CloseHandle(Event);
- return Result;
+ SetLastError(LastError);
+ return FALSE;
}
diff --git a/api/registry.h b/api/registry.h
index 0a02d42..a79370d 100644
--- a/api/registry.h
+++ b/api/registry.h
@@ -23,12 +23,11 @@
*
* @param Timeout Timeout to wait for the value in milliseconds.
*
- * @param KeyOut Pointer to a variable to receive the key handle.
- *
- * @return ERROR_SUCCESS on success; WAIT_TIMEOUT on timeout; Win32 error code otherwise.
+ * @return Key handle on success. If the function fails, the return value is zero. To get extended error information,
+ * call GetLastError.
*/
-WINTUN_STATUS
-RegistryOpenKeyWait(_In_ HKEY Key, _In_z_ const WCHAR *Path, _In_ DWORD Access, _In_ DWORD Timeout, _Out_ HKEY *KeyOut);
+_Return_type_success_(return != NULL) HKEY
+ RegistryOpenKeyWait(_In_ HKEY Key, _In_z_ const WCHAR *Path, _In_ DWORD Access, _In_ DWORD Timeout);
/**
* Validates and/or sanitizes string value read from registry.
@@ -42,10 +41,11 @@ RegistryOpenKeyWait(_In_ HKEY Key, _In_z_ const WCHAR *Path, _In_ DWORD Access,
* @param ValueType Type of data. Must be either REG_SZ or REG_EXPAND_SZ. REG_MULTI_SZ is treated like REG_SZ; only
* the first string of a multi-string is to be used.
*
- * @return ERROR_SUCCESS on success; Win32 error code otherwise.
+ * @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.
*/
-WINTUN_STATUS
-RegistryGetString(_Inout_ WCHAR **Buf, _In_ DWORD Len, _In_ DWORD ValueType);
+_Return_type_success_(return != FALSE) BOOL
+ RegistryGetString(_Inout_ WCHAR **Buf, _In_ DWORD Len, _In_ DWORD ValueType);
/**
* Validates and/or sanitizes multi-string value read from registry.
@@ -58,10 +58,11 @@ RegistryGetString(_Inout_ WCHAR **Buf, _In_ DWORD Len, _In_ DWORD ValueType);
*
* @param ValueType Type of data. Must be one of REG_MULTI_SZ, REG_SZ or REG_EXPAND_SZ.
*
- * @return ERROR_SUCCESS on success; Win32 error code otherwise.
+ * @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.
*/
-WINTUN_STATUS
-RegistryGetMultiString(_Inout_ WCHAR **Buf, _In_ DWORD Len, _In_ DWORD ValueType);
+_Return_type_success_(return != FALSE) BOOL
+ RegistryGetMultiString(_Inout_ WCHAR **Buf, _In_ DWORD Len, _In_ DWORD ValueType);
/**
* Reads string value from registry key.
@@ -79,11 +80,11 @@ RegistryGetMultiString(_Inout_ WCHAR **Buf, _In_ DWORD Len, _In_ DWORD ValueType
* errors reduces log clutter when we are using RegistryQueryString() from
* RegistryQueryStringWait() and some errors are expected to occur.
*
- * @return ERROR_SUCCESS on success; ERROR_INVALID_DATATYPE when the registry value is not a string; Win32 error code
- * otherwise.
+ * @return String with registry value on success; If the function fails, the return value is zero. To get extended error
+ * information, call GetLastError.
*/
-WINTUN_STATUS
-RegistryQueryString(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _Out_ WCHAR **Value, _In_ BOOL Log);
+_Return_type_success_(
+ return != NULL) WCHAR *RegistryQueryString(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ BOOL Log);
/**
* Reads string value from registry key. It waits for the registry value to become available.
@@ -94,16 +95,14 @@ RegistryQueryString(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _Out_ WCHAR **V
*
* @param Timeout Timeout to wait for the value in milliseconds.
*
- * @param Value Pointer to string to retrieve registry value. If the value type is REG_EXPAND_SZ the value is
- * expanded using ExpandEnvironmentStrings(). If the value type is REG_MULTI_SZ, only the first
- * string from the multi-string is returned. The string must be released with
- * HeapFree(ModuleHeap, 0, Value) after use.
- *
- * @return ERROR_SUCCESS on success; WAIT_TIMEOUT on timeout; ERROR_INVALID_DATATYPE when the registry value is not a
- * string; Win32 error code otherwise.
+ * @return Registry value. If the value type is REG_EXPAND_SZ the value is expanded using ExpandEnvironmentStrings(). If
+ * the value type is REG_MULTI_SZ, only the first string from the multi-string is returned. The string must be
+ * released with HeapFree(ModuleHeap, 0, Value) after use. If the function fails, the return value is zero. To
+ * get extended error information, call GetLastError. Possible errors include the following:
+ * ERROR_INVALID_DATATYPE when the registry value is not a string
*/
-WINTUN_STATUS
-RegistryQueryStringWait(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ DWORD Timeout, _Out_ WCHAR **Value);
+_Return_type_success_(
+ return != NULL) WCHAR *RegistryQueryStringWait(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ DWORD Timeout);
/**
* Reads a 32-bit DWORD value from registry key.
@@ -118,11 +117,11 @@ RegistryQueryStringWait(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ DWORD
* errors reduces log clutter when we are using RegistryQueryDWORD() from
* RegistryQueryDWORDWait() and some errors are expected to occur.
*
- * @return ERROR_SUCCESS on success; ERROR_INVALID_DATATYPE when registry value exist but not REG_DWORD type;
- * ERROR_INVALID_DATA when registry value size is not 4 bytes; Win32 error code otherwise.
+ * @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.
*/
-WINTUN_STATUS
-RegistryQueryDWORD(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _Out_ DWORD *Value, _In_ BOOL Log);
+_Return_type_success_(return != FALSE) BOOL
+ RegistryQueryDWORD(_In_ HKEY Key, _In_opt_z_ const WCHAR *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.
@@ -135,8 +134,10 @@ RegistryQueryDWORD(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _Out_ DWORD *Val
*
* @param Value Pointer to DWORD to retrieve registry value.
*
- * @return ERROR_SUCCESS on success; WAIT_TIMEOUT on timeout; ERROR_INVALID_DATATYPE when registry value exist but not
- * REG_DWORD type; ERROR_INVALID_DATA when registry value size is not 4 bytes; Win32 error code otherwise.
+ * @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. Possible errors include the following:
+ * ERROR_INVALID_DATATYPE when registry value exist but not REG_DWORD type;
+ * ERROR_INVALID_DATA when registry value size is not 4 bytes
*/
-WINTUN_STATUS
-RegistryQueryDWORDWait(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ DWORD Timeout, _Out_ DWORD *Value);
+_Return_type_success_(return != FALSE) BOOL
+ RegistryQueryDWORDWait(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ DWORD Timeout, _Out_ DWORD *Value);
diff --git a/api/resource.c b/api/resource.c
index ae88353..e4f4aaa 100644
--- a/api/resource.c
+++ b/api/resource.c
@@ -8,35 +8,47 @@
#include "resource.h"
#include <Windows.h>
-WINTUN_STATUS
-ResourceGetAddress(_In_z_ const WCHAR *ResourceName, _Out_ const void **Address, _Out_ DWORD *Size)
+_Return_type_success_(return != NULL) _Ret_bytecount_(*Size) const
+ void *ResourceGetAddress(_In_z_ const WCHAR *ResourceName, _Out_ DWORD *Size)
{
HRSRC FoundResource = FindResourceW(ResourceModule, ResourceName, RT_RCDATA);
if (!FoundResource)
- return LOG_LAST_ERROR(L"Failed to find resource");
+ {
+ LOG_LAST_ERROR(L"Failed to find resource");
+ return NULL;
+ }
*Size = SizeofResource(ResourceModule, FoundResource);
if (!*Size)
- return LOG_LAST_ERROR(L"Failed to query resource size");
+ {
+ LOG_LAST_ERROR(L"Failed to query resource size");
+ return NULL;
+ }
HGLOBAL LoadedResource = LoadResource(ResourceModule, FoundResource);
if (!LoadedResource)
- return LOG_LAST_ERROR(L"Failed to load resource");
- *Address = LockResource(LoadedResource);
- if (!*Address)
+ {
+ LOG_LAST_ERROR(L"Failed to load resource");
+ return NULL;
+ }
+ BYTE *Address = LockResource(LoadedResource);
+ if (!Address)
{
LOG(WINTUN_LOG_ERR, L"Failed to lock resource");
- return ERROR_LOCK_FAILED;
+ SetLastError(ERROR_LOCK_FAILED);
+ return NULL;
}
- return ERROR_SUCCESS;
+ return Address;
}
-WINTUN_STATUS
-ResourceCopyToFile(_In_z_ const WCHAR *DestinationPath, _In_z_ const WCHAR *ResourceName)
+_Return_type_success_(return != FALSE) BOOL
+ ResourceCopyToFile(_In_z_ const WCHAR *DestinationPath, _In_z_ const WCHAR *ResourceName)
{
- const void *LockedResource;
DWORD SizeResource;
- DWORD Result = ResourceGetAddress(ResourceName, &LockedResource, &SizeResource);
- if (Result != ERROR_SUCCESS)
- return LOG(WINTUN_LOG_ERR, L"Failed to locate resource"), Result;
+ const void *LockedResource = ResourceGetAddress(ResourceName, &SizeResource);
+ if (!LockedResource)
+ {
+ LOG(WINTUN_LOG_ERR, L"Failed to locate resource");
+ return FALSE;
+ }
HANDLE DestinationHandle = CreateFileW(
DestinationPath,
GENERIC_WRITE,
@@ -46,15 +58,25 @@ ResourceCopyToFile(_In_z_ const WCHAR *DestinationPath, _In_z_ const WCHAR *Reso
FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_TEMPORARY,
NULL);
if (DestinationHandle == INVALID_HANDLE_VALUE)
- return LOG_LAST_ERROR(L"Failed to create file");
+ {
+ LOG_LAST_ERROR(L"Failed to create file");
+ return FALSE;
+ }
DWORD BytesWritten;
+ DWORD LastError;
if (!WriteFile(DestinationHandle, LockedResource, SizeResource, &BytesWritten, NULL))
- Result = LOG_LAST_ERROR(L"Failed to write file");
+ {
+ LastError = LOG_LAST_ERROR(L"Failed to write file");
+ goto cleanupDestinationHandle;
+ }
if (BytesWritten != SizeResource)
{
LOG(WINTUN_LOG_ERR, L"Incomplete write");
- Result = Result != ERROR_SUCCESS ? Result : ERROR_WRITE_FAULT;
+ LastError = ERROR_WRITE_FAULT;
+ goto cleanupDestinationHandle;
}
+ LastError = ERROR_SUCCESS;
+cleanupDestinationHandle:
CloseHandle(DestinationHandle);
- return Result;
+ return RET_ERROR(TRUE, LastError);
}
diff --git a/api/resource.h b/api/resource.h
index 3cfc0a3..3572ace 100644
--- a/api/resource.h
+++ b/api/resource.h
@@ -13,14 +13,13 @@
*
* ResourceName Name of the RT_RCDATA resource. Use MAKEINTRESOURCEW to locate resource by ID.
*
- * Address Pointer to a pointer variable to receive resource address.
- *
* Size Pointer to a variable to receive resource size.
*
- * @return ERROR_SUCCESS on success; Win32 error code otherwise.
+ * @return Resource address on success. If the function fails, the return value is NULL. To get extended error
+ * information, call GetLastError.
*/
-WINTUN_STATUS
-ResourceGetAddress(_In_z_ const WCHAR *ResourceName, _Out_ const void **Address, _Out_ DWORD *Size);
+_Return_type_success_(return != NULL) _Ret_bytecount_(*Size) const
+ void *ResourceGetAddress(_In_z_ const WCHAR *ResourceName, _Out_ DWORD *Size);
/**
* Copies resource to a file.
@@ -29,7 +28,8 @@ ResourceGetAddress(_In_z_ const WCHAR *ResourceName, _Out_ const void **Address,
*
* ResourceName Name of the RT_RCDATA resource. Use MAKEINTRESOURCEW to locate resource by ID.
*
- * @return ERROR_SUCCESS on success; Win32 error code otherwise.
+ * @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.
*/
-WINTUN_STATUS
-ResourceCopyToFile(_In_z_ const WCHAR *DestinationPath, _In_z_ const WCHAR *ResourceName);
+_Return_type_success_(return != FALSE) BOOL
+ ResourceCopyToFile(_In_z_ const WCHAR *DestinationPath, _In_z_ const WCHAR *ResourceName);
diff --git a/api/rundll32.c b/api/rundll32.c
index bc07597..1d564ae 100644
--- a/api/rundll32.c
+++ b/api/rundll32.c
@@ -7,16 +7,16 @@
#if ACCEPT_WOW64 == 1
-#include "adapter.h"
-#include "logger.h"
-#include "wintun.h"
+# include "adapter.h"
+# include "logger.h"
+# include "wintun.h"
-#include <Windows.h>
-#include <cfgmgr32.h>
-#include <objbase.h>
-#include <assert.h>
+# include <Windows.h>
+# include <cfgmgr32.h>
+# include <objbase.h>
+# include <assert.h>
-#define EXPORT comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__)
+# define EXPORT comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__)
static DWORD
WriteFormatted(_In_ DWORD StdHandle, _In_z_ const WCHAR *Template, ...)
@@ -77,7 +77,7 @@ Done(void)
LocalFree(Argv);
}
-#pragma warning(disable: 4100) /* unreferenced formal parameter */
+# pragma warning(disable : 4100) /* unreferenced formal parameter */
VOID __stdcall CreateAdapter(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
{
@@ -94,18 +94,19 @@ VOID __stdcall CreateAdapter(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int
if (Argc > 4 && FAILED(CLSIDFromString(Argv[4], &RequestedGUID)))
goto cleanup;
- WINTUN_ADAPTER *Adapter;
BOOL RebootRequired;
- DWORD Result = WintunCreateAdapter(Argv[2], Argv[3], Argc > 4 ? &RequestedGUID : NULL, &Adapter, &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!",
- Result,
- StringFromGUID2(Result == ERROR_SUCCESS ? &Adapter->CfgInstanceID : &GUID_NULL, GuidStr, _countof(GuidStr)),
+ LastError,
+ StringFromGUID2(Adapter ? &Adapter->CfgInstanceID : &GUID_NULL, GuidStr, _countof(GuidStr)),
GuidStr,
RebootRequired);
- WintunFreeAdapter(Adapter);
+ if (Adapter)
+ WintunFreeAdapter(Adapter);
cleanup:
Done();
@@ -124,8 +125,9 @@ VOID __stdcall DeleteAdapter(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int
if (FAILED(CLSIDFromString(Argv[3], &Adapter.CfgInstanceID)))
goto cleanup;
BOOL RebootRequired;
- WINTUN_STATUS Ret = WintunDeleteAdapter(&Adapter, ForceCloseSessions, &RebootRequired);
- WriteFormatted(STD_OUTPUT_HANDLE, L"%1!X! %2!X!", Ret, RebootRequired);
+ DWORD LastError =
+ WintunDeleteAdapter(&Adapter, ForceCloseSessions, &RebootRequired) ? ERROR_SUCCESS : GetLastError();
+ WriteFormatted(STD_OUTPUT_HANDLE, L"%1!X! %2!X!", LastError, RebootRequired);
cleanup:
Done();
@@ -140,8 +142,8 @@ VOID __stdcall DeletePoolDriver(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, i
goto cleanup;
BOOL RebootRequired;
- WINTUN_STATUS Ret = WintunDeletePoolDriver(Argv[2], &RebootRequired);
- WriteFormatted(STD_OUTPUT_HANDLE, L"%1!X! %2!X!", Ret, RebootRequired);
+ DWORD LastError = WintunDeletePoolDriver(Argv[2], &RebootRequired) ? ERROR_SUCCESS : GetLastError();
+ WriteFormatted(STD_OUTPUT_HANDLE, L"%1!X! %2!X!", LastError, RebootRequired);
cleanup:
Done();
diff --git a/api/rundll32.h b/api/rundll32.h
index b445cf9..ca4a504 100644
--- a/api/rundll32.h
+++ b/api/rundll32.h
@@ -72,7 +72,7 @@ ProcessStderr(_In_ HANDLE Stderr)
else if (State == OnMsg && c == L'\n')
{
Msg[Count] = 0;
- Logger(Level, Msg);
+ LoggerLog(Level, Msg);
State = OnNone;
Count = 0;
}
@@ -80,27 +80,35 @@ ProcessStderr(_In_ HANDLE Stderr)
}
}
-static WINTUN_STATUS
-ExecuteRunDll32(
+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)))
- return LOG_LAST_ERROR(L"Failed to get Windows folder");
+ {
+ LOG_LAST_ERROR(L"Failed to get Windows folder");
+ return FALSE;
+ }
WCHAR RunDll32Path[MAX_PATH];
if (!PathCombineW(RunDll32Path, WindowsDirectory, L"Sysnative\\rundll32.exe"))
- return ERROR_BUFFER_OVERFLOW;
+ {
+ SetLastError(ERROR_BUFFER_OVERFLOW);
+ return FALSE;
+ }
- DWORD Result;
+ DWORD LastError;
WCHAR RandomTempSubDirectory[MAX_PATH];
- if ((Result = CreateTemporaryDirectory(RandomTempSubDirectory)) != ERROR_SUCCESS)
- return LOG(WINTUN_LOG_ERR, L"Failed to create temporary folder"), Result;
+ if (!CreateTemporaryDirectory(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"))
{
- Result = ERROR_BUFFER_OVERFLOW;
+ LastError = ERROR_BUFFER_OVERFLOW;
goto cleanupDirectory;
}
const WCHAR *WintunDllResourceName;
@@ -114,12 +122,12 @@ ExecuteRunDll32(
break;
default:
LOG(WINTUN_LOG_ERR, L"Unsupported platform");
- Result = ERROR_NOT_SUPPORTED;
+ LastError = ERROR_NOT_SUPPORTED;
goto cleanupDirectory;
}
- if ((Result = ResourceCopyToFile(DllPath, WintunDllResourceName)) != ERROR_SUCCESS)
+ if (!ResourceCopyToFile(DllPath, WintunDllResourceName))
{
- LOG(WINTUN_LOG_ERR, L"Failed to copy resource");
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to copy resource");
goto cleanupDelete;
}
size_t CommandLineLen = 10 + MAX_PATH + 2 + wcslen(Arguments) + 1;
@@ -127,14 +135,14 @@ ExecuteRunDll32(
if (!CommandLine)
{
LOG(WINTUN_LOG_ERR, L"Out of memory");
- Result = ERROR_OUTOFMEMORY;
+ LastError = ERROR_OUTOFMEMORY;
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");
- Result = ERROR_INVALID_PARAMETER;
+ LastError = ERROR_INVALID_PARAMETER;
goto cleanupDelete;
}
HANDLE StreamRStdout = INVALID_HANDLE_VALUE, StreamRStderr = INVALID_HANDLE_VALUE,
@@ -142,13 +150,13 @@ ExecuteRunDll32(
if (!CreatePipe(&StreamRStdout, &StreamWStdout, &SecurityAttributes, 0) ||
!CreatePipe(&StreamRStderr, &StreamWStderr, &SecurityAttributes, 0))
{
- Result = LOG_LAST_ERROR(L"Failed to create pipes");
+ 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))
{
- Result = LOG_LAST_ERROR(L"Failed to set handle info");
+ LastError = LOG_LAST_ERROR(L"Failed to set handle info");
goto cleanupPipes;
}
if (ResponseCapacity)
@@ -160,7 +168,7 @@ ExecuteRunDll32(
if ((ThreadStdout = CreateThread(NULL, 0, ProcessStdout, &ProcessStdoutState, 0, NULL)) == NULL ||
(ThreadStderr = CreateThread(NULL, 0, ProcessStderr, StreamRStderr, 0, NULL)) == NULL)
{
- Result = LOG_LAST_ERROR(L"Failed to spawn readers");
+ LastError = LOG_LAST_ERROR(L"Failed to spawn readers");
goto cleanupThreads;
}
STARTUPINFOW si = { .cb = sizeof(STARTUPINFO),
@@ -172,14 +180,15 @@ ExecuteRunDll32(
HANDLE ProcessToken = GetPrimarySystemTokenFromThread();
if (!ProcessToken)
{
- Result = LOG_LAST_ERROR(L"Failed to get primary system token from thread");
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to get primary system token from thread");
goto cleanupThreads;
}
if (!CreateProcessAsUserW(ProcessToken, RunDll32Path, CommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
{
- Result = LOG_LAST_ERROR(L"Failed to create process");
+ LastError = LOG_LAST_ERROR(L"Failed to create process");
goto cleanupToken;
}
+ LastError = ERROR_SUCCESS;
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
@@ -198,10 +207,10 @@ cleanupThreads:
CloseHandle(StreamWStdout);
StreamWStdout = INVALID_HANDLE_VALUE;
WaitForSingleObject(ThreadStdout, INFINITE);
- if (!GetExitCodeThread(ThreadStdout, &Result))
- Result = LOG_LAST_ERROR(L"Failed to retrieve stdout reader result");
- else if (Result != ERROR_SUCCESS)
- LOG_ERROR(L"Failed to read process output", Result);
+ if (!GetExitCodeThread(ThreadStdout, &LastError))
+ LastError = LOG_LAST_ERROR(L"Failed to retrieve stdout reader result");
+ else if (LastError != ERROR_SUCCESS)
+ LOG_ERROR(L"Failed to read process output", LastError);
CloseHandle(ThreadStdout);
}
cleanupPipes:
@@ -214,15 +223,13 @@ cleanupDelete:
DeleteFileW(DllPath);
cleanupDirectory:
RemoveDirectoryW(RandomTempSubDirectory);
- return Result;
+ return RET_ERROR(TRUE, LastError);
}
-static WINTUN_STATUS
-CreateAdapterViaRundll32(
+static _Return_type_success_(return != NULL) WINTUN_ADAPTER *CreateAdapterViaRundll32(
_In_z_ const WCHAR *Pool,
_In_z_ const WCHAR *Name,
_In_opt_ const GUID *RequestedGUID,
- _Out_ WINTUN_ADAPTER **Adapter,
_Inout_ BOOL *RebootRequired)
{
LOG(WINTUN_LOG_INFO, L"Spawning native process");
@@ -237,38 +244,46 @@ CreateAdapterViaRundll32(
Name,
RequestedGUID ? StringFromGUID2(RequestedGUID, RequestedGUIDStr, _countof(RequestedGUIDStr)) : 0,
RequestedGUIDStr) == -1)
- return LOG(WINTUN_LOG_ERR, L"Command line too long"), ERROR_INVALID_PARAMETER;
+ {
+ 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];
- DWORD Result = ExecuteRunDll32(Arguments, Response, _countof(Response));
- if (Result != ERROR_SUCCESS)
+ if (!ExecuteRunDll32(Arguments, Response, _countof(Response)))
{
LOG(WINTUN_LOG_ERR, L"Error executing worker process");
- return Result;
+ 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");
- Result = ERROR_INVALID_PARAMETER;
+ LastError = ERROR_INVALID_PARAMETER;
goto cleanupArgv;
}
- Result = wcstoul(Argv[0], NULL, 16);
- if (Result == ERROR_SUCCESS && GetAdapter(Pool, &CfgInstanceID, Adapter) != ERROR_SUCCESS)
+ LastError = wcstoul(Argv[0], NULL, 16);
+ if (LastError == ERROR_SUCCESS && (Adapter = GetAdapter(Pool, &CfgInstanceID)) == NULL)
{
LOG(WINTUN_LOG_ERR, L"Failed to get adapter");
- Result = ERROR_FILE_NOT_FOUND;
+ LastError = ERROR_FILE_NOT_FOUND;
}
if (wcstoul(Argv[2], NULL, 16))
*RebootRequired = TRUE;
cleanupArgv:
LocalFree(Argv);
- return Result;
+ SetLastError(LastError);
+ return Adapter;
}
-static WINTUN_STATUS
-DeleteAdapterViaRundll32(_In_ const WINTUN_ADAPTER *Adapter, _In_ BOOL ForceCloseSessions, _Inout_ BOOL *RebootRequired)
+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];
@@ -281,57 +296,65 @@ DeleteAdapterViaRundll32(_In_ const WINTUN_ADAPTER *Adapter, _In_ BOOL ForceClos
ForceCloseSessions ? 1 : 0,
StringFromGUID2(&Adapter->CfgInstanceID, GuidStr, _countof(GuidStr)),
GuidStr) == -1)
- return LOG(WINTUN_LOG_ERR, L"Command line too long"), ERROR_INVALID_PARAMETER;
+ {
+ LOG(WINTUN_LOG_ERR, L"Command line too long");
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
WCHAR Response[8 + 1 + 8 + 1];
- DWORD Result = ExecuteRunDll32(Arguments, Response, _countof(Response));
- if (Result != ERROR_SUCCESS)
+ DWORD LastError;
+ if (!ExecuteRunDll32(Arguments, Response, _countof(Response)))
{
LOG(WINTUN_LOG_ERR, L"Error executing worker process");
- return Result;
+ return FALSE;
}
int Argc;
WCHAR **Argv = CommandLineToArgvW(Response, &Argc);
if (Argc < 2)
{
LOG(WINTUN_LOG_ERR, L"Incomplete or invalid response");
- Result = ERROR_INVALID_PARAMETER;
+ LastError = ERROR_INVALID_PARAMETER;
goto cleanupArgv;
}
- Result = wcstoul(Argv[0], NULL, 16);
+ LastError = wcstoul(Argv[0], NULL, 16);
if (wcstoul(Argv[1], NULL, 16))
*RebootRequired = TRUE;
cleanupArgv:
LocalFree(Argv);
- return Result;
+ return RET_ERROR(TRUE, LastError);
}
-static WINTUN_STATUS
-DeletePoolDriverViaRundll32(_In_z_ const WCHAR Pool[WINTUN_MAX_POOL], _Inout_ BOOL *RebootRequired)
+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)
- return LOG(WINTUN_LOG_ERR, L"Command line too long"), ERROR_INVALID_PARAMETER;
+ {
+ LOG(WINTUN_LOG_ERR, L"Command line too long");
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
WCHAR Response[8 + 1 + 8 + 1];
- DWORD Result = ExecuteRunDll32(Arguments, Response, _countof(Response));
- if (Result != ERROR_SUCCESS)
+ DWORD LastError;
+ if (!ExecuteRunDll32(Arguments, Response, _countof(Response)))
{
LOG(WINTUN_LOG_ERR, L"Error executing worker process");
- return Result;
+ return FALSE;
}
int Argc;
WCHAR **Argv = CommandLineToArgvW(Response, &Argc);
if (Argc < 2)
{
LOG(WINTUN_LOG_ERR, L"Incomplete or invalid response");
- Result = ERROR_INVALID_PARAMETER;
+ LastError = ERROR_INVALID_PARAMETER;
goto cleanupArgv;
}
- Result = wcstoul(Argv[0], NULL, 16);
+ LastError = wcstoul(Argv[0], NULL, 16);
if (wcstoul(Argv[1], NULL, 16))
*RebootRequired = TRUE;
cleanupArgv:
LocalFree(Argv);
- return Result;
-} \ No newline at end of file
+ return RET_ERROR(TRUE, LastError);
+}
diff --git a/api/session.c b/api/session.c
index ebb8d59..c4e1c04 100644
--- a/api/session.c
+++ b/api/session.c
@@ -69,86 +69,87 @@ typedef struct _TUN_SESSION
HANDLE Handle;
} TUN_SESSION;
-WINTUN_STATUS WINAPI
-WintunStartSession(
- _In_ const WINTUN_ADAPTER *Adapter,
- _In_ DWORD Capacity,
- _Out_ TUN_SESSION **Session)
+_Return_type_success_(return != NULL) TUN_SESSION *WINAPI
+ WintunStartSession(_In_ const WINTUN_ADAPTER *Adapter, _In_ DWORD Capacity)
{
- TUN_SESSION *s = HeapAlloc(ModuleHeap, HEAP_ZERO_MEMORY, sizeof(TUN_SESSION));
- if (!s)
- return LOG(WINTUN_LOG_ERR, L"Out of memory"), ERROR_OUTOFMEMORY;
+ DWORD LastError;
+ TUN_SESSION *Session = HeapAlloc(ModuleHeap, HEAP_ZERO_MEMORY, sizeof(TUN_SESSION));
+ if (!Session)
+ {
+ LOG(WINTUN_LOG_ERR, L"Out of memory");
+ LastError = ERROR_OUTOFMEMORY;
+ goto out;
+ }
const ULONG RingSize = TUN_RING_SIZE(Capacity);
- DWORD Result;
BYTE *AllocatedRegion = VirtualAlloc(0, (size_t)RingSize * 2, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!AllocatedRegion)
{
- Result = LOG_LAST_ERROR(L"Failed to allocate ring memory");
+ LastError = LOG_LAST_ERROR(L"Failed to allocate ring memory");
goto cleanupRings;
}
if (!ElevateToSystem())
{
- LOG(WINTUN_LOG_ERR, L"Failed to impersonate SYSTEM user");
- Result = ERROR_ACCESS_DENIED;
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to impersonate SYSTEM user");
goto cleanupAllocatedRegion;
}
- s->Descriptor.Send.RingSize = RingSize;
- s->Descriptor.Send.Ring = (TUN_RING *)AllocatedRegion;
- s->Descriptor.Send.TailMoved = CreateEventW(&SecurityAttributes, FALSE, FALSE, NULL);
- if (!s->Descriptor.Send.TailMoved)
+ Session->Descriptor.Send.RingSize = RingSize;
+ Session->Descriptor.Send.Ring = (TUN_RING *)AllocatedRegion;
+ Session->Descriptor.Send.TailMoved = CreateEventW(&SecurityAttributes, FALSE, FALSE, NULL);
+ if (!Session->Descriptor.Send.TailMoved)
{
- Result = LOG_LAST_ERROR(L"Failed to create send event");
+ LastError = LOG_LAST_ERROR(L"Failed to create send event");
goto cleanupToken;
}
- s->Descriptor.Receive.RingSize = RingSize;
- s->Descriptor.Receive.Ring = (TUN_RING *)(AllocatedRegion + RingSize);
- s->Descriptor.Receive.TailMoved = CreateEventW(&SecurityAttributes, FALSE, FALSE, NULL);
- if (!s->Descriptor.Receive.TailMoved)
+ Session->Descriptor.Receive.RingSize = RingSize;
+ Session->Descriptor.Receive.Ring = (TUN_RING *)(AllocatedRegion + RingSize);
+ Session->Descriptor.Receive.TailMoved = CreateEventW(&SecurityAttributes, FALSE, FALSE, NULL);
+ if (!Session->Descriptor.Receive.TailMoved)
{
- Result = LOG_LAST_ERROR(L"Failed to create receive event");
+ LastError = LOG_LAST_ERROR(L"Failed to create receive event");
goto cleanupSendTailMoved;
}
- Result = WintunOpenAdapterDeviceObject(Adapter, &s->Handle);
- if (Result != ERROR_SUCCESS)
+ Session->Handle = WintunOpenAdapterDeviceObject(Adapter);
+ if (Session->Handle == INVALID_HANDLE_VALUE)
{
- LOG(WINTUN_LOG_ERR, L"Failed to open adapter device object");
+ LastError = LOG(WINTUN_LOG_ERR, L"Failed to open adapter device object");
goto cleanupReceiveTailMoved;
}
DWORD BytesReturned;
if (!DeviceIoControl(
- s->Handle,
+ Session->Handle,
TUN_IOCTL_REGISTER_RINGS,
- &s->Descriptor,
+ &Session->Descriptor,
sizeof(TUN_REGISTER_RINGS),
NULL,
0,
&BytesReturned,
NULL))
{
- Result = LOG_LAST_ERROR(L"Failed to register rings");
+ LastError = LOG_LAST_ERROR(L"Failed to register rings");
goto cleanupHandle;
}
RevertToSelf();
- s->Capacity = Capacity;
- (void)InitializeCriticalSectionAndSpinCount(&s->Receive.Lock, LOCK_SPIN_COUNT);
- (void)InitializeCriticalSectionAndSpinCount(&s->Send.Lock, LOCK_SPIN_COUNT);
- *Session = s;
- return ERROR_SUCCESS;
+ Session->Capacity = Capacity;
+ (void)InitializeCriticalSectionAndSpinCount(&Session->Receive.Lock, LOCK_SPIN_COUNT);
+ (void)InitializeCriticalSectionAndSpinCount(&Session->Send.Lock, LOCK_SPIN_COUNT);
+ return Session;
cleanupHandle:
- CloseHandle(s->Handle);
+ CloseHandle(Session->Handle);
cleanupReceiveTailMoved:
- CloseHandle(s->Descriptor.Receive.TailMoved);
+ CloseHandle(Session->Descriptor.Receive.TailMoved);
cleanupSendTailMoved:
- CloseHandle(s->Descriptor.Send.TailMoved);
+ CloseHandle(Session->Descriptor.Send.TailMoved);
cleanupToken:
RevertToSelf();
cleanupAllocatedRegion:
VirtualFree(AllocatedRegion, 0, MEM_RELEASE);
cleanupRings:
- HeapFree(ModuleHeap, 0, s);
- return Result;
+ HeapFree(ModuleHeap, 0, Session);
+out:
+ SetLastError(LastError);
+ return NULL;
}
void WINAPI
@@ -170,53 +171,55 @@ WintunGetReadWaitEvent(_In_ TUN_SESSION *Session)
return Session->Descriptor.Send.TailMoved;
}
-WINTUN_STATUS WINAPI
-WintunReceivePacket(_In_ TUN_SESSION *Session, _Out_bytecapcount_(*PacketSize) BYTE **Packet, _Out_ DWORD *PacketSize)
+_Return_type_success_(return != NULL) _Ret_bytecount_(*PacketSize) BYTE *WINAPI
+ WintunReceivePacket(_In_ TUN_SESSION *Session, _Out_ DWORD *PacketSize)
{
- DWORD Result;
+ DWORD LastError;
EnterCriticalSection(&Session->Send.Lock);
if (Session->Send.Head >= Session->Capacity)
{
- Result = ERROR_HANDLE_EOF;
+ LastError = ERROR_HANDLE_EOF;
goto cleanup;
}
const ULONG BuffTail = ReadULongAcquire(&Session->Descriptor.Send.Ring->Tail);
if (BuffTail >= Session->Capacity)
{
- Result = ERROR_HANDLE_EOF;
+ LastError = ERROR_HANDLE_EOF;
goto cleanup;
}
if (Session->Send.Head == BuffTail)
{
- Result = ERROR_NO_MORE_ITEMS;
+ LastError = ERROR_NO_MORE_ITEMS;
goto cleanup;
}
const ULONG BuffContent = TUN_RING_WRAP(BuffTail - Session->Send.Head, Session->Capacity);
if (BuffContent < sizeof(TUN_PACKET))
{
- Result = ERROR_INVALID_DATA;
+ LastError = ERROR_INVALID_DATA;
goto cleanup;
}
TUN_PACKET *BuffPacket = (TUN_PACKET *)&Session->Descriptor.Send.Ring->Data[Session->Send.Head];
if (BuffPacket->Size > WINTUN_MAX_IP_PACKET_SIZE)
{
- Result = ERROR_INVALID_DATA;
+ LastError = ERROR_INVALID_DATA;
goto cleanup;
}
const ULONG AlignedPacketSize = TUN_ALIGN(sizeof(TUN_PACKET) + BuffPacket->Size);
if (AlignedPacketSize > BuffContent)
{
- Result = ERROR_INVALID_DATA;
+ LastError = ERROR_INVALID_DATA;
goto cleanup;
}
*PacketSize = BuffPacket->Size;
- *Packet = BuffPacket->Data;
+ BYTE *Packet = BuffPacket->Data;
Session->Send.Head = TUN_RING_WRAP(Session->Send.Head + AlignedPacketSize, Session->Capacity);
Session->Send.PacketsToRelease++;
- Result = ERROR_SUCCESS;
+ LeaveCriticalSection(&Session->Send.Lock);
+ return Packet;
cleanup:
LeaveCriticalSection(&Session->Send.Lock);
- return Result;
+ SetLastError(LastError);
+ return NULL;
}
void WINAPI
@@ -238,38 +241,40 @@ WintunReceiveRelease(_In_ TUN_SESSION *Session, _In_ const BYTE *Packet)
LeaveCriticalSection(&Session->Send.Lock);
}
-WINTUN_STATUS WINAPI
-WintunAllocateSendPacket(_In_ TUN_SESSION *Session, _In_ DWORD PacketSize, _Out_bytecapcount_(PacketSize) BYTE **Packet)
+_Return_type_success_(return != NULL) _Ret_bytecount_(PacketSize) BYTE *WINAPI
+ WintunAllocateSendPacket(_In_ TUN_SESSION *Session, _In_ DWORD PacketSize)
{
- DWORD Result;
+ DWORD LastError;
EnterCriticalSection(&Session->Receive.Lock);
if (Session->Receive.Tail >= Session->Capacity)
{
- Result = ERROR_HANDLE_EOF;
+ LastError = ERROR_HANDLE_EOF;
goto cleanup;
}
const ULONG AlignedPacketSize = TUN_ALIGN(sizeof(TUN_PACKET) + PacketSize);
const ULONG BuffHead = ReadULongAcquire(&Session->Descriptor.Receive.Ring->Head);
if (BuffHead >= Session->Capacity)
{
- Result = ERROR_HANDLE_EOF;
+ LastError = ERROR_HANDLE_EOF;
goto cleanup;
}
const ULONG BuffSpace = TUN_RING_WRAP(BuffHead - Session->Receive.Tail - TUN_ALIGNMENT, Session->Capacity);
if (AlignedPacketSize > BuffSpace)
{
- Result = ERROR_BUFFER_OVERFLOW;
+ LastError = ERROR_BUFFER_OVERFLOW;
goto cleanup;
}
TUN_PACKET *BuffPacket = (TUN_PACKET *)&Session->Descriptor.Receive.Ring->Data[Session->Receive.Tail];
BuffPacket->Size = PacketSize | TUN_PACKET_RELEASE;
- *Packet = BuffPacket->Data;
+ BYTE *Packet = BuffPacket->Data;
Session->Receive.Tail = TUN_RING_WRAP(Session->Receive.Tail + AlignedPacketSize, Session->Capacity);
Session->Receive.PacketsToRelease++;
- Result = ERROR_SUCCESS;
+ LeaveCriticalSection(&Session->Receive.Lock);
+ return Packet;
cleanup:
LeaveCriticalSection(&Session->Receive.Lock);
- return Result;
+ SetLastError(LastError);
+ return NULL;
}
void WINAPI
diff --git a/api/wintun.h b/api/wintun.h
index bf95492..459a882 100644
--- a/api/wintun.h
+++ b/api/wintun.h
@@ -13,8 +13,6 @@
extern "C" {
#endif
-typedef _Return_type_success_(return == ERROR_SUCCESS) DWORD WINTUN_STATUS;
-
/**
* A handle representing Wintun adapter
*/
@@ -33,24 +31,20 @@ typedef void *WINTUN_ADAPTER_HANDLE;
* @param Name The requested name of the adapter. Zero-terminated string of up to MAX_ADAPTER_NAME-1
* characters.
*
- * @param RequestedGUID The GUID of the created network adapter, which then influences NLA generation
- * deterministically. If it is set to NULL, the GUID is chosen by the system at random, and hence
- * a new NLA entry is created for each new adapter. It is called "requested" GUID because the API
- * it uses is completely undocumented, and so there could be minor interesting complications with
- * its usage.
- *
- * @param Adapter Pointer to a handle to receive the adapter handle. Must be released with
- * WintunFreeAdapter.
+ * @param RequestedGUID The GUID of the created network adapter, which then influences NLA generation deterministically.
+ * If it is set to NULL, the GUID is chosen by the system at random, and hence a new NLA entry is
+ * created for each new adapter. It is called "requested" GUID because the API it uses is
+ * completely undocumented, and so there could be minor interesting complications with its usage.
*
* @param RebootRequired Optional pointer to a boolean flag to be set to TRUE in case SetupAPI suggests a reboot.
*
- * @return ERROR_SUCCESS on success; Win32 error code otherwise.
+ * @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.
*/
-typedef WINTUN_STATUS(WINAPI *WINTUN_CREATE_ADAPTER_FUNC)(
+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_ WINTUN_ADAPTER_HANDLE *Adapter,
_Out_opt_ BOOL *RebootRequired);
/**
@@ -64,9 +58,10 @@ typedef WINTUN_STATUS(WINAPI *WINTUN_CREATE_ADAPTER_FUNC)(
*
* @param RebootRequired Optional pointer to a boolean flag to be set to TRUE in case SetupAPI suggests a reboot.
*
- * @return ERROR_SUCCESS on success or the adapter was not found; Win32 error code otherwise.
+ * @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 WINTUN_STATUS(WINAPI *WINTUN_DELETE_ADAPTER_FUNC)(
+typedef _Return_type_success_(return != FALSE) BOOL(WINAPI *WINTUN_DELETE_ADAPTER_FUNC)(
_In_ WINTUN_ADAPTER_HANDLE Adapter,
_In_ BOOL ForceCloseSessions,
_Out_opt_ BOOL *RebootRequired);
@@ -79,11 +74,11 @@ typedef WINTUN_STATUS(WINAPI *WINTUN_DELETE_ADAPTER_FUNC)(
*
* @param RebootRequired Optional pointer to a boolean flag to be set to TRUE in case SetupAPI suggests a reboot.
*
- * @return ERROR_SUCCESS on success; Win32 error code otherwise.
+ * @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 WINTUN_STATUS(WINAPI *WINTUN_DELETE_POOL_DRIVER_FUNC)(
- _In_z_ const WCHAR Pool[WINTUN_MAX_POOL],
- _Out_opt_ BOOL *RebootRequired);
+typedef _Return_type_success_(return != FALSE)
+ BOOL(WINAPI *WINTUN_DELETE_POOL_DRIVER_FUNC)(_In_z_ const WCHAR *Pool, _Out_opt_ BOOL *RebootRequired);
/**
* Called by WintunEnumAdapters for each adapter in the pool.
@@ -106,9 +101,10 @@ typedef BOOL(CALLBACK *WINTUN_ENUM_CALLBACK_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Ada
*
* @param Param An application-defined value to be passed to the callback function.
*
- * @return ERROR_SUCCESS on success; Win32 error code otherwise.
+ * @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 WINTUN_STATUS(WINAPI *WINTUN_ENUM_ADAPTERS_FUNC)(
+typedef _Return_type_success_(return != FALSE) BOOL(WINAPI *WINTUN_ENUM_ADAPTERS_FUNC)(
_In_z_ const WCHAR *Pool,
_In_ WINTUN_ENUM_CALLBACK_FUNC Callback,
_In_ LPARAM Param);
@@ -127,27 +123,26 @@ typedef void(WINAPI *WINTUN_FREE_ADAPTER_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Adapte
*
* @param Name Adapter name. Zero-terminated string of up to MAX_ADAPTER_NAME-1 characters.
*
- * @param Adapter Pointer to a handle to receive the adapter handle. Must be released with WintunFreeAdapter.
- *
- * @return ERROR_SUCCESS on success; 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; Win32 error code otherwise
+ * @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
*/
-typedef WINTUN_STATUS(WINAPI *WINTUN_GET_ADAPTER_FUNC)(
- _In_z_ const WCHAR *Pool,
- _In_z_ const WCHAR *Name,
- _Out_ WINTUN_ADAPTER_HANDLE *Adapter);
+typedef _Return_type_success_(return != NULL)
+ WINTUN_ADAPTER_HANDLE(WINAPI *WINTUN_GET_ADAPTER_FUNC)(_In_z_ const WCHAR *Pool, _In_z_ const WCHAR *Name);
/**
* Returns a handle to the adapter device object.
*
* @param Adapter Adapter handle obtained with WintunGetAdapter or WintunCreateAdapter.
*
- * @param Handle Pointer to receive the adapter device object handle. Must be released with CloseHandle.
- *
- * @return ERROR_SUCCESS on success; Win32 error code otherwise.
+ * @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
+ * information, call GetLastError.
*/
-typedef WINTUN_STATUS(
- WINAPI *WINTUN_OPEN_ADAPTER_DEVICE_OBJECT_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Adapter, _Out_ HANDLE *Handle);
+typedef _Return_type_success_(return != INVALID_HANDLE_VALUE)
+ HANDLE(WINAPI *WINTUN_OPEN_ADAPTER_DEVICE_OBJECT_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Adapter);
/**
* Returns the LUID of the adapter.
@@ -165,9 +160,10 @@ typedef void(WINAPI *WINTUN_GET_ADAPTER_LUID_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Ad
*
* @param Name Pointer to a string to receive adapter name
*
- * @return ERROR_SUCCESS on success; Win32 error code otherwise.
+ * @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 WINTUN_STATUS(WINAPI *WINTUN_GET_ADAPTER_NAME_FUNC)(
+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);
@@ -178,15 +174,19 @@ typedef WINTUN_STATUS(WINAPI *WINTUN_GET_ADAPTER_NAME_FUNC)(
*
* @param Name Adapter name. Zero-terminated string of up to MAX_ADAPTER_NAME-1 characters.
*
- * @return ERROR_SUCCESS on success; Win32 error code otherwise.
+ * @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 WINTUN_STATUS(
- WINAPI *WINTUN_SET_ADAPTER_NAME_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Adapter, _In_z_ const WCHAR *Name);
+typedef _Return_type_success_(return != FALSE)
+ BOOL(WINAPI *WINTUN_SET_ADAPTER_NAME_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Adapter, _In_z_ const WCHAR *Name);
/**
* Determines the version of the Wintun driver currently loaded.
*
- * @return The version number on success, or 0 if failure or Wintun not loaded.
+ * @return If the function succeeds, the return value is the version number. If the function fails, the return value is
+ * zero. To get extended error information, call GetLastError. Possible errors include the following:
+ * ERROR_FILE_NOT_FOUND Wintun not loaded;
+ * ERROR_GEN_FAILURE Enumerating drivers failed
*/
typedef DWORD(WINAPI *WINTUN_GET_VERSION_FUNC)(void);
@@ -240,14 +240,11 @@ typedef void *WINTUN_SESSION_HANDLE;
* @param Capacity Rings capacity. Must be between WINTUN_MIN_RING_CAPACITY and WINTUN_MAX_RING_CAPACITY (incl.)
* Must be a power of two.
*
- * @param Session Pointer to a variable to receive Wintun session handle
- *
- * @return ERROR_SUCCESS on success; Win32 error code otherwise.
+ * @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 WINTUN_STATUS(WINAPI *WINTUN_START_SESSION_FUNC)(
- _In_ WINTUN_ADAPTER_HANDLE Adapter,
- _In_ DWORD Capacity,
- _Out_ WINTUN_SESSION_HANDLE *Session);
+typedef _Return_type_success_(return != NULL)
+ WINTUN_SESSION_HANDLE(WINAPI *WINTUN_START_SESSION_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Adapter, _In_ DWORD Capacity);
/**
* Ends Wintun session.
@@ -279,22 +276,17 @@ typedef HANDLE(WINAPI *WINTUN_GET_READ_WAIT_EVENT_FUNC)(_In_ WINTUN_SESSION_HAND
*
* @param Session Wintun session handle obtained with WintunStartSession
*
- * @param Packet Pointer to receive pointer to layer 3 IPv4 or IPv6 packet. Client may modify its content at
- * will.
+ * @param PacketSize Pointer to receive packet size.
*
- * @param PacketSize Pointer to receive Packet size.
- *
- * @return Returns one of the following values:
- * ERROR_HANDLE_EOF Wintun adapter is terminating;
- * ERROR_NO_MORE_ITEMS Wintun buffer is exhausted;
- * ERROR_INVALID_DATA Wintun buffer is corrupt;
- * ERROR_SUCCESS on success.
- * Regardless, if the error was returned, some packets might have been read nevertheless.
+ * @return Pointer to layer 3 IPv4 or IPv6 packet. Client may modify its content at will. If the function fails, the
+ * return value is NULL. To get extended error information, call GetLastError. Possible errors include the
+ * following:
+ * ERROR_HANDLE_EOF Wintun adapter is terminating;
+ * ERROR_NO_MORE_ITEMS Wintun buffer is exhausted;
+ * ERROR_INVALID_DATA Wintun buffer is corrupt
*/
-typedef WINTUN_STATUS(WINAPI *WINTUN_RECEIVE_PACKET_FUNC)(
- _In_ WINTUN_SESSION_HANDLE *Session,
- _Out_bytecapcount_(*PacketSize) BYTE **Packet,
- _Out_ DWORD *PacketSize);
+typedef _Return_type_success_(return != NULL) _Ret_bytecount_(*PacketSize) BYTE *(
+ WINAPI *WINTUN_RECEIVE_PACKET_FUNC)(_In_ WINTUN_SESSION_HANDLE *Session, _Out_ DWORD *PacketSize);
/**
* Releases internal buffer after the received packet has been processed by the client. This function is thread-safe.
@@ -314,17 +306,14 @@ typedef void(WINAPI *WINTUN_RECEIVE_RELEASE_FUNC)(_In_ WINTUN_SESSION_HANDLE *Se
*
* @param PacketSize Exact packet size. Must be less or equal to WINTUN_MAX_IP_PACKET_SIZE.
*
- * @param Packet Pointer to receive pointer to memory where to prepare layer 3 IPv4 or IPv6 packet for sending.
- *
- * @return Returns one of the following values:
- * ERROR_HANDLE_EOF Wintun adapter is terminating;
- * ERROR_BUFFER_OVERFLOW Wintun buffer is full;
- * ERROR_SUCCESS on success.
+ * @return Returns pointer to memory where to prepare layer 3 IPv4 or IPv6 packet for sending. If the function fails,
+ * the return value is NULL. To get extended error information, call GetLastError. Possible errors include the
+ * following:
+ * ERROR_HANDLE_EOF Wintun adapter is terminating;
+ * ERROR_BUFFER_OVERFLOW Wintun buffer is full;
*/
-typedef WINTUN_STATUS(WINAPI *WINTUN_ALLOCATE_SEND_PACKET_FUNC)(
- _In_ WINTUN_SESSION_HANDLE *Session,
- _In_ DWORD PacketSize,
- _Out_bytecapcount_(PacketSize) BYTE **Packet);
+typedef _Return_type_success_(return != NULL) _Ret_bytecount_(PacketSize) BYTE *(
+ WINAPI *WINTUN_ALLOCATE_SEND_PACKET_FUNC)(_In_ WINTUN_SESSION_HANDLE *Session, _In_ DWORD PacketSize);
/**
* Sends the packet and releases internal buffer. WintunSendPacket is thread-safe, but the WintunAllocateSendPacket
diff --git a/example/example.c b/example/example.c
index cc3c32b..f6eec93 100644
--- a/example/example.c
+++ b/example/example.c
@@ -100,6 +100,15 @@ LogError(_In_z_ const WCHAR *Prefix, _In_ DWORD Error)
return Error;
}
+static DWORD
+LogLastError(_In_z_ const WCHAR *Prefix)
+{
+ DWORD LastError = GetLastError();
+ LogError(Prefix, LastError);
+ SetLastError(LastError);
+ return LastError;
+}
+
static void
Log(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ const WCHAR *Format, ...)
{
@@ -206,22 +215,26 @@ ReceivePackets(_Inout_ DWORD_PTR SessionPtr)
while (!HaveQuit)
{
- BYTE *Packet;
DWORD PacketSize;
- DWORD Result = WintunReceivePacket(Session, &Packet, &PacketSize);
- switch (Result)
+ BYTE *Packet = WintunReceivePacket(Session, &PacketSize);
+ if (Packet)
{
- case ERROR_SUCCESS:
PrintPacket(Packet, PacketSize);
WintunReceiveRelease(Session, Packet);
- continue;
- case ERROR_NO_MORE_ITEMS:
- if (WaitForMultipleObjects(_countof(WaitHandles), WaitHandles, FALSE, INFINITE) == WAIT_OBJECT_0)
- continue;
- return ERROR_SUCCESS;
- default:
- LogError(L"Packet read failed", Result);
- return Result;
+ }
+ else
+ {
+ DWORD LastError = GetLastError();
+ switch (LastError)
+ {
+ case ERROR_NO_MORE_ITEMS:
+ if (WaitForMultipleObjects(_countof(WaitHandles), WaitHandles, FALSE, INFINITE) == WAIT_OBJECT_0)
+ continue;
+ return ERROR_SUCCESS;
+ default:
+ LogError(L"Packet read failed", LastError);
+ return LastError;
+ }
}
}
return ERROR_SUCCESS;
@@ -233,8 +246,9 @@ SendPackets(_Inout_ DWORD_PTR SessionPtr)
WINTUN_SESSION_HANDLE Session = (WINTUN_SESSION_HANDLE)SessionPtr;
while (!HaveQuit)
{
- BYTE *Packet;
- WintunAllocateSendPacket(Session, 28, &Packet);
+ BYTE *Packet = WintunAllocateSendPacket(Session, 28);
+ if (!Packet)
+ return LogLastError(L"Packet write failed");
MakeICMP(Packet);
WintunSendPacket(Session, Packet);
@@ -269,9 +283,9 @@ InitializeWintun(void)
X(WintunAllocateSendPacket, WINTUN_ALLOCATE_SEND_PACKET_FUNC) || X(WintunSendPacket, WINTUN_SEND_PACKET_FUNC))
#undef X
{
- DWORD Result = GetLastError();
+ DWORD LastError = GetLastError();
FreeLibrary(Wintun);
- SetLastError(Result);
+ SetLastError(LastError);
return NULL;
}
SetLastError(ERROR_SUCCESS);
@@ -287,29 +301,31 @@ main(void)
WintunSetLogger(ConsoleLogger);
Log(WINTUN_LOG_INFO, L"Wintun library loaded");
- DWORD Result;
+ DWORD LastError;
HaveQuit = FALSE;
QuitEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
if (!QuitEvent)
{
- Result = LogError(L"Failed to create event", GetLastError());
+ LastError = LogError(L"Failed to create event", GetLastError());
goto cleanupWintun;
}
if (!SetConsoleCtrlHandler(CtrlHandler, TRUE))
{
- Result = LogError(L"Failed to set console handler", GetLastError());
+ LastError = LogError(L"Failed to set console handler", GetLastError());
goto cleanupQuit;
}
GUID ExampleGuid = { 0xdeadbabe, 0xcafe, 0xbeef, { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef } };
- WINTUN_ADAPTER_HANDLE Adapter;
- Result = WintunGetAdapter(L"Example", L"Demo", &Adapter);
- if (Result != ERROR_SUCCESS)
- Result = WintunCreateAdapter(L"Example", L"Demo", &ExampleGuid, &Adapter, NULL);
- if (Result != ERROR_SUCCESS)
+ WINTUN_ADAPTER_HANDLE Adapter = WintunGetAdapter(L"Example", L"Demo");
+ if (!Adapter)
{
- LogError(L"Failed to create adapter", Result);
- goto cleanupQuit;
+ Adapter = WintunCreateAdapter(L"Example", L"Demo", &ExampleGuid, NULL);
+ if (!Adapter)
+ {
+ LastError = GetLastError();
+ LogError(L"Failed to create adapter", LastError);
+ goto cleanupQuit;
+ }
}
DWORD Version = WintunGetVersion();
@@ -321,18 +337,17 @@ main(void)
AddressRow.Address.Ipv4.sin_family = AF_INET;
AddressRow.Address.Ipv4.sin_addr.S_un.S_addr = htonl((10 << 24) | (6 << 16) | (7 << 8) | (7 << 0)); /* 10.6.7.7 */
AddressRow.OnLinkPrefixLength = 24; /* This is a /24 network */
- Result = CreateUnicastIpAddressEntry(&AddressRow);
- if (Result != ERROR_SUCCESS && Result != ERROR_OBJECT_ALREADY_EXISTS)
+ LastError = CreateUnicastIpAddressEntry(&AddressRow);
+ if (LastError != ERROR_SUCCESS && LastError != ERROR_OBJECT_ALREADY_EXISTS)
{
- LogError(L"Failed to set IP address", Result);
+ LogError(L"Failed to set IP address", LastError);
goto cleanupAdapter;
}
- WINTUN_SESSION_HANDLE Session;
- Result = WintunStartSession(Adapter, 0x40000, &Session);
- if (Result != ERROR_SUCCESS)
+ WINTUN_SESSION_HANDLE Session = WintunStartSession(Adapter, 0x40000);
+ if (!Session)
{
- LogError(L"Failed to create adapter", Result);
+ LastError = LogLastError(L"Failed to create adapter");
goto cleanupAdapter;
}
@@ -342,11 +357,11 @@ main(void)
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SendPackets, (LPVOID)Session, 0, NULL) };
if (!Workers[0] || !Workers[1])
{
- Result = LogError(L"Failed to create threads", GetLastError());
+ LastError = LogError(L"Failed to create threads", GetLastError());
goto cleanupWorkers;
}
WaitForMultipleObjectsEx(_countof(Workers), Workers, TRUE, INFINITE, TRUE);
- Result = ERROR_SUCCESS;
+ LastError = ERROR_SUCCESS;
cleanupWorkers:
HaveQuit = TRUE;
@@ -368,5 +383,5 @@ cleanupQuit:
CloseHandle(QuitEvent);
cleanupWintun:
FreeLibrary(Wintun);
- return Result;
+ return LastError;
}