diff options
author | Simon Rozman <simon@rozman.si> | 2020-10-13 19:40:52 +0200 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2020-10-30 16:50:59 +0100 |
commit | f316c13b3e9548d8694bad9a1d634c15f31fa52d (patch) | |
tree | 1e9967655a2094425ce3f4f2d078025dfdf0c736 /api/driver.c | |
parent | api: split api.h (diff) | |
download | wintun-f316c13b3e9548d8694bad9a1d634c15f31fa52d.tar.xz wintun-f316c13b3e9548d8694bad9a1d634c15f31fa52d.zip |
api: introduce logging
And other unifications with installer before merging.
Signed-off-by: Simon Rozman <simon@rozman.si>
Diffstat (limited to 'api/driver.c')
-rw-r--r-- | api/driver.c | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/api/driver.c b/api/driver.c new file mode 100644 index 0000000..b6bf11c --- /dev/null +++ b/api/driver.c @@ -0,0 +1,149 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2018-2020 WireGuard LLC. All Rights Reserved. + */ + +#include "pch.h" + +/** + * Retrieves driver information detail for a device information set or a particular device information element in the + * device information set. + * + * @param DevInfo A handle to the device information set that contains a device information element that + * represents the device for which to retrieve driver information. + * + * @param DevInfoData A pointer to a structure that specifies the device information element in DevInfo. + * + * @param DrvInfoData A pointer to a structure that specifies the driver information element that represents the + * driver for which to retrieve details. + * + * @param DrvInfoDetailData A pointer to a structure that receives detailed information about the specified driver. + * Must be released with HeapFree(GetProcessHeap(), 0, *DrvInfoDetailData) after use. + * + * @return non-zero on success; zero otherwise - use GetLastError(). + */ +_Return_type_success_(return != NULL) SP_DRVINFO_DETAIL_DATA_W *DriverGetDrvInfoDetail( + _In_ HDEVINFO DevInfo, + _In_opt_ SP_DEVINFO_DATA *DevInfoData, + _In_ SP_DRVINFO_DATA_W *DrvInfoData) +{ + HANDLE Heap = GetProcessHeap(); + DWORD Size = sizeof(SP_DRVINFO_DETAIL_DATA_W) + 0x100; + DWORD Result; + for (;;) + { + SP_DRVINFO_DETAIL_DATA_W *DrvInfoDetailData = HeapAlloc(Heap, 0, Size); + if (!DrvInfoDetailData) + { + Result = ERROR_OUTOFMEMORY; + goto out; + } + DrvInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W); + if (SetupDiGetDriverInfoDetailW(DevInfo, DevInfoData, DrvInfoData, DrvInfoDetailData, Size, &Size)) + return DrvInfoDetailData; + Result = GetLastError(); + HeapFree(Heap, 0, DrvInfoDetailData); + if (Result != ERROR_INSUFFICIENT_BUFFER) + { + WINTUN_LOGGER_ERROR(L"Failed", Result); + goto out; + } + } +out: + SetLastError(Result); + return NULL; +} + +/** + * Checks if the device (i.e. network adapter) is using Wintun driver. + * + * @param DevInfo A handle to the device information set that contains a device information element that + * represents the device. + * + * @param DevInfoData A pointer to a structure that specifies the device information element in DevInfo. + * + * @return non-zero when using Wintun driver; zero when not or error - use GetLastError(). + */ +BOOL +DriverIsWintunAdapter(_In_ HDEVINFO DevInfo, _In_opt_ SP_DEVINFO_DATA *DevInfoData) +{ + BOOL Found = FALSE; + if (!SetupDiBuildDriverInfoList(DevInfo, DevInfoData, SPDIT_COMPATDRIVER)) + { + WINTUN_LOGGER_LAST_ERROR(L"Failed to build list of drivers"); + return FALSE; + } + HANDLE Heap = GetProcessHeap(); + for (DWORD EnumIndex = 0; !Found; ++EnumIndex) + { + SP_DRVINFO_DATA_W DrvInfoData = { .cbSize = sizeof(SP_DRVINFO_DATA_W) }; + if (!SetupDiEnumDriverInfoW(DevInfo, DevInfoData, SPDIT_COMPATDRIVER, EnumIndex, &DrvInfoData)) + { + if (GetLastError() == ERROR_NO_MORE_ITEMS) + break; + continue; + } + SP_DRVINFO_DETAIL_DATA_W *DrvInfoDetailData = DriverGetDrvInfoDetail(DevInfo, DevInfoData, &DrvInfoData); + if (!DrvInfoDetailData) + continue; + Found = !_wcsicmp(DrvInfoDetailData->HardwareID, L"wintun"); + HeapFree(Heap, 0, DrvInfoDetailData); + } + SetupDiDestroyDriverInfoList(DevInfo, DevInfoData, SPDIT_COMPATDRIVER); + SetLastError(ERROR_SUCCESS); + return Found; +} + +/** + * Returns a handle to the adapter device object. + * + * @param InstanceId Adapter device instance ID. + * + * @return device handle on success; INVALID_HANDLE_VALUE otherwise - use GetLastError(). + */ +_Return_type_success_(return != INVALID_HANDLE_VALUE) HANDLE + DriverGetAdapterDeviceObject(_In_opt_z_ const WCHAR *InstanceId) +{ + HANDLE Heap = GetProcessHeap(); + ULONG InterfacesLen; + HANDLE Handle = INVALID_HANDLE_VALUE; + DWORD Result = CM_Get_Device_Interface_List_SizeW( + &InterfacesLen, (GUID *)&GUID_DEVINTERFACE_NET, (DEVINSTID_W)InstanceId, CM_GET_DEVICE_INTERFACE_LIST_PRESENT); + if (Result != CR_SUCCESS) + { + WINTUN_LOGGER(WINTUN_LOG_ERR, L"Failed to get device associated device instances size"); + SetLastError(ERROR_GEN_FAILURE); + return INVALID_HANDLE_VALUE; + } + WCHAR *Interfaces = HeapAlloc(Heap, 0, InterfacesLen * sizeof(WCHAR)); + if (!Interfaces) + { + SetLastError(ERROR_OUTOFMEMORY); + return INVALID_HANDLE_VALUE; + } + Result = CM_Get_Device_Interface_ListW( + (GUID *)&GUID_DEVINTERFACE_NET, + (DEVINSTID_W)InstanceId, + Interfaces, + InterfacesLen, + CM_GET_DEVICE_INTERFACE_LIST_PRESENT); + if (Result != CR_SUCCESS) + { + WINTUN_LOGGER(WINTUN_LOG_ERR, L"Failed to get device associated device instances"); + Result = ERROR_GEN_FAILURE; + goto cleanupBuf; + } + Handle = CreateFileW( + Interfaces, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + 0, + NULL); + Result = Handle != INVALID_HANDLE_VALUE ? ERROR_SUCCESS : WINTUN_LOGGER_LAST_ERROR(L"Failed to connect to device"); +cleanupBuf: + HeapFree(Heap, 0, Interfaces); + SetLastError(Result); + return Handle; +} |