diff options
| author | David Lönnhager <david.l@mullvad.net> | 2022-07-21 16:30:28 +0200 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2022-08-25 15:16:40 +0200 |
| commit | 29df2434c5e726574379860329eb123c2139dad6 (patch) | |
| tree | 34be2878dae0de5a5929d8eaa53f82cf89667fc1 | |
| parent | 91d8377262050012de75979e5c940cb6812f25ea (diff) | |
| download | mullvadvpn-29df2434c5e726574379860329eb123c2139dad6.tar.xz mullvadvpn-29df2434c5e726574379860329eb123c2139dad6.zip | |
Remove ST setup from installer and increase robustness of cleanup
Cleanup will now succeed in these cases:
1. There is no devnode, but the driver service exists.
2. There is no driver service, but there is a devnode.
3. The service exists but isn't running.
| -rw-r--r-- | dist-assets/windows/installer.nsh | 140 | ||||
| -rw-r--r-- | windows/driverlogic/driverlogic.vcxproj | 2 | ||||
| -rw-r--r-- | windows/driverlogic/driverlogic.vcxproj.filters | 2 | ||||
| -rw-r--r-- | windows/driverlogic/src/device.cpp | 170 | ||||
| -rw-r--r-- | windows/driverlogic/src/device.h | 7 | ||||
| -rw-r--r-- | windows/driverlogic/src/driverlogic.cpp | 115 | ||||
| -rw-r--r-- | windows/driverlogic/src/service.cpp | 93 | ||||
| -rw-r--r-- | windows/driverlogic/src/service.h | 2 | ||||
| -rw-r--r-- | windows/driverlogic/src/version.cpp | 125 | ||||
| -rw-r--r-- | windows/driverlogic/src/version.h | 30 |
10 files changed, 105 insertions, 581 deletions
diff --git a/dist-assets/windows/installer.nsh b/dist-assets/windows/installer.nsh index 7b1f552e2e..c02ade6ed5 100644 --- a/dist-assets/windows/installer.nsh +++ b/dist-assets/windows/installer.nsh @@ -23,10 +23,6 @@ # Return codes from driverlogic !define DL_GENERAL_SUCCESS 0 !define DL_GENERAL_ERROR 1 -!define DL_ST_DRIVER_NONE_INSTALLED 2 -!define DL_ST_DRIVER_SAME_VERSION_INSTALLED 3 -!define DL_ST_DRIVER_OLDER_VERSION_INSTALLED 4 -!define DL_ST_DRIVER_NEWER_VERSION_INSTALLED 5 # Log targets !define LOG_INSTALL 0 @@ -74,7 +70,6 @@ # The working directory cannot be deleted, so make sure it's set to $TEMP. SetOutPath "$TEMP" - RMDir /r "$TEMP\mullvad-split-tunnel" Delete "$TEMP\wintun.dll" Delete "$TEMP\mullvad-wireguard.dll" Delete "$TEMP\driverlogic.exe" @@ -88,6 +83,20 @@ !define CleanupTempFiles '!insertmacro "CleanupTempFiles"' # +# ExtractDriverlogic +# +# Extract device setup tools to $TEMP +# +!macro ExtractDriverlogic + + SetOutPath "$TEMP" + File "${BUILD_RESOURCES_DIR}\..\windows\driverlogic\bin\x64-$%CPP_BUILD_MODE%\driverlogic.exe" + +!macroend + +!define ExtractDriverlogic '!insertmacro "ExtractDriverlogic"' + +# # ExtractWireGuard # # Extract Wintun and WireGuardNT installer into $TEMP @@ -97,7 +106,6 @@ SetOutPath "$TEMP" File "${BUILD_RESOURCES_DIR}\binaries\x86_64-pc-windows-msvc\wintun\wintun.dll" File "${BUILD_RESOURCES_DIR}\binaries\x86_64-pc-windows-msvc\wireguard-nt\mullvad-wireguard.dll" - File "${BUILD_RESOURCES_DIR}\..\windows\driverlogic\bin\x64-$%CPP_BUILD_MODE%\driverlogic.exe" !macroend @@ -119,23 +127,6 @@ !define ExtractMullvadSetup '!insertmacro "ExtractMullvadSetup"' # -# ExtractSplitTunnelDriver -# -# Extract split tunnel driver and associated files into $TEMP\mullvad-split-tunnel -# -!macro ExtractSplitTunnelDriver - - SetOutPath "$TEMP\mullvad-split-tunnel" - File "${BUILD_RESOURCES_DIR}\binaries\x86_64-pc-windows-msvc\split-tunnel\mullvad-split-tunnel.cat" - File "${BUILD_RESOURCES_DIR}\binaries\x86_64-pc-windows-msvc\split-tunnel\mullvad-split-tunnel.inf" - File "${BUILD_RESOURCES_DIR}\binaries\x86_64-pc-windows-msvc\split-tunnel\mullvad-split-tunnel.sys" - File "${BUILD_RESOURCES_DIR}\..\windows\driverlogic\bin\x64-$%CPP_BUILD_MODE%\driverlogic.exe" - -!macroend - -!define ExtractSplitTunnelDriver '!insertmacro "ExtractSplitTunnelDriver"' - -# # RemoveWintun # # Try to remove Wintun @@ -314,97 +305,6 @@ !define InstallService '!insertmacro "InstallService"' # -# InstallSplitTunnelDriver -# -# Install split tunnel driver -# -# Returns: 0 in $R0 on success, otherwise an error message in $R0 -# -!macro InstallSplitTunnelDriver - - log::Log "InstallSplitTunnelDriver()" - - Push $0 - Push $1 - - log::Log "Searching for and evaluating already installed Split Tunneling driver" - nsExec::ExecToStack '"$TEMP\mullvad-split-tunnel\driverlogic.exe" st-evaluate "$TEMP\mullvad-split-tunnel\mullvad-split-tunnel.inf"' - - Pop $0 - Pop $1 - - ${If} $0 == ${DL_ST_DRIVER_NONE_INSTALLED} - log::Log "No currently installed Split Tunneling driver" - Goto InstallSplitTunnelDriver_new_install - ${OrIf} $0 == ${DL_ST_DRIVER_SAME_VERSION_INSTALLED} - log::Log "Up-to-date Split Tunneling driver already installed" - Goto InstallSplitTunnelDriver_success - ${OrIf} $0 == ${DL_ST_DRIVER_OLDER_VERSION_INSTALLED} - log::Log "An older version of the Split Tunneling driver is installed" - Goto InstallSplitTunnelDriver_force_install - ${OrIf} $0 == ${DL_ST_DRIVER_NEWER_VERSION_INSTALLED} - log::Log "A newer version of the Split Tunneling driver is installed" - Goto InstallSplitTunnelDriver_force_install - ${Else} - IntFmt $0 "0x%X" $0 - StrCpy $R0 "Failed to search for and evaluate driver: error $0" - log::LogWithDetails $R0 $1 - Goto InstallSplitTunnelDriver_return - ${EndIf} - - InstallSplitTunnelDriver_new_install: - - log::Log "Installing Split Tunneling driver" - nsExec::ExecToStack '"$TEMP\mullvad-split-tunnel\driverlogic.exe" st-new-install "$TEMP\mullvad-split-tunnel\mullvad-split-tunnel.inf"' - - Pop $0 - Pop $1 - - ${If} $0 != ${DL_GENERAL_SUCCESS} - IntFmt $0 "0x%X" $0 - StrCpy $R0 "Failed to install driver: error $0" - log::LogWithDetails $R0 $1 - Goto InstallSplitTunnelDriver_return - ${EndIf} - - Goto InstallSplitTunnelDriver_success - - InstallSplitTunnelDriver_force_install: - - # - # Would be possible to check driver state here and warn the user if driver is engaged. - # - - log::Log "Installing Split Tunneling driver" - nsExec::ExecToStack '"$TEMP\mullvad-split-tunnel\driverlogic.exe" st-force-install "$TEMP\mullvad-split-tunnel\mullvad-split-tunnel.inf"' - - Pop $0 - Pop $1 - - ${If} $0 != ${DL_GENERAL_SUCCESS} - IntFmt $0 "0x%X" $0 - StrCpy $R0 "Failed to install driver: error $0" - log::LogWithDetails $R0 $1 - Goto InstallSplitTunnelDriver_return - ${EndIf} - - InstallSplitTunnelDriver_success: - - log::Log "InstallSplitTunnelDriver() completed successfully" - - Push 0 - Pop $R0 - - InstallSplitTunnelDriver_return: - - Pop $1 - Pop $0 - -!macroend - -!define InstallSplitTunnelDriver '!insertmacro "InstallSplitTunnelDriver"' - -# # RemoveSplitTunnelDriver # # Reset and remove split tunnel driver @@ -417,7 +317,7 @@ Push $1 log::Log "Removing Split Tunneling driver" - nsExec::ExecToStack '"$TEMP\mullvad-split-tunnel\driverlogic.exe" st-remove' + nsExec::ExecToStack '"$TEMP\driverlogic.exe" st-remove' Pop $0 Pop $1 @@ -893,12 +793,9 @@ ${RemoveRelayCache} ${RemoveApiAddressCache} - SetOutPath "$TEMP" - File "${BUILD_RESOURCES_DIR}\..\windows\driverlogic\bin\x64-$%CPP_BUILD_MODE%\driverlogic.exe" + ${ExtractDriverlogic} ${RemoveAbandonedWintunAdapter} - - ${ExtractSplitTunnelDriver} - ${InstallSplitTunnelDriver} + ${RemoveSplitTunnelDriver} ${If} $R0 != 0 MessageBox MB_OK "$R0" @@ -1208,11 +1105,10 @@ ${ClearFirewallRules} ${RemoveCurrentDevice} + ${ExtractDriverlogic} ${ExtractWireGuard} ${RemoveWintun} ${RemoveWireGuardNt} - - ${ExtractSplitTunnelDriver} ${RemoveSplitTunnelDriver} log::SetLogTarget ${LOG_VOID} diff --git a/windows/driverlogic/driverlogic.vcxproj b/windows/driverlogic/driverlogic.vcxproj index cc46c1ac72..3172356a60 100644 --- a/windows/driverlogic/driverlogic.vcxproj +++ b/windows/driverlogic/driverlogic.vcxproj @@ -104,7 +104,6 @@ <ClCompile Include="src\service.cpp" /> <ClCompile Include="src\stdafx.cpp" /> <ClCompile Include="src\util.cpp" /> - <ClCompile Include="src\version.cpp" /> </ItemGroup> <ItemGroup> <ClInclude Include="src\devenum.h" /> @@ -115,7 +114,6 @@ <ClInclude Include="src\stdafx.h" /> <ClInclude Include="src\targetver.h" /> <ClInclude Include="src\util.h" /> - <ClInclude Include="src\version.h" /> <ClInclude Include="src\wintun.h" /> <ClInclude Include="src\wireguard.h" /> </ItemGroup> diff --git a/windows/driverlogic/driverlogic.vcxproj.filters b/windows/driverlogic/driverlogic.vcxproj.filters index 9665231376..bd73d30029 100644 --- a/windows/driverlogic/driverlogic.vcxproj.filters +++ b/windows/driverlogic/driverlogic.vcxproj.filters @@ -13,7 +13,6 @@ <ClCompile Include="src\device.cpp" /> <ClCompile Include="src\service.cpp" /> <ClCompile Include="src\log.cpp" /> - <ClCompile Include="src\version.cpp" /> <ClCompile Include="src\util.cpp" /> <ClCompile Include="src\devenum.cpp" /> </ItemGroup> @@ -24,7 +23,6 @@ <ClInclude Include="src\device.h" /> <ClInclude Include="src\service.h" /> <ClInclude Include="src\log.h" /> - <ClInclude Include="src\version.h" /> <ClInclude Include="src\util.h" /> <ClInclude Include="src\wintun.h" /> <ClInclude Include="src\devenum.h" /> diff --git a/windows/driverlogic/src/device.cpp b/windows/driverlogic/src/device.cpp index e38709f01d..71abb56266 100644 --- a/windows/driverlogic/src/device.cpp +++ b/windows/driverlogic/src/device.cpp @@ -38,47 +38,6 @@ constexpr SIZE_T ST_DRIVER_STATE_STARTED = 1; // Onwards. // -void -ThrowUpdateException -( - DWORD lastError, - const char *operation -) -{ - if (ERROR_DEVICE_INSTALLER_NOT_READY == lastError) - { - bool deviceInstallDisabled = false; - - try - { - const auto key = common::registry::Registry::OpenKey - ( - HKEY_LOCAL_MACHINE, - L"SYSTEM\\CurrentControlSet\\Services\\DeviceInstall\\Parameters" - ); - - deviceInstallDisabled = (0 != key->readUint32(L"DeviceInstallDisabled")); - } - catch (...) - { - } - - if (deviceInstallDisabled) - { - throw common::error::WindowsException - ( - "Device installs must be enabled to continue. " - "Enable them in the Local Group Policy editor, or " - "update the registry value DeviceInstallDisabled in " - "[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\DeviceInstall\\Parameters]", - lastError - ); - } - } - - THROW_SETUPAPI_ERROR(lastError, operation); -} - } // anonymous namespace std::wstring @@ -196,135 +155,6 @@ GetDeviceNetCfgInstanceId } void -CreateDevice -( - const GUID &classGuid, - const std::wstring &deviceName, - const std::wstring &deviceHardwareId -) -{ - Log(L"Attempting to create device"); - - const auto deviceInfoSet = SetupDiCreateDeviceInfoList(&classGuid, 0); - - if (INVALID_HANDLE_VALUE == deviceInfoSet) - { - THROW_SETUPAPI_ERROR(GetLastError(), "SetupDiCreateDeviceInfoList"); - } - - common::memory::ScopeDestructor scopeDestructor; - - scopeDestructor += [&deviceInfoSet]() - { - SetupDiDestroyDeviceInfoList(deviceInfoSet); - }; - - SP_DEVINFO_DATA devInfoData {0}; - devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); - - auto status = SetupDiCreateDeviceInfoW - ( - deviceInfoSet, - deviceName.c_str(), - &classGuid, - nullptr, - 0, - DICD_GENERATE_ID, - &devInfoData - ); - - if (FALSE == status) - { - THROW_SETUPAPI_ERROR(GetLastError(), "SetupDiCreateDeviceInfoW"); - } - - status = SetupDiSetDeviceRegistryPropertyW - ( - deviceInfoSet, - &devInfoData, - SPDRP_HARDWAREID, - reinterpret_cast<const BYTE *>(deviceHardwareId.c_str()), - static_cast<DWORD>(deviceHardwareId.size() * sizeof(wchar_t)) - ); - - if (FALSE == status) - { - THROW_SETUPAPI_ERROR(GetLastError(), "SetupDiSetDeviceRegistryPropertyW"); - } - - // - // Create a devnode in the PnP HW tree - // - status = SetupDiCallClassInstaller - ( - DIF_REGISTERDEVICE, - deviceInfoSet, - &devInfoData - ); - - if (FALSE == status) - { - THROW_SETUPAPI_ERROR(GetLastError(), "SetupDiCallClassInstaller"); - } - - Log(L"Created new device successfully"); -} - -void -InstallDriverForDevice -( - const std::wstring &deviceHardwareId, - const std::wstring &infPath -) -{ - Log(L"Attempting to install new driver"); - - DWORD installFlags = 0; - BOOL rebootRequired = FALSE; - - for (;;) - { - auto result = UpdateDriverForPlugAndPlayDevicesW - ( - nullptr, - deviceHardwareId.c_str(), - infPath.c_str(), - installFlags, - &rebootRequired - ); - - if (FALSE != result) - { - break; - } - - const auto lastError = GetLastError(); - - if (ERROR_NO_MORE_ITEMS == lastError - && (0 == (installFlags & INSTALLFLAG_FORCE))) - { - Log(L"Driver installation/update failed. Attempting forced install."); - installFlags |= INSTALLFLAG_FORCE; - - continue; - } - - ThrowUpdateException(lastError, "UpdateDriverForPlugAndPlayDevicesW"); - } - - // - // Driver successfully installed or updated - // - - std::wstringstream ss; - - ss << L"Device driver update complete. Reboot required: " - << rebootRequired; - - Log(ss.str()); -} - -void UninstallDevice ( const EnumeratedDevice &device diff --git a/windows/driverlogic/src/device.h b/windows/driverlogic/src/device.h index b8bc0e7f41..4dc8c4500d 100644 --- a/windows/driverlogic/src/device.h +++ b/windows/driverlogic/src/device.h @@ -39,13 +39,6 @@ CreateDevice ); void -InstallDriverForDevice -( - const std::wstring &deviceHardwareId, - const std::wstring &infPath -); - -void UninstallDevice ( const EnumeratedDevice &device diff --git a/windows/driverlogic/src/driverlogic.cpp b/windows/driverlogic/src/driverlogic.cpp index 2fdcc3046c..895272fa4f 100644 --- a/windows/driverlogic/src/driverlogic.cpp +++ b/windows/driverlogic/src/driverlogic.cpp @@ -3,7 +3,6 @@ #include "device.h" #include "service.h" #include "log.h" -#include "version.h" #include "wintun.h" #include "wireguard.h" #include "devenum.h" @@ -20,8 +19,6 @@ namespace { -constexpr wchar_t SPLIT_TUNNEL_HARDWARE_ID[] = L"Root\\mullvad-split-tunnel"; - DEFINE_GUID(WFP_CALLOUTS_CLASS_ID, 0x57465043, 0x616C, 0x6C6F, 0x75, 0x74, 0x5F, 0x63, 0x6C, 0x61, 0x73, 0x73); @@ -30,11 +27,7 @@ constexpr wchar_t SPLIT_TUNNEL_DEVICE_NAME[] = L"Mullvad Split Tunnel Device"; enum ReturnCode { GENERAL_SUCCESS = 0, - GENERAL_ERROR = 1, - ST_DRIVER_NONE_INSTALLED = 2, - ST_DRIVER_SAME_VERSION_INSTALLED = 3, - ST_DRIVER_OLDER_VERSION_INSTALLED = 4, - ST_DRIVER_NEWER_VERSION_INSTALLED = 5 + GENERAL_ERROR = 1 }; class ArgumentContext @@ -105,74 +98,6 @@ std::unique_ptr<DeviceEnumerator> CreateSplitTunnelDeviceEnumerator() } // -// CommandSplitTunnelEvaluate() -// -// Search for existing device. -// Evaluate if provided inf can/should be installed. -// -ReturnCode CommandSplitTunnelEvaluate(const std::vector<std::wstring> &args) -{ - ArgumentContext argsContext(args); - - argsContext.ensureExactArgumentCount(1); - - const auto infPath = argsContext.next(); - - // - // Find first matching device - // - - auto enumerator = CreateSplitTunnelDeviceEnumerator(); - - EnumeratedDevice device; - - if (!enumerator->next(device)) - { - return ReturnCode::ST_DRIVER_NONE_INSTALLED; - } - - // - // Retrieve driver versions - // - - auto existingVersion = GetDriverVersion(device); - auto proposedVersion = InfGetDriverVersion(infPath); - - // - // Compare driver versions - // - - switch (EvaluateDriverUpgrade(existingVersion, proposedVersion)) - { - case DRIVER_UPGRADE_STATUS::WOULD_UPGRADE: - return ReturnCode::ST_DRIVER_OLDER_VERSION_INSTALLED; - case DRIVER_UPGRADE_STATUS::WOULD_DOWNGRADE: - return ReturnCode::ST_DRIVER_NEWER_VERSION_INSTALLED; - case DRIVER_UPGRADE_STATUS::WOULD_INSTALL_SAME_VERSION: - return ReturnCode::ST_DRIVER_SAME_VERSION_INSTALLED; - default: - Log(L"Unexpected return value from EvaluateDriverUpgrade()"); - } - - return ReturnCode::GENERAL_ERROR; -} - -ReturnCode CommandSplitTunnelNewInstall(const std::vector<std::wstring> &args) -{ - ArgumentContext argsContext(args); - - argsContext.ensureExactArgumentCount(1); - - const auto infPath = argsContext.next(); - - CreateDevice(WFP_CALLOUTS_CLASS_ID, SPLIT_TUNNEL_DEVICE_NAME, SPLIT_TUNNEL_HARDWARE_ID); - - InstallDriverForDevice(SPLIT_TUNNEL_HARDWARE_ID, infPath); - - return ReturnCode::GENERAL_SUCCESS; -} - -// // CommandSplitTunnelRemove() // // Reset driver @@ -186,48 +111,29 @@ ReturnCode CommandSplitTunnelRemove(const std::vector<std::wstring> &args) argsContext.ensureExactArgumentCount(0); + if (ServiceIsRunning(L"mullvad-split-tunnel")) + { + ResetDriverState(); + } + // - // Find first matching device + // Uninstall device, if it exists // auto enumerator = CreateSplitTunnelDeviceEnumerator(); EnumeratedDevice device; - if (!enumerator->next(device)) + if (enumerator->next(device)) { - Log(L"Could not find split tunnel device"); - - return ReturnCode::GENERAL_SUCCESS; + UninstallDevice(device); } - ResetDriverState(); - - UninstallDevice(device); - PokeService(L"mullvad-split-tunnel", true, true); return ReturnCode::GENERAL_SUCCESS; } -// -// CommandSplitTunnelForceInstall() -// -// There's an existing device that needs to be stopped and removed. -// After this, create a new device and associate the specified inf. -// -ReturnCode CommandSplitTunnelForceInstall(const std::vector<std::wstring> &args) -{ - auto status = CommandSplitTunnelRemove({}); - - if (ReturnCode::GENERAL_SUCCESS != status) - { - return status; - } - - return CommandSplitTunnelNewInstall(args); -} - ReturnCode CommandWintunDeleteDriver(const std::vector<std::wstring> &args) { ArgumentContext argsContext(args); @@ -336,9 +242,6 @@ int wmain(int argc, const wchar_t *argv[]) std::vector<CommandHandler> handlers = { - { L"st-evaluate", CommandSplitTunnelEvaluate }, - { L"st-new-install", CommandSplitTunnelNewInstall }, - { L"st-force-install", CommandSplitTunnelForceInstall }, { L"st-remove", CommandSplitTunnelRemove }, { L"wintun-delete-driver", CommandWintunDeleteDriver }, { L"wintun-delete-abandoned-device", CommandWintunDeleteAbandonedDevice }, diff --git a/windows/driverlogic/src/service.cpp b/windows/driverlogic/src/service.cpp index 14ed7880fa..f1daa1abfb 100644 --- a/windows/driverlogic/src/service.cpp +++ b/windows/driverlogic/src/service.cpp @@ -43,29 +43,46 @@ private: TTime m_maxWaitTime; }; +SERVICE_STATUS_PROCESS GetServiceProcessStatus(SC_HANDLE service) +{ + SERVICE_STATUS_PROCESS ssp; + + DWORD bytesNeeded; + + auto status = QueryServiceStatusEx + ( + service, + SC_STATUS_PROCESS_INFO, + reinterpret_cast<BYTE*>(&ssp), + sizeof(ssp), + &bytesNeeded + ); + + if (status != 0) + { + return ssp; + } + + THROW_WINDOWS_ERROR(GetLastError(), "QueryServiceStatusEx"); +} + void WaitUntilServiceStopped(SC_HANDLE service, DWORD maxWaitMs) { TimeBox timer(maxWaitMs); for (;;) { - SERVICE_STATUS_PROCESS ssp; - - DWORD bytesNeeded; - - auto status = QueryServiceStatusEx - ( - service, - SC_STATUS_PROCESS_INFO, - reinterpret_cast<BYTE*>(&ssp), - sizeof(ssp), - &bytesNeeded - ); + try + { + const auto status = GetServiceProcessStatus(service); - if (status != 0 - && ssp.dwCurrentState == SERVICE_STOPPED) + if (status.dwCurrentState == SERVICE_STOPPED) + { + return; + } + } + catch (...) { - return; } if (timer.expired()) @@ -77,6 +94,41 @@ void WaitUntilServiceStopped(SC_HANDLE service, DWORD maxWaitMs) } } +bool ServiceIsRunning(const std::wstring &serviceName) +{ + const auto serviceManager = OpenSCManagerW(nullptr, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS); + + if (serviceManager == NULL) + { + THROW_WINDOWS_ERROR(GetLastError(), "OpenSCManagerW"); + } + + common::memory::ScopeDestructor dtor; + + dtor += [serviceManager]() + { + CloseServiceHandle(serviceManager); + }; + + const auto service = OpenServiceW(serviceManager, serviceName.c_str(), SERVICE_ALL_ACCESS); + + if (service == NULL) + { + const auto error = GetLastError(); + + if (error != ERROR_SERVICE_DOES_NOT_EXIST) + { + THROW_WINDOWS_ERROR(error, "OpenServiceW"); + } + + return false; + } + + CloseServiceHandle(service); + + return GetServiceProcessStatus(service).dwCurrentState == SERVICE_RUNNING; +} + void PokeService(const std::wstring &serviceName, bool stopService, bool deleteService) { auto serviceManager = OpenSCManagerW(nullptr, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS); @@ -97,7 +149,16 @@ void PokeService(const std::wstring &serviceName, bool stopService, bool deleteS if (service == NULL) { - THROW_WINDOWS_ERROR(GetLastError(), "OpenServiceW"); + const auto error = GetLastError(); + + if (error != ERROR_SERVICE_DOES_NOT_EXIST) + { + THROW_WINDOWS_ERROR(error, "OpenServiceW"); + } + + // If the service does not exist, we're done. + + return; } dtor += [service]() diff --git a/windows/driverlogic/src/service.h b/windows/driverlogic/src/service.h index 87632faf1b..423d16c0f0 100644 --- a/windows/driverlogic/src/service.h +++ b/windows/driverlogic/src/service.h @@ -2,6 +2,6 @@ #include <windows.h> -void WaitUntilServiceStopped(SC_HANDLE service, DWORD maxWaitMs); +bool ServiceIsRunning(const std::wstring &serviceName); void PokeService(const std::wstring &serviceName, bool stopService, bool deleteService); diff --git a/windows/driverlogic/src/version.cpp b/windows/driverlogic/src/version.cpp deleted file mode 100644 index d7394e224b..0000000000 --- a/windows/driverlogic/src/version.cpp +++ /dev/null @@ -1,125 +0,0 @@ -#include "stdafx.h" -#include "version.h" -#include "device.h" -#include <setupapi.h> -#include <initguid.h> -#include <devpkey.h> -#include <libcommon/string.h> -#include <libcommon/memory.h> -#include <stdexcept> - -DRIVER_UPGRADE_STATUS -EvaluateDriverUpgrade -( - const std::wstring &existingVersion, - const std::wstring &proposedVersion -) -{ - // - // "x.y.z.a" - // - - using namespace common::string; - - auto et = Tokenize(existingVersion, L"."); - auto pt = Tokenize(proposedVersion, L"."); - - auto items = min(et.size(), pt.size()); - - for (auto index = 0; index < items; ++index) - { - auto ev = wcstoul(et[index].c_str(), nullptr, 10); - auto pv = wcstoul(pt[index].c_str(), nullptr, 10); - - if (pv > ev) - { - return DRIVER_UPGRADE_STATUS::WOULD_UPGRADE; - } - - if (ev > pv) - { - return DRIVER_UPGRADE_STATUS::WOULD_DOWNGRADE; - } - } - - if (pt.size() > et.size()) - { - return DRIVER_UPGRADE_STATUS::WOULD_UPGRADE; - } - - if (et.size() > pt.size()) - { - return DRIVER_UPGRADE_STATUS::WOULD_DOWNGRADE; - } - - return DRIVER_UPGRADE_STATUS::WOULD_INSTALL_SAME_VERSION; -} - -std::wstring -InfGetDriverVersion -( - const std::wstring &filePath -) -{ - auto infHandle = SetupOpenInfFileW(filePath.c_str(), nullptr, INF_STYLE_WIN4, nullptr); - - if (infHandle == INVALID_HANDLE_VALUE) - { - throw std::runtime_error("SetupOpenInfFileW()"); - } - - common::memory::ScopeDestructor dtor; - - dtor += [infHandle]() - { - SetupCloseInfFile(infHandle); - }; - - INFCONTEXT infContext { 0 }; - - auto status = SetupFindFirstLineW(infHandle, L"Version", L"DriverVer", &infContext); - - if (status == FALSE) - { - throw std::runtime_error("SetupFindFirstLineW()"); - } - - DWORD requiredSize; - - // - // This is a multi-value key. - // 0 = key, 1 = driver date - // - const DWORD VersionFieldIndex = 2; - - status = SetupGetStringFieldW(&infContext, VersionFieldIndex, nullptr, 0, &requiredSize); - - if (status == FALSE || requiredSize < 2) - { - throw std::runtime_error("SetupGetStringFieldW()"); - } - - std::vector<wchar_t> buffer(requiredSize); - - status = SetupGetStringFieldW(&infContext, VersionFieldIndex, - &buffer[0], static_cast<DWORD>(buffer.size()), nullptr); - - if (status == FALSE) - { - throw std::runtime_error("SetupGetStringFieldW()"); - } - - // Remove null terminator. - buffer.resize(requiredSize - 1); - - return buffer.data(); -} - -std::wstring -GetDriverVersion -( - const EnumeratedDevice &device -) -{ - return GetDeviceStringProperty(device.deviceInfoSet, device.deviceInfo, &DEVPKEY_Device_DriverVersion); -} diff --git a/windows/driverlogic/src/version.h b/windows/driverlogic/src/version.h deleted file mode 100644 index fc88b3b232..0000000000 --- a/windows/driverlogic/src/version.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include <string> -#include "device.h" - -enum class DRIVER_UPGRADE_STATUS -{ - WOULD_DOWNGRADE, - WOULD_INSTALL_SAME_VERSION, - WOULD_UPGRADE -}; - -DRIVER_UPGRADE_STATUS -EvaluateDriverUpgrade -( - const std::wstring &existingVersion, - const std::wstring &proposedVersion -); - -std::wstring -InfGetDriverVersion -( - const std::wstring &filePath -); - -std::wstring -GetDriverVersion -( - const EnumeratedDevice &device -); |
