api: add pool/driver removal for uninstaller semantics
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
parent
0c85a2ebf1
commit
7dede73406
@ -1750,12 +1750,18 @@ cleanupToken:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static WINTUN_STATUS
|
static WINTUN_STATUS
|
||||||
DeleteAllOurAdapters(void)
|
DeleteAllOurAdapters(_In_ WCHAR Pool[WINTUN_MAX_POOL], _Inout_ BOOL *RebootRequired)
|
||||||
{
|
{
|
||||||
|
HANDLE Mutex = NamespaceTakePoolMutex(Pool);
|
||||||
|
if (!Mutex)
|
||||||
|
return ERROR_INVALID_HANDLE;
|
||||||
DWORD Result = ERROR_SUCCESS;
|
DWORD Result = ERROR_SUCCESS;
|
||||||
HDEVINFO DevInfo = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL);
|
HDEVINFO DevInfo = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, NULL, NULL, DIGCF_PRESENT, NULL, NULL, NULL);
|
||||||
if (DevInfo == INVALID_HANDLE_VALUE)
|
if (DevInfo == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
NamespaceReleaseMutex(Mutex);
|
||||||
return LOG_LAST_ERROR(L"Failed to get present adapters");
|
return LOG_LAST_ERROR(L"Failed to get present adapters");
|
||||||
|
}
|
||||||
SP_REMOVEDEVICE_PARAMS Params = { .ClassInstallHeader = { .cbSize = sizeof(SP_CLASSINSTALL_HEADER),
|
SP_REMOVEDEVICE_PARAMS Params = { .ClassInstallHeader = { .cbSize = sizeof(SP_CLASSINSTALL_HEADER),
|
||||||
.InstallFunction = DIF_REMOVE },
|
.InstallFunction = DIF_REMOVE },
|
||||||
.Scope = DI_REMOVEDEVICE_GLOBAL };
|
.Scope = DI_REMOVEDEVICE_GLOBAL };
|
||||||
@ -1772,39 +1778,58 @@ DeleteAllOurAdapters(void)
|
|||||||
BOOL IsOurs;
|
BOOL IsOurs;
|
||||||
if (IsOurAdapter(DevInfo, &DevInfoData, &IsOurs) != ERROR_SUCCESS || !IsOurs)
|
if (IsOurAdapter(DevInfo, &DevInfoData, &IsOurs) != ERROR_SUCCESS || !IsOurs)
|
||||||
continue;
|
continue;
|
||||||
|
BOOL IsMember;
|
||||||
|
Result = IsPoolMember(Pool, DevInfo, &DevInfoData, &IsMember);
|
||||||
|
if (Result != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
LOG(WINTUN_LOG_ERR, L"Failed to get pool membership");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!IsMember)
|
||||||
|
continue;
|
||||||
|
|
||||||
LOG(WINTUN_LOG_INFO, L"Force closing all open handles for existing adapter");
|
LOG(WINTUN_LOG_INFO, L"Force closing all open handles for existing adapter");
|
||||||
if (ForceCloseWintunAdapterHandle(DevInfo, &DevInfoData) != ERROR_SUCCESS)
|
if (ForceCloseWintunAdapterHandle(DevInfo, &DevInfoData) != ERROR_SUCCESS)
|
||||||
LOG(WINTUN_LOG_WARN, L"Failed to force close adapter handles");
|
LOG(WINTUN_LOG_WARN, L"Failed to force close adapter handles");
|
||||||
|
|
||||||
LOG(WINTUN_LOG_INFO, L"Removing existing adapter");
|
LOG(WINTUN_LOG_INFO, L"Removing existing adapter");
|
||||||
if (!SetupDiSetClassInstallParamsW(DevInfo, &DevInfoData, &Params.ClassInstallHeader, sizeof(Params)) ||
|
if (SetupDiSetClassInstallParamsW(DevInfo, &DevInfoData, &Params.ClassInstallHeader, sizeof(Params)) &&
|
||||||
!SetupDiCallClassInstaller(DIF_REMOVE, DevInfo, &DevInfoData))
|
SetupDiCallClassInstaller(DIF_REMOVE, DevInfo, &DevInfoData))
|
||||||
|
*RebootRequired = *RebootRequired || CheckReboot(DevInfo, &DevInfoData);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
LOG_LAST_ERROR(L"Failed to remove existing adapter");
|
LOG_LAST_ERROR(L"Failed to remove existing adapter");
|
||||||
Result = Result != ERROR_SUCCESS ? Result : GetLastError();
|
Result = Result != ERROR_SUCCESS ? Result : GetLastError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SetupDiDestroyDeviceInfoList(DevInfo);
|
SetupDiDestroyDeviceInfoList(DevInfo);
|
||||||
|
NamespaceReleaseMutex(Mutex);
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
WINTUN_STATUS WINAPI
|
WINTUN_STATUS WINAPI
|
||||||
WintunDeleteDriver(void)
|
WintunDeletePoolDriver(_In_z_ WCHAR Pool[WINTUN_MAX_POOL], _Out_opt_ BOOL *RebootRequired)
|
||||||
{
|
{
|
||||||
if (!ElevateToSystem())
|
if (!ElevateToSystem())
|
||||||
return LOG_LAST_ERROR(L"Failed to impersonate SYSTEM user");
|
return LOG_LAST_ERROR(L"Failed to impersonate SYSTEM user");
|
||||||
|
|
||||||
DWORD Result = ERROR_SUCCESS;
|
BOOL DummyRebootRequired;
|
||||||
|
if (!RebootRequired)
|
||||||
|
RebootRequired = &DummyRebootRequired;
|
||||||
|
*RebootRequired = FALSE;
|
||||||
|
|
||||||
|
DWORD Result;
|
||||||
if (MAYBE_WOW64 && NativeMachine != IMAGE_FILE_PROCESS)
|
if (MAYBE_WOW64 && NativeMachine != IMAGE_FILE_PROCESS)
|
||||||
{
|
{
|
||||||
Result = DeleteDriverViaRundll32();
|
Result = DeletePoolDriverViaRundll32(Pool, RebootRequired);
|
||||||
RevertToSelf();
|
RevertToSelf();
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DeleteAllOurAdapters(); */
|
Result = DeleteAllOurAdapters(Pool, RebootRequired);
|
||||||
|
if (Result != ERROR_SUCCESS)
|
||||||
|
goto cleanupToken;
|
||||||
|
|
||||||
HANDLE DriverInstallationLock = NamespaceTakeDriverInstallationMutex();
|
HANDLE DriverInstallationLock = NamespaceTakeDriverInstallationMutex();
|
||||||
if (!DriverInstallationLock)
|
if (!DriverInstallationLock)
|
||||||
{
|
{
|
||||||
@ -1837,7 +1862,7 @@ WintunDeleteDriver(void)
|
|||||||
if (!_wcsicmp(DriverDetail->HardwareID, WINTUN_HWID))
|
if (!_wcsicmp(DriverDetail->HardwareID, WINTUN_HWID))
|
||||||
{
|
{
|
||||||
LOG(WINTUN_LOG_INFO, TEXT("Removing existing driver"));
|
LOG(WINTUN_LOG_INFO, TEXT("Removing existing driver"));
|
||||||
if (!SetupUninstallOEMInfW(PathFindFileNameW(DriverDetail->InfFileName), SUOI_FORCEDELETE, NULL))
|
if (!SetupUninstallOEMInfW(PathFindFileNameW(DriverDetail->InfFileName), 0, NULL))
|
||||||
{
|
{
|
||||||
LOG_LAST_ERROR(TEXT("Unable to remove existing driver"));
|
LOG_LAST_ERROR(TEXT("Unable to remove existing driver"));
|
||||||
Result = Result != ERROR_SUCCESS ? Result : GetLastError();
|
Result = Result != ERROR_SUCCESS ? Result : GetLastError();
|
||||||
|
@ -58,7 +58,7 @@ WINTUN_STATUS WINAPI
|
|||||||
WintunDeleteAdapter(_In_ const WINTUN_ADAPTER *Adapter, _In_ BOOL ForceCloseSessions, _Out_opt_ BOOL *RebootRequired);
|
WintunDeleteAdapter(_In_ const WINTUN_ADAPTER *Adapter, _In_ BOOL ForceCloseSessions, _Out_opt_ BOOL *RebootRequired);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @copydoc WINTUN_DELETE_DRIVER_FUNC
|
* @copydoc WINTUN_DELETE_POOL_DRIVER_FUNC
|
||||||
*/
|
*/
|
||||||
WINTUN_STATUS WINAPI
|
WINTUN_STATUS WINAPI
|
||||||
WintunDeleteDriver(void);
|
WintunDeletePoolDriver(_In_z_ WCHAR Pool[WINTUN_MAX_POOL], _Out_opt_ BOOL *RebootRequired);
|
@ -3,7 +3,7 @@ EXPORTS
|
|||||||
WintunAllocateSendPacket
|
WintunAllocateSendPacket
|
||||||
WintunCreateAdapter
|
WintunCreateAdapter
|
||||||
WintunDeleteAdapter
|
WintunDeleteAdapter
|
||||||
WintunDeleteDriver
|
WintunDeletePoolDriver
|
||||||
WintunEndSession
|
WintunEndSession
|
||||||
WintunEnumAdapters
|
WintunEnumAdapters
|
||||||
WintunFreeAdapter
|
WintunFreeAdapter
|
||||||
|
@ -131,12 +131,19 @@ cleanup:
|
|||||||
Done();
|
Done();
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID __stdcall DeleteDriver(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
|
VOID __stdcall DeletePoolDriver(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
|
||||||
{
|
{
|
||||||
# pragma EXPORT
|
# pragma EXPORT
|
||||||
|
|
||||||
Init();
|
Init();
|
||||||
WriteFormatted(STD_OUTPUT_HANDLE, L"%1!X!", WintunDeleteDriver());
|
if (Argc < 2)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
BOOL RebootRequired;
|
||||||
|
WINTUN_STATUS Ret = WintunDeletePoolDriver(Argv[2], &RebootRequired);
|
||||||
|
WriteFormatted(STD_OUTPUT_HANDLE, L"%1!X! %2!X!", Ret, RebootRequired);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
Done();
|
Done();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -306,11 +306,15 @@ cleanupArgv:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static WINTUN_STATUS
|
static WINTUN_STATUS
|
||||||
DeleteDriverViaRundll32()
|
DeletePoolDriverViaRundll32(_In_z_ WCHAR Pool[WINTUN_MAX_POOL], _Inout_ BOOL *RebootRequired)
|
||||||
{
|
{
|
||||||
LOG(WINTUN_LOG_INFO, L"Spawning native process");
|
LOG(WINTUN_LOG_INFO, L"Spawning native process");
|
||||||
WCHAR Response[8 + 1];
|
|
||||||
DWORD Result = ExecuteRunDll32(L"DeleteDriver", Response, _countof(Response));
|
WCHAR Arguments[17 + WINTUN_MAX_POOL + 1];
|
||||||
|
if (_snwprintf_s(Arguments, _countof(Arguments), _TRUNCATE, L"DeletePoolDriver %s", Pool) == -1)
|
||||||
|
return LOG(WINTUN_LOG_ERR, L"Command line too long"), ERROR_INVALID_PARAMETER;
|
||||||
|
WCHAR Response[8 + 1 + 8 + 1];
|
||||||
|
DWORD Result = ExecuteRunDll32(Arguments, Response, _countof(Response));
|
||||||
if (Result != ERROR_SUCCESS)
|
if (Result != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
LOG(WINTUN_LOG_ERR, L"Error executing worker process");
|
LOG(WINTUN_LOG_ERR, L"Error executing worker process");
|
||||||
@ -318,13 +322,15 @@ DeleteDriverViaRundll32()
|
|||||||
}
|
}
|
||||||
int Argc;
|
int Argc;
|
||||||
WCHAR **Argv = CommandLineToArgvW(Response, &Argc);
|
WCHAR **Argv = CommandLineToArgvW(Response, &Argc);
|
||||||
if (Argc < 1)
|
if (Argc < 2)
|
||||||
{
|
{
|
||||||
LOG(WINTUN_LOG_ERR, L"Incomplete or invalid response");
|
LOG(WINTUN_LOG_ERR, L"Incomplete or invalid response");
|
||||||
Result = ERROR_INVALID_PARAMETER;
|
Result = ERROR_INVALID_PARAMETER;
|
||||||
goto cleanupArgv;
|
goto cleanupArgv;
|
||||||
}
|
}
|
||||||
Result = wcstoul(Argv[0], NULL, 16);
|
Result = wcstoul(Argv[0], NULL, 16);
|
||||||
|
if (wcstoul(Argv[1], NULL, 16))
|
||||||
|
*RebootRequired = TRUE;
|
||||||
cleanupArgv:
|
cleanupArgv:
|
||||||
LocalFree(Argv);
|
LocalFree(Argv);
|
||||||
return Result;
|
return Result;
|
||||||
|
13
api/wintun.h
13
api/wintun.h
@ -33,7 +33,7 @@ typedef void *WINTUN_ADAPTER_HANDLE;
|
|||||||
* @param Name The requested name of the adapter. Zero-terminated string of up to MAX_ADAPTER_NAME-1
|
* @param Name The requested name of the adapter. Zero-terminated string of up to MAX_ADAPTER_NAME-1
|
||||||
* characters.
|
* characters.
|
||||||
*
|
*
|
||||||
* @param RequestedGUID The GUID of the created network adapter, which then influences NLA generation
|
* @param RequestedGUID The GUID of the created network adapter, which then influences NLA generation
|
||||||
* deterministically. If it is set to NULL, the GUID is chosen by the system at random, and hence
|
* deterministically. If it is set to NULL, the GUID is chosen by the system at random, and hence
|
||||||
* a new NLA entry is created for each new adapter. It is called "requested" GUID because the API
|
* a new NLA entry is created for each new adapter. It is called "requested" GUID because the API
|
||||||
* it uses is completely undocumented, and so there could be minor interesting complications with
|
* it uses is completely undocumented, and so there could be minor interesting complications with
|
||||||
@ -72,11 +72,18 @@ typedef WINTUN_STATUS(WINAPI *WINTUN_DELETE_ADAPTER_FUNC)(
|
|||||||
_Out_opt_ BOOL *RebootRequired);
|
_Out_opt_ BOOL *RebootRequired);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all Wintun drivers from the driver store
|
* Deletes all Wintun adapters in a pool and if there are no more adapters in any other pools, also removes Wintun
|
||||||
|
* from the driver store, usually called by uninstallers.
|
||||||
|
*
|
||||||
|
* @param Pool Name of the adapter pool. Zero-terminated string of up to WINTUN_MAX_POOL-1 characters.
|
||||||
|
*
|
||||||
|
* @param RebootRequired Optional pointer to a boolean flag to be set to TRUE in case SetupAPI suggests a reboot.
|
||||||
*
|
*
|
||||||
* @return ERROR_SUCCESS on success; Win32 error code otherwise.
|
* @return ERROR_SUCCESS on success; Win32 error code otherwise.
|
||||||
*/
|
*/
|
||||||
typedef WINTUN_STATUS(WINAPI *WINTUN_DELETE_DRIVER_FUNC)(void);
|
typedef WINTUN_STATUS(WINAPI *WINTUN_DELETE_POOL_DRIVER_FUNC)(
|
||||||
|
_In_z_ WCHAR Pool[WINTUN_MAX_POOL],
|
||||||
|
_Out_opt_ BOOL *RebootRequired);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by WintunEnumAdapters for each adapter in the pool.
|
* Called by WintunEnumAdapters for each adapter in the pool.
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
static WINTUN_CREATE_ADAPTER_FUNC WintunCreateAdapter;
|
static WINTUN_CREATE_ADAPTER_FUNC WintunCreateAdapter;
|
||||||
static WINTUN_DELETE_ADAPTER_FUNC WintunDeleteAdapter;
|
static WINTUN_DELETE_ADAPTER_FUNC WintunDeleteAdapter;
|
||||||
static WINTUN_DELETE_DRIVER_FUNC WintunDeleteDriver;
|
static WINTUN_DELETE_POOL_DRIVER_FUNC WintunDeletePoolDriver;
|
||||||
static WINTUN_ENUM_ADAPTERS_FUNC WintunEnumAdapters;
|
static WINTUN_ENUM_ADAPTERS_FUNC WintunEnumAdapters;
|
||||||
static WINTUN_FREE_ADAPTER_FUNC WintunFreeAdapter;
|
static WINTUN_FREE_ADAPTER_FUNC WintunFreeAdapter;
|
||||||
static WINTUN_GET_ADAPTER_FUNC WintunGetAdapter;
|
static WINTUN_GET_ADAPTER_FUNC WintunGetAdapter;
|
||||||
@ -258,8 +258,9 @@ InitializeWintun(void)
|
|||||||
return NULL;
|
return NULL;
|
||||||
#define X(Name, Type) ((Name = (Type)GetProcAddress(Wintun, #Name)) == NULL)
|
#define X(Name, Type) ((Name = (Type)GetProcAddress(Wintun, #Name)) == NULL)
|
||||||
if (X(WintunCreateAdapter, WINTUN_CREATE_ADAPTER_FUNC) || X(WintunDeleteAdapter, WINTUN_DELETE_ADAPTER_FUNC) ||
|
if (X(WintunCreateAdapter, WINTUN_CREATE_ADAPTER_FUNC) || X(WintunDeleteAdapter, WINTUN_DELETE_ADAPTER_FUNC) ||
|
||||||
X(WintunDeleteDriver, WINTUN_DELETE_DRIVER_FUNC) || X(WintunEnumAdapters, WINTUN_ENUM_ADAPTERS_FUNC) ||
|
X(WintunDeletePoolDriver, WINTUN_DELETE_POOL_DRIVER_FUNC) ||
|
||||||
X(WintunFreeAdapter, WINTUN_FREE_ADAPTER_FUNC) || X(WintunGetAdapter, WINTUN_GET_ADAPTER_FUNC) ||
|
X(WintunEnumAdapters, WINTUN_ENUM_ADAPTERS_FUNC) || X(WintunFreeAdapter, WINTUN_FREE_ADAPTER_FUNC) ||
|
||||||
|
X(WintunGetAdapter, WINTUN_GET_ADAPTER_FUNC) ||
|
||||||
X(WintunGetAdapterDeviceObject, WINTUN_GET_ADAPTER_DEVICE_OBJECT_FUNC) ||
|
X(WintunGetAdapterDeviceObject, WINTUN_GET_ADAPTER_DEVICE_OBJECT_FUNC) ||
|
||||||
X(WintunGetAdapterGUID, WINTUN_GET_ADAPTER_GUID_FUNC) ||
|
X(WintunGetAdapterGUID, WINTUN_GET_ADAPTER_GUID_FUNC) ||
|
||||||
X(WintunGetAdapterLUID, WINTUN_GET_ADAPTER_LUID_FUNC) ||
|
X(WintunGetAdapterLUID, WINTUN_GET_ADAPTER_LUID_FUNC) ||
|
||||||
@ -315,17 +316,14 @@ main(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
DWORD Version = WintunGetVersion();
|
DWORD Version = WintunGetVersion();
|
||||||
Log(WINTUN_LOG_INFO,
|
Log(WINTUN_LOG_INFO, L"Wintun v%u.%u loaded", (Version >> 16) & 0xff, (Version >> 0) & 0xff);
|
||||||
L"Wintun v%u.%u loaded",
|
|
||||||
(Version >> 16) & 0xff,
|
|
||||||
(Version >> 0) & 0xff);
|
|
||||||
|
|
||||||
MIB_UNICASTIPADDRESS_ROW AddressRow;
|
MIB_UNICASTIPADDRESS_ROW AddressRow;
|
||||||
InitializeUnicastIpAddressEntry(&AddressRow);
|
InitializeUnicastIpAddressEntry(&AddressRow);
|
||||||
WintunGetAdapterLUID(Adapter, &AddressRow.InterfaceLuid);
|
WintunGetAdapterLUID(Adapter, &AddressRow.InterfaceLuid);
|
||||||
AddressRow.Address.Ipv4.sin_family = AF_INET;
|
AddressRow.Address.Ipv4.sin_family = AF_INET;
|
||||||
AddressRow.Address.Ipv4.sin_addr.S_un.S_addr = htonl((10 << 24) | (6 << 16) | (7 << 8) | (7 << 0)); /* 10.6.7.7 */
|
AddressRow.Address.Ipv4.sin_addr.S_un.S_addr = htonl((10 << 24) | (6 << 16) | (7 << 8) | (7 << 0)); /* 10.6.7.7 */
|
||||||
AddressRow.OnLinkPrefixLength = 24; /* This is a /24 network */
|
AddressRow.OnLinkPrefixLength = 24; /* This is a /24 network */
|
||||||
Result = CreateUnicastIpAddressEntry(&AddressRow);
|
Result = CreateUnicastIpAddressEntry(&AddressRow);
|
||||||
if (Result != ERROR_SUCCESS)
|
if (Result != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user