diff options
| author | 2026-05-04 23:33:13 +0200 | |
|---|---|---|
| committer | 2026-05-07 14:24:51 +0200 | |
| commit | 765f429ac12b1d39b22df4e8beb3a0558a9d9e82 (patch) | |
| tree | a7d4e7372d9b3e67a611d6fa9b20a204bf813741 | |
| parent | version: bump (diff) | |
| download | wireguard-nt-jd/cm_register_notification.tar.xz wireguard-nt-jd/cm_register_notification.zip | |
api: use CM_Register_Notification instead of DevCreateObjectQueryjd/cm_register_notification
CM_Register_Notification uses lower level WNF notifications, rather than
the more convoluted registry-based watching. Hopefully this addresses
certain races with incoming events.
See comments in link. This didn't work.
Link: https://github.com/WireGuard/wintun/pull/7
Suggested-by: Aaron Klotz <aaron@tailscale.com>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
| -rw-r--r-- | api/adapter.c | 105 | ||||
| -rw-r--r-- | api/api.vcxproj | 2 |
2 files changed, 35 insertions, 72 deletions
diff --git a/api/adapter.c b/api/adapter.c index 14b1ab6..5ab3385 100644 --- a/api/adapter.c +++ b/api/adapter.c @@ -15,7 +15,6 @@ #include <wchar.h> #include <initguid.h> /* Keep these at the bottom in this order, so that we only generate extra GUIDs for devpkey. The other keys we'll get from uuid.lib like usual. */ #include <devpkey.h> -#include <devquery.h> #include <swdevice.h> #include "adapter.h" @@ -391,34 +390,17 @@ AdapterGetDeviceObjectFileName(LPCWSTR InstanceId) return Interfaces; } -typedef struct _WAIT_FOR_INTERFACE_CTX -{ - HANDLE Event; - DWORD LastError; -} WAIT_FOR_INTERFACE_CTX; - -static VOID WINAPI +static DWORD CALLBACK WaitForInterfaceCallback( - _In_ HDEVQUERY DevQuery, - _Inout_ PVOID Context, - _In_ const DEV_QUERY_RESULT_ACTION_DATA *ActionData) + _In_ HCMNOTIFICATION Notification, + _In_opt_ PVOID Context, + _In_ CM_NOTIFY_ACTION Action, + _In_reads_bytes_(EventDataSize) PCM_NOTIFY_EVENT_DATA EventData, + _In_ DWORD EventDataSize) { - WAIT_FOR_INTERFACE_CTX *Ctx = Context; - DWORD Ret = ERROR_SUCCESS; - switch (ActionData->Action) - { - case DevQueryResultStateChange: - if (ActionData->Data.State != DevQueryStateAborted) - return; - Ret = ERROR_DEVICE_NOT_AVAILABLE; - case DevQueryResultAdd: - case DevQueryResultUpdate: - break; - default: - return; - } - Ctx->LastError = Ret; - SetEvent(Ctx->Event); + if (Action == CM_NOTIFY_ACTION_DEVICEINSTANCESTARTED) + SetEvent((HANDLE)Context); + return ERROR_SUCCESS; } _Must_inspect_result_ @@ -426,65 +408,46 @@ static _Return_type_success_(return != FALSE) BOOL WaitForInterface(_In_ WCHAR *InstanceId) { - DWORD LastError = ERROR_SUCCESS; - static const DEVPROP_BOOLEAN DevPropTrue = DEVPROP_TRUE; - const DEVPROP_FILTER_EXPRESSION Filters[] = { { .Operator = DEVPROP_OPERATOR_EQUALS_IGNORE_CASE, - .Property.CompKey.Key = DEVPKEY_Device_InstanceId, - .Property.CompKey.Store = DEVPROP_STORE_SYSTEM, - .Property.Type = DEVPROP_TYPE_STRING, - .Property.Buffer = InstanceId, - .Property.BufferSize = - (ULONG)((wcslen(InstanceId) + 1) * sizeof(InstanceId[0])) }, - { .Operator = DEVPROP_OPERATOR_EQUALS, - .Property.CompKey.Key = DEVPKEY_DeviceInterface_Enabled, - .Property.CompKey.Store = DEVPROP_STORE_SYSTEM, - .Property.Type = DEVPROP_TYPE_BOOLEAN, - .Property.Buffer = (PVOID)&DevPropTrue, - .Property.BufferSize = sizeof(DevPropTrue) }, - { .Operator = DEVPROP_OPERATOR_EQUALS, - .Property.CompKey.Key = DEVPKEY_DeviceInterface_ClassGuid, - .Property.CompKey.Store = DEVPROP_STORE_SYSTEM, - .Property.Type = DEVPROP_TYPE_GUID, - .Property.Buffer = (PVOID)&GUID_DEVINTERFACE_NET, - .Property.BufferSize = sizeof(GUID_DEVINTERFACE_NET) } }; - WAIT_FOR_INTERFACE_CTX Ctx = { .Event = CreateEventW(NULL, FALSE, FALSE, NULL) }; - if (!Ctx.Event) + DWORD LastError; + CM_NOTIFY_FILTER Filter = { .cbSize = sizeof(Filter), .FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINSTANCE }; + if (wcsncpy_s(Filter.u.DeviceInstance.InstanceId, _countof(Filter.u.DeviceInstance.InstanceId), InstanceId, _TRUNCATE) == STRUNCATE) + { + LastError = LOG_ERROR(ERROR_BUFFER_OVERFLOW, L"Instance ID too long: %s", InstanceId); + goto cleanup; + } + HANDLE Event = CreateEventW(NULL, FALSE, FALSE, NULL); + if (!Event) { LastError = LOG_LAST_ERROR(L"Failed to create event"); goto cleanup; } - HDEVQUERY Query; - HRESULT HRet = DevCreateObjectQuery( - DevObjectTypeDeviceInterface, - DevQueryFlagUpdateResults, - 0, - NULL, - _countof(Filters), - Filters, - WaitForInterfaceCallback, - &Ctx, - &Query); - if (FAILED(HRet)) + HCMNOTIFICATION Notification; + LastError = CM_MapCrToWin32Err( + CM_Register_Notification(&Filter, Event, WaitForInterfaceCallback, &Notification), + ERROR_GEN_FAILURE); + if (LastError != ERROR_SUCCESS) { - LastError = LOG_ERROR(HRet, L"Failed to create device query"); + LastError = LOG_ERROR(LastError, L"Failed to register for instance arrival notification"); goto cleanupEvent; } - LastError = WaitForSingleObject(Ctx.Event, 15000); + LPWSTR Existing = AdapterGetDeviceObjectFileName(InstanceId); + if (Existing) + { + Free(Existing); + goto cleanupNotification; + } + LastError = WaitForSingleObject(Event, 15000); if (LastError != WAIT_OBJECT_0) { if (LastError == WAIT_FAILED) LastError = LOG_LAST_ERROR(L"Failed to wait for device query"); else LastError = LOG_ERROR(LastError, L"Timed out waiting for device query"); - goto cleanupQuery; } - LastError = Ctx.LastError; - if (LastError != ERROR_SUCCESS) - LastError = LOG_ERROR(LastError, L"Failed to get enabled device"); -cleanupQuery: - DevCloseObjectQuery(Query); +cleanupNotification: + CM_Unregister_Notification(Notification); cleanupEvent: - CloseHandle(Ctx.Event); + CloseHandle(Event); cleanup: return RET_ERROR(TRUE, LastError); } diff --git a/api/api.vcxproj b/api/api.vcxproj index 0520b78..fd7c8e5 100644 --- a/api/api.vcxproj +++ b/api/api.vcxproj @@ -34,7 +34,7 @@ <PreprocessorDefinitions Condition="'$(Platform)'=='ARM'">WANT_ARM64_WOW64;%(PreprocessorDefinitions)</PreprocessorDefinitions> </ResourceCompile> <Link> - <DelayLoadDLLs>advapi32.dll;api-ms-win-devices-query-l1-1-0.dll;api-ms-win-devices-swdevice-l1-1-0.dll;cfgmgr32.dll;iphlpapi.dll;ole32.dll;nci.dll;setupapi.dll;shlwapi.dll;version.dll</DelayLoadDLLs> + <DelayLoadDLLs>advapi32.dll;api-ms-win-devices-swdevice-l1-1-0.dll;cfgmgr32.dll;iphlpapi.dll;ole32.dll;nci.dll;setupapi.dll;shlwapi.dll;version.dll</DelayLoadDLLs> <DelayLoadDLLs Condition="'$(Platform)'!='ARM64'">shell32.dll;%(DelayLoadDLLs)</DelayLoadDLLs> <AdditionalDependencies>Cfgmgr32.lib;Iphlpapi.lib;onecore.lib;$(IntDir)nci.lib;ntdll.lib;Setupapi.lib;shlwapi.lib;swdevice.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies> <ModuleDefinitionFile>exports.def</ModuleDefinitionFile> |
