diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2021-10-11 23:21:31 -0600 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2021-10-12 18:54:20 +0000 |
commit | 544fdaaf8fb970d9657a59c1fc4c4569de4f2d3e (patch) | |
tree | 715e49e1f325bf7795face50ff84936b05ab86e2 /api/driver.c | |
parent | proj: remove SDV and DVL support (diff) | |
download | wintun-544fdaaf8fb970d9657a59c1fc4c4569de4f2d3e.tar.xz wintun-544fdaaf8fb970d9657a59c1fc4c4569de4f2d3e.zip |
api: rewrite based on SwDevice
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'api/driver.c')
-rw-r--r-- | api/driver.c | 587 |
1 files changed, 587 insertions, 0 deletions
diff --git a/api/driver.c b/api/driver.c new file mode 100644 index 0000000..3fb4909 --- /dev/null +++ b/api/driver.c @@ -0,0 +1,587 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved. + */ + +#include <Windows.h> +#include <winternl.h> +#include <cfgmgr32.h> +#include <SetupAPI.h> +#include <devguid.h> +#include <ndisguid.h> +#include <Shlwapi.h> +#include <shellapi.h> +#include <wchar.h> + +#include "driver.h" +#include "adapter.h" +#include "logger.h" +#include "namespace.h" +#include "resource.h" +#include "registry.h" +#include "ntdll.h" +#include "rundll32.h" +#include "wintun-inf.h" + +#pragma warning(disable : 4221) /* nonstandard: address of automatic in initializer */ + +struct _SP_DEVINFO_DATA_LIST +{ + SP_DEVINFO_DATA Data; + struct _SP_DEVINFO_DATA_LIST *Next; +}; + +static _Return_type_success_(return != FALSE) +BOOL +DisableAllOurAdapters(_In_ HDEVINFO DevInfo, _Inout_ SP_DEVINFO_DATA_LIST **DisabledAdapters) +{ + DWORD LastError = ERROR_SUCCESS; + for (DWORD EnumIndex = 0;; ++EnumIndex) + { + SP_DEVINFO_DATA_LIST *DeviceNode = Zalloc(sizeof(*DeviceNode)); + if (!DeviceNode) + return FALSE; + DeviceNode->Data.cbSize = sizeof(SP_DEVINFO_DATA); + if (!SetupDiEnumDeviceInfo(DevInfo, EnumIndex, &DeviceNode->Data)) + { + if (GetLastError() == ERROR_NO_MORE_ITEMS) + { + Free(DeviceNode); + break; + } + goto cleanupDeviceNode; + } + + DEVPROPTYPE PropType; + WCHAR Name[MAX_ADAPTER_NAME] = L"<unknown>"; + SetupDiGetDevicePropertyW( + DevInfo, + &DeviceNode->Data, + &DEVPKEY_Wintun_Name, + &PropType, + (PBYTE)Name, + MAX_ADAPTER_NAME * sizeof(Name[0]), + NULL, + 0); + + ULONG Status, ProblemCode; + if (CM_Get_DevNode_Status(&Status, &ProblemCode, DeviceNode->Data.DevInst, 0) != CR_SUCCESS || + ((Status & DN_HAS_PROBLEM) && ProblemCode == CM_PROB_DISABLED)) + goto cleanupDeviceNode; + + LOG(WINTUN_LOG_INFO, L"Force closing adapter \"%s\" open handles", Name); + if (!AdapterForceCloseHandles(DevInfo, &DeviceNode->Data)) + LOG(WINTUN_LOG_WARN, L"Failed to force close adapter \"%s\" open handles", Name); + + LOG(WINTUN_LOG_INFO, L"Disabling adapter \"%s\"", Name); + if (!AdapterDisableInstance(DevInfo, &DeviceNode->Data)) + { + LOG_LAST_ERROR(L"Failed to disable adapter \"%s\"", Name); + LastError = LastError != ERROR_SUCCESS ? LastError : GetLastError(); + goto cleanupDeviceNode; + } + + DeviceNode->Next = *DisabledAdapters; + *DisabledAdapters = DeviceNode; + continue; + + cleanupDeviceNode: + Free(DeviceNode); + } + return RET_ERROR(TRUE, LastError); +} + +static _Return_type_success_(return != FALSE) +BOOL +EnableAllOurAdapters(_In_ HDEVINFO DevInfo, _In_ SP_DEVINFO_DATA_LIST *AdaptersToEnable) +{ + DWORD LastError = ERROR_SUCCESS; + for (SP_DEVINFO_DATA_LIST *DeviceNode = AdaptersToEnable; DeviceNode; DeviceNode = DeviceNode->Next) + { + DEVPROPTYPE PropType; + WCHAR Name[MAX_ADAPTER_NAME] = L"<unknown>"; + SetupDiGetDevicePropertyW( + DevInfo, + &DeviceNode->Data, + &DEVPKEY_Wintun_Name, + &PropType, + (PBYTE)Name, + MAX_ADAPTER_NAME * sizeof(Name[0]), + NULL, + 0); + + LOG(WINTUN_LOG_INFO, L"Enabling adapter \"%s\"", Name); + if (!AdapterEnableInstance(DevInfo, &DeviceNode->Data)) + { + LOG_LAST_ERROR(L"Failed to enable adapter \"%s\"", Name); + LastError = LastError != ERROR_SUCCESS ? LastError : GetLastError(); + } + } + return RET_ERROR(TRUE, LastError); +} + +static BOOL +IsNewer( + _In_ const FILETIME *DriverDate1, + _In_ DWORDLONG DriverVersion1, + _In_ const FILETIME *DriverDate2, + _In_ DWORDLONG DriverVersion2) +{ + if (DriverDate1->dwHighDateTime > DriverDate2->dwHighDateTime) + return TRUE; + if (DriverDate1->dwHighDateTime < DriverDate2->dwHighDateTime) + return FALSE; + + if (DriverDate1->dwLowDateTime > DriverDate2->dwLowDateTime) + return TRUE; + if (DriverDate1->dwLowDateTime < DriverDate2->dwLowDateTime) + return FALSE; + + if (DriverVersion1 > DriverVersion2) + return TRUE; + if (DriverVersion1 < DriverVersion2) + return FALSE; + + return FALSE; +} + +static _Return_type_success_(return != 0) +DWORD +VersionOfFile(_In_z_ LPCWSTR Filename) +{ + DWORD Zero; + DWORD Len = GetFileVersionInfoSizeW(Filename, &Zero); + if (!Len) + { + LOG_LAST_ERROR(L"Failed to query %s version info size", Filename); + return 0; + } + VOID *VersionInfo = Alloc(Len); + if (!VersionInfo) + return 0; + DWORD LastError = ERROR_SUCCESS, Version = 0; + VS_FIXEDFILEINFO *FixedInfo; + UINT FixedInfoLen = sizeof(*FixedInfo); + if (!GetFileVersionInfoW(Filename, 0, Len, VersionInfo)) + { + LastError = LOG_LAST_ERROR(L"Failed to get %s version info", Filename); + goto out; + } + if (!VerQueryValueW(VersionInfo, L"\\", &FixedInfo, &FixedInfoLen)) + { + LastError = LOG_LAST_ERROR(L"Failed to get %s version info root", Filename); + goto out; + } + Version = FixedInfo->dwFileVersionMS; + if (!Version) + { + LOG(WINTUN_LOG_WARN, L"Determined version of %s, but was v0.0, so returning failure", Filename); + LastError = ERROR_VERSION_PARSE_ERROR; + } +out: + Free(VersionInfo); + return RET_ERROR(Version, LastError); +} + +static DWORD WINAPI +MaybeGetRunningDriverVersion(BOOL ReturnOneIfRunningInsteadOfVersion) +{ + PRTL_PROCESS_MODULES Modules; + ULONG BufferSize = 128 * 1024; + for (;;) + { + Modules = Alloc(BufferSize); + if (!Modules) + return 0; + NTSTATUS Status = NtQuerySystemInformation(SystemModuleInformation, Modules, BufferSize, &BufferSize); + if (NT_SUCCESS(Status)) + break; + Free(Modules); + if (Status == STATUS_INFO_LENGTH_MISMATCH) + continue; + LOG(WINTUN_LOG_ERR, L"Failed to enumerate drivers (status: 0x%x)", Status); + SetLastError(RtlNtStatusToDosError(Status)); + return 0; + } + DWORD LastError = ERROR_SUCCESS, Version = 0; + for (ULONG i = Modules->NumberOfModules; i-- > 0;) + { + LPCSTR NtPath = (LPCSTR)Modules->Modules[i].FullPathName; + if (!_stricmp(&NtPath[Modules->Modules[i].OffsetToFileName], "wintun.sys")) + { + if (ReturnOneIfRunningInsteadOfVersion) + { + Version = 1; + goto cleanupModules; + } + WCHAR FilePath[MAX_PATH * 3 + 15]; + if (_snwprintf_s(FilePath, _countof(FilePath), _TRUNCATE, L"\\\\?\\GLOBALROOT%S", NtPath) == -1) + continue; + Version = VersionOfFile(FilePath); + if (!Version) + LastError = GetLastError(); + goto cleanupModules; + } + } + LastError = ERROR_FILE_NOT_FOUND; +cleanupModules: + Free(Modules); + return RET_ERROR(Version, LastError); +} + +_Use_decl_annotations_ +DWORD WINAPI WintunGetRunningDriverVersion(VOID) +{ + return MaybeGetRunningDriverVersion(FALSE); +} + +static BOOL EnsureWintunUnloaded(VOID) +{ + BOOL Loaded; + for (DWORD Tries = 0; Tries < 1500; ++Tries) + { + if (Tries) + Sleep(50); + Loaded = MaybeGetRunningDriverVersion(TRUE) != 0; + if (!Loaded) + break; + } + return !Loaded; +} + +_Use_decl_annotations_ +VOID +DriverInstallDeferredCleanup(HDEVINFO DevInfoExistingAdapters, SP_DEVINFO_DATA_LIST *ExistingAdapters) +{ + if (ExistingAdapters) + { + EnableAllOurAdapters(DevInfoExistingAdapters, ExistingAdapters); + while (ExistingAdapters) + { + SP_DEVINFO_DATA_LIST *Next = ExistingAdapters->Next; + Free(ExistingAdapters); + ExistingAdapters = Next; + } + } + if (DevInfoExistingAdapters != INVALID_HANDLE_VALUE) + SetupDiDestroyDeviceInfoList(DevInfoExistingAdapters); +} + +_Use_decl_annotations_ +BOOL +DriverInstall(HDEVINFO *DevInfoExistingAdaptersForCleanup, SP_DEVINFO_DATA_LIST **ExistingAdaptersForCleanup) +{ + static const FILETIME OurDriverDate = WINTUN_INF_FILETIME; + static const DWORDLONG OurDriverVersion = WINTUN_INF_VERSION; + HANDLE DriverInstallationLock = NamespaceTakeDriverInstallationMutex(); + if (!DriverInstallationLock) + { + LOG(WINTUN_LOG_ERR, L"Failed to take driver installation mutex"); + return FALSE; + } + DWORD LastError = ERROR_SUCCESS; + HDEVINFO DevInfo = SetupDiCreateDeviceInfoListExW(&GUID_DEVCLASS_NET, NULL, NULL, NULL); + if (DevInfo == INVALID_HANDLE_VALUE) + { + LastError = LOG_LAST_ERROR(L"Failed to create empty device information set"); + goto cleanupDriverInstallationLock; + } + SP_DEVINFO_DATA DevInfoData = { .cbSize = sizeof(DevInfoData) }; + if (!SetupDiCreateDeviceInfoW(DevInfo, WINTUN_HWID, &GUID_DEVCLASS_NET, NULL, NULL, DICD_GENERATE_ID, &DevInfoData)) + { + LastError = LOG_LAST_ERROR(L"Failed to create new device information element"); + goto cleanupDevInfo; + } + static const WCHAR Hwids[_countof(WINTUN_HWID) + 1 /*Multi-string terminator*/] = WINTUN_HWID; + if (!SetupDiSetDeviceRegistryPropertyW(DevInfo, &DevInfoData, SPDRP_HARDWAREID, (const BYTE *)Hwids, sizeof(Hwids))) + { + LastError = LOG_LAST_ERROR(L"Failed to set adapter hardware ID"); + goto cleanupDevInfo; + } + if (!SetupDiBuildDriverInfoList(DevInfo, &DevInfoData, SPDIT_COMPATDRIVER)) + { + LastError = LOG_LAST_ERROR(L"Failed building adapter driver info list"); + goto cleanupDevInfo; + } + FILETIME DriverDate = { 0 }; + DWORDLONG DriverVersion = 0; + HDEVINFO DevInfoExistingAdapters = INVALID_HANDLE_VALUE; + SP_DEVINFO_DATA_LIST *ExistingAdapters = NULL; + for (DWORD EnumIndex = 0;; ++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; + } + if (IsNewer(&OurDriverDate, OurDriverVersion, &DrvInfoData.DriverDate, DrvInfoData.DriverVersion)) + { + if (DevInfoExistingAdapters == INVALID_HANDLE_VALUE) + { + DevInfoExistingAdapters = SetupDiGetClassDevsExW( + &GUID_DEVCLASS_NET, WINTUN_ENUMERATOR, NULL, DIGCF_PRESENT, NULL, NULL, NULL); + if (DevInfoExistingAdapters == INVALID_HANDLE_VALUE) + { + LastError = LOG_LAST_ERROR(L"Failed to get present adapters"); + SetupDiDestroyDriverInfoList(DevInfo, &DevInfoData, SPDIT_COMPATDRIVER); + goto cleanupExistingAdapters; + } + _Analysis_assume_(DevInfoExistingAdapters != NULL); + DisableAllOurAdapters(DevInfoExistingAdapters, &ExistingAdapters); + LOG(WINTUN_LOG_INFO, L"Waiting for existing driver to unload from kernel"); + if (!EnsureWintunUnloaded()) + LOG(WINTUN_LOG_WARN, + L"Failed to unload existing driver, which means a reboot will likely be required"); + } + LOG(WINTUN_LOG_INFO, + L"Removing existing driver %u.%u", + (DWORD)((DrvInfoData.DriverVersion & 0xffff000000000000) >> 48), + (DWORD)((DrvInfoData.DriverVersion & 0x0000ffff00000000) >> 32)); + BYTE LargeBuffer[0x2000]; + DWORD Size = sizeof(LargeBuffer); + SP_DRVINFO_DETAIL_DATA_W *DrvInfoDetailData = (SP_DRVINFO_DETAIL_DATA_W *)LargeBuffer; + DrvInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W); + if (!SetupDiGetDriverInfoDetailW(DevInfo, &DevInfoData, &DrvInfoData, DrvInfoDetailData, Size, &Size)) + { + LOG(WINTUN_LOG_WARN, L"Failed getting adapter driver info detail"); + continue; + } + LPWSTR InfFileName = PathFindFileNameW(DrvInfoDetailData->InfFileName); + if (!SetupUninstallOEMInfW(InfFileName, SUOI_FORCEDELETE, NULL)) + LOG_LAST_ERROR(L"Unable to remove existing driver %s", InfFileName); + continue; + } + if (!IsNewer(&DrvInfoData.DriverDate, DrvInfoData.DriverVersion, &DriverDate, DriverVersion)) + continue; + DriverDate = DrvInfoData.DriverDate; + DriverVersion = DrvInfoData.DriverVersion; + } + SetupDiDestroyDriverInfoList(DevInfo, &DevInfoData, SPDIT_COMPATDRIVER); + + if (DriverVersion) + { + LOG(WINTUN_LOG_INFO, + L"Using existing driver %u.%u", + (DWORD)((DriverVersion & 0xffff000000000000) >> 48), + (DWORD)((DriverVersion & 0x0000ffff00000000) >> 32)); + LastError = ERROR_SUCCESS; + goto cleanupExistingAdapters; + } + + LOG(WINTUN_LOG_INFO, + L"Installing driver %u.%u", + (DWORD)((OurDriverVersion & 0xffff000000000000) >> 48), + (DWORD)((OurDriverVersion & 0x0000ffff00000000) >> 32)); + WCHAR RandomTempSubDirectory[MAX_PATH]; + if (!ResourceCreateTemporaryDirectory(RandomTempSubDirectory)) + { + LastError = LOG_LAST_ERROR(L"Failed to create temporary folder %s", RandomTempSubDirectory); + goto cleanupExistingAdapters; + } + + WCHAR CatPath[MAX_PATH] = { 0 }; + WCHAR SysPath[MAX_PATH] = { 0 }; + WCHAR InfPath[MAX_PATH] = { 0 }; + WCHAR DownlevelShimPath[MAX_PATH] = { 0 }; + if (!PathCombineW(CatPath, RandomTempSubDirectory, L"wintun.cat") || + !PathCombineW(SysPath, RandomTempSubDirectory, L"wintun.sys") || + !PathCombineW(InfPath, RandomTempSubDirectory, L"wintun.inf")) + { + LastError = ERROR_BUFFER_OVERFLOW; + goto cleanupDirectory; + } + + WCHAR *CatSource, *SysSource, *InfSource; + if (NativeMachine == IMAGE_FILE_PROCESS) + { + CatSource = L"wintun.cat"; + SysSource = L"wintun.sys"; + InfSource = L"wintun.inf"; + } + else if (NativeMachine == IMAGE_FILE_MACHINE_AMD64) + { + CatSource = L"wintun-amd64.cat"; + SysSource = L"wintun-amd64.sys"; + InfSource = L"wintun-amd64.inf"; + } + else if (NativeMachine == IMAGE_FILE_MACHINE_ARM64) + { + CatSource = L"wintun-arm64.cat"; + SysSource = L"wintun-arm64.sys"; + InfSource = L"wintun-arm64.inf"; + } + else + { + LastError = LOG_ERROR(ERROR_NOT_SUPPORTED, L"Unsupported platform 0x%x", NativeMachine); + goto cleanupDirectory; + } + + LOG(WINTUN_LOG_INFO, L"Extracting driver"); + if (!ResourceCopyToFile(CatPath, CatSource) || !ResourceCopyToFile(SysPath, SysSource) || + !ResourceCopyToFile(InfPath, InfSource)) + { + LastError = LOG_LAST_ERROR(L"Failed to extract driver"); + goto cleanupDelete; + } + + WCHAR *WintrustKeyOriginalValue = NULL; + HKEY WintrustKey = NULL; + if (!IsWindows10) + { + LOG(WINTUN_LOG_INFO, L"Shimming downlevel driver loader"); + if (!PathCombineW(DownlevelShimPath, RandomTempSubDirectory, L"downlevelshim.dll")) + { + DownlevelShimPath[0] = L'\0'; + LastError = ERROR_BUFFER_OVERFLOW; + goto cleanupDelete; + } + if (!ResourceCopyToFile(DownlevelShimPath, L"downlevelshim.dll")) + { + LastError = LOG_LAST_ERROR(L"Failed to extract downlevel shim"); + goto cleanupDelete; + } + LastError = RegOpenKeyExW( + HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Microsoft\\Cryptography\\Providers\\Trust\\FinalPolicy\\{F750E6C3-38EE-11D1-85E5-00C04FC295EE}", + 0, + KEY_QUERY_VALUE | KEY_SET_VALUE, + &WintrustKey); + if (LastError != ERROR_SUCCESS) + { + LOG_ERROR(LastError, L"Failed to open Wintrust FinalPolicy key"); + goto cleanupDelete; + } + WintrustKeyOriginalValue = RegistryQueryString(WintrustKey, L"$DLL", TRUE); + if (!WintrustKeyOriginalValue) + { + LastError = LOG_LAST_ERROR(L"Failed to read current Wintrust FinalPolicy key"); + goto cleanupWintrustKey; + } + LastError = RegSetValueExW( + WintrustKey, + L"$DLL", + 0, + REG_SZ, + (BYTE *)DownlevelShimPath, + (DWORD)((wcslen(DownlevelShimPath) + 1) * sizeof(DownlevelShimPath[0]))); + if (LastError != ERROR_SUCCESS) + { + LOG_ERROR(LastError, L"Failed to set Wintrust FinalPolicy key"); + goto cleanupWintrustChangedKey; + } + } + + LOG(WINTUN_LOG_INFO, L"Installing driver"); + if (!SetupCopyOEMInfW(InfPath, NULL, SPOST_NONE, 0, NULL, 0, NULL, NULL)) + LastError = LOG_LAST_ERROR(L"Could not install driver %s to store", InfPath); + +cleanupWintrustChangedKey: + if (WintrustKeyOriginalValue) + RegSetValueExW( + WintrustKey, + L"$DLL", + 0, + REG_SZ, + (BYTE *)WintrustKeyOriginalValue, + (DWORD)((wcslen(WintrustKeyOriginalValue) + 1) * sizeof(WintrustKeyOriginalValue[0]))); +cleanupWintrustKey: + if (WintrustKey) + RegCloseKey(WintrustKey); + if (WintrustKeyOriginalValue) + Free(WintrustKeyOriginalValue); +cleanupDelete: + DeleteFileW(CatPath); + DeleteFileW(SysPath); + DeleteFileW(InfPath); + if (DownlevelShimPath[0]) + DeleteFileW(DownlevelShimPath); +cleanupDirectory: + RemoveDirectoryW(RandomTempSubDirectory); +cleanupExistingAdapters: + if (LastError == ERROR_SUCCESS) + { + *DevInfoExistingAdaptersForCleanup = DevInfoExistingAdapters; + *ExistingAdaptersForCleanup = ExistingAdapters; + } + else + DriverInstallDeferredCleanup(DevInfoExistingAdapters, ExistingAdapters); +cleanupDevInfo: + SetupDiDestroyDeviceInfoList(DevInfo); +cleanupDriverInstallationLock: + NamespaceReleaseMutex(DriverInstallationLock); + return RET_ERROR(TRUE, LastError); +} + +_Use_decl_annotations_ +BOOL WINAPI WintunDeleteDriver(VOID) +{ + DWORD LastError = ERROR_SUCCESS; + + AdapterCleanupOrphanedDevices(); + + HANDLE DriverInstallationLock = NamespaceTakeDriverInstallationMutex(); + if (!DriverInstallationLock) + { + LastError = LOG(WINTUN_LOG_ERR, L"Failed to take driver installation mutex"); + goto cleanup; + } + + HDEVINFO DevInfo = SetupDiCreateDeviceInfoListExW(&GUID_DEVCLASS_NET, NULL, NULL, NULL); + if (DevInfo == INVALID_HANDLE_VALUE) + { + LastError = LOG_LAST_ERROR(L"Failed to create empty device information set"); + goto cleanupDriverInstallationLock; + } + SP_DEVINFO_DATA DevInfoData = { .cbSize = sizeof(DevInfoData) }; + if (!SetupDiCreateDeviceInfoW(DevInfo, WINTUN_HWID, &GUID_DEVCLASS_NET, NULL, NULL, DICD_GENERATE_ID, &DevInfoData)) + { + LastError = LOG_LAST_ERROR(L"Failed to create new device information element"); + goto cleanupDevInfo; + } + static const WCHAR Hwids[_countof(WINTUN_HWID) + 1 /*Multi-string terminator*/] = WINTUN_HWID; + if (!SetupDiSetDeviceRegistryPropertyW(DevInfo, &DevInfoData, SPDRP_HARDWAREID, (const BYTE *)Hwids, sizeof(Hwids))) + { + LastError = LOG_LAST_ERROR(L"Failed to set adapter hardware ID"); + goto cleanupDevInfo; + } + if (!SetupDiBuildDriverInfoList(DevInfo, &DevInfoData, SPDIT_COMPATDRIVER)) + { + LastError = LOG_LAST_ERROR(L"Failed building adapter driver info list"); + goto cleanupDevInfo; + } + for (DWORD EnumIndex = 0;; ++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; + } + BYTE LargeBuffer[0x2000]; + DWORD Size = sizeof(LargeBuffer); + SP_DRVINFO_DETAIL_DATA_W *DrvInfoDetailData = (SP_DRVINFO_DETAIL_DATA_W *)LargeBuffer; + DrvInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA_W); + if (!SetupDiGetDriverInfoDetailW(DevInfo, &DevInfoData, &DrvInfoData, DrvInfoDetailData, Size, &Size)) + { + LOG(WINTUN_LOG_WARN, L"Failed getting adapter driver info detail"); + continue; + } + LPCWSTR Path = PathFindFileNameW(DrvInfoDetailData->InfFileName); + LOG(WINTUN_LOG_INFO, L"Removing driver %s", Path); + if (!SetupUninstallOEMInfW(Path, 0, NULL)) + { + LOG_LAST_ERROR(L"Unable to remove driver %s", Path); + LastError = LastError != ERROR_SUCCESS ? LastError : GetLastError(); + } + } + SetupDiDestroyDriverInfoList(DevInfo, &DevInfoData, SPDIT_COMPATDRIVER); +cleanupDevInfo: + SetupDiDestroyDeviceInfoList(DevInfo); +cleanupDriverInstallationLock: + NamespaceReleaseMutex(DriverInstallationLock); +cleanup: + return RET_ERROR(TRUE, LastError); +} |