150 lines
5.4 KiB
C
150 lines
5.4 KiB
C
|
/* 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;
|
||
|
}
|