}
-static VOID
-ScmDereferenceServiceImage(PSERVICE_IMAGE pServiceImage)
+VOID
+ScmRemoveServiceImage(PSERVICE_IMAGE pServiceImage)
{
- DPRINT1("ScmDereferenceServiceImage() called\n");
-
- pServiceImage->dwImageRunCount--;
-
- if (pServiceImage->dwImageRunCount == 0)
- {
- DPRINT1("dwImageRunCount == 0\n");
+ DPRINT1("ScmRemoveServiceImage() called\n");
- /* FIXME: Terminate the process */
+ /* FIXME: Terminate the process */
- /* Remove the service image from the list */
- RemoveEntryList(&pServiceImage->ImageListEntry);
+ /* Remove the service image from the list */
+ RemoveEntryList(&pServiceImage->ImageListEntry);
- /* Close the process handle */
- if (pServiceImage->hProcess != INVALID_HANDLE_VALUE)
- CloseHandle(pServiceImage->hProcess);
+ /* Close the process handle */
+ if (pServiceImage->hProcess != INVALID_HANDLE_VALUE)
+ CloseHandle(pServiceImage->hProcess);
- /* Close the control pipe */
- if (pServiceImage->hControlPipe != INVALID_HANDLE_VALUE)
- CloseHandle(pServiceImage->hControlPipe);
+ /* Close the control pipe */
+ if (pServiceImage->hControlPipe != INVALID_HANDLE_VALUE)
+ CloseHandle(pServiceImage->hControlPipe);
- /* Unload the user profile */
- if (pServiceImage->hProfile != NULL)
- UnloadUserProfile(pServiceImage->hToken, pServiceImage->hProfile);
+ /* Unload the user profile */
+ if (pServiceImage->hProfile != NULL)
+ UnloadUserProfile(pServiceImage->hToken, pServiceImage->hProfile);
- /* Close the logon token */
- if (pServiceImage->hToken != NULL)
- CloseHandle(pServiceImage->hToken);
+ /* Close the logon token */
+ if (pServiceImage->hToken != NULL)
+ CloseHandle(pServiceImage->hToken);
- /* Release the service image */
- HeapFree(GetProcessHeap(), 0, pServiceImage);
- }
+ /* Release the service image */
+ HeapFree(GetProcessHeap(), 0, pServiceImage);
}
/* Dereference the service image */
if (lpService->lpImage)
- ScmDereferenceServiceImage(lpService->lpImage);
+ {
+ lpService->lpImage->dwImageRunCount--;
+
+ if (lpService->lpImage->dwImageRunCount == 0)
+ {
+ ScmRemoveServiceImage(lpService->lpImage);
+ lpService->lpImage = NULL;
+ }
+ }
/* Decrement the group reference counter */
ScmSetServiceGroup(lpService, NULL);
DWORD
-ScmControlService(PSERVICE Service,
+ScmControlService(HANDLE hControlPipe,
+ PWSTR pServiceName,
+ SERVICE_STATUS_HANDLE hServiceStatus,
DWORD dwControl)
{
PSCM_CONTROL_PACKET ControlPacket;
/* Calculate the total length of the start command line */
PacketSize = sizeof(SCM_CONTROL_PACKET);
- PacketSize += (DWORD)((wcslen(Service->lpServiceName) + 1) * sizeof(WCHAR));
+ PacketSize += (DWORD)((wcslen(pServiceName) + 1) * sizeof(WCHAR));
ControlPacket = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
ControlPacket->dwSize = PacketSize;
ControlPacket->dwControl = dwControl;
- ControlPacket->hServiceStatus = (SERVICE_STATUS_HANDLE)Service;
+ ControlPacket->hServiceStatus = hServiceStatus;
ControlPacket->dwServiceNameOffset = sizeof(SCM_CONTROL_PACKET);
Ptr = (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset);
- wcscpy(Ptr, Service->lpServiceName);
+ wcscpy(Ptr, pServiceName);
ControlPacket->dwArgumentsCount = 0;
ControlPacket->dwArgumentsOffset = 0;
- bResult = WriteFile(Service->lpImage->hControlPipe,
+ bResult = WriteFile(hControlPipe,
ControlPacket,
PacketSize,
&dwWriteCount,
{
DPRINT("dwError: ERROR_IO_PENDING\n");
- dwError = WaitForSingleObject(Service->lpImage->hControlPipe,
+ dwError = WaitForSingleObject(hControlPipe,
PipeTimeout);
DPRINT("WaitForSingleObject() returned %lu\n", dwError);
if (dwError == WAIT_TIMEOUT)
{
- bResult = CancelIo(Service->lpImage->hControlPipe);
+ bResult = CancelIo(hControlPipe);
if (bResult == FALSE)
{
DPRINT1("CancelIo() failed (Error: %lu)\n", GetLastError());
}
else if (dwError == WAIT_OBJECT_0)
{
- bResult = GetOverlappedResult(Service->lpImage->hControlPipe,
+ bResult = GetOverlappedResult(hControlPipe,
&Overlapped,
&dwWriteCount,
TRUE);
/* Read the reply */
Overlapped.hEvent = (HANDLE) NULL;
- bResult = ReadFile(Service->lpImage->hControlPipe,
+ bResult = ReadFile(hControlPipe,
&ReplyPacket,
sizeof(SCM_REPLY_PACKET),
&dwReadCount,
{
DPRINT("dwError: ERROR_IO_PENDING\n");
- dwError = WaitForSingleObject(Service->lpImage->hControlPipe,
+ dwError = WaitForSingleObject(hControlPipe,
PipeTimeout);
DPRINT("WaitForSingleObject() returned %lu\n", dwError);
if (dwError == WAIT_TIMEOUT)
{
- bResult = CancelIo(Service->lpImage->hControlPipe);
+ bResult = CancelIo(hControlPipe);
if (bResult == FALSE)
{
DPRINT1("CancelIo() failed (Error: %lu)\n", GetLastError());
}
else if (dwError == WAIT_OBJECT_0)
{
- bResult = GetOverlappedResult(Service->lpImage->hControlPipe,
+ bResult = GetOverlappedResult(hControlPipe,
&Overlapped,
&dwReadCount,
TRUE);
dwError = ReplyPacket.dwError;
}
- if (dwError == ERROR_SUCCESS &&
- dwControl == SERVICE_CONTROL_STOP)
- {
- ScmDereferenceServiceImage(Service->lpImage);
- Service->lpImage = NULL;
- }
-
LeaveCriticalSection(&ControlServiceCriticalSection);
DPRINT("ScmControlService() done\n");
}
else
{
- ScmDereferenceServiceImage(Service->lpImage);
- Service->lpImage = NULL;
+ Service->lpImage->dwImageRunCount--;
+ if (Service->lpImage->dwImageRunCount == 0)
+ {
+ ScmRemoveServiceImage(Service->lpImage);
+ Service->lpImage = NULL;
+ }
}
}
}
CurrentService->Status.dwCurrentState == SERVICE_START_PENDING)
{
/* shutdown service */
- DPRINT("Shutdown service: %S\n", CurrentService->szServiceName);
- ScmControlService(CurrentService, SERVICE_CONTROL_SHUTDOWN);
+ DPRINT("Shutdown service: %S\n", CurrentService->lpServiceName);
+ ScmControlService(CurrentService->lpImage->hControlPipe,
+ CurrentService->lpServiceName,
+ (SERVICE_STATUS_HANDLE)CurrentService,
+ SERVICE_CONTROL_SHUTDOWN);
}
ServiceEntry = ServiceEntry->Flink;
}
/* 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 */
/* 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();
lpLogStrings);
}
+
+
DPRINT("Set %S to %lu\n", lpService->lpDisplayName, lpService->Status.dwCurrentState);
DPRINT("RSetServiceStatus() done\n");
{
DWORD Count;
BOOL bResult;
- DWORD dwRunningServices = 0;
+ BOOL bRunning = TRUE;
LPWSTR lpServiceName;
PACTIVE_SERVICE lpService;
SCM_REPLY_PACKET ReplyPacket;
if (ControlPacket == NULL || dwBufferSize < sizeof(SCM_CONTROL_PACKET))
return FALSE;
- while (TRUE)
+ while (bRunning)
{
/* Read command from the control pipe */
bResult = ReadFile(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;
ERR("Pipe write failed (Error: %lu)\n", GetLastError());
return FALSE;
}
-
- if (dwRunningServices == 0)
- break;
}
return TRUE;