[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

@ -1228,7 +1228,9 @@ RControlService(
}
/* Send control code to the service */
dwError = ScmControlService(lpService,
dwError = ScmControlService(lpService->lpImage->hControlPipe,
lpService->lpServiceName,
(SERVICE_STATUS_HANDLE)lpService,
dwControl);
/* Return service status information */
@ -1725,6 +1727,28 @@ RSetServiceStatus(
/* Restore the previous service type */
lpService->Status.dwServiceType = dwPreviousType;
/* Handle a stopped service */
if ((lpServiceStatus->dwServiceType & SERVICE_WIN32) &&
(lpServiceStatus->dwCurrentState == SERVICE_STOPPED))
{
/* Decrement the image run counter */
lpService->lpImage->dwImageRunCount--;
/* If we just stopped the last running service... */
if (lpService->lpImage->dwImageRunCount == 0)
{
/* Stop the dispatcher thread */
ScmControlService(lpService->lpImage->hControlPipe,
L"",
(SERVICE_STATUS_HANDLE)lpService,
SERVICE_CONTROL_STOP);
/* Remove the service image */
ScmRemoveServiceImage(lpService->lpImage);
lpService->lpImage = NULL;
}
}
/* Unlock the service database */
ScmUnlockDatabase();
@ -1773,6 +1797,8 @@ RSetServiceStatus(
lpLogStrings);
}
DPRINT("Set %S to %lu\n", lpService->lpDisplayName, lpService->Status.dwCurrentState);
DPRINT("RSetServiceStatus() done\n");