api: disable driver management for wintun.dll that don't have a driver

Namely the 32-bit ARM platform, which we will ship wintun.dll for ARM on
ARM64 clients exclusively.

Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
Simon Rozman 2020-10-14 09:09:27 +02:00 committed by Jason A. Donenfeld
parent 84113bd294
commit 85c32a5566
2 changed files with 102 additions and 96 deletions

View File

@ -62,6 +62,102 @@ out:
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, WINTUN_HWID);
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;
}
#if defined(HAVE_EV) || defined(HAVE_WHQL)
/**
* Checks if the Wintun driver is loaded.
*
@ -267,8 +363,6 @@ InstallDriver(_In_ BOOL UpdateExisting)
UseWHQL = FALSE;
#elif defined(HAVE_WHQL)
UseWHQL = TRUE;
#else
# error No driver available
#endif
if (!UseWHQL && (Result = InstallCertificate(L"wintun.sys")) != ERROR_SUCCESS)
WINTUN_LOGGER_ERROR(L"Unable to install code signing certificate", Result);
@ -353,100 +447,6 @@ cleanupDeviceInfoSet:
return Result;
}
/**
* 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, WINTUN_HWID);
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;
}
#define TUN_IOCTL_FORCE_CLOSE_HANDLES CTL_CODE(51820U, 0x971U, METHOD_NEITHER, FILE_READ_DATA | FILE_WRITE_DATA)
/**
@ -695,3 +695,5 @@ WINTUN_STATUS DriverUninstall(VOID)
WINTUN_LOGGER(WINTUN_LOG_INFO, L"Uninstallation successful");
return Result;
}
#endif

View File

@ -22,6 +22,10 @@ DriverIsWintunAdapter(_In_ HDEVINFO DevInfo, _In_opt_ SP_DEVINFO_DATA *DevInfoDa
_Return_type_success_(return != INVALID_HANDLE_VALUE) HANDLE
DriverGetAdapterDeviceObject(_In_opt_z_ const WCHAR *InstanceId);
#if defined(HAVE_EV) || defined(HAVE_WHQL)
WINTUN_STATUS DriverInstallOrUpdate(VOID);
WINTUN_STATUS DriverUninstall(VOID);
#endif