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 /windows/driverlogic/src/service.cpp | |
| 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.
Diffstat (limited to 'windows/driverlogic/src/service.cpp')
| -rw-r--r-- | windows/driverlogic/src/service.cpp | 93 |
1 files changed, 77 insertions, 16 deletions
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]() |
