diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2021-02-03 22:32:58 +0100 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2021-02-03 22:36:41 +0100 |
commit | fb416747dcfb6e53df5d249d07123989e4ddc796 (patch) | |
tree | e6a92a53820b48e451eb080aca959d38103da404 | |
parent | global: bump copyright (diff) | |
download | wintun-fb416747dcfb6e53df5d249d07123989e4ddc796.tar.xz wintun-fb416747dcfb6e53df5d249d07123989e4ddc796.zip |
api: ensure that device object exists before returning from open/create0.10.1
Some users are seeing errors like this after rebooting from Windows
Update:
2021-01-28 18:39:45.220197: [TUN] Creating Wintun interface
2021-01-28 18:39:49.420116: [TUN] [Wintun] CreateAdapter: Creating adapter
2021-01-28 18:39:53.704007: [TUN] [Wintun] OpenDeviceObject: Failed to connect to adapter: The system cannot find the path specified. (Code 0x00000003)
2021-01-28 18:39:53.704007: [TUN] [Wintun] WintunStartSession: Failed to open adapter device object
2021-01-28 18:39:54.097037: [TUN] Unable to create Wintun interface: Error starting session: The system cannot find the path specified.
It appears that creation of the device object file might happen
asynchronously, so this commit polls for it.
Reported-by: Artem Kuroptev <artem@kuroptev.com>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r-- | api/adapter.c | 75 |
1 files changed, 62 insertions, 13 deletions
diff --git a/api/adapter.c b/api/adapter.c index 6766b9e..298e038 100644 --- a/api/adapter.c +++ b/api/adapter.c @@ -178,7 +178,7 @@ IsOurAdapter(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA *DevInfoData) return IsOurs; } -static _Return_type_success_(return != INVALID_HANDLE_VALUE) HANDLE OpenDeviceObject(_In_opt_z_ const WCHAR *InstanceId) +static _Return_type_success_(return != NULL) WCHAR *GetDeviceObjectFileName(_In_opt_z_ const WCHAR *InstanceId) { ULONG InterfacesLen; DWORD LastError = CM_MapCrToWin32Err( @@ -191,12 +191,11 @@ static _Return_type_success_(return != INVALID_HANDLE_VALUE) HANDLE OpenDeviceOb if (LastError != ERROR_SUCCESS) { SetLastError(LOG_ERROR(L"Failed to query associated instances size", LastError)); - return INVALID_HANDLE_VALUE; + return NULL; } WCHAR *Interfaces = Alloc(InterfacesLen * sizeof(WCHAR)); if (!Interfaces) - return INVALID_HANDLE_VALUE; - HANDLE Handle = INVALID_HANDLE_VALUE; + return NULL; LastError = CM_MapCrToWin32Err( CM_Get_Device_Interface_ListW( (GUID *)&GUID_DEVINTERFACE_NET, @@ -208,24 +207,57 @@ static _Return_type_success_(return != INVALID_HANDLE_VALUE) HANDLE OpenDeviceOb if (LastError != ERROR_SUCCESS) { LOG_ERROR(L"Failed to get associated instances", LastError); - goto cleanupBuf; + Free(Interfaces); + SetLastError(LastError); + return NULL; } - Handle = CreateFileW( - Interfaces, + return Interfaces; +} + +static _Return_type_success_(return != INVALID_HANDLE_VALUE) HANDLE OpenDeviceObject(_In_opt_z_ const WCHAR *InstanceId) +{ + WCHAR *Filename = GetDeviceObjectFileName(InstanceId); + if (!Filename) + return INVALID_HANDLE_VALUE; + HANDLE Handle = CreateFileW( + Filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL); - LastError = Handle != INVALID_HANDLE_VALUE ? ERROR_SUCCESS : LOG_LAST_ERROR(L"Failed to connect to adapter"); -cleanupBuf: - Free(Interfaces); - if (LastError != ERROR_SUCCESS) - SetLastError(LastError); + Free(Filename); + if (Handle == INVALID_HANDLE_VALUE) + LOG_LAST_ERROR(L"Failed to connect to adapter"); return Handle; } +static BOOL +EnsureDeviceObject(_In_opt_z_ const WCHAR *InstanceId) +{ + WCHAR *Filename = GetDeviceObjectFileName(InstanceId); + if (!Filename) + return FALSE; + BOOL Exists = TRUE; + const int Attempts = 100; + for (int i = 0; i < Attempts; ++i) + { + HANDLE Handle = CreateFileW(Filename, 0, 0, NULL, OPEN_EXISTING, 0, NULL); + if (Handle != INVALID_HANDLE_VALUE) + { + CloseHandle(Handle); + goto out; + } + if (i != Attempts - 1) + Sleep(50); + } + Exists = FALSE; +out: + Free(Filename); + return Exists; +} + #define TUN_IOCTL_FORCE_CLOSE_HANDLES CTL_CODE(51820U, 0x971U, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA) static _Return_type_success_(return != FALSE) BOOL @@ -679,7 +711,19 @@ _Return_type_success_(return != NULL) WINTUN_ADAPTER *WINAPI } Adapter = CreateAdapterData(Pool, DevInfo, &DevInfoData); - LastError = Adapter ? ERROR_SUCCESS : LOG(WINTUN_LOG_ERR, L"Failed to create adapter data"); + if (!Adapter) + { + LastError = LOG(WINTUN_LOG_ERR, L"Failed to create adapter data"); + goto cleanupDevInfo; + } + + if (!EnsureDeviceObject(Adapter->DevInstanceID)) + { + LastError = LOG_LAST_ERROR(L"Device object file did not appear"); + goto cleanupDevInfo; + } + + LastError = ERROR_SUCCESS; goto cleanupDevInfo; } LastError = ERROR_FILE_NOT_FOUND; @@ -1591,6 +1635,11 @@ static _Return_type_success_(return != NULL) WINTUN_ADAPTER *CreateAdapter( else break; } + if (!EnsureDeviceObject(Adapter->DevInstanceID)) + { + LastError = LOG_LAST_ERROR(L"Device object file did not appear"); + goto cleanupTcpipAdapterRegKey; + } LastError = ERROR_SUCCESS; cleanupTcpipAdapterRegKey: |