[SERVICES][ADVAPI32] Fix the broken service stop sequence

services\database.c:
- Refactor ScmControlService() so that it can be used to send the dispatcher loop stop command.
- Separate the code to decrement the image run counter from the service image cleanup code.

services\rpcserver.c:
- RSetServiceStatus(): Stop the dispatcher loop when the image run counter is zero and remove the service image after that.

advapi32\service\sctrl.c:
- Do not terminate the service dispatcher loop when the last service is being stopped. Wait for an explicit dispatcher stop command (empty service name).

CORE-12413
This commit is contained in:
Eric Kohl 2018-02-24 11:14:05 +01:00
parent b6c060ce04
commit 1dfbed9c3d
4 changed files with 121 additions and 87 deletions

View file

@ -544,7 +544,7 @@ ScServiceDispatcher(HANDLE hPipe,
{
DWORD Count;
BOOL bResult;
DWORD dwRunningServices = 0;
BOOL bRunning = TRUE;
LPWSTR lpServiceName;
PACTIVE_SERVICE lpService;
SCM_REPLY_PACKET ReplyPacket;
@ -555,7 +555,7 @@ ScServiceDispatcher(HANDLE hPipe,
if (ControlPacket == NULL || dwBufferSize < sizeof(SCM_CONTROL_PACKET))
return FALSE;
while (TRUE)
while (bRunning)
{
/* Read command from the control pipe */
bResult = ReadFile(hPipe,
@ -572,39 +572,44 @@ ScServiceDispatcher(HANDLE hPipe,
lpServiceName = (LPWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset);
TRACE("Service: %S\n", lpServiceName);
if (ControlPacket->dwControl == SERVICE_CONTROL_START_OWN)
lpActiveServices[0].bOwnProcess = TRUE;
lpService = ScLookupServiceByServiceName(lpServiceName);
if (lpService != NULL)
if (lpServiceName[0] == UNICODE_NULL)
{
/* Execute command */
switch (ControlPacket->dwControl)
{
case SERVICE_CONTROL_START_SHARE:
case SERVICE_CONTROL_START_OWN:
TRACE("Start command - received SERVICE_CONTROL_START\n");
dwError = ScStartService(lpService, ControlPacket);
if (dwError == ERROR_SUCCESS)
dwRunningServices++;
break;
case SERVICE_CONTROL_STOP:
TRACE("Stop command - received SERVICE_CONTROL_STOP\n");
dwError = ScControlService(lpService, ControlPacket);
if (dwError == ERROR_SUCCESS)
dwRunningServices--;
break;
default:
TRACE("Command %lu received", ControlPacket->dwControl);
dwError = ScControlService(lpService, ControlPacket);
break;
}
ERR("Stop dispatcher thread\n");
bRunning = FALSE;
dwError = ERROR_SUCCESS;
}
else
{
dwError = ERROR_SERVICE_DOES_NOT_EXIST;
if (ControlPacket->dwControl == SERVICE_CONTROL_START_OWN)
lpActiveServices[0].bOwnProcess = TRUE;
lpService = ScLookupServiceByServiceName(lpServiceName);
if (lpService != NULL)
{
/* Execute command */
switch (ControlPacket->dwControl)
{
case SERVICE_CONTROL_START_SHARE:
case SERVICE_CONTROL_START_OWN:
TRACE("Start command - received SERVICE_CONTROL_START\n");
dwError = ScStartService(lpService, ControlPacket);
break;
case SERVICE_CONTROL_STOP:
TRACE("Stop command - received SERVICE_CONTROL_STOP\n");
dwError = ScControlService(lpService, ControlPacket);
break;
default:
TRACE("Command %lu received", ControlPacket->dwControl);
dwError = ScControlService(lpService, ControlPacket);
break;
}
}
else
{
dwError = ERROR_SERVICE_DOES_NOT_EXIST;
}
}
ReplyPacket.dwError = dwError;
@ -620,9 +625,6 @@ ScServiceDispatcher(HANDLE hPipe,
ERR("Pipe write failed (Error: %lu)\n", GetLastError());
return FALSE;
}
if (dwRunningServices == 0)
break;
}
return TRUE;