api: upgrade
Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
parent
d61007297d
commit
d675646ab8
1129
api/adapter.c
1129
api/adapter.c
File diff suppressed because it is too large
Load Diff
@ -13,58 +13,96 @@
|
|||||||
#define MAX_INSTANCE_ID MAX_PATH /* TODO: Is MAX_PATH always enough? */
|
#define MAX_INSTANCE_ID MAX_PATH /* TODO: Is MAX_PATH always enough? */
|
||||||
#define WINTUN_HWID L"Wintun"
|
#define WINTUN_HWID L"Wintun"
|
||||||
|
|
||||||
void
|
|
||||||
AdapterInit(void);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wintun adapter descriptor.
|
* Wintun adapter descriptor.
|
||||||
*/
|
*/
|
||||||
typedef struct _WINTUN_ADAPTER
|
typedef struct _WINTUN_ADAPTER
|
||||||
{
|
{
|
||||||
|
HDEVINFO DevInfo;
|
||||||
|
SP_DEVINFO_DATA DevInfoData;
|
||||||
GUID CfgInstanceID;
|
GUID CfgInstanceID;
|
||||||
WCHAR DevInstanceID[MAX_INSTANCE_ID];
|
WCHAR DevInstanceID[MAX_INSTANCE_ID];
|
||||||
DWORD LuidIndex;
|
DWORD LuidIndex;
|
||||||
DWORD IfType;
|
DWORD IfType;
|
||||||
|
DWORD IfIndex;
|
||||||
WCHAR Pool[WINTUN_MAX_POOL];
|
WCHAR Pool[WINTUN_MAX_POOL];
|
||||||
} WINTUN_ADAPTER;
|
} WINTUN_ADAPTER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @copydoc WINTUN_FREE_ADAPTER_FUNC
|
* @copydoc WINTUN_FREE_ADAPTER_FUNC
|
||||||
*/
|
*/
|
||||||
void WINAPI
|
WINTUN_FREE_ADAPTER_FUNC_IMPL WintunFreeAdapter;
|
||||||
WintunFreeAdapter(_In_ WINTUN_ADAPTER *Adapter);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @copydoc WINTUN_CREATE_ADAPTER_FUNC
|
* @copydoc WINTUN_CREATE_ADAPTER_FUNC
|
||||||
*/
|
*/
|
||||||
_Return_type_success_(return != NULL) WINTUN_ADAPTER *WINAPI WintunCreateAdapter(
|
WINTUN_CREATE_ADAPTER_FUNC_IMPL WintunCreateAdapter;
|
||||||
_In_z_ const WCHAR *Pool,
|
|
||||||
_In_z_ const WCHAR *Name,
|
/**
|
||||||
_In_opt_ const GUID *RequestedGUID,
|
* @copydoc WINTUN_OPEN_ADAPTER_FUNC
|
||||||
_Out_opt_ BOOL *RebootRequired);
|
*/
|
||||||
|
WINTUN_OPEN_ADAPTER_FUNC_IMPL WintunOpenAdapter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @copydoc WINTUN_DELETE_ADAPTER_FUNC
|
* @copydoc WINTUN_DELETE_ADAPTER_FUNC
|
||||||
*/
|
*/
|
||||||
_Return_type_success_(return != FALSE) BOOL WINAPI WintunDeleteAdapter(
|
WINTUN_DELETE_ADAPTER_FUNC_IMPL WintunDeleteAdapter;
|
||||||
_In_ const WINTUN_ADAPTER *Adapter,
|
|
||||||
_In_ BOOL ForceCloseSessions,
|
/**
|
||||||
_Out_opt_ BOOL *RebootRequired);
|
* @copydoc WINTUN_ENUM_ADAPTERS_FUNC
|
||||||
|
*/
|
||||||
|
WINTUN_ENUM_ADAPTERS_FUNC_IMPL WintunEnumAdapters;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @copydoc WINTUN_DELETE_POOL_DRIVER_FUNC
|
* @copydoc WINTUN_DELETE_POOL_DRIVER_FUNC
|
||||||
*/
|
*/
|
||||||
_Return_type_success_(return != FALSE) BOOL WINAPI
|
WINTUN_DELETE_POOL_DRIVER_FUNC_IMPL WintunDeletePoolDriver;
|
||||||
WintunDeletePoolDriver(_In_z_ const WCHAR *Pool, _Out_opt_ BOOL *RebootRequired);
|
|
||||||
|
/**
|
||||||
|
* @copydoc WINTUN_GET_ADAPTER_LUID_FUNC
|
||||||
|
*/
|
||||||
|
WINTUN_GET_ADAPTER_LUID_FUNC_IMPL WintunGetAdapterLUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc WINTUN_GET_ADAPTER_NAME_FUNC
|
||||||
|
*/
|
||||||
|
WINTUN_GET_ADAPTER_NAME_FUNC_IMPL WintunGetAdapterName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc WINTUN_SET_ADAPTER_NAME_FUNC
|
||||||
|
*/
|
||||||
|
WINTUN_SET_ADAPTER_NAME_FUNC_IMPL WintunSetAdapterName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copydoc WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC
|
||||||
|
*/
|
||||||
|
WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC_IMPL WintunGetRunningDriverVersion;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a handle to the adapter device object.
|
* Returns a handle to the adapter device object.
|
||||||
*
|
*
|
||||||
* @param Adapter Adapter handle obtained with WintunOpenAdapter or WintunCreateAdapter.
|
* @param Adapter Adapter handle obtained with WintunOpenAdapter or WintunCreateAdapter.
|
||||||
*
|
*
|
||||||
* @return If the function succeeds, the return value is adapter device object handle. Must be released with
|
* @return If the function succeeds, the return value is adapter device object handle.
|
||||||
* CloseHandle. If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error
|
* If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error
|
||||||
* information, call GetLastError.
|
* information, call GetLastError.
|
||||||
*/
|
*/
|
||||||
_Return_type_success_(return != INVALID_HANDLE_VALUE) HANDLE WINAPI
|
_Return_type_success_(return != INVALID_HANDLE_VALUE)
|
||||||
AdapterOpenDeviceObject(_In_ const WINTUN_ADAPTER *Adapter);
|
HANDLE WINAPI
|
||||||
|
AdapterOpenDeviceObject(_In_ const WINTUN_ADAPTER *Adapter);
|
||||||
|
/**
|
||||||
|
* Returns an adapter object based on a devnode instance ID.
|
||||||
|
*
|
||||||
|
* @param Pool Pool name of adapter object to be opened.
|
||||||
|
*
|
||||||
|
* @param DevInstanceID Instance ID of devnode for opening adapter.
|
||||||
|
*
|
||||||
|
* @return If the function succeeds, the return value is adapter object..
|
||||||
|
* If the function fails, the return value is NULL. To get extended error
|
||||||
|
* information, call GetLastError.
|
||||||
|
*/
|
||||||
|
_Must_inspect_result_
|
||||||
|
_Return_type_success_(return != NULL)
|
||||||
|
_Post_maybenull_
|
||||||
|
WINTUN_ADAPTER *
|
||||||
|
AdapterOpenFromDevInstanceId(_In_z_ LPCWSTR Pool, _In_z_ LPCWSTR DevInstanceID);
|
||||||
|
@ -53,15 +53,13 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="main.h" />
|
<ClInclude Include="main.h" />
|
||||||
<ClInclude Include="adapter.h" />
|
<ClInclude Include="adapter.h" />
|
||||||
<ClInclude Include="rundll32_i.c">
|
|
||||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="logger.h" />
|
<ClInclude Include="logger.h" />
|
||||||
<ClInclude Include="namespace.h" />
|
<ClInclude Include="namespace.h" />
|
||||||
<ClInclude Include="nci.h" />
|
<ClInclude Include="nci.h" />
|
||||||
<ClInclude Include="ntdll.h" />
|
<ClInclude Include="ntdll.h" />
|
||||||
<ClInclude Include="registry.h" />
|
<ClInclude Include="registry.h" />
|
||||||
<ClInclude Include="resource.h" />
|
<ClInclude Include="resource.h" />
|
||||||
|
<ClInclude Include="rundll32.h" />
|
||||||
<ClInclude Include="wintun.h" />
|
<ClInclude Include="wintun.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
51
api/logger.c
51
api/logger.c
@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
|
#include "adapter.h"
|
||||||
#include "ntdll.h"
|
#include "ntdll.h"
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <winternl.h>
|
#include <winternl.h>
|
||||||
@ -11,17 +12,16 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
static BOOL CALLBACK
|
static BOOL CALLBACK
|
||||||
NopLogger(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ const WCHAR *LogLine)
|
NopLogger(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ LPCWSTR LogLine)
|
||||||
{
|
{
|
||||||
UNREFERENCED_PARAMETER(Level);
|
|
||||||
UNREFERENCED_PARAMETER(LogLine);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
WINTUN_LOGGER_CALLBACK Logger = NopLogger;
|
WINTUN_LOGGER_CALLBACK Logger = NopLogger;
|
||||||
|
|
||||||
void CALLBACK
|
_Use_decl_annotations_
|
||||||
WintunSetLogger(_In_ WINTUN_LOGGER_CALLBACK NewLogger)
|
VOID WINAPI
|
||||||
|
WintunSetLogger(WINTUN_LOGGER_CALLBACK NewLogger)
|
||||||
{
|
{
|
||||||
if (!NewLogger)
|
if (!NewLogger)
|
||||||
NewLogger = NopLogger;
|
NewLogger = NopLogger;
|
||||||
@ -29,14 +29,15 @@ WintunSetLogger(_In_ WINTUN_LOGGER_CALLBACK NewLogger)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static VOID
|
static VOID
|
||||||
StrTruncate(_Inout_count_(StrChars) WCHAR *Str, _In_ SIZE_T StrChars)
|
StrTruncate(_Inout_count_(StrChars) LPWSTR Str, _In_ SIZE_T StrChars)
|
||||||
{
|
{
|
||||||
Str[StrChars - 2] = L'\u2026'; /* Horizontal Ellipsis */
|
Str[StrChars - 2] = L'\u2026'; /* Horizontal Ellipsis */
|
||||||
Str[StrChars - 1] = 0;
|
Str[StrChars - 1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Post_equals_last_error_ DWORD
|
_Use_decl_annotations_
|
||||||
LoggerLog(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ const WCHAR *Function, _In_z_ const WCHAR *LogLine)
|
DWORD
|
||||||
|
LoggerLog(WINTUN_LOGGER_LEVEL Level, LPCWSTR Function, LPCWSTR LogLine)
|
||||||
{
|
{
|
||||||
DWORD LastError = GetLastError();
|
DWORD LastError = GetLastError();
|
||||||
if (Function)
|
if (Function)
|
||||||
@ -52,12 +53,9 @@ LoggerLog(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ const WCHAR *Function, _In_z_ c
|
|||||||
return LastError;
|
return LastError;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Post_equals_last_error_ DWORD
|
_Use_decl_annotations_
|
||||||
LoggerLogV(
|
DWORD
|
||||||
_In_ WINTUN_LOGGER_LEVEL Level,
|
LoggerLogV(WINTUN_LOGGER_LEVEL Level, LPCWSTR Function, LPCWSTR Format, va_list Args)
|
||||||
_In_z_ const WCHAR *Function,
|
|
||||||
_In_z_ _Printf_format_string_ const WCHAR *Format,
|
|
||||||
_In_ va_list Args)
|
|
||||||
{
|
{
|
||||||
DWORD LastError = GetLastError();
|
DWORD LastError = GetLastError();
|
||||||
WCHAR LogLine[0x400];
|
WCHAR LogLine[0x400];
|
||||||
@ -71,16 +69,17 @@ LoggerLogV(
|
|||||||
return LastError;
|
return LastError;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Post_equals_last_error_ DWORD
|
_Use_decl_annotations_
|
||||||
LoggerError(_In_ DWORD Error, _In_z_ const WCHAR *Function, _In_z_ const WCHAR *Prefix)
|
DWORD
|
||||||
|
LoggerError(DWORD Error, LPCWSTR Function, LPCWSTR Prefix)
|
||||||
{
|
{
|
||||||
WCHAR *SystemMessage = NULL, *FormattedMessage = NULL;
|
LPWSTR SystemMessage = NULL, FormattedMessage = NULL;
|
||||||
FormatMessageW(
|
FormatMessageW(
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
||||||
NULL,
|
NULL,
|
||||||
HRESULT_FROM_SETUPAPI(Error),
|
HRESULT_FROM_SETUPAPI(Error),
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
(void *)&SystemMessage,
|
(VOID *)&SystemMessage,
|
||||||
0,
|
0,
|
||||||
NULL);
|
NULL);
|
||||||
FormatMessageW(
|
FormatMessageW(
|
||||||
@ -89,7 +88,7 @@ LoggerError(_In_ DWORD Error, _In_z_ const WCHAR *Function, _In_z_ const WCHAR *
|
|||||||
SystemMessage ? L"%4: %1: %3(Code 0x%2!08X!)" : L"%4: %1: Code 0x%2!08X!",
|
SystemMessage ? L"%4: %1: %3(Code 0x%2!08X!)" : L"%4: %1: Code 0x%2!08X!",
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
(void *)&FormattedMessage,
|
(VOID *)&FormattedMessage,
|
||||||
0,
|
0,
|
||||||
(va_list *)(DWORD_PTR[]){ (DWORD_PTR)Prefix, (DWORD_PTR)Error, (DWORD_PTR)SystemMessage, (DWORD_PTR)Function });
|
(va_list *)(DWORD_PTR[]){ (DWORD_PTR)Prefix, (DWORD_PTR)Error, (DWORD_PTR)SystemMessage, (DWORD_PTR)Function });
|
||||||
if (FormattedMessage)
|
if (FormattedMessage)
|
||||||
@ -99,12 +98,9 @@ LoggerError(_In_ DWORD Error, _In_z_ const WCHAR *Function, _In_z_ const WCHAR *
|
|||||||
return Error;
|
return Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Post_equals_last_error_ DWORD
|
_Use_decl_annotations_
|
||||||
LoggerErrorV(
|
DWORD
|
||||||
_In_ DWORD Error,
|
LoggerErrorV(DWORD Error, LPCWSTR Function, LPCWSTR Format, va_list Args)
|
||||||
_In_z_ const WCHAR *Function,
|
|
||||||
_In_z_ _Printf_format_string_ const WCHAR *Format,
|
|
||||||
_In_ va_list Args)
|
|
||||||
{
|
{
|
||||||
WCHAR Prefix[0x400];
|
WCHAR Prefix[0x400];
|
||||||
if (_vsnwprintf_s(Prefix, _countof(Prefix), _TRUNCATE, Format, Args) == -1)
|
if (_vsnwprintf_s(Prefix, _countof(Prefix), _TRUNCATE, Format, Args) == -1)
|
||||||
@ -112,13 +108,14 @@ LoggerErrorV(
|
|||||||
return LoggerError(Error, Function, Prefix);
|
return LoggerError(Error, Function, Prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_Use_decl_annotations_
|
||||||
VOID
|
VOID
|
||||||
LoggerGetRegistryKeyPath(_In_ HKEY Key, _Out_cap_c_(MAX_REG_PATH) WCHAR *Path)
|
LoggerGetRegistryKeyPath(HKEY Key, LPWSTR Path)
|
||||||
{
|
{
|
||||||
DWORD LastError = GetLastError();
|
DWORD LastError = GetLastError();
|
||||||
if (Key == NULL)
|
if (Key == NULL)
|
||||||
{
|
{
|
||||||
wcscpy_s(Path, MAX_REG_PATH, L"<null>");
|
wcsncpy_s(Path, MAX_REG_PATH, L"<null>", _TRUNCATE);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (_snwprintf_s(Path, MAX_REG_PATH, _TRUNCATE, L"0x%p", Key) == -1)
|
if (_snwprintf_s(Path, MAX_REG_PATH, _TRUNCATE, L"0x%p", Key) == -1)
|
||||||
|
123
api/logger.h
123
api/logger.h
@ -9,6 +9,7 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "registry.h"
|
#include "registry.h"
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
#include <intsafe.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
|
||||||
@ -17,25 +18,23 @@ extern WINTUN_LOGGER_CALLBACK Logger;
|
|||||||
/**
|
/**
|
||||||
* @copydoc WINTUN_SET_LOGGER_FUNC
|
* @copydoc WINTUN_SET_LOGGER_FUNC
|
||||||
*/
|
*/
|
||||||
void WINAPI
|
WINTUN_SET_LOGGER_FUNC_IMPL WintunSetLogger;
|
||||||
WintunSetLogger(_In_ WINTUN_LOGGER_CALLBACK NewLogger);
|
|
||||||
|
|
||||||
_Post_equals_last_error_ DWORD
|
_Post_equals_last_error_
|
||||||
LoggerLog(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ const WCHAR *Function, _In_z_ const WCHAR *LogLine);
|
DWORD
|
||||||
|
LoggerLog(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ LPCWSTR Function, _In_z_ LPCWSTR LogLine);
|
||||||
|
|
||||||
_Post_equals_last_error_ DWORD
|
_Post_equals_last_error_
|
||||||
|
DWORD
|
||||||
LoggerLogV(
|
LoggerLogV(
|
||||||
_In_ WINTUN_LOGGER_LEVEL Level,
|
_In_ WINTUN_LOGGER_LEVEL Level,
|
||||||
_In_z_ const WCHAR *Function,
|
_In_z_ LPCWSTR Function,
|
||||||
_In_z_ _Printf_format_string_ const WCHAR *Format,
|
_In_z_ _Printf_format_string_ LPCWSTR Format,
|
||||||
_In_ va_list Args);
|
_In_ va_list Args);
|
||||||
|
|
||||||
static inline _Post_equals_last_error_ DWORD
|
_Post_equals_last_error_
|
||||||
LoggerLogFmt(
|
static inline DWORD
|
||||||
_In_ WINTUN_LOGGER_LEVEL Level,
|
LoggerLogFmt(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ LPCWSTR Function, _In_z_ _Printf_format_string_ LPCWSTR Format, ...)
|
||||||
_In_z_ const WCHAR *Function,
|
|
||||||
_In_z_ _Printf_format_string_ const WCHAR *Format,
|
|
||||||
...)
|
|
||||||
{
|
{
|
||||||
va_list Args;
|
va_list Args;
|
||||||
va_start(Args, Format);
|
va_start(Args, Format);
|
||||||
@ -44,18 +43,21 @@ LoggerLogFmt(
|
|||||||
return LastError;
|
return LastError;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Post_equals_last_error_ DWORD
|
_Post_equals_last_error_
|
||||||
LoggerError(_In_ DWORD Error, _In_z_ const WCHAR *Function, _In_z_ const WCHAR *Prefix);
|
DWORD
|
||||||
|
LoggerError(_In_ DWORD Error, _In_z_ LPCWSTR Function, _In_z_ LPCWSTR Prefix);
|
||||||
|
|
||||||
_Post_equals_last_error_ DWORD
|
_Post_equals_last_error_
|
||||||
|
DWORD
|
||||||
LoggerErrorV(
|
LoggerErrorV(
|
||||||
_In_ DWORD Error,
|
_In_ DWORD Error,
|
||||||
_In_z_ const WCHAR *Function,
|
_In_z_ LPCWSTR Function,
|
||||||
_In_z_ _Printf_format_string_ const WCHAR *Format,
|
_In_z_ _Printf_format_string_ LPCWSTR Format,
|
||||||
_In_ va_list Args);
|
_In_ va_list Args);
|
||||||
|
|
||||||
static inline _Post_equals_last_error_ DWORD
|
_Post_equals_last_error_
|
||||||
LoggerErrorFmt(_In_ DWORD Error, _In_z_ const WCHAR *Function, _In_z_ _Printf_format_string_ const WCHAR *Format, ...)
|
static inline DWORD
|
||||||
|
LoggerErrorFmt(_In_ DWORD Error, _In_z_ LPCWSTR Function, _In_z_ _Printf_format_string_ LPCWSTR Format, ...)
|
||||||
{
|
{
|
||||||
va_list Args;
|
va_list Args;
|
||||||
va_start(Args, Format);
|
va_start(Args, Format);
|
||||||
@ -64,8 +66,9 @@ LoggerErrorFmt(_In_ DWORD Error, _In_z_ const WCHAR *Function, _In_z_ _Printf_fo
|
|||||||
return LastError;
|
return LastError;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline _Post_equals_last_error_ DWORD
|
_Post_equals_last_error_
|
||||||
LoggerLastErrorV(_In_z_ const WCHAR *Function, _In_z_ _Printf_format_string_ const WCHAR *Format, _In_ va_list Args)
|
static inline DWORD
|
||||||
|
LoggerLastErrorV(_In_z_ LPCWSTR Function, _In_z_ _Printf_format_string_ LPCWSTR Format, _In_ va_list Args)
|
||||||
{
|
{
|
||||||
DWORD LastError = GetLastError();
|
DWORD LastError = GetLastError();
|
||||||
LoggerErrorV(LastError, Function, Format, Args);
|
LoggerErrorV(LastError, Function, Format, Args);
|
||||||
@ -73,8 +76,9 @@ LoggerLastErrorV(_In_z_ const WCHAR *Function, _In_z_ _Printf_format_string_ con
|
|||||||
return LastError;
|
return LastError;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline _Post_equals_last_error_ DWORD
|
_Post_equals_last_error_
|
||||||
LoggerLastErrorFmt(_In_z_ const WCHAR *Function, _In_z_ _Printf_format_string_ const WCHAR *Format, ...)
|
static inline DWORD
|
||||||
|
LoggerLastErrorFmt(_In_z_ LPCWSTR Function, _In_z_ _Printf_format_string_ LPCWSTR Format, ...)
|
||||||
{
|
{
|
||||||
va_list Args;
|
va_list Args;
|
||||||
va_start(Args, Format);
|
va_start(Args, Format);
|
||||||
@ -84,7 +88,7 @@ LoggerLastErrorFmt(_In_z_ const WCHAR *Function, _In_z_ _Printf_format_string_ c
|
|||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
LoggerGetRegistryKeyPath(_In_ HKEY Key, _Out_cap_c_(MAX_REG_PATH) WCHAR *Path);
|
LoggerGetRegistryKeyPath(_In_ HKEY Key, _Out_writes_z_(MAX_REG_PATH) LPWSTR Path);
|
||||||
|
|
||||||
#define __L(x) L##x
|
#define __L(x) L##x
|
||||||
#define _L(x) __L(x)
|
#define _L(x) __L(x)
|
||||||
@ -94,10 +98,31 @@ LoggerGetRegistryKeyPath(_In_ HKEY Key, _Out_cap_c_(MAX_REG_PATH) WCHAR *Path);
|
|||||||
|
|
||||||
#define RET_ERROR(Ret, Error) ((Error) == ERROR_SUCCESS ? (Ret) : (SetLastError(Error), 0))
|
#define RET_ERROR(Ret, Error) ((Error) == ERROR_SUCCESS ? (Ret) : (SetLastError(Error), 0))
|
||||||
|
|
||||||
static inline _Return_type_success_(return != NULL) _Ret_maybenull_
|
_Must_inspect_result_
|
||||||
_Post_writable_byte_size_(Size) void *LoggerAlloc(_In_z_ const WCHAR *Function, _In_ DWORD Flags, _In_ SIZE_T Size)
|
DECLSPEC_ALLOCATOR
|
||||||
|
static inline _Return_type_success_(return != NULL)
|
||||||
|
_Post_maybenull_
|
||||||
|
_Post_writable_byte_size_(Size)
|
||||||
|
VOID *
|
||||||
|
LoggerAlloc(_In_z_ LPCWSTR Function, _In_ DWORD Flags, _In_ SIZE_T Size)
|
||||||
{
|
{
|
||||||
void *Data = HeapAlloc(ModuleHeap, Flags, Size);
|
VOID *Data = HeapAlloc(ModuleHeap, Flags, Size);
|
||||||
|
if (!Data)
|
||||||
|
{
|
||||||
|
LoggerLogFmt(WINTUN_LOG_ERR, Function, L"Out of memory (flags: 0x%x, requested size: 0x%zx)", Flags, Size);
|
||||||
|
SetLastError(ERROR_OUTOFMEMORY);
|
||||||
|
}
|
||||||
|
return Data;
|
||||||
|
}
|
||||||
|
_Must_inspect_result_
|
||||||
|
DECLSPEC_ALLOCATOR
|
||||||
|
static inline _Return_type_success_(return != NULL)
|
||||||
|
_Post_maybenull_
|
||||||
|
_Post_writable_byte_size_(Size)
|
||||||
|
VOID *
|
||||||
|
LoggerReAlloc(_In_z_ LPCWSTR Function, _In_ DWORD Flags, _Frees_ptr_opt_ LPVOID Mem, _In_ SIZE_T Size)
|
||||||
|
{
|
||||||
|
VOID *Data = Mem ? HeapReAlloc(ModuleHeap, Flags, Mem, Size) : HeapAlloc(ModuleHeap, Flags, Size);
|
||||||
if (!Data)
|
if (!Data)
|
||||||
{
|
{
|
||||||
LoggerLogFmt(WINTUN_LOG_ERR, Function, L"Out of memory (flags: 0x%x, requested size: 0x%zx)", Flags, Size);
|
LoggerLogFmt(WINTUN_LOG_ERR, Function, L"Out of memory (flags: 0x%x, requested size: 0x%zx)", Flags, Size);
|
||||||
@ -106,10 +131,48 @@ static inline _Return_type_success_(return != NULL) _Ret_maybenull_
|
|||||||
return Data;
|
return Data;
|
||||||
}
|
}
|
||||||
#define Alloc(Size) LoggerAlloc(_L(__FUNCTION__), 0, Size)
|
#define Alloc(Size) LoggerAlloc(_L(__FUNCTION__), 0, Size)
|
||||||
|
#define ReAlloc(Mem, Size) LoggerReAlloc(_L(__FUNCTION__), 0, Mem, Size)
|
||||||
#define Zalloc(Size) LoggerAlloc(_L(__FUNCTION__), HEAP_ZERO_MEMORY, Size)
|
#define Zalloc(Size) LoggerAlloc(_L(__FUNCTION__), HEAP_ZERO_MEMORY, Size)
|
||||||
|
#define ReZalloc(Mem, Size) LoggerReAlloc(_L(__FUNCTION__), HEAP_ZERO_MEMORY, Mem, Size)
|
||||||
|
|
||||||
static inline void
|
_Must_inspect_result_
|
||||||
Free(void *Ptr)
|
DECLSPEC_ALLOCATOR
|
||||||
|
static inline _Return_type_success_(return != NULL)
|
||||||
|
_Post_maybenull_
|
||||||
|
_Post_writable_byte_size_((NumberOfElements) * (SizeOfOneElement))
|
||||||
|
VOID *
|
||||||
|
LoggerAllocArray(_In_z_ LPCWSTR Function, _In_ DWORD Flags, _In_ SIZE_T NumberOfElements, _In_ SIZE_T SizeOfOneElement)
|
||||||
|
{
|
||||||
|
SIZE_T Size;
|
||||||
|
if (FAILED(SIZETMult(NumberOfElements, SizeOfOneElement, &Size)))
|
||||||
|
return NULL;
|
||||||
|
return LoggerAlloc(Function, Flags, Size);
|
||||||
|
}
|
||||||
|
_Must_inspect_result_
|
||||||
|
DECLSPEC_ALLOCATOR
|
||||||
|
static inline _Return_type_success_(return != NULL)
|
||||||
|
_Post_maybenull_
|
||||||
|
_Post_writable_byte_size_((NumberOfElements) * (SizeOfOneElement))
|
||||||
|
VOID *
|
||||||
|
LoggerReAllocArray(
|
||||||
|
_In_z_ LPCWSTR Function,
|
||||||
|
_In_ DWORD Flags,
|
||||||
|
_Frees_ptr_opt_ LPVOID Mem,
|
||||||
|
_In_ SIZE_T NumberOfElements,
|
||||||
|
_In_ SIZE_T SizeOfOneElement)
|
||||||
|
{
|
||||||
|
SIZE_T Size;
|
||||||
|
if (FAILED(SIZETMult(NumberOfElements, SizeOfOneElement, &Size)))
|
||||||
|
return NULL;
|
||||||
|
return LoggerReAlloc(Function, Flags, Mem, Size);
|
||||||
|
}
|
||||||
|
#define AllocArray(Count, Size) LoggerAllocArray(_L(__FUNCTION__), 0, Count, Size)
|
||||||
|
#define ReAllocArray(Mem, Count, Size) LoggerReAllocArray(_L(__FUNCTION__), 0, Mem, Count, Size)
|
||||||
|
#define ZallocArray(Count, Size) LoggerAllocArray(_L(__FUNCTION__), HEAP_ZERO_MEMORY, Count, Size)
|
||||||
|
#define ReZallocArray(Mem, Count, Size) LoggerReAllocArray(_L(__FUNCTION__), HEAP_ZERO_MEMORY, Mem, Count, Size)
|
||||||
|
|
||||||
|
static inline VOID
|
||||||
|
Free(_Frees_ptr_opt_ VOID *Ptr)
|
||||||
{
|
{
|
||||||
if (!Ptr)
|
if (!Ptr)
|
||||||
return;
|
return;
|
||||||
|
43
api/main.c
43
api/main.c
@ -3,18 +3,15 @@
|
|||||||
* Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved.
|
* Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "adapter.h"
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "registry.h"
|
#include "adapter.h"
|
||||||
|
#include "main.h"
|
||||||
#include "namespace.h"
|
#include "namespace.h"
|
||||||
#include "wintun.h"
|
#include "registry.h"
|
||||||
|
#include "ntdll.h"
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#pragma warning(push)
|
|
||||||
#pragma warning(disable : 4201)
|
|
||||||
/* nonstandard extension used: nameless struct/union */
|
|
||||||
#include <delayimp.h>
|
#include <delayimp.h>
|
||||||
#pragma warning(pop)
|
|
||||||
#include <sddl.h>
|
#include <sddl.h>
|
||||||
#include <winefs.h>
|
#include <winefs.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -23,6 +20,8 @@ HINSTANCE ResourceModule;
|
|||||||
HANDLE ModuleHeap;
|
HANDLE ModuleHeap;
|
||||||
SECURITY_ATTRIBUTES SecurityAttributes = { .nLength = sizeof(SECURITY_ATTRIBUTES) };
|
SECURITY_ATTRIBUTES SecurityAttributes = { .nLength = sizeof(SECURITY_ATTRIBUTES) };
|
||||||
BOOL IsLocalSystem;
|
BOOL IsLocalSystem;
|
||||||
|
USHORT NativeMachine = IMAGE_FILE_PROCESS;
|
||||||
|
BOOL IsWindows10;
|
||||||
|
|
||||||
static FARPROC WINAPI
|
static FARPROC WINAPI
|
||||||
DelayedLoadLibraryHook(unsigned dliNotify, PDelayLoadInfo pdli)
|
DelayedLoadLibraryHook(unsigned dliNotify, PDelayLoadInfo pdli)
|
||||||
@ -37,8 +36,7 @@ DelayedLoadLibraryHook(unsigned dliNotify, PDelayLoadInfo pdli)
|
|||||||
|
|
||||||
const PfnDliHook __pfnDliNotifyHook2 = DelayedLoadLibraryHook;
|
const PfnDliHook __pfnDliNotifyHook2 = DelayedLoadLibraryHook;
|
||||||
|
|
||||||
static BOOL
|
static BOOL InitializeSecurityObjects(VOID)
|
||||||
InitializeSecurityObjects(void)
|
|
||||||
{
|
{
|
||||||
BYTE LocalSystemSid[MAX_SID_SIZE];
|
BYTE LocalSystemSid[MAX_SID_SIZE];
|
||||||
DWORD RequiredBytes = sizeof(LocalSystemSid);
|
DWORD RequiredBytes = sizeof(LocalSystemSid);
|
||||||
@ -72,11 +70,32 @@ cleanupProcessToken:
|
|||||||
return Ret;
|
return Ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VOID EnvInit(VOID)
|
||||||
|
{
|
||||||
|
DWORD MajorVersion;
|
||||||
|
RtlGetNtVersionNumbers(&MajorVersion, NULL, NULL);
|
||||||
|
IsWindows10 = MajorVersion >= 10;
|
||||||
|
|
||||||
|
#ifdef MAYBE_WOW64
|
||||||
|
typedef BOOL(WINAPI * IsWow64Process2_t)(
|
||||||
|
_In_ HANDLE hProcess, _Out_ USHORT * pProcessMachine, _Out_opt_ USHORT * pNativeMachine);
|
||||||
|
HANDLE Kernel32;
|
||||||
|
IsWow64Process2_t IsWow64Process2;
|
||||||
|
USHORT ProcessMachine;
|
||||||
|
if ((Kernel32 = GetModuleHandleW(L"kernel32.dll")) == NULL ||
|
||||||
|
(IsWow64Process2 = (IsWow64Process2_t)GetProcAddress(Kernel32, "IsWow64Process2")) == NULL ||
|
||||||
|
!IsWow64Process2(GetCurrentProcess(), &ProcessMachine, &NativeMachine))
|
||||||
|
{
|
||||||
|
BOOL IsWoW64;
|
||||||
|
NativeMachine =
|
||||||
|
IsWow64Process(GetCurrentProcess(), &IsWoW64) && IsWoW64 ? IMAGE_FILE_MACHINE_AMD64 : IMAGE_FILE_PROCESS;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
BOOL APIENTRY
|
BOOL APIENTRY
|
||||||
DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved)
|
DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved)
|
||||||
{
|
{
|
||||||
UNREFERENCED_PARAMETER(lpvReserved);
|
|
||||||
|
|
||||||
switch (fdwReason)
|
switch (fdwReason)
|
||||||
{
|
{
|
||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
@ -89,7 +108,7 @@ DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved)
|
|||||||
HeapDestroy(ModuleHeap);
|
HeapDestroy(ModuleHeap);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
AdapterInit();
|
EnvInit();
|
||||||
NamespaceInit();
|
NamespaceInit();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
27
api/main.h
27
api/main.h
@ -7,26 +7,21 @@
|
|||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
/* TODO: Replace with is_defined. MSVC has issues with the linux kernel varadic macro trick for this. */
|
#if defined(_M_IX86)
|
||||||
#if defined(_M_IX86) || defined(_M_AMD64) || defined(_M_ARM)
|
# define IMAGE_FILE_PROCESS IMAGE_FILE_MACHINE_I386
|
||||||
# define MAYBE_WOW64 1
|
#elif defined(_M_AMD64)
|
||||||
|
# define IMAGE_FILE_PROCESS IMAGE_FILE_MACHINE_AMD64
|
||||||
|
#elif defined(_M_ARM)
|
||||||
|
# define IMAGE_FILE_PROCESS IMAGE_FILE_MACHINE_ARMNT
|
||||||
|
#elif defined(_M_ARM64)
|
||||||
|
# define IMAGE_FILE_PROCESS IMAGE_FILE_MACHINE_ARM64
|
||||||
#else
|
#else
|
||||||
# define MAYBE_WOW64 0
|
# error Unsupported architecture
|
||||||
#endif
|
#endif
|
||||||
#if defined(_M_AMD64) || defined(_M_ARM64)
|
|
||||||
# define ACCEPT_WOW64 1
|
|
||||||
#else
|
|
||||||
# define ACCEPT_WOW64 0
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_WHQL
|
|
||||||
# undef HAVE_WHQL
|
|
||||||
# define HAVE_WHQL 1
|
|
||||||
#else
|
|
||||||
# define HAVE_WHQL 0
|
|
||||||
#endif
|
|
||||||
#pragma warning(disable : 4127) /* conditional expression is constant */
|
|
||||||
|
|
||||||
extern HINSTANCE ResourceModule;
|
extern HINSTANCE ResourceModule;
|
||||||
extern HANDLE ModuleHeap;
|
extern HANDLE ModuleHeap;
|
||||||
extern SECURITY_ATTRIBUTES SecurityAttributes;
|
extern SECURITY_ATTRIBUTES SecurityAttributes;
|
||||||
extern BOOL IsLocalSystem;
|
extern BOOL IsLocalSystem;
|
||||||
|
extern USHORT NativeMachine;
|
||||||
|
extern BOOL IsWindows10;
|
@ -19,13 +19,16 @@ static HANDLE BoundaryDescriptor = NULL;
|
|||||||
static CRITICAL_SECTION Initializing;
|
static CRITICAL_SECTION Initializing;
|
||||||
static BCRYPT_ALG_HANDLE AlgProvider;
|
static BCRYPT_ALG_HANDLE AlgProvider;
|
||||||
|
|
||||||
static _Return_type_success_(
|
_Must_inspect_result_
|
||||||
return != NULL) WCHAR *NormalizeStringAlloc(_In_ NORM_FORM NormForm, _In_z_ const WCHAR *Source)
|
static _Return_type_success_(return != NULL)
|
||||||
|
_Post_maybenull_
|
||||||
|
LPWSTR
|
||||||
|
NormalizeStringAlloc(_In_ NORM_FORM NormForm, _In_z_ LPCWSTR Source)
|
||||||
{
|
{
|
||||||
int Len = NormalizeString(NormForm, Source, -1, NULL, 0);
|
int Len = NormalizeString(NormForm, Source, -1, NULL, 0);
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
WCHAR *Str = Alloc(sizeof(WCHAR) * Len);
|
LPWSTR Str = AllocArray(Len, sizeof(*Str));
|
||||||
if (!Str)
|
if (!Str)
|
||||||
return NULL;
|
return NULL;
|
||||||
Len = NormalizeString(NormForm, Source, -1, Str, Len);
|
Len = NormalizeString(NormForm, Source, -1, Str, Len);
|
||||||
@ -41,7 +44,8 @@ static _Return_type_success_(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static _Return_type_success_(return != FALSE) BOOL NamespaceRuntimeInit(void)
|
static _Return_type_success_(return != FALSE)
|
||||||
|
BOOL NamespaceRuntimeInit(VOID)
|
||||||
{
|
{
|
||||||
DWORD LastError;
|
DWORD LastError;
|
||||||
|
|
||||||
@ -110,8 +114,9 @@ cleanupLeaveCriticalSection:
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Check_return_
|
_Use_decl_annotations_
|
||||||
_Return_type_success_(return != NULL) HANDLE NamespaceTakePoolMutex(_In_z_ const WCHAR *Pool)
|
HANDLE
|
||||||
|
NamespaceTakePoolMutex(LPCWSTR Pool)
|
||||||
{
|
{
|
||||||
if (!NamespaceRuntimeInit())
|
if (!NamespaceRuntimeInit())
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -133,7 +138,7 @@ _Return_type_success_(return != NULL) HANDLE NamespaceTakePoolMutex(_In_z_ const
|
|||||||
LastError = RtlNtStatusToDosError(Status);
|
LastError = RtlNtStatusToDosError(Status);
|
||||||
goto cleanupSha256;
|
goto cleanupSha256;
|
||||||
}
|
}
|
||||||
WCHAR *PoolNorm = NormalizeStringAlloc(NormalizationC, Pool);
|
LPWSTR PoolNorm = NormalizeStringAlloc(NormalizationC, Pool);
|
||||||
if (!PoolNorm)
|
if (!PoolNorm)
|
||||||
{
|
{
|
||||||
LastError = GetLastError();
|
LastError = GetLastError();
|
||||||
@ -184,8 +189,9 @@ cleanupSha256:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Check_return_
|
_Use_decl_annotations_
|
||||||
_Return_type_success_(return != NULL) HANDLE NamespaceTakeDriverInstallationMutex(void)
|
HANDLE
|
||||||
|
NamespaceTakeDriverInstallationMutex(VOID)
|
||||||
{
|
{
|
||||||
if (!NamespaceRuntimeInit())
|
if (!NamespaceRuntimeInit())
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -208,21 +214,20 @@ _Return_type_success_(return != NULL) HANDLE NamespaceTakeDriverInstallationMute
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
_Use_decl_annotations_
|
||||||
NamespaceReleaseMutex(_In_ HANDLE Mutex)
|
VOID
|
||||||
|
NamespaceReleaseMutex(HANDLE Mutex)
|
||||||
{
|
{
|
||||||
ReleaseMutex(Mutex);
|
ReleaseMutex(Mutex);
|
||||||
CloseHandle(Mutex);
|
CloseHandle(Mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
VOID NamespaceInit(VOID)
|
||||||
NamespaceInit(void)
|
|
||||||
{
|
{
|
||||||
InitializeCriticalSection(&Initializing);
|
InitializeCriticalSection(&Initializing);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
VOID NamespaceDone(VOID)
|
||||||
NamespaceDone(void)
|
|
||||||
{
|
{
|
||||||
EnterCriticalSection(&Initializing);
|
EnterCriticalSection(&Initializing);
|
||||||
if (PrivateNamespace)
|
if (PrivateNamespace)
|
||||||
|
@ -7,17 +7,24 @@
|
|||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
|
||||||
_Check_return_
|
_Must_inspect_result_
|
||||||
_Return_type_success_(return != NULL) HANDLE NamespaceTakePoolMutex(_In_z_ const WCHAR *Pool);
|
_Return_type_success_(return != NULL)
|
||||||
|
_Post_maybenull_
|
||||||
|
_Acquires_lock_(_Curr_)
|
||||||
|
HANDLE
|
||||||
|
NamespaceTakePoolMutex(_In_z_ LPCWSTR Pool);
|
||||||
|
|
||||||
_Check_return_
|
_Must_inspect_result_
|
||||||
_Return_type_success_(return != NULL) HANDLE NamespaceTakeDriverInstallationMutex(void);
|
_Return_type_success_(return != NULL)
|
||||||
|
_Post_maybenull_
|
||||||
|
_Acquires_lock_(_Curr_)
|
||||||
|
HANDLE
|
||||||
|
NamespaceTakeDriverInstallationMutex(VOID);
|
||||||
|
|
||||||
void
|
_Releases_lock_(Mutex)
|
||||||
|
VOID
|
||||||
NamespaceReleaseMutex(_In_ HANDLE Mutex);
|
NamespaceReleaseMutex(_In_ HANDLE Mutex);
|
||||||
|
|
||||||
void
|
VOID NamespaceInit(VOID);
|
||||||
NamespaceInit(void);
|
|
||||||
|
|
||||||
void
|
VOID NamespaceDone(VOID);
|
||||||
NamespaceDone(void);
|
|
||||||
|
16
api/nci.h
16
api/nci.h
@ -9,19 +9,23 @@
|
|||||||
|
|
||||||
#ifdef GENERATE_LIB
|
#ifdef GENERATE_LIB
|
||||||
# define DECLSPEC __declspec(dllexport)
|
# define DECLSPEC __declspec(dllexport)
|
||||||
# define STUB { return 0; }
|
# define STUB \
|
||||||
|
{ \
|
||||||
|
return 0; \
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
# define DECLSPEC __declspec(dllimport)
|
# define DECLSPEC __declspec(dllimport)
|
||||||
# define STUB ;
|
# define STUB ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
EXTERN_C
|
||||||
|
DECLSPEC DWORD WINAPI
|
||||||
|
NciSetConnectionName(_In_ const GUID *Guid, _In_z_ LPCWSTR NewName) STUB
|
||||||
|
|
||||||
EXTERN_C DECLSPEC DWORD WINAPI
|
EXTERN_C
|
||||||
NciSetConnectionName(_In_ const GUID *Guid, _In_z_ const WCHAR *NewName) STUB
|
DECLSPEC DWORD WINAPI
|
||||||
|
|
||||||
EXTERN_C DECLSPEC DWORD WINAPI
|
|
||||||
NciGetConnectionName(
|
NciGetConnectionName(
|
||||||
_In_ const GUID *Guid,
|
_In_ const GUID *Guid,
|
||||||
_Out_z_bytecap_(InDestNameBytes) WCHAR *Name,
|
_Out_z_bytecap_(InDestNameBytes) LPWSTR Name,
|
||||||
_In_ DWORD InDestNameBytes,
|
_In_ DWORD InDestNameBytes,
|
||||||
_Out_opt_ DWORD *OutDestNameBytes) STUB
|
_Out_opt_ DWORD *OutDestNameBytes) STUB
|
@ -45,7 +45,7 @@ typedef struct _KEY_NAME_INFORMATION
|
|||||||
* when run from legacy contexts. So, we instead use the undocumented RtlGetNtVersionNumbers.
|
* when run from legacy contexts. So, we instead use the undocumented RtlGetNtVersionNumbers.
|
||||||
*
|
*
|
||||||
* Another way would be reading from the PEB directly:
|
* Another way would be reading from the PEB directly:
|
||||||
* ((DWORD *)NtCurrentTeb()->ProcessEnvironmentBlock)[sizeof(void *) == 8 ? 70 : 41]
|
* ((DWORD *)NtCurrentTeb()->ProcessEnvironmentBlock)[sizeof(VOID *) == 8 ? 70 : 41]
|
||||||
* Or just read from KUSER_SHARED_DATA the same way on 32-bit and 64-bit:
|
* Or just read from KUSER_SHARED_DATA the same way on 32-bit and 64-bit:
|
||||||
* *(DWORD *)0x7FFE026C
|
* *(DWORD *)0x7FFE026C
|
||||||
*/
|
*/
|
||||||
@ -61,9 +61,3 @@ NtQueryKey(
|
|||||||
_Out_bytecap_post_bytecount_(Length, *ResultLength) PVOID KeyInformation,
|
_Out_bytecap_post_bytecount_(Length, *ResultLength) PVOID KeyInformation,
|
||||||
_In_ ULONG Length,
|
_In_ ULONG Length,
|
||||||
_Out_ PULONG ResultLength);
|
_Out_ PULONG ResultLength);
|
||||||
|
|
||||||
/* This is documented in NTSecAPI.h, which we can't include, due to header conflicts. It actually lives in advapi32.dll. */
|
|
||||||
#define RtlGenRandom SystemFunction036
|
|
||||||
BOOLEAN
|
|
||||||
NTAPI
|
|
||||||
RtlGenRandom(_Out_writes_bytes_all_(RandomBufferLength) PVOID RandomBuffer, _In_ ULONG RandomBufferLength);
|
|
160
api/registry.c
160
api/registry.c
@ -10,11 +10,14 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <strsafe.h>
|
#include <strsafe.h>
|
||||||
|
|
||||||
static _Return_type_success_(return != NULL) HKEY
|
_Must_inspect_result_
|
||||||
OpenKeyWait(_In_ HKEY Key, _Inout_z_ WCHAR *Path, _In_ DWORD Access, _In_ ULONGLONG Deadline)
|
static _Return_type_success_(return != NULL)
|
||||||
|
_Post_maybenull_
|
||||||
|
HKEY
|
||||||
|
OpenKeyWait(_In_ HKEY Key, _Inout_z_ LPWSTR Path, _In_ DWORD Access, _In_ ULONGLONG Deadline)
|
||||||
{
|
{
|
||||||
DWORD LastError;
|
DWORD LastError;
|
||||||
WCHAR *PathNext = wcschr(Path, L'\\');
|
LPWSTR PathNext = wcschr(Path, L'\\');
|
||||||
if (PathNext)
|
if (PathNext)
|
||||||
*PathNext = 0;
|
*PathNext = 0;
|
||||||
|
|
||||||
@ -87,8 +90,9 @@ static _Return_type_success_(return != NULL) HKEY
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Return_type_success_(return != NULL) HKEY
|
_Use_decl_annotations_
|
||||||
RegistryOpenKeyWait(_In_ HKEY Key, _In_z_ const WCHAR *Path, _In_ DWORD Access, _In_ DWORD Timeout)
|
HKEY
|
||||||
|
RegistryOpenKeyWait(HKEY Key, LPCWSTR Path, DWORD Access, DWORD Timeout)
|
||||||
{
|
{
|
||||||
WCHAR Buf[MAX_REG_PATH];
|
WCHAR Buf[MAX_REG_PATH];
|
||||||
if (wcsncpy_s(Buf, _countof(Buf), Path, _TRUNCATE) == STRUNCATE)
|
if (wcsncpy_s(Buf, _countof(Buf), Path, _TRUNCATE) == STRUNCATE)
|
||||||
@ -100,17 +104,17 @@ _Return_type_success_(return != NULL) HKEY
|
|||||||
return OpenKeyWait(Key, Buf, Access, GetTickCount64() + Timeout);
|
return OpenKeyWait(Key, Buf, Access, GetTickCount64() + Timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
_Return_type_success_(return != FALSE) BOOL RegistryGetString(_Inout_ WCHAR **Buf, _In_ DWORD Len, _In_ DWORD ValueType)
|
_Use_decl_annotations_
|
||||||
|
BOOL
|
||||||
|
RegistryGetString(LPWSTR *Buf, DWORD Len, DWORD ValueType)
|
||||||
{
|
{
|
||||||
if (wcsnlen(*Buf, Len) >= Len)
|
if (wcsnlen(*Buf, Len) >= Len)
|
||||||
{
|
{
|
||||||
/* String is missing zero-terminator. */
|
/* String is missing zero-terminator. */
|
||||||
WCHAR *BufZ = Alloc(((size_t)Len + 1) * sizeof(WCHAR));
|
LPWSTR BufZ = ReZallocArray(*Buf, (SIZE_T)Len + 1, sizeof(*BufZ));
|
||||||
if (!BufZ)
|
if (!BufZ)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
wmemcpy(BufZ, *Buf, Len);
|
_Analysis_assume_((wmemset(BufZ, L'A', (SIZE_T)Len + 1), TRUE));
|
||||||
BufZ[Len] = 0;
|
|
||||||
Free(*Buf);
|
|
||||||
*Buf = BufZ;
|
*Buf = BufZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,10 +126,9 @@ _Return_type_success_(return != FALSE) BOOL RegistryGetString(_Inout_ WCHAR **Bu
|
|||||||
if (!(*Buf)[0])
|
if (!(*Buf)[0])
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
Len = Len * 2 + 64;
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
WCHAR *Expanded = Alloc(Len * sizeof(WCHAR));
|
LPWSTR Expanded = AllocArray(Len, sizeof(*Expanded));
|
||||||
if (!Expanded)
|
if (!Expanded)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
DWORD Result = ExpandEnvironmentStringsW(*Buf, Expanded, Len);
|
DWORD Result = ExpandEnvironmentStringsW(*Buf, Expanded, Len);
|
||||||
@ -147,8 +150,9 @@ _Return_type_success_(return != FALSE) BOOL RegistryGetString(_Inout_ WCHAR **Bu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_Return_type_success_(return != FALSE) BOOL
|
_Use_decl_annotations_
|
||||||
RegistryGetMultiString(_Inout_ WCHAR **Buf, _In_ DWORD Len, _In_ DWORD ValueType)
|
BOOL
|
||||||
|
RegistryGetMultiString(PZZWSTR *Buf, DWORD Len, DWORD ValueType)
|
||||||
{
|
{
|
||||||
if (ValueType == REG_MULTI_SZ)
|
if (ValueType == REG_MULTI_SZ)
|
||||||
{
|
{
|
||||||
@ -157,25 +161,18 @@ _Return_type_success_(return != FALSE) BOOL
|
|||||||
if (i > Len)
|
if (i > Len)
|
||||||
{
|
{
|
||||||
/* Missing string and list terminators. */
|
/* Missing string and list terminators. */
|
||||||
WCHAR *BufZ = Alloc(((size_t)Len + 2) * sizeof(WCHAR));
|
PZZWSTR BufZ = ReZallocArray(*Buf, (SIZE_T)Len + 2, sizeof(*BufZ));
|
||||||
if (!BufZ)
|
if (!BufZ)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
wmemcpy(BufZ, *Buf, Len);
|
|
||||||
BufZ[Len] = 0;
|
|
||||||
BufZ[Len + 1] = 0;
|
|
||||||
Free(*Buf);
|
|
||||||
*Buf = BufZ;
|
*Buf = BufZ;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
if (i == Len)
|
if (i == Len)
|
||||||
{
|
{
|
||||||
/* Missing list terminator. */
|
/* Missing list terminator. */
|
||||||
WCHAR *BufZ = Alloc(((size_t)Len + 1) * sizeof(WCHAR));
|
PZZWSTR BufZ = ReZallocArray(*Buf, (SIZE_T)Len + 1, sizeof(*BufZ));
|
||||||
if (!BufZ)
|
if (!BufZ)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
wmemcpy(BufZ, *Buf, Len);
|
|
||||||
BufZ[Len] = 0;
|
|
||||||
Free(*Buf);
|
|
||||||
*Buf = BufZ;
|
*Buf = BufZ;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -188,22 +185,19 @@ _Return_type_success_(return != FALSE) BOOL
|
|||||||
if (!RegistryGetString(Buf, Len, ValueType))
|
if (!RegistryGetString(Buf, Len, ValueType))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
Len = (DWORD)wcslen(*Buf) + 1;
|
Len = (DWORD)wcslen(*Buf) + 1;
|
||||||
WCHAR *BufZ = Alloc(((size_t)Len + 1) * sizeof(WCHAR));
|
PZZWSTR BufZ = ReZallocArray(*Buf, (SIZE_T)Len + 1, sizeof(WCHAR));
|
||||||
if (!BufZ)
|
if (!BufZ)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
wmemcpy(BufZ, *Buf, Len);
|
|
||||||
BufZ[Len] = 0;
|
|
||||||
Free(*Buf);
|
|
||||||
*Buf = BufZ;
|
*Buf = BufZ;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static _Return_type_success_(return != NULL) void *RegistryQuery(
|
_Must_inspect_result_
|
||||||
_In_ HKEY Key,
|
static _Return_type_success_(return != NULL)
|
||||||
_In_opt_z_ const WCHAR *Name,
|
_Post_maybenull_
|
||||||
_Out_opt_ DWORD *ValueType,
|
_Post_writable_byte_size_(*BufLen)
|
||||||
_Inout_ DWORD *BufLen,
|
VOID *
|
||||||
_In_ BOOL Log)
|
RegistryQuery(_In_ HKEY Key, _In_opt_z_ LPCWSTR Name, _Out_opt_ DWORD *ValueType, _Inout_ DWORD *BufLen, _In_ BOOL Log)
|
||||||
{
|
{
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
@ -220,7 +214,7 @@ static _Return_type_success_(return != NULL) void *RegistryQuery(
|
|||||||
{
|
{
|
||||||
WCHAR RegPath[MAX_REG_PATH];
|
WCHAR RegPath[MAX_REG_PATH];
|
||||||
LoggerGetRegistryKeyPath(Key, RegPath);
|
LoggerGetRegistryKeyPath(Key, RegPath);
|
||||||
LOG_ERROR(LastError, L"Querying registry value %.*s\\%s failed", MAX_REG_PATH, RegPath, Name);
|
LOG_ERROR(LastError, L"Failed to query registry value %.*s\\%s", MAX_REG_PATH, RegPath, Name);
|
||||||
}
|
}
|
||||||
SetLastError(LastError);
|
SetLastError(LastError);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -228,11 +222,12 @@ static _Return_type_success_(return != NULL) void *RegistryQuery(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_Return_type_success_(
|
_Use_decl_annotations_
|
||||||
return != NULL) WCHAR *RegistryQueryString(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ BOOL Log)
|
LPWSTR
|
||||||
|
RegistryQueryString(HKEY Key, LPCWSTR Name, BOOL Log)
|
||||||
{
|
{
|
||||||
DWORD LastError, ValueType, Size = 256 * sizeof(WCHAR);
|
DWORD LastError, ValueType, Size = 256 * sizeof(WCHAR);
|
||||||
WCHAR *Value = RegistryQuery(Key, Name, &ValueType, &Size, Log);
|
LPWSTR Value = RegistryQuery(Key, Name, &ValueType, &Size, Log);
|
||||||
if (!Value)
|
if (!Value)
|
||||||
return NULL;
|
return NULL;
|
||||||
switch (ValueType)
|
switch (ValueType)
|
||||||
@ -240,7 +235,7 @@ _Return_type_success_(
|
|||||||
case REG_SZ:
|
case REG_SZ:
|
||||||
case REG_EXPAND_SZ:
|
case REG_EXPAND_SZ:
|
||||||
case REG_MULTI_SZ:
|
case REG_MULTI_SZ:
|
||||||
if (RegistryGetString(&Value, Size / sizeof(WCHAR), ValueType))
|
if (RegistryGetString(&Value, Size / sizeof(*Value), ValueType))
|
||||||
return Value;
|
return Value;
|
||||||
LastError = GetLastError();
|
LastError = GetLastError();
|
||||||
break;
|
break;
|
||||||
@ -261,8 +256,9 @@ _Return_type_success_(
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Return_type_success_(
|
_Use_decl_annotations_
|
||||||
return != NULL) WCHAR *RegistryQueryStringWait(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ DWORD Timeout)
|
LPWSTR
|
||||||
|
RegistryQueryStringWait(HKEY Key, LPCWSTR Name, DWORD Timeout)
|
||||||
{
|
{
|
||||||
DWORD LastError;
|
DWORD LastError;
|
||||||
ULONGLONG Deadline = GetTickCount64() + Timeout;
|
ULONGLONG Deadline = GetTickCount64() + Timeout;
|
||||||
@ -282,7 +278,7 @@ _Return_type_success_(
|
|||||||
LOG_ERROR(LastError, L"Failed to setup registry key %.*s notification", MAX_REG_PATH, RegPath);
|
LOG_ERROR(LastError, L"Failed to setup registry key %.*s notification", MAX_REG_PATH, RegPath);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
WCHAR *Value = RegistryQueryString(Key, Name, FALSE);
|
LPWSTR Value = RegistryQueryString(Key, Name, FALSE);
|
||||||
if (Value)
|
if (Value)
|
||||||
{
|
{
|
||||||
CloseHandle(Event);
|
CloseHandle(Event);
|
||||||
@ -313,8 +309,9 @@ _Return_type_success_(
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Return_type_success_(return != FALSE) BOOL
|
_Use_decl_annotations_
|
||||||
RegistryQueryDWORD(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _Out_ DWORD *Value, _In_ BOOL Log)
|
BOOL
|
||||||
|
RegistryQueryDWORD(HKEY Key, LPCWSTR Name, DWORD *Value, BOOL Log)
|
||||||
{
|
{
|
||||||
DWORD ValueType, Size = sizeof(DWORD);
|
DWORD ValueType, Size = sizeof(DWORD);
|
||||||
DWORD LastError = RegQueryValueExW(Key, Name, NULL, &ValueType, (BYTE *)Value, &Size);
|
DWORD LastError = RegQueryValueExW(Key, Name, NULL, &ValueType, (BYTE *)Value, &Size);
|
||||||
@ -324,7 +321,7 @@ _Return_type_success_(return != FALSE) BOOL
|
|||||||
{
|
{
|
||||||
WCHAR RegPath[MAX_REG_PATH];
|
WCHAR RegPath[MAX_REG_PATH];
|
||||||
LoggerGetRegistryKeyPath(Key, RegPath);
|
LoggerGetRegistryKeyPath(Key, RegPath);
|
||||||
LOG_ERROR(LastError, L"Querying registry value %.*s\\%s failed", MAX_REG_PATH, RegPath, Name);
|
LOG_ERROR(LastError, L"Failed to query registry value %.*s\\%s", MAX_REG_PATH, RegPath, Name);
|
||||||
}
|
}
|
||||||
SetLastError(LastError);
|
SetLastError(LastError);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -348,8 +345,9 @@ _Return_type_success_(return != FALSE) BOOL
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Return_type_success_(return != FALSE) BOOL
|
_Use_decl_annotations_
|
||||||
RegistryQueryDWORDWait(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ DWORD Timeout, _Out_ DWORD *Value)
|
BOOL
|
||||||
|
RegistryQueryDWORDWait(HKEY Key, LPCWSTR Name, DWORD Timeout, DWORD *Value)
|
||||||
{
|
{
|
||||||
DWORD LastError;
|
DWORD LastError;
|
||||||
ULONGLONG Deadline = GetTickCount64() + Timeout;
|
ULONGLONG Deadline = GetTickCount64() + Timeout;
|
||||||
@ -398,73 +396,3 @@ _Return_type_success_(return != FALSE) BOOL
|
|||||||
SetLastError(LastError);
|
SetLastError(LastError);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Return_type_success_(return != FALSE) static BOOL
|
|
||||||
DeleteNodeRecurse(_In_ HKEY Key, _In_z_ WCHAR *Name)
|
|
||||||
{
|
|
||||||
LSTATUS Ret;
|
|
||||||
DWORD Size;
|
|
||||||
SIZE_T Len;
|
|
||||||
WCHAR SubName[MAX_REG_PATH], *End;
|
|
||||||
HKEY SubKey;
|
|
||||||
|
|
||||||
Len = wcslen(Name);
|
|
||||||
if (Len >= MAX_REG_PATH || !Len)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
if (RegDeleteKeyW(Key, Name) == ERROR_SUCCESS)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
Ret = RegOpenKeyEx(Key, Name, 0, KEY_READ, &SubKey);
|
|
||||||
if (Ret != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
if (Ret == ERROR_FILE_NOT_FOUND)
|
|
||||||
return TRUE;
|
|
||||||
SetLastError(Ret);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
End = Name + Len;
|
|
||||||
if (End[-1] != L'\\')
|
|
||||||
{
|
|
||||||
*(End++) = L'\\';
|
|
||||||
*End = L'\0';
|
|
||||||
}
|
|
||||||
Size = MAX_REG_PATH;
|
|
||||||
Ret = RegEnumKeyEx(SubKey, 0, SubName, &Size, NULL, NULL, NULL, NULL);
|
|
||||||
if (Ret == ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
End[0] = L'\0';
|
|
||||||
StringCchCatW(Name, MAX_REG_PATH * 2, SubName);
|
|
||||||
if (!DeleteNodeRecurse(Key, Name))
|
|
||||||
break;
|
|
||||||
Size = MAX_REG_PATH;
|
|
||||||
Ret = RegEnumKeyEx(SubKey, 0, SubName, &Size, NULL, NULL, NULL, NULL);
|
|
||||||
} while (Ret == ERROR_SUCCESS);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SetLastError(Ret);
|
|
||||||
*(--End) = L'\0';
|
|
||||||
RegCloseKey(SubKey);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
*(--End) = L'\0';
|
|
||||||
RegCloseKey(SubKey);
|
|
||||||
|
|
||||||
Ret = RegDeleteKey(Key, Name);
|
|
||||||
if (Ret == ERROR_SUCCESS)
|
|
||||||
return TRUE;
|
|
||||||
SetLastError(Ret);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_Return_type_success_(return != FALSE) BOOL
|
|
||||||
RegistryDeleteKeyRecursive(_In_ HKEY Key, _In_z_ const WCHAR *Name)
|
|
||||||
{
|
|
||||||
WCHAR NameBuf[(MAX_REG_PATH + 2) * 2] = { 0 };
|
|
||||||
StringCchCopyW(NameBuf, MAX_REG_PATH * 2, Name);
|
|
||||||
return DeleteNodeRecurse(Key, NameBuf);
|
|
||||||
}
|
|
@ -26,8 +26,11 @@
|
|||||||
* @return Key handle on success. If the function fails, the return value is zero. To get extended error information,
|
* @return Key handle on success. If the function fails, the return value is zero. To get extended error information,
|
||||||
* call GetLastError.
|
* call GetLastError.
|
||||||
*/
|
*/
|
||||||
_Return_type_success_(return != NULL) HKEY
|
_Must_inspect_result_
|
||||||
RegistryOpenKeyWait(_In_ HKEY Key, _In_z_ const WCHAR *Path, _In_ DWORD Access, _In_ DWORD Timeout);
|
_Return_type_success_(return != NULL)
|
||||||
|
_Post_maybenull_
|
||||||
|
HKEY
|
||||||
|
RegistryOpenKeyWait(_In_ HKEY Key, _In_z_ LPCWSTR Path, _In_ DWORD Access, _In_ DWORD Timeout);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates and/or sanitizes string value read from registry.
|
* Validates and/or sanitizes string value read from registry.
|
||||||
@ -44,8 +47,10 @@ _Return_type_success_(return != NULL) HKEY
|
|||||||
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
|
* @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.
|
* get extended error information, call GetLastError.
|
||||||
*/
|
*/
|
||||||
_Return_type_success_(return != FALSE) BOOL
|
_Must_inspect_result_
|
||||||
RegistryGetString(_Inout_ WCHAR **Buf, _In_ DWORD Len, _In_ DWORD ValueType);
|
_Return_type_success_(return != FALSE)
|
||||||
|
BOOL
|
||||||
|
RegistryGetString(_Inout_ LPWSTR *Buf, _In_ DWORD Len, _In_ DWORD ValueType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates and/or sanitizes multi-string value read from registry.
|
* Validates and/or sanitizes multi-string value read from registry.
|
||||||
@ -61,8 +66,10 @@ _Return_type_success_(return != FALSE) BOOL
|
|||||||
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
|
* @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.
|
* get extended error information, call GetLastError.
|
||||||
*/
|
*/
|
||||||
_Return_type_success_(return != FALSE) BOOL
|
_Must_inspect_result_
|
||||||
RegistryGetMultiString(_Inout_ WCHAR **Buf, _In_ DWORD Len, _In_ DWORD ValueType);
|
_Return_type_success_(return != FALSE)
|
||||||
|
BOOL
|
||||||
|
RegistryGetMultiString(_Inout_ PZZWSTR *Buf, _In_ DWORD Len, _In_ DWORD ValueType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads string value from registry key.
|
* Reads string value from registry key.
|
||||||
@ -83,8 +90,11 @@ _Return_type_success_(return != FALSE) BOOL
|
|||||||
* @return String with registry value on success; If the function fails, the return value is zero. To get extended error
|
* @return String with registry value on success; If the function fails, the return value is zero. To get extended error
|
||||||
* information, call GetLastError.
|
* information, call GetLastError.
|
||||||
*/
|
*/
|
||||||
_Return_type_success_(
|
_Must_inspect_result_
|
||||||
return != NULL) WCHAR *RegistryQueryString(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ BOOL Log);
|
_Return_type_success_(return != NULL)
|
||||||
|
_Post_maybenull_
|
||||||
|
LPWSTR
|
||||||
|
RegistryQueryString(_In_ HKEY Key, _In_opt_z_ LPCWSTR Name, _In_ BOOL Log);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads string value from registry key. It waits for the registry value to become available.
|
* Reads string value from registry key. It waits for the registry value to become available.
|
||||||
@ -101,8 +111,11 @@ _Return_type_success_(
|
|||||||
* get extended error information, call GetLastError. Possible errors include the following:
|
* get extended error information, call GetLastError. Possible errors include the following:
|
||||||
* ERROR_INVALID_DATATYPE when the registry value is not a string
|
* ERROR_INVALID_DATATYPE when the registry value is not a string
|
||||||
*/
|
*/
|
||||||
_Return_type_success_(
|
_Must_inspect_result_
|
||||||
return != NULL) WCHAR *RegistryQueryStringWait(_In_ HKEY Key, _In_opt_z_ const WCHAR *Name, _In_ DWORD Timeout);
|
_Return_type_success_(return != NULL)
|
||||||
|
_Post_maybenull_
|
||||||
|
LPWSTR
|
||||||
|
RegistryQueryStringWait(_In_ HKEY Key, _In_opt_z_ LPCWSTR Name, _In_ DWORD Timeout);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a 32-bit DWORD value from registry key.
|
* Reads a 32-bit DWORD value from registry key.
|
||||||
@ -120,8 +133,10 @@ _Return_type_success_(
|
|||||||
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
|
* @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.
|
* get extended error information, call GetLastError.
|
||||||
*/
|
*/
|
||||||
_Return_type_success_(return != FALSE) BOOL
|
_Must_inspect_result_
|
||||||
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_ LPCWSTR Name, _Out_ DWORD *Value, _In_ BOOL Log);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a 32-bit DWORD value from registry key. It waits for the registry value to become available.
|
* Reads a 32-bit DWORD value from registry key. It waits for the registry value to become available.
|
||||||
@ -139,17 +154,7 @@ _Return_type_success_(return != FALSE) BOOL
|
|||||||
* ERROR_INVALID_DATATYPE when registry value exist but not REG_DWORD type;
|
* ERROR_INVALID_DATATYPE when registry value exist but not REG_DWORD type;
|
||||||
* ERROR_INVALID_DATA when registry value size is not 4 bytes
|
* ERROR_INVALID_DATA when registry value size is not 4 bytes
|
||||||
*/
|
*/
|
||||||
_Return_type_success_(return != FALSE) BOOL
|
_Must_inspect_result_
|
||||||
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_ LPCWSTR Name, _In_ DWORD Timeout, _Out_ DWORD *Value);
|
||||||
* Deletes the entire registry key subtree recursively.
|
|
||||||
*
|
|
||||||
* @param Key Handle of the registry key to at which the subtree is rooted.
|
|
||||||
*
|
|
||||||
* @param Name Name of the subtree to delete.
|
|
||||||
*
|
|
||||||
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
|
|
||||||
* get extended error information, call GetLastError.
|
|
||||||
*/
|
|
||||||
_Return_type_success_(return != FALSE) BOOL RegistryDeleteKeyRecursive(_In_ HKEY Key, _In_z_ const WCHAR *Name);
|
|
||||||
|
@ -7,9 +7,12 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
#include <Shlwapi.h>
|
||||||
|
#include <NTSecAPI.h>
|
||||||
|
|
||||||
_Return_type_success_(return != NULL) _Ret_bytecount_(*Size) const
|
_Use_decl_annotations_
|
||||||
void *ResourceGetAddress(_In_z_ const WCHAR *ResourceName, _Out_ DWORD *Size)
|
const VOID *
|
||||||
|
ResourceGetAddress(LPCWSTR ResourceName, DWORD *Size)
|
||||||
{
|
{
|
||||||
HRSRC FoundResource = FindResourceW(ResourceModule, ResourceName, RT_RCDATA);
|
HRSRC FoundResource = FindResourceW(ResourceModule, ResourceName, RT_RCDATA);
|
||||||
if (!FoundResource)
|
if (!FoundResource)
|
||||||
@ -39,11 +42,12 @@ _Return_type_success_(return != NULL) _Ret_bytecount_(*Size) const
|
|||||||
return Address;
|
return Address;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Return_type_success_(return != FALSE) BOOL
|
_Use_decl_annotations_
|
||||||
ResourceCopyToFile(_In_z_ const WCHAR *DestinationPath, _In_z_ const WCHAR *ResourceName)
|
BOOL
|
||||||
|
ResourceCopyToFile(LPCWSTR DestinationPath, LPCWSTR ResourceName)
|
||||||
{
|
{
|
||||||
DWORD SizeResource;
|
DWORD SizeResource;
|
||||||
const void *LockedResource = ResourceGetAddress(ResourceName, &SizeResource);
|
const VOID *LockedResource = ResourceGetAddress(ResourceName, &SizeResource);
|
||||||
if (!LockedResource)
|
if (!LockedResource)
|
||||||
{
|
{
|
||||||
LOG(WINTUN_LOG_ERR, L"Failed to locate resource %s", ResourceName);
|
LOG(WINTUN_LOG_ERR, L"Failed to locate resource %s", ResourceName);
|
||||||
@ -84,3 +88,42 @@ cleanupDestinationHandle:
|
|||||||
CloseHandle(DestinationHandle);
|
CloseHandle(DestinationHandle);
|
||||||
return RET_ERROR(TRUE, LastError);
|
return RET_ERROR(TRUE, LastError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_Return_type_success_(return != FALSE)
|
||||||
|
BOOL
|
||||||
|
ResourceCreateTemporaryDirectory(_Out_writes_z_(MAX_PATH) LPWSTR RandomTempSubDirectory)
|
||||||
|
{
|
||||||
|
WCHAR WindowsDirectory[MAX_PATH];
|
||||||
|
if (!GetWindowsDirectoryW(WindowsDirectory, _countof(WindowsDirectory)))
|
||||||
|
{
|
||||||
|
LOG_LAST_ERROR(L"Failed to get Windows folder");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
WCHAR WindowsTempDirectory[MAX_PATH];
|
||||||
|
if (!PathCombineW(WindowsTempDirectory, WindowsDirectory, L"Temp"))
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_BUFFER_OVERFLOW);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
UCHAR RandomBytes[32] = { 0 };
|
||||||
|
if (!RtlGenRandom(RandomBytes, sizeof(RandomBytes)))
|
||||||
|
{
|
||||||
|
LOG(WINTUN_LOG_ERR, L"Failed to generate random");
|
||||||
|
SetLastError(ERROR_GEN_FAILURE);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
WCHAR RandomSubDirectory[sizeof(RandomBytes) * 2 + 1];
|
||||||
|
for (int i = 0; i < sizeof(RandomBytes); ++i)
|
||||||
|
swprintf_s(&RandomSubDirectory[i * 2], 3, L"%02x", RandomBytes[i]);
|
||||||
|
if (!PathCombineW(RandomTempSubDirectory, WindowsTempDirectory, RandomSubDirectory))
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_BUFFER_OVERFLOW);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (!CreateDirectoryW(RandomTempSubDirectory, &SecurityAttributes))
|
||||||
|
{
|
||||||
|
LOG_LAST_ERROR(L"Failed to create temporary folder %s", RandomTempSubDirectory);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
@ -11,25 +11,40 @@
|
|||||||
/**
|
/**
|
||||||
* Locates RT_RCDATA resource memory address and size.
|
* Locates RT_RCDATA resource memory address and size.
|
||||||
*
|
*
|
||||||
* ResourceName Name of the RT_RCDATA resource. Use MAKEINTRESOURCEW to locate resource by ID.
|
* @param ResourceName Name of the RT_RCDATA resource. Use MAKEINTRESOURCEW to locate resource by ID.
|
||||||
*
|
*
|
||||||
* Size Pointer to a variable to receive resource size.
|
* @param Size Pointer to a variable to receive resource size.
|
||||||
*
|
*
|
||||||
* @return Resource address on success. If the function fails, the return value is NULL. To get extended error
|
* @return Resource address on success. If the function fails, the return value is NULL. To get extended error
|
||||||
* information, call GetLastError.
|
* information, call GetLastError.
|
||||||
*/
|
*/
|
||||||
_Return_type_success_(return != NULL) _Ret_bytecount_(*Size) const
|
_Must_inspect_result_
|
||||||
void *ResourceGetAddress(_In_z_ const WCHAR *ResourceName, _Out_ DWORD *Size);
|
_Return_type_success_(return != NULL)
|
||||||
|
_Post_maybenull_
|
||||||
|
_Post_readable_byte_size_(*Size) const VOID *ResourceGetAddress(_In_z_ LPCWSTR ResourceName, _Out_ DWORD *Size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copies resource to a file.
|
* Copies resource to a file.
|
||||||
*
|
*
|
||||||
* DestinationPath File path
|
* @param DestinationPath File path
|
||||||
*
|
*
|
||||||
* ResourceName Name of the RT_RCDATA resource. Use MAKEINTRESOURCEW to locate resource by ID.
|
* @param ResourceName Name of the RT_RCDATA resource. Use MAKEINTRESOURCEW to locate resource by ID.
|
||||||
*
|
*
|
||||||
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
|
* @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.
|
* get extended error information, call GetLastError.
|
||||||
*/
|
*/
|
||||||
_Return_type_success_(return != FALSE) BOOL
|
_Return_type_success_(return != FALSE)
|
||||||
ResourceCopyToFile(_In_z_ const WCHAR *DestinationPath, _In_z_ const WCHAR *ResourceName);
|
BOOL
|
||||||
|
ResourceCopyToFile(_In_z_ LPCWSTR DestinationPath, _In_z_ LPCWSTR ResourceName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a temporary directory.
|
||||||
|
*
|
||||||
|
* @param RandomTempSubDirectory Name of random temporary directory.
|
||||||
|
*
|
||||||
|
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
|
||||||
|
* get extended error information, call GetLastError.
|
||||||
|
*/
|
||||||
|
_Return_type_success_(return != FALSE)
|
||||||
|
BOOL
|
||||||
|
ResourceCreateTemporaryDirectory(_Out_writes_z_(MAX_PATH) LPWSTR RandomTempSubDirectory);
|
||||||
|
544
api/rundll32.c
544
api/rundll32.c
@ -3,12 +3,14 @@
|
|||||||
* Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved.
|
* Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "rundll32.h"
|
||||||
#include "adapter.h"
|
#include "adapter.h"
|
||||||
|
#include "main.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "wintun.h"
|
#include "resource.h"
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
|
#include <Shlwapi.h>
|
||||||
#include <cfgmgr32.h>
|
#include <cfgmgr32.h>
|
||||||
#include <objbase.h>
|
#include <objbase.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@ -18,10 +20,10 @@
|
|||||||
# define EXPORT comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__)
|
# define EXPORT comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__)
|
||||||
|
|
||||||
static DWORD
|
static DWORD
|
||||||
WriteFormatted(_In_ DWORD StdHandle, _In_z_ const WCHAR *Template, ...)
|
WriteFormatted(_In_ DWORD StdHandle, _In_z_ LPCWSTR Template, ...)
|
||||||
{
|
{
|
||||||
WCHAR *FormattedMessage = NULL;
|
LPWSTR FormattedMessage = NULL;
|
||||||
DWORD SizeWritten;
|
DWORD Size;
|
||||||
va_list Arguments;
|
va_list Arguments;
|
||||||
va_start(Arguments, Template);
|
va_start(Arguments, Template);
|
||||||
DWORD Len = FormatMessageW(
|
DWORD Len = FormatMessageW(
|
||||||
@ -29,19 +31,22 @@ WriteFormatted(_In_ DWORD StdHandle, _In_z_ const WCHAR *Template, ...)
|
|||||||
Template,
|
Template,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
(void *)&FormattedMessage,
|
(VOID *)&FormattedMessage,
|
||||||
0,
|
0,
|
||||||
&Arguments);
|
&Arguments);
|
||||||
WriteFile(GetStdHandle(StdHandle), FormattedMessage, Len * sizeof(WCHAR), &SizeWritten, NULL);
|
if (SUCCEEDED(DWordMult(Len, sizeof(*FormattedMessage), &Size)))
|
||||||
|
WriteFile(GetStdHandle(StdHandle), FormattedMessage, Size, &Size, NULL);
|
||||||
|
else
|
||||||
|
Size = 0;
|
||||||
LocalFree(FormattedMessage);
|
LocalFree(FormattedMessage);
|
||||||
va_end(Arguments);
|
va_end(Arguments);
|
||||||
return SizeWritten / sizeof(WCHAR);
|
return Size / sizeof(*FormattedMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CALLBACK
|
static VOID CALLBACK
|
||||||
ConsoleLogger(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ const WCHAR *LogLine)
|
ConsoleLogger(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ LPCWSTR LogLine)
|
||||||
{
|
{
|
||||||
const WCHAR *Template;
|
LPCWSTR Template;
|
||||||
switch (Level)
|
switch (Level)
|
||||||
{
|
{
|
||||||
case WINTUN_LOG_INFO:
|
case WINTUN_LOG_INFO:
|
||||||
@ -59,29 +64,14 @@ ConsoleLogger(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ const WCHAR *LogLine)
|
|||||||
WriteFormatted(STD_ERROR_HANDLE, Template, LogLine);
|
WriteFormatted(STD_ERROR_HANDLE, Template, LogLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int Argc;
|
|
||||||
static WCHAR **Argv;
|
|
||||||
|
|
||||||
static void
|
|
||||||
Init(void)
|
|
||||||
{
|
|
||||||
WintunSetLogger(ConsoleLogger);
|
|
||||||
Argv = CommandLineToArgvW(GetCommandLineW(), &Argc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
Done(void)
|
|
||||||
{
|
|
||||||
LocalFree(Argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
# pragma warning(disable : 4100) /* unreferenced formal parameter */
|
|
||||||
|
|
||||||
VOID __stdcall CreateAdapter(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
|
VOID __stdcall CreateAdapter(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
|
||||||
{
|
{
|
||||||
# pragma EXPORT
|
# pragma EXPORT
|
||||||
|
|
||||||
Init();
|
int Argc;
|
||||||
|
LPWSTR *Argv = CommandLineToArgvW(GetCommandLineW(), &Argc);
|
||||||
|
WintunSetLogger(ConsoleLogger);
|
||||||
|
|
||||||
if (Argc < 4)
|
if (Argc < 4)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
if (wcslen(Argv[2]) >= WINTUN_MAX_POOL)
|
if (wcslen(Argv[2]) >= WINTUN_MAX_POOL)
|
||||||
@ -95,47 +85,52 @@ VOID __stdcall CreateAdapter(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int
|
|||||||
BOOL RebootRequired;
|
BOOL RebootRequired;
|
||||||
WINTUN_ADAPTER *Adapter = WintunCreateAdapter(Argv[2], Argv[3], Argc > 4 ? &RequestedGUID : NULL, &RebootRequired);
|
WINTUN_ADAPTER *Adapter = WintunCreateAdapter(Argv[2], Argv[3], Argc > 4 ? &RequestedGUID : NULL, &RebootRequired);
|
||||||
DWORD LastError = Adapter ? ERROR_SUCCESS : GetLastError();
|
DWORD LastError = Adapter ? ERROR_SUCCESS : GetLastError();
|
||||||
WCHAR GuidStr[MAX_GUID_STRING_LEN];
|
|
||||||
WriteFormatted(
|
WriteFormatted(
|
||||||
STD_OUTPUT_HANDLE,
|
STD_OUTPUT_HANDLE, L"%1!X! %2!s! %3!X!", LastError, Adapter ? Adapter->DevInstanceID : L"", RebootRequired);
|
||||||
L"%1!X! %2!.*s! %3!X!",
|
|
||||||
LastError,
|
|
||||||
StringFromGUID2(Adapter ? &Adapter->CfgInstanceID : &GUID_NULL, GuidStr, _countof(GuidStr)),
|
|
||||||
GuidStr,
|
|
||||||
RebootRequired);
|
|
||||||
if (Adapter)
|
if (Adapter)
|
||||||
WintunFreeAdapter(Adapter);
|
WintunFreeAdapter(Adapter);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
Done();
|
LocalFree(Argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID __stdcall DeleteAdapter(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
|
VOID __stdcall DeleteAdapter(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
|
||||||
{
|
{
|
||||||
# pragma EXPORT
|
# pragma EXPORT
|
||||||
|
|
||||||
Init();
|
int Argc;
|
||||||
if (Argc < 3)
|
LPWSTR *Argv = CommandLineToArgvW(GetCommandLineW(), &Argc);
|
||||||
|
WintunSetLogger(ConsoleLogger);
|
||||||
|
|
||||||
|
if (Argc < 4)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
WINTUN_ADAPTER Adapter = { 0 };
|
DWORD LastError;
|
||||||
BOOL ForceCloseSessions = wcstoul(Argv[2], NULL, 10);
|
BOOL RebootRequired = FALSE;
|
||||||
if (FAILED(CLSIDFromString(Argv[3], &Adapter.CfgInstanceID)))
|
WINTUN_ADAPTER *Adapter = AdapterOpenFromDevInstanceId(Argv[2], Argv[3]);
|
||||||
goto cleanup;
|
if (!Adapter)
|
||||||
BOOL RebootRequired;
|
{
|
||||||
DWORD LastError =
|
LastError = GetLastError();
|
||||||
WintunDeleteAdapter(&Adapter, ForceCloseSessions, &RebootRequired) ? ERROR_SUCCESS : GetLastError();
|
goto write;
|
||||||
|
}
|
||||||
|
BOOL ForceCloseSessions = wcstoul(Argv[4], NULL, 10);
|
||||||
|
LastError = WintunDeleteAdapter(Adapter, ForceCloseSessions, &RebootRequired) ? ERROR_SUCCESS : GetLastError();
|
||||||
|
WintunFreeAdapter(Adapter);
|
||||||
|
write:
|
||||||
WriteFormatted(STD_OUTPUT_HANDLE, L"%1!X! %2!X!", LastError, RebootRequired);
|
WriteFormatted(STD_OUTPUT_HANDLE, L"%1!X! %2!X!", LastError, RebootRequired);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
Done();
|
LocalFree(Argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID __stdcall DeletePoolDriver(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
|
VOID __stdcall DeletePoolDriver(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
|
||||||
{
|
{
|
||||||
# pragma EXPORT
|
# pragma EXPORT
|
||||||
|
|
||||||
Init();
|
int Argc;
|
||||||
|
LPWSTR *Argv = CommandLineToArgvW(GetCommandLineW(), &Argc);
|
||||||
|
WintunSetLogger(ConsoleLogger);
|
||||||
|
|
||||||
if (Argc < 2)
|
if (Argc < 2)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
@ -144,6 +139,455 @@ VOID __stdcall DeletePoolDriver(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, i
|
|||||||
WriteFormatted(STD_OUTPUT_HANDLE, L"%1!X! %2!X!", LastError, RebootRequired);
|
WriteFormatted(STD_OUTPUT_HANDLE, L"%1!X! %2!X!", LastError, RebootRequired);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
Done();
|
LocalFree(Argv);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MAYBE_WOW64
|
||||||
|
|
||||||
|
_Return_type_success_(return != FALSE)
|
||||||
|
static BOOL
|
||||||
|
AppendToBuffer(_Inout_ LPWSTR *Buffer, _In_ CONST WCHAR Addition, _Inout_ SIZE_T *BufferPos, _Inout_ SIZE_T *BufferLen)
|
||||||
|
{
|
||||||
|
SIZE_T NewPos;
|
||||||
|
if (FAILED(SIZETAdd(*BufferPos, sizeof(Addition), &NewPos)))
|
||||||
|
return FALSE;
|
||||||
|
if (NewPos >= *BufferLen)
|
||||||
|
{
|
||||||
|
SIZE_T NewLen;
|
||||||
|
if (FAILED(SIZETMult(NewPos, 3, &NewLen)))
|
||||||
|
return FALSE;
|
||||||
|
LPWSTR NewBuffer = ReZalloc(*Buffer, NewLen);
|
||||||
|
if (!NewBuffer)
|
||||||
|
return FALSE;
|
||||||
|
*Buffer = NewBuffer;
|
||||||
|
*BufferLen = NewLen;
|
||||||
|
}
|
||||||
|
SIZE_T NewIndex = *BufferPos / sizeof(**Buffer);
|
||||||
|
if (*Buffer + NewIndex < *Buffer)
|
||||||
|
return FALSE;
|
||||||
|
(*Buffer)[NewIndex] = Addition;
|
||||||
|
*BufferPos = NewPos;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_Must_inspect_result_
|
||||||
|
static _Return_type_success_(return != NULL)
|
||||||
|
_Post_maybenull_
|
||||||
|
LPWSTR
|
||||||
|
ArgvToCommandLineW(_In_ SIZE_T ArgCount, ...)
|
||||||
|
{
|
||||||
|
LPWSTR Output = NULL;
|
||||||
|
SIZE_T BufferPos = 0, BufferLen = 0;
|
||||||
|
# define Append(Char) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (!AppendToBuffer(&Output, Char, &BufferPos, &BufferLen)) \
|
||||||
|
goto cleanupBuffer; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
va_list Args;
|
||||||
|
va_start(Args, ArgCount);
|
||||||
|
for (SIZE_T i = 0; i < ArgCount; ++i)
|
||||||
|
{
|
||||||
|
LPCWSTR Arg = va_arg(Args, LPCWSTR);
|
||||||
|
SIZE_T ArgLen = wcslen(Arg);
|
||||||
|
if (ArgLen >= DWORD_MAX >> 3)
|
||||||
|
goto cleanupBuffer;
|
||||||
|
if (i)
|
||||||
|
Append(L' ');
|
||||||
|
Append(L'"');
|
||||||
|
for (SIZE_T j = 0;; ++j)
|
||||||
|
{
|
||||||
|
SIZE_T NumberBackslashes = 0;
|
||||||
|
|
||||||
|
while (j < ArgLen && Arg[j] == L'\\')
|
||||||
|
{
|
||||||
|
++j;
|
||||||
|
++NumberBackslashes;
|
||||||
|
}
|
||||||
|
if (j >= ArgLen)
|
||||||
|
{
|
||||||
|
for (SIZE_T k = 0; k < NumberBackslashes * 2; ++k)
|
||||||
|
Append(L'\\');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (Arg[j] == L'"')
|
||||||
|
{
|
||||||
|
for (SIZE_T k = 0; k < NumberBackslashes * 2 + 1; ++k)
|
||||||
|
Append(L'\\');
|
||||||
|
Append(Arg[j]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (SIZE_T k = 0; k < NumberBackslashes; ++k)
|
||||||
|
Append(L'\\');
|
||||||
|
Append(Arg[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Append(L'"');
|
||||||
|
}
|
||||||
|
va_end(Args);
|
||||||
|
return Output;
|
||||||
|
|
||||||
|
cleanupBuffer:
|
||||||
|
Free(Output);
|
||||||
|
return NULL;
|
||||||
|
# undef Append
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct _PROCESS_STDOUT_STATE
|
||||||
|
{
|
||||||
|
HANDLE Stdout;
|
||||||
|
LPWSTR Response;
|
||||||
|
DWORD ResponseCapacity;
|
||||||
|
} PROCESS_STDOUT_STATE;
|
||||||
|
|
||||||
|
_Return_type_success_(return != ERROR_SUCCESS)
|
||||||
|
static DWORD WINAPI
|
||||||
|
ProcessStdout(_Inout_ PROCESS_STDOUT_STATE *State)
|
||||||
|
{
|
||||||
|
for (DWORD Offset = 0, MaxLen = State->ResponseCapacity - 1; Offset < MaxLen;)
|
||||||
|
{
|
||||||
|
DWORD Size;
|
||||||
|
if (FAILED(DWordMult(MaxLen - Offset, sizeof(WCHAR), &Size)))
|
||||||
|
return ERROR_BUFFER_OVERFLOW;
|
||||||
|
if (!ReadFile(State->Stdout, State->Response + Offset, Size, &Size, NULL))
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
if (Size % sizeof(WCHAR))
|
||||||
|
return ERROR_INVALID_DATA;
|
||||||
|
Offset += Size / sizeof(WCHAR);
|
||||||
|
State->Response[Offset] = 0;
|
||||||
|
}
|
||||||
|
return ERROR_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD WINAPI
|
||||||
|
ProcessStderr(_In_ HANDLE Stderr)
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
OnNone,
|
||||||
|
OnLevelStart,
|
||||||
|
OnLevel,
|
||||||
|
OnLevelEnd,
|
||||||
|
OnSpace,
|
||||||
|
OnMsg
|
||||||
|
} State = OnNone;
|
||||||
|
WCHAR Msg[0x200];
|
||||||
|
DWORD Count = 0;
|
||||||
|
WINTUN_LOGGER_LEVEL Level = WINTUN_LOG_INFO;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
WCHAR Buf[0x200];
|
||||||
|
DWORD SizeRead;
|
||||||
|
if (!ReadFile(Stderr, Buf, sizeof(Buf), &SizeRead, NULL))
|
||||||
|
return ERROR_SUCCESS;
|
||||||
|
if (SizeRead % sizeof(*Buf))
|
||||||
|
return ERROR_INVALID_DATA;
|
||||||
|
SizeRead /= sizeof(*Buf);
|
||||||
|
for (DWORD i = 0; i < SizeRead; ++i)
|
||||||
|
{
|
||||||
|
WCHAR c = Buf[i];
|
||||||
|
if (State == OnNone && c == L'[')
|
||||||
|
State = OnLevelStart;
|
||||||
|
else if (
|
||||||
|
State == OnLevelStart && ((Level = WINTUN_LOG_INFO, c == L'+') ||
|
||||||
|
(Level = WINTUN_LOG_WARN, c == L'-') || (Level = WINTUN_LOG_ERR, c == L'!')))
|
||||||
|
State = OnLevelEnd;
|
||||||
|
else if (State == OnLevelEnd && c == L']')
|
||||||
|
State = OnSpace;
|
||||||
|
else if (State == OnSpace && !iswspace(c) || State == OnMsg && c != L'\r' && c != L'\n')
|
||||||
|
{
|
||||||
|
if (Count < _countof(Msg) - 1)
|
||||||
|
Msg[Count++] = c;
|
||||||
|
State = OnMsg;
|
||||||
|
}
|
||||||
|
else if (State == OnMsg && c == L'\n')
|
||||||
|
{
|
||||||
|
Msg[Count] = 0;
|
||||||
|
LoggerLog(Level, NULL, Msg);
|
||||||
|
State = OnNone;
|
||||||
|
Count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static _Return_type_success_(return != FALSE)
|
||||||
|
BOOL
|
||||||
|
ExecuteRunDll32(
|
||||||
|
_In_z_ LPCWSTR Function,
|
||||||
|
_In_z_ LPCWSTR Arguments,
|
||||||
|
_Out_z_cap_c_(ResponseCapacity) LPWSTR Response,
|
||||||
|
_In_ DWORD ResponseCapacity)
|
||||||
|
{
|
||||||
|
WCHAR WindowsDirectory[MAX_PATH];
|
||||||
|
if (!GetWindowsDirectoryW(WindowsDirectory, _countof(WindowsDirectory)))
|
||||||
|
{
|
||||||
|
LOG_LAST_ERROR(L"Failed to get Windows folder");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
WCHAR RunDll32Path[MAX_PATH];
|
||||||
|
if (!PathCombineW(RunDll32Path, WindowsDirectory, L"Sysnative\\rundll32.exe"))
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_BUFFER_OVERFLOW);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD LastError;
|
||||||
|
WCHAR RandomTempSubDirectory[MAX_PATH];
|
||||||
|
if (!ResourceCreateTemporaryDirectory(RandomTempSubDirectory))
|
||||||
|
{
|
||||||
|
LOG(WINTUN_LOG_ERR, L"Failed to create temporary folder");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
WCHAR DllPath[MAX_PATH] = { 0 };
|
||||||
|
if (!PathCombineW(DllPath, RandomTempSubDirectory, L"wintun.dll"))
|
||||||
|
{
|
||||||
|
LastError = ERROR_BUFFER_OVERFLOW;
|
||||||
|
goto cleanupDirectory;
|
||||||
|
}
|
||||||
|
LPCWSTR WintunDllResourceName;
|
||||||
|
switch (NativeMachine)
|
||||||
|
{
|
||||||
|
case IMAGE_FILE_MACHINE_AMD64:
|
||||||
|
WintunDllResourceName = L"wintun-amd64.dll";
|
||||||
|
break;
|
||||||
|
case IMAGE_FILE_MACHINE_ARM64:
|
||||||
|
WintunDllResourceName = L"wintun-arm64.dll";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG(WINTUN_LOG_ERR, L"Unsupported platform 0x%x", NativeMachine);
|
||||||
|
LastError = ERROR_NOT_SUPPORTED;
|
||||||
|
goto cleanupDirectory;
|
||||||
|
}
|
||||||
|
if (!ResourceCopyToFile(DllPath, WintunDllResourceName))
|
||||||
|
{
|
||||||
|
LastError = LOG(WINTUN_LOG_ERR, L"Failed to copy resource %s to %s", WintunDllResourceName, DllPath);
|
||||||
|
goto cleanupDelete;
|
||||||
|
}
|
||||||
|
size_t CommandLineLen = 10 + MAX_PATH + 2 + wcslen(Arguments) + 1 + wcslen(Function) + 1;
|
||||||
|
LPWSTR CommandLine = AllocArray(CommandLineLen, sizeof(*CommandLine));
|
||||||
|
if (!CommandLine)
|
||||||
|
{
|
||||||
|
LastError = GetLastError();
|
||||||
|
goto cleanupDelete;
|
||||||
|
}
|
||||||
|
if (_snwprintf_s(
|
||||||
|
CommandLine,
|
||||||
|
CommandLineLen,
|
||||||
|
_TRUNCATE,
|
||||||
|
L"rundll32 \"%.*s\",%s %s",
|
||||||
|
MAX_PATH,
|
||||||
|
DllPath,
|
||||||
|
Function,
|
||||||
|
Arguments) == -1)
|
||||||
|
{
|
||||||
|
LOG(WINTUN_LOG_ERR, L"Command line too long");
|
||||||
|
LastError = ERROR_INVALID_PARAMETER;
|
||||||
|
goto cleanupDelete;
|
||||||
|
}
|
||||||
|
HANDLE StreamRStdout = INVALID_HANDLE_VALUE, StreamRStderr = INVALID_HANDLE_VALUE,
|
||||||
|
StreamWStdout = INVALID_HANDLE_VALUE, StreamWStderr = INVALID_HANDLE_VALUE;
|
||||||
|
if (!CreatePipe(&StreamRStdout, &StreamWStdout, &SecurityAttributes, 0) ||
|
||||||
|
!CreatePipe(&StreamRStderr, &StreamWStderr, &SecurityAttributes, 0))
|
||||||
|
{
|
||||||
|
LastError = LOG_LAST_ERROR(L"Failed to create pipes");
|
||||||
|
goto cleanupPipes;
|
||||||
|
}
|
||||||
|
if (!SetHandleInformation(StreamWStdout, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT) ||
|
||||||
|
!SetHandleInformation(StreamWStderr, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
|
||||||
|
{
|
||||||
|
LastError = LOG_LAST_ERROR(L"Failed to set handle info");
|
||||||
|
goto cleanupPipes;
|
||||||
|
}
|
||||||
|
if (ResponseCapacity)
|
||||||
|
Response[0] = 0;
|
||||||
|
PROCESS_STDOUT_STATE ProcessStdoutState = { .Stdout = StreamRStdout,
|
||||||
|
.Response = Response,
|
||||||
|
.ResponseCapacity = ResponseCapacity };
|
||||||
|
HANDLE ThreadStdout = NULL, ThreadStderr = NULL;
|
||||||
|
if ((ThreadStdout = CreateThread(NULL, 0, ProcessStdout, &ProcessStdoutState, 0, NULL)) == NULL ||
|
||||||
|
(ThreadStderr = CreateThread(NULL, 0, ProcessStderr, StreamRStderr, 0, NULL)) == NULL)
|
||||||
|
{
|
||||||
|
LastError = LOG_LAST_ERROR(L"Failed to spawn readers");
|
||||||
|
goto cleanupThreads;
|
||||||
|
}
|
||||||
|
STARTUPINFOW si = { .cb = sizeof(STARTUPINFO),
|
||||||
|
.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES,
|
||||||
|
.wShowWindow = SW_HIDE,
|
||||||
|
.hStdOutput = StreamWStdout,
|
||||||
|
.hStdError = StreamWStderr };
|
||||||
|
PROCESS_INFORMATION pi;
|
||||||
|
if (!CreateProcessW(RunDll32Path, CommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
|
||||||
|
{
|
||||||
|
LastError = LOG_LAST_ERROR(L"Failed to create process: %s", CommandLine);
|
||||||
|
goto cleanupThreads;
|
||||||
|
}
|
||||||
|
LastError = ERROR_SUCCESS;
|
||||||
|
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||||
|
CloseHandle(pi.hProcess);
|
||||||
|
CloseHandle(pi.hThread);
|
||||||
|
cleanupThreads:
|
||||||
|
if (ThreadStderr)
|
||||||
|
{
|
||||||
|
CloseHandle(StreamWStderr);
|
||||||
|
StreamWStderr = INVALID_HANDLE_VALUE;
|
||||||
|
WaitForSingleObject(ThreadStderr, INFINITE);
|
||||||
|
CloseHandle(ThreadStderr);
|
||||||
|
}
|
||||||
|
if (ThreadStdout)
|
||||||
|
{
|
||||||
|
CloseHandle(StreamWStdout);
|
||||||
|
StreamWStdout = INVALID_HANDLE_VALUE;
|
||||||
|
WaitForSingleObject(ThreadStdout, INFINITE);
|
||||||
|
DWORD ThreadResult;
|
||||||
|
if (!GetExitCodeThread(ThreadStdout, &ThreadResult))
|
||||||
|
LOG_LAST_ERROR(L"Failed to retrieve stdout reader result");
|
||||||
|
else if (ThreadResult != ERROR_SUCCESS)
|
||||||
|
LOG_ERROR(LastError, L"Failed to read process output");
|
||||||
|
CloseHandle(ThreadStdout);
|
||||||
|
}
|
||||||
|
cleanupPipes:
|
||||||
|
CloseHandle(StreamRStderr);
|
||||||
|
CloseHandle(StreamWStderr);
|
||||||
|
CloseHandle(StreamRStdout);
|
||||||
|
CloseHandle(StreamWStdout);
|
||||||
|
Free(CommandLine);
|
||||||
|
cleanupDelete:
|
||||||
|
DeleteFileW(DllPath);
|
||||||
|
cleanupDirectory:
|
||||||
|
RemoveDirectoryW(RandomTempSubDirectory);
|
||||||
|
return RET_ERROR(TRUE, LastError);
|
||||||
|
}
|
||||||
|
|
||||||
|
_Use_decl_annotations_
|
||||||
|
WINTUN_ADAPTER *
|
||||||
|
CreateAdapterViaRundll32(LPCWSTR Pool, LPCWSTR Name, const GUID *RequestedGUID, BOOL *RebootRequired)
|
||||||
|
{
|
||||||
|
LOG(WINTUN_LOG_INFO, L"Spawning native process");
|
||||||
|
LPWSTR Arguments = NULL;
|
||||||
|
if (RequestedGUID)
|
||||||
|
{
|
||||||
|
WCHAR RequestedGUIDStr[MAX_GUID_STRING_LEN];
|
||||||
|
if (StringFromGUID2(RequestedGUID, RequestedGUIDStr, _countof(RequestedGUIDStr)))
|
||||||
|
Arguments = ArgvToCommandLineW(3, Pool, Name, RequestedGUIDStr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Arguments = ArgvToCommandLineW(2, Pool, Name);
|
||||||
|
if (!Arguments)
|
||||||
|
{
|
||||||
|
LOG(WINTUN_LOG_ERR, L"Command line too long");
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
WINTUN_ADAPTER *Adapter = NULL;
|
||||||
|
DWORD LastError;
|
||||||
|
WCHAR Response[8 + 1 + MAX_GUID_STRING_LEN + 1 + 8 + 1];
|
||||||
|
if (!ExecuteRunDll32(L"CreateAdapter", Arguments, Response, _countof(Response)))
|
||||||
|
{
|
||||||
|
LastError = GetLastError();
|
||||||
|
LOG(WINTUN_LOG_ERR, L"Error executing worker process: %s", Arguments);
|
||||||
|
goto cleanupArguments;
|
||||||
|
}
|
||||||
|
int Argc;
|
||||||
|
LPWSTR *Argv = CommandLineToArgvW(Response, &Argc);
|
||||||
|
if (Argc < 3)
|
||||||
|
{
|
||||||
|
LOG(WINTUN_LOG_ERR, L"Incomplete response: %s", Response);
|
||||||
|
LastError = ERROR_INVALID_PARAMETER;
|
||||||
|
goto cleanupArgv;
|
||||||
|
}
|
||||||
|
LastError = wcstoul(Argv[0], NULL, 16);
|
||||||
|
if (LastError == ERROR_SUCCESS && (Adapter = AdapterOpenFromDevInstanceId(Pool, Argv[1])) == NULL)
|
||||||
|
{
|
||||||
|
LOG(WINTUN_LOG_ERR, L"Failed to get adapter %s", Argv[1]);
|
||||||
|
LastError = ERROR_FILE_NOT_FOUND;
|
||||||
|
}
|
||||||
|
if (wcstoul(Argv[2], NULL, 16))
|
||||||
|
*RebootRequired = TRUE;
|
||||||
|
cleanupArgv:
|
||||||
|
LocalFree(Argv);
|
||||||
|
cleanupArguments:
|
||||||
|
Free(Arguments);
|
||||||
|
SetLastError(LastError);
|
||||||
|
return Adapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
_Use_decl_annotations_
|
||||||
|
BOOL
|
||||||
|
DeleteAdapterViaRundll32(const WINTUN_ADAPTER *Adapter, BOOL ForceCloseSessions, BOOL *RebootRequired)
|
||||||
|
{
|
||||||
|
LOG(WINTUN_LOG_INFO, L"Spawning native process");
|
||||||
|
LPWSTR Arguments = ArgvToCommandLineW(3, Adapter->Pool, Adapter->DevInstanceID, ForceCloseSessions ? L"1" : L"0");
|
||||||
|
if (!Arguments)
|
||||||
|
{
|
||||||
|
LOG(WINTUN_LOG_ERR, L"Command line too long");
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
WCHAR Response[8 + 1 + 8 + 1];
|
||||||
|
DWORD LastError;
|
||||||
|
if (!ExecuteRunDll32(L"DeleteAdapter", Arguments, Response, _countof(Response)))
|
||||||
|
{
|
||||||
|
LastError = GetLastError();
|
||||||
|
LOG(WINTUN_LOG_ERR, L"Error executing worker process: %s", Arguments);
|
||||||
|
goto cleanupArguments;
|
||||||
|
}
|
||||||
|
int Argc;
|
||||||
|
LPWSTR *Argv = CommandLineToArgvW(Response, &Argc);
|
||||||
|
if (Argc < 2)
|
||||||
|
{
|
||||||
|
LOG(WINTUN_LOG_ERR, L"Incomplete response: %s", Response);
|
||||||
|
LastError = ERROR_INVALID_PARAMETER;
|
||||||
|
goto cleanupArgv;
|
||||||
|
}
|
||||||
|
LastError = wcstoul(Argv[0], NULL, 16);
|
||||||
|
if (wcstoul(Argv[1], NULL, 16))
|
||||||
|
*RebootRequired = TRUE;
|
||||||
|
cleanupArgv:
|
||||||
|
LocalFree(Argv);
|
||||||
|
cleanupArguments:
|
||||||
|
Free(Arguments);
|
||||||
|
return RET_ERROR(TRUE, LastError);
|
||||||
|
}
|
||||||
|
|
||||||
|
_Use_decl_annotations_
|
||||||
|
BOOL
|
||||||
|
DeletePoolDriverViaRundll32(LPCWSTR Pool, BOOL *RebootRequired)
|
||||||
|
{
|
||||||
|
LOG(WINTUN_LOG_INFO, L"Spawning native process");
|
||||||
|
LPWSTR Arguments = ArgvToCommandLineW(1, Pool);
|
||||||
|
if (!Arguments)
|
||||||
|
{
|
||||||
|
LOG(WINTUN_LOG_ERR, L"Command line too long");
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
WCHAR Response[8 + 1 + 8 + 1];
|
||||||
|
DWORD LastError;
|
||||||
|
if (!ExecuteRunDll32(L"DeletePoolDriver", Arguments, Response, _countof(Response)))
|
||||||
|
{
|
||||||
|
LastError = GetLastError();
|
||||||
|
LOG(WINTUN_LOG_ERR, L"Error executing worker process: %s", Arguments);
|
||||||
|
goto cleanupArguments;
|
||||||
|
}
|
||||||
|
int Argc;
|
||||||
|
LPWSTR *Argv = CommandLineToArgvW(Response, &Argc);
|
||||||
|
if (Argc < 2)
|
||||||
|
{
|
||||||
|
LOG(WINTUN_LOG_ERR, L"Incomplete response: %s", Response);
|
||||||
|
LastError = ERROR_INVALID_PARAMETER;
|
||||||
|
goto cleanupArgv;
|
||||||
|
}
|
||||||
|
LastError = wcstoul(Argv[0], NULL, 16);
|
||||||
|
if (wcstoul(Argv[1], NULL, 16))
|
||||||
|
*RebootRequired = TRUE;
|
||||||
|
cleanupArgv:
|
||||||
|
LocalFree(Argv);
|
||||||
|
cleanupArguments:
|
||||||
|
Free(Arguments);
|
||||||
|
return RET_ERROR(TRUE, LastError);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
29
api/rundll32.h
Normal file
29
api/rundll32.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "adapter.h"
|
||||||
|
|
||||||
|
_Must_inspect_result_
|
||||||
|
_Return_type_success_(return != NULL)
|
||||||
|
_Post_maybenull_
|
||||||
|
WINTUN_ADAPTER *
|
||||||
|
CreateAdapterViaRundll32(
|
||||||
|
_In_z_ LPCWSTR Pool,
|
||||||
|
_In_z_ LPCWSTR Name,
|
||||||
|
_In_opt_ const GUID *RequestedGUID,
|
||||||
|
_Inout_ BOOL *RebootRequired);
|
||||||
|
|
||||||
|
_Return_type_success_(return != FALSE)
|
||||||
|
BOOL
|
||||||
|
DeleteAdapterViaRundll32(
|
||||||
|
_In_ const WINTUN_ADAPTER *Adapter,
|
||||||
|
_In_ BOOL ForceCloseSessions,
|
||||||
|
_Inout_ BOOL *RebootRequired);
|
||||||
|
|
||||||
|
_Return_type_success_(return != FALSE)
|
||||||
|
BOOL
|
||||||
|
DeletePoolDriverViaRundll32(_In_z_ LPCWSTR Pool, _Inout_ BOOL *RebootRequired);
|
352
api/rundll32_i.c
352
api/rundll32_i.c
@ -1,352 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0
|
|
||||||
*
|
|
||||||
* Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* TODO: This is currently #include'd in adapter.c. Move into rundll32.c properly. */
|
|
||||||
|
|
||||||
typedef struct _PROCESS_STDOUT_STATE
|
|
||||||
{
|
|
||||||
HANDLE Stdout;
|
|
||||||
WCHAR *Response;
|
|
||||||
DWORD ResponseCapacity;
|
|
||||||
} PROCESS_STDOUT_STATE;
|
|
||||||
|
|
||||||
static DWORD WINAPI
|
|
||||||
ProcessStdout(_Inout_ PROCESS_STDOUT_STATE *State)
|
|
||||||
{
|
|
||||||
for (DWORD Offset = 0, MaxLen = State->ResponseCapacity - 1; Offset < MaxLen;)
|
|
||||||
{
|
|
||||||
DWORD SizeRead;
|
|
||||||
if (!ReadFile(State->Stdout, State->Response + Offset, sizeof(WCHAR) * (MaxLen - Offset), &SizeRead, NULL))
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
if (SizeRead % sizeof(WCHAR))
|
|
||||||
return ERROR_INVALID_DATA;
|
|
||||||
Offset += SizeRead / sizeof(WCHAR);
|
|
||||||
State->Response[Offset] = 0;
|
|
||||||
}
|
|
||||||
return ERROR_BUFFER_OVERFLOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
static DWORD WINAPI
|
|
||||||
ProcessStderr(_In_ HANDLE Stderr)
|
|
||||||
{
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
OnNone,
|
|
||||||
OnLevelStart,
|
|
||||||
OnLevel,
|
|
||||||
OnLevelEnd,
|
|
||||||
OnSpace,
|
|
||||||
OnMsg
|
|
||||||
} State = OnNone;
|
|
||||||
WCHAR Msg[0x200];
|
|
||||||
DWORD Count = 0;
|
|
||||||
WINTUN_LOGGER_LEVEL Level = WINTUN_LOG_INFO;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
WCHAR Buf[0x200];
|
|
||||||
DWORD SizeRead;
|
|
||||||
if (!ReadFile(Stderr, Buf, sizeof(Buf), &SizeRead, NULL))
|
|
||||||
return ERROR_SUCCESS;
|
|
||||||
if (SizeRead % sizeof(WCHAR))
|
|
||||||
return ERROR_INVALID_DATA;
|
|
||||||
SizeRead /= sizeof(WCHAR);
|
|
||||||
for (DWORD i = 0; i < SizeRead; ++i)
|
|
||||||
{
|
|
||||||
WCHAR c = Buf[i];
|
|
||||||
if (State == OnNone && c == L'[')
|
|
||||||
State = OnLevelStart;
|
|
||||||
else if (
|
|
||||||
State == OnLevelStart && ((Level = WINTUN_LOG_INFO, c == L'+') ||
|
|
||||||
(Level = WINTUN_LOG_WARN, c == L'-') || (Level = WINTUN_LOG_ERR, c == L'!')))
|
|
||||||
State = OnLevelEnd;
|
|
||||||
else if (State == OnLevelEnd && c == L']')
|
|
||||||
State = OnSpace;
|
|
||||||
else if (State == OnSpace && !iswspace(c) || State == OnMsg && c != L'\r' && c != L'\n')
|
|
||||||
{
|
|
||||||
if (Count < _countof(Msg) - 1)
|
|
||||||
Msg[Count++] = c;
|
|
||||||
State = OnMsg;
|
|
||||||
}
|
|
||||||
else if (State == OnMsg && c == L'\n')
|
|
||||||
{
|
|
||||||
Msg[Count] = 0;
|
|
||||||
LoggerLog(Level, NULL, Msg);
|
|
||||||
State = OnNone;
|
|
||||||
Count = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static _Return_type_success_(return != FALSE) BOOL ExecuteRunDll32(
|
|
||||||
_In_z_ const WCHAR *Arguments,
|
|
||||||
_Out_z_cap_c_(ResponseCapacity) WCHAR *Response,
|
|
||||||
_In_ DWORD ResponseCapacity)
|
|
||||||
{
|
|
||||||
WCHAR WindowsDirectory[MAX_PATH];
|
|
||||||
if (!GetWindowsDirectoryW(WindowsDirectory, _countof(WindowsDirectory)))
|
|
||||||
{
|
|
||||||
LOG_LAST_ERROR(L"Failed to get Windows folder");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
WCHAR RunDll32Path[MAX_PATH];
|
|
||||||
if (!PathCombineW(RunDll32Path, WindowsDirectory, L"Sysnative\\rundll32.exe"))
|
|
||||||
{
|
|
||||||
SetLastError(ERROR_BUFFER_OVERFLOW);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD LastError;
|
|
||||||
WCHAR RandomTempSubDirectory[MAX_PATH];
|
|
||||||
if (!CreateTemporaryDirectory(RandomTempSubDirectory))
|
|
||||||
{
|
|
||||||
LOG(WINTUN_LOG_ERR, L"Failed to create temporary folder %s", RandomTempSubDirectory);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
WCHAR DllPath[MAX_PATH] = { 0 };
|
|
||||||
if (!PathCombineW(DllPath, RandomTempSubDirectory, L"wintun.dll"))
|
|
||||||
{
|
|
||||||
LastError = ERROR_BUFFER_OVERFLOW;
|
|
||||||
goto cleanupDirectory;
|
|
||||||
}
|
|
||||||
const WCHAR *WintunDllResourceName;
|
|
||||||
switch (NativeMachine)
|
|
||||||
{
|
|
||||||
case IMAGE_FILE_MACHINE_AMD64:
|
|
||||||
WintunDllResourceName = L"wintun-amd64.dll";
|
|
||||||
break;
|
|
||||||
case IMAGE_FILE_MACHINE_ARM64:
|
|
||||||
WintunDllResourceName = L"wintun-arm64.dll";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG(WINTUN_LOG_ERR, L"Unsupported platform 0x%x", NativeMachine);
|
|
||||||
LastError = ERROR_NOT_SUPPORTED;
|
|
||||||
goto cleanupDirectory;
|
|
||||||
}
|
|
||||||
if (!ResourceCopyToFile(DllPath, WintunDllResourceName))
|
|
||||||
{
|
|
||||||
LastError = LOG(WINTUN_LOG_ERR, L"Failed to copy resource %s to %s", WintunDllResourceName, DllPath);
|
|
||||||
goto cleanupDelete;
|
|
||||||
}
|
|
||||||
size_t CommandLineLen = 10 + MAX_PATH + 2 + wcslen(Arguments) + 1;
|
|
||||||
WCHAR *CommandLine = Alloc(CommandLineLen * sizeof(WCHAR));
|
|
||||||
if (!CommandLine)
|
|
||||||
{
|
|
||||||
LastError = GetLastError();
|
|
||||||
goto cleanupDelete;
|
|
||||||
}
|
|
||||||
if (_snwprintf_s(CommandLine, CommandLineLen, _TRUNCATE, L"rundll32 \"%.*s\",%s", MAX_PATH, DllPath, Arguments) ==
|
|
||||||
-1)
|
|
||||||
{
|
|
||||||
LOG(WINTUN_LOG_ERR, L"Command line too long");
|
|
||||||
LastError = ERROR_INVALID_PARAMETER;
|
|
||||||
goto cleanupDelete;
|
|
||||||
}
|
|
||||||
HANDLE StreamRStdout = INVALID_HANDLE_VALUE, StreamRStderr = INVALID_HANDLE_VALUE,
|
|
||||||
StreamWStdout = INVALID_HANDLE_VALUE, StreamWStderr = INVALID_HANDLE_VALUE;
|
|
||||||
if (!CreatePipe(&StreamRStdout, &StreamWStdout, &SecurityAttributes, 0) ||
|
|
||||||
!CreatePipe(&StreamRStderr, &StreamWStderr, &SecurityAttributes, 0))
|
|
||||||
{
|
|
||||||
LastError = LOG_LAST_ERROR(L"Failed to create pipes");
|
|
||||||
goto cleanupPipes;
|
|
||||||
}
|
|
||||||
if (!SetHandleInformation(StreamWStdout, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT) ||
|
|
||||||
!SetHandleInformation(StreamWStderr, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
|
|
||||||
{
|
|
||||||
LastError = LOG_LAST_ERROR(L"Failed to set handle info");
|
|
||||||
goto cleanupPipes;
|
|
||||||
}
|
|
||||||
if (ResponseCapacity)
|
|
||||||
Response[0] = 0;
|
|
||||||
PROCESS_STDOUT_STATE ProcessStdoutState = { .Stdout = StreamRStdout,
|
|
||||||
.Response = Response,
|
|
||||||
.ResponseCapacity = ResponseCapacity };
|
|
||||||
HANDLE ThreadStdout = NULL, ThreadStderr = NULL;
|
|
||||||
if ((ThreadStdout = CreateThread(NULL, 0, ProcessStdout, &ProcessStdoutState, 0, NULL)) == NULL ||
|
|
||||||
(ThreadStderr = CreateThread(NULL, 0, ProcessStderr, StreamRStderr, 0, NULL)) == NULL)
|
|
||||||
{
|
|
||||||
LastError = LOG_LAST_ERROR(L"Failed to spawn readers");
|
|
||||||
goto cleanupThreads;
|
|
||||||
}
|
|
||||||
STARTUPINFOW si = { .cb = sizeof(STARTUPINFO),
|
|
||||||
.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES,
|
|
||||||
.wShowWindow = SW_HIDE,
|
|
||||||
.hStdOutput = StreamWStdout,
|
|
||||||
.hStdError = StreamWStderr };
|
|
||||||
PROCESS_INFORMATION pi;
|
|
||||||
if (!CreateProcessW(RunDll32Path, CommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
|
|
||||||
{
|
|
||||||
LastError = LOG_LAST_ERROR(L"Failed to create process: %s", CommandLine);
|
|
||||||
goto cleanupThreads;
|
|
||||||
}
|
|
||||||
LastError = ERROR_SUCCESS;
|
|
||||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
|
||||||
CloseHandle(pi.hProcess);
|
|
||||||
CloseHandle(pi.hThread);
|
|
||||||
cleanupThreads:
|
|
||||||
if (ThreadStderr)
|
|
||||||
{
|
|
||||||
CloseHandle(StreamWStderr);
|
|
||||||
StreamWStderr = INVALID_HANDLE_VALUE;
|
|
||||||
WaitForSingleObject(ThreadStderr, INFINITE);
|
|
||||||
CloseHandle(ThreadStderr);
|
|
||||||
}
|
|
||||||
if (ThreadStdout)
|
|
||||||
{
|
|
||||||
CloseHandle(StreamWStdout);
|
|
||||||
StreamWStdout = INVALID_HANDLE_VALUE;
|
|
||||||
WaitForSingleObject(ThreadStdout, INFINITE);
|
|
||||||
DWORD ThreadResult;
|
|
||||||
if (!GetExitCodeThread(ThreadStdout, &ThreadResult))
|
|
||||||
LOG_LAST_ERROR(L"Failed to retrieve stdout reader result");
|
|
||||||
else if (ThreadResult != ERROR_SUCCESS)
|
|
||||||
LOG_ERROR(LastError, L"Failed to read process output");
|
|
||||||
CloseHandle(ThreadStdout);
|
|
||||||
}
|
|
||||||
cleanupPipes:
|
|
||||||
CloseHandle(StreamRStderr);
|
|
||||||
CloseHandle(StreamWStderr);
|
|
||||||
CloseHandle(StreamRStdout);
|
|
||||||
CloseHandle(StreamWStdout);
|
|
||||||
Free(CommandLine);
|
|
||||||
cleanupDelete:
|
|
||||||
DeleteFileW(DllPath);
|
|
||||||
cleanupDirectory:
|
|
||||||
RemoveDirectoryW(RandomTempSubDirectory);
|
|
||||||
return RET_ERROR(TRUE, LastError);
|
|
||||||
}
|
|
||||||
|
|
||||||
static _Return_type_success_(return != NULL) WINTUN_ADAPTER *CreateAdapterViaRundll32(
|
|
||||||
_In_z_ const WCHAR *Pool,
|
|
||||||
_In_z_ const WCHAR *Name,
|
|
||||||
_In_opt_ const GUID *RequestedGUID,
|
|
||||||
_Inout_ BOOL *RebootRequired)
|
|
||||||
{
|
|
||||||
LOG(WINTUN_LOG_INFO, L"Spawning native process");
|
|
||||||
WCHAR RequestedGUIDStr[MAX_GUID_STRING_LEN];
|
|
||||||
WCHAR Arguments[15 + WINTUN_MAX_POOL + 3 + MAX_ADAPTER_NAME + 2 + MAX_GUID_STRING_LEN + 1];
|
|
||||||
if (_snwprintf_s(
|
|
||||||
Arguments,
|
|
||||||
_countof(Arguments),
|
|
||||||
_TRUNCATE,
|
|
||||||
RequestedGUID ? L"CreateAdapter \"%s\" \"%s\" %.*s" : L"CreateAdapter \"%s\" \"%s\"",
|
|
||||||
Pool,
|
|
||||||
Name,
|
|
||||||
RequestedGUID ? StringFromGUID2(RequestedGUID, RequestedGUIDStr, _countof(RequestedGUIDStr)) : 0,
|
|
||||||
RequestedGUIDStr) == -1)
|
|
||||||
{
|
|
||||||
LOG(WINTUN_LOG_ERR, L"Command line too long");
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
WCHAR Response[8 + 1 + MAX_GUID_STRING_LEN + 1 + 8 + 1];
|
|
||||||
if (!ExecuteRunDll32(Arguments, Response, _countof(Response)))
|
|
||||||
{
|
|
||||||
LOG(WINTUN_LOG_ERR, L"Error executing worker process: %s", Arguments);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
DWORD LastError;
|
|
||||||
WINTUN_ADAPTER *Adapter = NULL;
|
|
||||||
int Argc;
|
|
||||||
WCHAR **Argv = CommandLineToArgvW(Response, &Argc);
|
|
||||||
GUID CfgInstanceID;
|
|
||||||
if (Argc < 3 || FAILED(CLSIDFromString(Argv[1], &CfgInstanceID)))
|
|
||||||
{
|
|
||||||
LOG(WINTUN_LOG_ERR, L"Incomplete or invalid response: %s", Response);
|
|
||||||
LastError = ERROR_INVALID_PARAMETER;
|
|
||||||
goto cleanupArgv;
|
|
||||||
}
|
|
||||||
LastError = wcstoul(Argv[0], NULL, 16);
|
|
||||||
if (LastError == ERROR_SUCCESS && (Adapter = GetAdapter(Pool, &CfgInstanceID)) == NULL)
|
|
||||||
{
|
|
||||||
LOG(WINTUN_LOG_ERR, L"Failed to get adapter %s", Argv[1]);
|
|
||||||
LastError = ERROR_FILE_NOT_FOUND;
|
|
||||||
}
|
|
||||||
if (wcstoul(Argv[2], NULL, 16))
|
|
||||||
*RebootRequired = TRUE;
|
|
||||||
cleanupArgv:
|
|
||||||
LocalFree(Argv);
|
|
||||||
SetLastError(LastError);
|
|
||||||
return Adapter;
|
|
||||||
}
|
|
||||||
|
|
||||||
static _Return_type_success_(return != FALSE) BOOL DeleteAdapterViaRundll32(
|
|
||||||
_In_ const WINTUN_ADAPTER *Adapter,
|
|
||||||
_In_ BOOL ForceCloseSessions,
|
|
||||||
_Inout_ BOOL *RebootRequired)
|
|
||||||
{
|
|
||||||
LOG(WINTUN_LOG_INFO, L"Spawning native process");
|
|
||||||
WCHAR GuidStr[MAX_GUID_STRING_LEN];
|
|
||||||
WCHAR Arguments[16 + MAX_GUID_STRING_LEN + 1];
|
|
||||||
if (_snwprintf_s(
|
|
||||||
Arguments,
|
|
||||||
_countof(Arguments),
|
|
||||||
_TRUNCATE,
|
|
||||||
L"DeleteAdapter %d %.*s",
|
|
||||||
ForceCloseSessions ? 1 : 0,
|
|
||||||
StringFromGUID2(&Adapter->CfgInstanceID, GuidStr, _countof(GuidStr)),
|
|
||||||
GuidStr) == -1)
|
|
||||||
{
|
|
||||||
LOG(WINTUN_LOG_ERR, L"Command line too long");
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
WCHAR Response[8 + 1 + 8 + 1];
|
|
||||||
DWORD LastError;
|
|
||||||
if (!ExecuteRunDll32(Arguments, Response, _countof(Response)))
|
|
||||||
{
|
|
||||||
LOG(WINTUN_LOG_ERR, L"Error executing worker process: %s", Arguments);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
int Argc;
|
|
||||||
WCHAR **Argv = CommandLineToArgvW(Response, &Argc);
|
|
||||||
if (Argc < 2)
|
|
||||||
{
|
|
||||||
LOG(WINTUN_LOG_ERR, L"Incomplete or invalid response: %s", Response);
|
|
||||||
LastError = ERROR_INVALID_PARAMETER;
|
|
||||||
goto cleanupArgv;
|
|
||||||
}
|
|
||||||
LastError = wcstoul(Argv[0], NULL, 16);
|
|
||||||
if (wcstoul(Argv[1], NULL, 16))
|
|
||||||
*RebootRequired = TRUE;
|
|
||||||
cleanupArgv:
|
|
||||||
LocalFree(Argv);
|
|
||||||
return RET_ERROR(TRUE, LastError);
|
|
||||||
}
|
|
||||||
|
|
||||||
static _Return_type_success_(return != FALSE) BOOL
|
|
||||||
DeletePoolDriverViaRundll32(_In_z_ const WCHAR Pool[WINTUN_MAX_POOL], _Inout_ BOOL *RebootRequired)
|
|
||||||
{
|
|
||||||
LOG(WINTUN_LOG_INFO, L"Spawning native process");
|
|
||||||
|
|
||||||
WCHAR Arguments[17 + WINTUN_MAX_POOL + 1];
|
|
||||||
if (_snwprintf_s(Arguments, _countof(Arguments), _TRUNCATE, L"DeletePoolDriver %s", Pool) == -1)
|
|
||||||
{
|
|
||||||
LOG(WINTUN_LOG_ERR, L"Command line too long");
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
WCHAR Response[8 + 1 + 8 + 1];
|
|
||||||
DWORD LastError;
|
|
||||||
if (!ExecuteRunDll32(Arguments, Response, _countof(Response)))
|
|
||||||
{
|
|
||||||
LOG(WINTUN_LOG_ERR, L"Error executing worker process: %s", Arguments);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
int Argc;
|
|
||||||
WCHAR **Argv = CommandLineToArgvW(Response, &Argc);
|
|
||||||
if (Argc < 2)
|
|
||||||
{
|
|
||||||
LOG(WINTUN_LOG_ERR, L"Incomplete or invalid response: %s", Response);
|
|
||||||
LastError = ERROR_INVALID_PARAMETER;
|
|
||||||
goto cleanupArgv;
|
|
||||||
}
|
|
||||||
LastError = wcstoul(Argv[0], NULL, 16);
|
|
||||||
if (wcstoul(Argv[1], NULL, 16))
|
|
||||||
*RebootRequired = TRUE;
|
|
||||||
cleanupArgv:
|
|
||||||
LocalFree(Argv);
|
|
||||||
return RET_ERROR(TRUE, LastError);
|
|
||||||
}
|
|
@ -70,8 +70,10 @@ typedef struct _TUN_SESSION
|
|||||||
HANDLE Handle;
|
HANDLE Handle;
|
||||||
} TUN_SESSION;
|
} TUN_SESSION;
|
||||||
|
|
||||||
_Return_type_success_(return != NULL) TUN_SESSION *WINAPI
|
WINTUN_START_SESSION_FUNC_IMPL WintunStartSession;
|
||||||
WintunStartSession(_In_ const WINTUN_ADAPTER *Adapter, _In_ DWORD Capacity)
|
_Use_decl_annotations_
|
||||||
|
TUN_SESSION *WINAPI
|
||||||
|
WintunStartSession(WINTUN_ADAPTER *Adapter, DWORD Capacity)
|
||||||
{
|
{
|
||||||
DWORD LastError;
|
DWORD LastError;
|
||||||
TUN_SESSION *Session = Zalloc(sizeof(TUN_SESSION));
|
TUN_SESSION *Session = Zalloc(sizeof(TUN_SESSION));
|
||||||
@ -126,8 +128,8 @@ _Return_type_success_(return != NULL) TUN_SESSION *WINAPI
|
|||||||
goto cleanupHandle;
|
goto cleanupHandle;
|
||||||
}
|
}
|
||||||
Session->Capacity = Capacity;
|
Session->Capacity = Capacity;
|
||||||
(void)InitializeCriticalSectionAndSpinCount(&Session->Receive.Lock, LOCK_SPIN_COUNT);
|
(VOID) InitializeCriticalSectionAndSpinCount(&Session->Receive.Lock, LOCK_SPIN_COUNT);
|
||||||
(void)InitializeCriticalSectionAndSpinCount(&Session->Send.Lock, LOCK_SPIN_COUNT);
|
(VOID) InitializeCriticalSectionAndSpinCount(&Session->Send.Lock, LOCK_SPIN_COUNT);
|
||||||
return Session;
|
return Session;
|
||||||
cleanupHandle:
|
cleanupHandle:
|
||||||
CloseHandle(Session->Handle);
|
CloseHandle(Session->Handle);
|
||||||
@ -144,8 +146,10 @@ cleanup:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WINAPI
|
WINTUN_END_SESSION_FUNC_IMPL WintunEndSession;
|
||||||
WintunEndSession(_In_ TUN_SESSION *Session)
|
_Use_decl_annotations_
|
||||||
|
VOID WINAPI
|
||||||
|
WintunEndSession(TUN_SESSION *Session)
|
||||||
{
|
{
|
||||||
DeleteCriticalSection(&Session->Send.Lock);
|
DeleteCriticalSection(&Session->Send.Lock);
|
||||||
DeleteCriticalSection(&Session->Receive.Lock);
|
DeleteCriticalSection(&Session->Receive.Lock);
|
||||||
@ -156,14 +160,18 @@ WintunEndSession(_In_ TUN_SESSION *Session)
|
|||||||
Free(Session);
|
Free(Session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WINTUN_GET_READ_WAIT_EVENT_FUNC_IMPL WintunGetReadWaitEvent;
|
||||||
|
_Use_decl_annotations_
|
||||||
HANDLE WINAPI
|
HANDLE WINAPI
|
||||||
WintunGetReadWaitEvent(_In_ TUN_SESSION *Session)
|
WintunGetReadWaitEvent(TUN_SESSION *Session)
|
||||||
{
|
{
|
||||||
return Session->Descriptor.Send.TailMoved;
|
return Session->Descriptor.Send.TailMoved;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Return_type_success_(return != NULL) _Ret_bytecount_(*PacketSize) BYTE *WINAPI
|
WINTUN_RECEIVE_PACKET_FUNC_IMPL WintunReceivePacket;
|
||||||
WintunReceivePacket(_In_ TUN_SESSION *Session, _Out_ DWORD *PacketSize)
|
_Use_decl_annotations_
|
||||||
|
BYTE *WINAPI
|
||||||
|
WintunReceivePacket(TUN_SESSION *Session, DWORD *PacketSize)
|
||||||
{
|
{
|
||||||
DWORD LastError;
|
DWORD LastError;
|
||||||
EnterCriticalSection(&Session->Send.Lock);
|
EnterCriticalSection(&Session->Send.Lock);
|
||||||
@ -213,8 +221,10 @@ cleanup:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WINAPI
|
WINTUN_RELEASE_RECEIVE_PACKET_FUNC_IMPL WintunReleaseReceivePacket;
|
||||||
WintunReleaseReceivePacket(_In_ TUN_SESSION *Session, _In_ const BYTE *Packet)
|
_Use_decl_annotations_
|
||||||
|
VOID WINAPI
|
||||||
|
WintunReleaseReceivePacket(TUN_SESSION *Session, const BYTE *Packet)
|
||||||
{
|
{
|
||||||
EnterCriticalSection(&Session->Send.Lock);
|
EnterCriticalSection(&Session->Send.Lock);
|
||||||
TUN_PACKET *ReleasedBuffPacket = (TUN_PACKET *)(Packet - offsetof(TUN_PACKET, Data));
|
TUN_PACKET *ReleasedBuffPacket = (TUN_PACKET *)(Packet - offsetof(TUN_PACKET, Data));
|
||||||
@ -232,8 +242,10 @@ WintunReleaseReceivePacket(_In_ TUN_SESSION *Session, _In_ const BYTE *Packet)
|
|||||||
LeaveCriticalSection(&Session->Send.Lock);
|
LeaveCriticalSection(&Session->Send.Lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
_Return_type_success_(return != NULL) _Ret_bytecount_(PacketSize) BYTE *WINAPI
|
WINTUN_ALLOCATE_SEND_PACKET_FUNC_IMPL WintunAllocateSendPacket;
|
||||||
WintunAllocateSendPacket(_In_ TUN_SESSION *Session, _In_ DWORD PacketSize)
|
_Use_decl_annotations_
|
||||||
|
BYTE *WINAPI
|
||||||
|
WintunAllocateSendPacket(TUN_SESSION *Session, DWORD PacketSize)
|
||||||
{
|
{
|
||||||
DWORD LastError;
|
DWORD LastError;
|
||||||
EnterCriticalSection(&Session->Receive.Lock);
|
EnterCriticalSection(&Session->Receive.Lock);
|
||||||
@ -268,8 +280,10 @@ cleanup:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WINAPI
|
WINTUN_SEND_PACKET_FUNC_IMPL WintunSendPacket;
|
||||||
WintunSendPacket(_In_ TUN_SESSION *Session, _In_ const BYTE *Packet)
|
_Use_decl_annotations_
|
||||||
|
VOID WINAPI
|
||||||
|
WintunSendPacket(TUN_SESSION *Session, const BYTE *Packet)
|
||||||
{
|
{
|
||||||
EnterCriticalSection(&Session->Receive.Lock);
|
EnterCriticalSection(&Session->Receive.Lock);
|
||||||
TUN_PACKET *ReleasedBuffPacket = (TUN_PACKET *)(Packet - offsetof(TUN_PACKET, Data));
|
TUN_PACKET *ReleasedBuffPacket = (TUN_PACKET *)(Packet - offsetof(TUN_PACKET, Data));
|
||||||
@ -285,7 +299,8 @@ WintunSendPacket(_In_ TUN_SESSION *Session, _In_ const BYTE *Packet)
|
|||||||
TUN_RING_WRAP(Session->Receive.TailRelease + AlignedPacketSize, Session->Capacity);
|
TUN_RING_WRAP(Session->Receive.TailRelease + AlignedPacketSize, Session->Capacity);
|
||||||
Session->Receive.PacketsToRelease--;
|
Session->Receive.PacketsToRelease--;
|
||||||
}
|
}
|
||||||
if (Session->Descriptor.Receive.Ring->Tail != Session->Receive.TailRelease) {
|
if (Session->Descriptor.Receive.Ring->Tail != Session->Receive.TailRelease)
|
||||||
|
{
|
||||||
WriteULongRelease(&Session->Descriptor.Receive.Ring->Tail, Session->Receive.TailRelease);
|
WriteULongRelease(&Session->Descriptor.Receive.Ring->Tail, Session->Receive.TailRelease);
|
||||||
if (ReadAcquire(&Session->Descriptor.Receive.Ring->Alertable))
|
if (ReadAcquire(&Session->Descriptor.Receive.Ring->Alertable))
|
||||||
SetEvent(Session->Descriptor.Receive.TailMoved);
|
SetEvent(Session->Descriptor.Receive.TailMoved);
|
||||||
|
110
api/wintun.h
110
api/wintun.h
@ -16,7 +16,7 @@ extern "C" {
|
|||||||
/**
|
/**
|
||||||
* A handle representing Wintun adapter
|
* A handle representing Wintun adapter
|
||||||
*/
|
*/
|
||||||
typedef void *WINTUN_ADAPTER_HANDLE;
|
typedef struct _WINTUN_ADAPTER *WINTUN_ADAPTER_HANDLE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum pool name length including zero terminator
|
* Maximum pool name length including zero terminator
|
||||||
@ -39,13 +39,14 @@ typedef void *WINTUN_ADAPTER_HANDLE;
|
|||||||
* @param RebootRequired Optional pointer to a boolean flag to be set to TRUE in case SetupAPI suggests a reboot.
|
* @param RebootRequired Optional pointer to a boolean flag to be set to TRUE in case SetupAPI suggests a reboot.
|
||||||
*
|
*
|
||||||
* @return If the function succeeds, the return value is the adapter handle. Must be released with WintunFreeAdapter. If
|
* @return If the function succeeds, the return value is the adapter handle. Must be released with WintunFreeAdapter. If
|
||||||
* the function fails, the return value is NULL. To get extended error information, call GetLastError.
|
* the function fails, the return value is NULL. To get extended error information, call GetLastError.
|
||||||
*/
|
*/
|
||||||
typedef _Return_type_success_(return != NULL) WINTUN_ADAPTER_HANDLE(WINAPI *WINTUN_CREATE_ADAPTER_FUNC)(
|
typedef _Must_inspect_result_
|
||||||
_In_z_ const WCHAR *Pool,
|
_Return_type_success_(return != NULL)
|
||||||
_In_z_ const WCHAR *Name,
|
_Post_maybenull_
|
||||||
_In_opt_ const GUID *RequestedGUID,
|
WINTUN_ADAPTER_HANDLE(WINAPI WINTUN_CREATE_ADAPTER_FUNC_IMPL)
|
||||||
_Out_opt_ BOOL *RebootRequired);
|
(_In_z_ LPCWSTR Pool, _In_z_ LPCWSTR Name, _In_opt_ const GUID *RequestedGUID, _Out_opt_ BOOL *RebootRequired);
|
||||||
|
typedef WINTUN_CREATE_ADAPTER_FUNC_IMPL *WINTUN_CREATE_ADAPTER_FUNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens an existing Wintun adapter.
|
* Opens an existing Wintun adapter.
|
||||||
@ -55,14 +56,15 @@ typedef _Return_type_success_(return != NULL) WINTUN_ADAPTER_HANDLE(WINAPI *WINT
|
|||||||
* @param Name Adapter name. Zero-terminated string of up to MAX_ADAPTER_NAME-1 characters.
|
* @param Name Adapter name. Zero-terminated string of up to MAX_ADAPTER_NAME-1 characters.
|
||||||
*
|
*
|
||||||
* @return If the function succeeds, the return value is adapter handle. Must be released with WintunFreeAdapter. If the
|
* @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
|
* function fails, the return value is NULL. To get extended error information, call GetLastError. Possible errors
|
||||||
* errors include the following:
|
* include the following: ERROR_FILE_NOT_FOUND if adapter with given name is not found; ERROR_ALREADY_EXISTS if adapter
|
||||||
* ERROR_FILE_NOT_FOUND if adapter with given name is not found;
|
* is found but not a Wintun-class or not a member of the pool
|
||||||
* ERROR_ALREADY_EXISTS if adapter is found but not a Wintun-class or not a member of the pool
|
|
||||||
*/
|
*/
|
||||||
typedef _Return_type_success_(return != NULL)
|
typedef _Must_inspect_result_
|
||||||
WINTUN_ADAPTER_HANDLE(WINAPI *WINTUN_OPEN_ADAPTER_FUNC)(_In_z_ const WCHAR *Pool, _In_z_ const WCHAR *Name);
|
_Return_type_success_(return != NULL)
|
||||||
|
_Post_maybenull_
|
||||||
|
WINTUN_ADAPTER_HANDLE(WINAPI WINTUN_OPEN_ADAPTER_FUNC_IMPL)(_In_z_ LPCWSTR Pool, _In_z_ LPCWSTR Name);
|
||||||
|
typedef WINTUN_OPEN_ADAPTER_FUNC_IMPL *WINTUN_OPEN_ADAPTER_FUNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a Wintun adapter.
|
* Deletes a Wintun adapter.
|
||||||
@ -78,10 +80,10 @@ typedef _Return_type_success_(return != NULL)
|
|||||||
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
|
* @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.
|
* get extended error information, call GetLastError.
|
||||||
*/
|
*/
|
||||||
typedef _Return_type_success_(return != FALSE) BOOL(WINAPI *WINTUN_DELETE_ADAPTER_FUNC)(
|
typedef _Return_type_success_(return != FALSE)
|
||||||
_In_ WINTUN_ADAPTER_HANDLE Adapter,
|
BOOL(WINAPI WINTUN_DELETE_ADAPTER_FUNC_IMPL)
|
||||||
_In_ BOOL ForceCloseSessions,
|
(_In_ WINTUN_ADAPTER_HANDLE Adapter, _In_ BOOL ForceCloseSessions, _Out_opt_ BOOL *RebootRequired);
|
||||||
_Out_opt_ BOOL *RebootRequired);
|
typedef WINTUN_DELETE_ADAPTER_FUNC_IMPL *WINTUN_DELETE_ADAPTER_FUNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by WintunEnumAdapters for each adapter in the pool.
|
* Called by WintunEnumAdapters for each adapter in the pool.
|
||||||
@ -107,15 +109,17 @@ typedef BOOL(CALLBACK *WINTUN_ENUM_CALLBACK)(_In_ WINTUN_ADAPTER_HANDLE Adapter,
|
|||||||
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
|
* @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.
|
* get extended error information, call GetLastError.
|
||||||
*/
|
*/
|
||||||
typedef _Return_type_success_(return != FALSE) BOOL(
|
typedef _Return_type_success_(return != FALSE)
|
||||||
WINAPI *WINTUN_ENUM_ADAPTERS_FUNC)(_In_z_ const WCHAR *Pool, _In_ WINTUN_ENUM_CALLBACK Callback, _In_ LPARAM Param);
|
BOOL(WINAPI WINTUN_ENUM_ADAPTERS_FUNC_IMPL)(_In_z_ LPCWSTR Pool, _In_ WINTUN_ENUM_CALLBACK Callback, _In_ LPARAM Param);
|
||||||
|
typedef WINTUN_ENUM_ADAPTERS_FUNC_IMPL *WINTUN_ENUM_ADAPTERS_FUNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Releases Wintun adapter resources.
|
* Releases Wintun adapter resources.
|
||||||
*
|
*
|
||||||
* @param Adapter Adapter handle obtained with WintunOpenAdapter or WintunCreateAdapter.
|
* @param Adapter Adapter handle obtained with WintunOpenAdapter or WintunCreateAdapter.
|
||||||
*/
|
*/
|
||||||
typedef void(WINAPI *WINTUN_FREE_ADAPTER_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Adapter);
|
typedef VOID(WINAPI WINTUN_FREE_ADAPTER_FUNC_IMPL)(_In_ WINTUN_ADAPTER_HANDLE Adapter);
|
||||||
|
typedef WINTUN_FREE_ADAPTER_FUNC_IMPL *WINTUN_FREE_ADAPTER_FUNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all Wintun adapters in a pool and if there are no more adapters in any other pools, also removes Wintun
|
* Deletes all Wintun adapters in a pool and if there are no more adapters in any other pools, also removes Wintun
|
||||||
@ -129,7 +133,8 @@ typedef void(WINAPI *WINTUN_FREE_ADAPTER_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Adapte
|
|||||||
* get extended error information, call GetLastError.
|
* get extended error information, call GetLastError.
|
||||||
*/
|
*/
|
||||||
typedef _Return_type_success_(return != FALSE)
|
typedef _Return_type_success_(return != FALSE)
|
||||||
BOOL(WINAPI *WINTUN_DELETE_POOL_DRIVER_FUNC)(_In_z_ const WCHAR *Pool, _Out_opt_ BOOL *RebootRequired);
|
BOOL(WINAPI WINTUN_DELETE_POOL_DRIVER_FUNC_IMPL)(_In_z_ LPCWSTR Pool, _Out_opt_ BOOL *RebootRequired);
|
||||||
|
typedef WINTUN_DELETE_POOL_DRIVER_FUNC_IMPL *WINTUN_DELETE_POOL_DRIVER_FUNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the LUID of the adapter.
|
* Returns the LUID of the adapter.
|
||||||
@ -138,7 +143,8 @@ typedef _Return_type_success_(return != FALSE)
|
|||||||
*
|
*
|
||||||
* @param Luid Pointer to LUID to receive adapter LUID.
|
* @param Luid Pointer to LUID to receive adapter LUID.
|
||||||
*/
|
*/
|
||||||
typedef void(WINAPI *WINTUN_GET_ADAPTER_LUID_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Adapter, _Out_ NET_LUID *Luid);
|
typedef VOID(WINAPI WINTUN_GET_ADAPTER_LUID_FUNC_IMPL)(_In_ WINTUN_ADAPTER_HANDLE Adapter, _Out_ NET_LUID *Luid);
|
||||||
|
typedef WINTUN_GET_ADAPTER_LUID_FUNC_IMPL *WINTUN_GET_ADAPTER_LUID_FUNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the name of the Wintun adapter.
|
* Returns the name of the Wintun adapter.
|
||||||
@ -150,9 +156,11 @@ typedef void(WINAPI *WINTUN_GET_ADAPTER_LUID_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Ad
|
|||||||
* @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To
|
* @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.
|
* get extended error information, call GetLastError.
|
||||||
*/
|
*/
|
||||||
typedef _Return_type_success_(return != FALSE) BOOL(WINAPI *WINTUN_GET_ADAPTER_NAME_FUNC)(
|
typedef _Must_inspect_result_
|
||||||
_In_ WINTUN_ADAPTER_HANDLE Adapter,
|
_Return_type_success_(return != FALSE)
|
||||||
_Out_cap_c_(MAX_ADAPTER_NAME) WCHAR *Name);
|
BOOL(WINAPI WINTUN_GET_ADAPTER_NAME_FUNC_IMPL)
|
||||||
|
(_In_ WINTUN_ADAPTER_HANDLE Adapter, _Out_writes_z_(MAX_ADAPTER_NAME) LPWSTR Name);
|
||||||
|
typedef WINTUN_GET_ADAPTER_NAME_FUNC_IMPL *WINTUN_GET_ADAPTER_NAME_FUNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets name of the Wintun adapter.
|
* Sets name of the Wintun adapter.
|
||||||
@ -165,7 +173,8 @@ typedef _Return_type_success_(return != FALSE) BOOL(WINAPI *WINTUN_GET_ADAPTER_N
|
|||||||
* get extended error information, call GetLastError.
|
* get extended error information, call GetLastError.
|
||||||
*/
|
*/
|
||||||
typedef _Return_type_success_(return != FALSE)
|
typedef _Return_type_success_(return != FALSE)
|
||||||
BOOL(WINAPI *WINTUN_SET_ADAPTER_NAME_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Adapter, _In_z_ const WCHAR *Name);
|
BOOL(WINAPI WINTUN_SET_ADAPTER_NAME_FUNC_IMPL)(_In_ WINTUN_ADAPTER_HANDLE Adapter, _In_z_ LPCWSTR Name);
|
||||||
|
typedef WINTUN_SET_ADAPTER_NAME_FUNC_IMPL *WINTUN_SET_ADAPTER_NAME_FUNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines the version of the Wintun driver currently loaded.
|
* Determines the version of the Wintun driver currently loaded.
|
||||||
@ -174,7 +183,9 @@ typedef _Return_type_success_(return != FALSE)
|
|||||||
* zero. To get extended error information, call GetLastError. Possible errors include the following:
|
* zero. To get extended error information, call GetLastError. Possible errors include the following:
|
||||||
* ERROR_FILE_NOT_FOUND Wintun not loaded
|
* ERROR_FILE_NOT_FOUND Wintun not loaded
|
||||||
*/
|
*/
|
||||||
typedef DWORD(WINAPI *WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC)(void);
|
typedef _Return_type_success_(return != 0)
|
||||||
|
DWORD(WINAPI WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC_IMPL)(VOID);
|
||||||
|
typedef WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC_IMPL *WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines the level of logging, passed to WINTUN_LOGGER_CALLBACK.
|
* Determines the level of logging, passed to WINTUN_LOGGER_CALLBACK.
|
||||||
@ -193,7 +204,7 @@ typedef enum
|
|||||||
*
|
*
|
||||||
* @param Message Message text.
|
* @param Message Message text.
|
||||||
*/
|
*/
|
||||||
typedef void(CALLBACK *WINTUN_LOGGER_CALLBACK)(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ const WCHAR *Message);
|
typedef VOID(CALLBACK *WINTUN_LOGGER_CALLBACK)(_In_ WINTUN_LOGGER_LEVEL Level, _In_z_ LPCWSTR Message);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets logger callback function.
|
* Sets logger callback function.
|
||||||
@ -202,7 +213,8 @@ typedef void(CALLBACK *WINTUN_LOGGER_CALLBACK)(_In_ WINTUN_LOGGER_LEVEL Level, _
|
|||||||
* threads concurrently. Should the logging require serialization, you must handle serialization in
|
* threads concurrently. Should the logging require serialization, you must handle serialization in
|
||||||
* NewLogger. Set to NULL to disable.
|
* NewLogger. Set to NULL to disable.
|
||||||
*/
|
*/
|
||||||
typedef void(WINAPI *WINTUN_SET_LOGGER_FUNC)(_In_ WINTUN_LOGGER_CALLBACK NewLogger);
|
typedef VOID(WINAPI WINTUN_SET_LOGGER_FUNC_IMPL)(_In_ WINTUN_LOGGER_CALLBACK NewLogger);
|
||||||
|
typedef WINTUN_SET_LOGGER_FUNC_IMPL *WINTUN_SET_LOGGER_FUNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Minimum ring capacity.
|
* Minimum ring capacity.
|
||||||
@ -217,7 +229,7 @@ typedef void(WINAPI *WINTUN_SET_LOGGER_FUNC)(_In_ WINTUN_LOGGER_CALLBACK NewLogg
|
|||||||
/**
|
/**
|
||||||
* A handle representing Wintun session
|
* A handle representing Wintun session
|
||||||
*/
|
*/
|
||||||
typedef void *WINTUN_SESSION_HANDLE;
|
typedef struct _TUN_SESSION *WINTUN_SESSION_HANDLE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts Wintun session.
|
* Starts Wintun session.
|
||||||
@ -230,15 +242,19 @@ typedef void *WINTUN_SESSION_HANDLE;
|
|||||||
* @return Wintun session handle. Must be released with WintunEndSession. If the function fails, the return value is
|
* @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.
|
* NULL. To get extended error information, call GetLastError.
|
||||||
*/
|
*/
|
||||||
typedef _Return_type_success_(return != NULL)
|
typedef _Must_inspect_result_
|
||||||
WINTUN_SESSION_HANDLE(WINAPI *WINTUN_START_SESSION_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Adapter, _In_ DWORD Capacity);
|
_Return_type_success_(return != NULL)
|
||||||
|
_Post_maybenull_
|
||||||
|
WINTUN_SESSION_HANDLE(WINAPI WINTUN_START_SESSION_FUNC_IMPL)(_In_ WINTUN_ADAPTER_HANDLE Adapter, _In_ DWORD Capacity);
|
||||||
|
typedef WINTUN_START_SESSION_FUNC_IMPL *WINTUN_START_SESSION_FUNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ends Wintun session.
|
* Ends Wintun session.
|
||||||
*
|
*
|
||||||
* @param Session Wintun session handle obtained with WintunStartSession
|
* @param Session Wintun session handle obtained with WintunStartSession
|
||||||
*/
|
*/
|
||||||
typedef void(WINAPI *WINTUN_END_SESSION_FUNC)(_In_ WINTUN_SESSION_HANDLE Session);
|
typedef VOID(WINAPI WINTUN_END_SESSION_FUNC_IMPL)(_In_ WINTUN_SESSION_HANDLE Session);
|
||||||
|
typedef WINTUN_END_SESSION_FUNC_IMPL *WINTUN_END_SESSION_FUNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets Wintun session's read-wait event handle.
|
* Gets Wintun session's read-wait event handle.
|
||||||
@ -250,7 +266,8 @@ typedef void(WINAPI *WINTUN_END_SESSION_FUNC)(_In_ WINTUN_SESSION_HANDLE Session
|
|||||||
* load), wait for this event to become signaled before retrying WintunReceivePackets. Do not call
|
* load), wait for this event to become signaled before retrying WintunReceivePackets. Do not call
|
||||||
* CloseHandle on this event - it is managed by the session.
|
* CloseHandle on this event - it is managed by the session.
|
||||||
*/
|
*/
|
||||||
typedef HANDLE(WINAPI *WINTUN_GET_READ_WAIT_EVENT_FUNC)(_In_ WINTUN_SESSION_HANDLE Session);
|
typedef HANDLE(WINAPI WINTUN_GET_READ_WAIT_EVENT_FUNC_IMPL)(_In_ WINTUN_SESSION_HANDLE Session);
|
||||||
|
typedef WINTUN_GET_READ_WAIT_EVENT_FUNC_IMPL *WINTUN_GET_READ_WAIT_EVENT_FUNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum IP packet size
|
* Maximum IP packet size
|
||||||
@ -272,8 +289,12 @@ typedef HANDLE(WINAPI *WINTUN_GET_READ_WAIT_EVENT_FUNC)(_In_ WINTUN_SESSION_HAND
|
|||||||
* ERROR_NO_MORE_ITEMS Wintun buffer is exhausted;
|
* ERROR_NO_MORE_ITEMS Wintun buffer is exhausted;
|
||||||
* ERROR_INVALID_DATA Wintun buffer is corrupt
|
* ERROR_INVALID_DATA Wintun buffer is corrupt
|
||||||
*/
|
*/
|
||||||
typedef _Return_type_success_(return != NULL) _Ret_bytecount_(*PacketSize) BYTE *(
|
typedef _Must_inspect_result_
|
||||||
WINAPI *WINTUN_RECEIVE_PACKET_FUNC)(_In_ WINTUN_SESSION_HANDLE Session, _Out_ DWORD *PacketSize);
|
_Return_type_success_(return != NULL)
|
||||||
|
_Post_maybenull_
|
||||||
|
_Post_writable_byte_size_(*PacketSize)
|
||||||
|
BYTE *(WINAPI WINTUN_RECEIVE_PACKET_FUNC_IMPL)(_In_ WINTUN_SESSION_HANDLE Session, _Out_ DWORD *PacketSize);
|
||||||
|
typedef WINTUN_RECEIVE_PACKET_FUNC_IMPL *WINTUN_RECEIVE_PACKET_FUNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Releases internal buffer after the received packet has been processed by the client. This function is thread-safe.
|
* Releases internal buffer after the received packet has been processed by the client. This function is thread-safe.
|
||||||
@ -282,7 +303,9 @@ typedef _Return_type_success_(return != NULL) _Ret_bytecount_(*PacketSize) BYTE
|
|||||||
*
|
*
|
||||||
* @param Packet Packet obtained with WintunReceivePacket
|
* @param Packet Packet obtained with WintunReceivePacket
|
||||||
*/
|
*/
|
||||||
typedef void(WINAPI *WINTUN_RELEASE_RECEIVE_PACKET_FUNC)(_In_ WINTUN_SESSION_HANDLE Session, _In_ const BYTE *Packet);
|
typedef VOID(
|
||||||
|
WINAPI WINTUN_RELEASE_RECEIVE_PACKET_FUNC_IMPL)(_In_ WINTUN_SESSION_HANDLE Session, _In_ const BYTE *Packet);
|
||||||
|
typedef WINTUN_RELEASE_RECEIVE_PACKET_FUNC_IMPL *WINTUN_RELEASE_RECEIVE_PACKET_FUNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocates memory for a packet to send. After the memory is filled with packet data, call WintunSendPacket to send
|
* Allocates memory for a packet to send. After the memory is filled with packet data, call WintunSendPacket to send
|
||||||
@ -299,8 +322,12 @@ typedef void(WINAPI *WINTUN_RELEASE_RECEIVE_PACKET_FUNC)(_In_ WINTUN_SESSION_HAN
|
|||||||
* ERROR_HANDLE_EOF Wintun adapter is terminating;
|
* ERROR_HANDLE_EOF Wintun adapter is terminating;
|
||||||
* ERROR_BUFFER_OVERFLOW Wintun buffer is full;
|
* ERROR_BUFFER_OVERFLOW Wintun buffer is full;
|
||||||
*/
|
*/
|
||||||
typedef _Return_type_success_(return != NULL) _Ret_bytecount_(PacketSize) BYTE *(
|
typedef _Must_inspect_result_
|
||||||
WINAPI *WINTUN_ALLOCATE_SEND_PACKET_FUNC)(_In_ WINTUN_SESSION_HANDLE Session, _In_ DWORD PacketSize);
|
_Return_type_success_(return != NULL)
|
||||||
|
_Post_maybenull_
|
||||||
|
_Post_writable_byte_size_(PacketSize)
|
||||||
|
BYTE *(WINAPI WINTUN_ALLOCATE_SEND_PACKET_FUNC_IMPL)(_In_ WINTUN_SESSION_HANDLE Session, _In_ DWORD PacketSize);
|
||||||
|
typedef WINTUN_ALLOCATE_SEND_PACKET_FUNC_IMPL *WINTUN_ALLOCATE_SEND_PACKET_FUNC;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends the packet and releases internal buffer. WintunSendPacket is thread-safe, but the WintunAllocateSendPacket
|
* Sends the packet and releases internal buffer. WintunSendPacket is thread-safe, but the WintunAllocateSendPacket
|
||||||
@ -311,7 +338,8 @@ typedef _Return_type_success_(return != NULL) _Ret_bytecount_(PacketSize) BYTE *
|
|||||||
*
|
*
|
||||||
* @param Packet Packet obtained with WintunAllocateSendPacket
|
* @param Packet Packet obtained with WintunAllocateSendPacket
|
||||||
*/
|
*/
|
||||||
typedef void(WINAPI *WINTUN_SEND_PACKET_FUNC)(_In_ WINTUN_SESSION_HANDLE Session, _In_ const BYTE *Packet);
|
typedef VOID(WINAPI WINTUN_SEND_PACKET_FUNC_IMPL)(_In_ WINTUN_SESSION_HANDLE Session, _In_ const BYTE *Packet);
|
||||||
|
typedef WINTUN_SEND_PACKET_FUNC_IMPL *WINTUN_SEND_PACKET_FUNC;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user