UI: Fix service stopping on uninstall with "Disable Service controls" option

This commit is contained in:
Nodir Temirkhodjaev 2023-03-11 12:11:27 +03:00
parent a3f1b1a86c
commit dac55059b5
4 changed files with 32 additions and 15 deletions

View File

@ -174,7 +174,7 @@ begin
if Form.ShowModal() = mrOk then if Form.ShowModal() = mrOk then
begin begin
Result := GetSHA1OfString(PwdEdit.Text); Result := PwdEdit.Text;
end; end;
finally finally
Form.Free(); Form.Free();
@ -194,7 +194,7 @@ begin
Exit; Exit;
end; end;
if AskPassword() <> passwordHash then if GetSHA1OfString(AskPassword()) <> passwordHash then
begin begin
SuppressibleMsgBox('Wrong password', mbError, MB_OK, IDOK); SuppressibleMsgBox('Wrong password', mbError, MB_OK, IDOK);
@ -218,16 +218,17 @@ begin
Result := CheckPasswordHash(); Result := CheckPasswordHash();
end; end;
function InitializeUninstall(): Boolean;
begin
Result := CheckPasswordHash();
end;
function PrepareToInstall(var NeedsRestart: Boolean): String; function PrepareToInstall(var NeedsRestart: Boolean): String;
var var
ResultCode: Integer; ResultCode: Integer;
begin begin
if Exec('sc.exe', ExpandConstant('stop {#APP_SVC_NAME}'), '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then if Exec('sc.exe', ExpandConstant('stop {#APP_SVC_NAME}'), '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then
if ResultCode = 0 then Sleep(100); // Let the service to stop if ResultCode = 0 then Sleep(100); // Let the service to stop
Result := ''; Result := '';
end; end;
function InitializeUninstall(): Boolean;
begin
Result := CheckPasswordHash();
end;

View File

@ -97,6 +97,7 @@ void ServiceManager::processControl(quint32 code)
break; break;
Q_FALLTHROUGH(); Q_FALLTHROUGH();
case FORT_SERVICE_CONTROL_UNINSTALL:
case SERVICE_CONTROL_SHUTDOWN: { case SERVICE_CONTROL_SHUTDOWN: {
qCDebug(LC) << "Quit due service control"; qCDebug(LC) << "Quit due service control";

View File

@ -3,6 +3,8 @@
#include <QObject> #include <QObject>
#define FORT_SERVICE_CONTROL_UNINSTALL 128
class ServiceManagerIface class ServiceManagerIface
{ {
public: public:

View File

@ -11,6 +11,7 @@
#include "fileutil.h" #include "fileutil.h"
#include "regkey.h" #include "regkey.h"
#include "service/servicemanageriface.h"
namespace { namespace {
@ -134,6 +135,24 @@ bool installService(const wchar_t *serviceName, const wchar_t *serviceDisplay,
return res; return res;
} }
void stopService(SC_HANDLE svc)
{
int n = 3; /* count of attempts to stop the service */
do {
SERVICE_STATUS status;
if (QueryServiceStatus(svc, &status) && status.dwCurrentState == SERVICE_STOPPED)
break;
const DWORD controlCode = (status.dwControlsAccepted & SERVICE_ACCEPT_STOP) != 0
? SERVICE_CONTROL_STOP
: FORT_SERVICE_CONTROL_UNINSTALL;
ControlService(svc, controlCode, &status);
QThread::msleep(n * 100);
} while (--n > 0);
}
bool uninstallService(const wchar_t *serviceName) bool uninstallService(const wchar_t *serviceName)
{ {
bool res = false; bool res = false;
@ -141,14 +160,8 @@ bool uninstallService(const wchar_t *serviceName)
if (mngr) { if (mngr) {
const SC_HANDLE svc = OpenServiceW(mngr, serviceName, SERVICE_ALL_ACCESS | DELETE); const SC_HANDLE svc = OpenServiceW(mngr, serviceName, SERVICE_ALL_ACCESS | DELETE);
if (svc) { if (svc) {
int n = 3; /* count of attempts to stop the service */ stopService(svc);
do {
SERVICE_STATUS status;
if (QueryServiceStatus(svc, &status) && status.dwCurrentState == SERVICE_STOPPED)
break;
ControlService(svc, SERVICE_CONTROL_STOP, &status);
QThread::msleep(n * 100);
} while (--n > 0);
res = DeleteService(svc); res = DeleteService(svc);
CloseServiceHandle(svc); CloseServiceHandle(svc);
} }