[host] Windows: service (un)install now starts/stops the service

In addition to starting and stopping the service, it now also stops the
LG process if the service started it.
This commit is contained in:
Geoffrey McRae 2020-08-12 20:54:20 +10:00
parent 431ae3fc55
commit 64fdb8b7bb

View File

@ -40,6 +40,8 @@ Place, Suite 330, Boston, MA 02111-1307 USA
struct Service struct Service
{ {
FILE * logFile; FILE * logFile;
bool running;
DWORD processId;
}; };
struct Service service = { 0 }; struct Service service = { 0 };
@ -294,11 +296,15 @@ void Launch()
&pi &pi
)) ))
{ {
service.running = false;
doLog("failed to launch\n"); doLog("failed to launch\n");
winerr(); winerr();
goto fail_exe; goto fail_exe;
} }
service.processId = pi.dwProcessId;
service.running = true;
fail_exe: fail_exe:
free(exe); free(exe);
@ -387,6 +393,46 @@ void Install()
else else
doLog("Service installed successfully\n"); doLog("Service installed successfully\n");
// Start the service
doLog("Starting the service\n");
StartService(schService, 0, NULL);
SERVICE_STATUS_PROCESS ssp;
DWORD dwBytesNeeded;
if (!QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO,
(LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded))
{
doLog("QueryServiceStatusEx failed (0x%lx)\n", GetLastError());
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return;
}
while (ssp.dwCurrentState == SERVICE_START_PENDING)
{
DWORD dwWaitTime = ssp.dwWaitHint / 10;
if(dwWaitTime < 1000)
dwWaitTime = 1000;
else if (dwWaitTime > 10000)
dwWaitTime = 10000;
Sleep(dwWaitTime);
if (!QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO,
(LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded))
{
doLog("QueryServiceStatusEx failed (0x%lx)\n", GetLastError());
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return;
}
}
if (ssp.dwCurrentState != SERVICE_RUNNING)
doLog("Failed to start the service.\n");
else
doLog("Service started.\n");
CloseServiceHandle(schService); CloseServiceHandle(schService);
CloseServiceHandle(schSCManager); CloseServiceHandle(schSCManager);
} }
@ -407,7 +453,9 @@ void Uninstall()
return; return;
} }
schService = OpenService(schSCManager, SVCNAME, DELETE); schService = OpenService(schSCManager, SVCNAME,
SERVICE_STOP | SERVICE_QUERY_STATUS | DELETE);
if (!schService) if (!schService)
{ {
doLog("OpenService failed (0x%lx)\n", GetLastError()); doLog("OpenService failed (0x%lx)\n", GetLastError());
@ -415,21 +463,74 @@ void Uninstall()
return; return;
} }
SERVICE_STATUS status; SERVICE_STATUS_PROCESS ssp;
if (ControlService(schService, SERVICE_CONTROL_STOP, &status)) DWORD dwBytesNeeded;
while(status.dwCurrentState != SERVICE_STOPPED) if (!QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO,
{ (LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded))
Sleep(1);
QueryServiceStatus(schService, &status);
}
if (!DeleteService(schService))
{ {
doLog("DeleteService failed (0x%lx)\n", GetLastError()); doLog("QueryServiceStatusEx failed (0x%lx)\n", GetLastError());
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager); CloseServiceHandle(schSCManager);
return; return;
} }
bool stop = false;
if (ssp.dwCurrentState == SERVICE_RUNNING)
{
stop = true;
doLog("Stopping the service...\n");
SERVICE_STATUS status;
if (!ControlService(schService, SERVICE_CONTROL_STOP, &status))
{
doLog("ControlService failed (%0xlx)\n", GetLastError());
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return;
}
ssp.dwCurrentState = SERVICE_STOP_PENDING;
}
while(ssp.dwCurrentState == SERVICE_STOP_PENDING)
{
DWORD dwWaitTime = ssp.dwWaitHint / 10;
if(dwWaitTime < 1000)
dwWaitTime = 1000;
else if (dwWaitTime > 10000)
dwWaitTime = 10000;
Sleep(dwWaitTime);
if (!QueryServiceStatusEx(schService, SC_STATUS_PROCESS_INFO,
(LPBYTE)&ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded))
{
doLog("QueryServiceStatusEx failed (0x%lx)\n", GetLastError());
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return;
}
}
if (ssp.dwCurrentState != SERVICE_STOPPED)
{
doLog("Failed to stop the service");
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return;
}
if (stop)
doLog("Service stopped.\n");
if (!DeleteService(schService))
{
doLog("DeleteService failed (0x%lx)\n", GetLastError());
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return;
}
doLog("Service removed.\n");
CloseServiceHandle(schService); CloseServiceHandle(schService);
CloseServiceHandle(schSCManager); CloseServiceHandle(schSCManager);
} }
@ -506,6 +607,7 @@ VOID WINAPI SvcMain(DWORD dwArgc, LPTSTR *lpszArgv)
if (WaitForSingleObject(m, 0) == WAIT_OBJECT_0) if (WaitForSingleObject(m, 0) == WAIT_OBJECT_0)
{ {
running = false; running = false;
service.running = false;
ReleaseMutex(m); ReleaseMutex(m);
} }
CloseHandle(m); CloseHandle(m);
@ -521,6 +623,28 @@ VOID WINAPI SvcMain(DWORD dwArgc, LPTSTR *lpszArgv)
break; break;
} }
if (service.running)
{
doLog("Terminating the host application\n");
HANDLE proc = OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE, TRUE,
service.processId);
if (proc)
{
if (TerminateProcess(proc, 0))
{
while(WaitForSingleObject(proc, INFINITE) != WAIT_OBJECT_0) {}
doLog("Host application terminated\n");
}
else
doLog("Failed to terminate the host application\n");
CloseHandle(proc);
}
else
{
doLog("OpenProcess failed (%0xlx)\n", GetLastError());
}
}
ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0); ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
CloseHandle(ghSvcStopEvent); CloseHandle(ghSvcStopEvent);
finishLogging(); finishLogging();