[SERVICES]

Implement check for SERVICE_WIN32_OWN_PROCESS or SERVICE_WIN32_SHARE_PROCESS type.
Patch by Hermes Belusca.

See issue #7179 for more details.

svn path=/trunk/; revision=56900
This commit is contained in:
Eric Kohl 2012-07-15 18:27:29 +00:00
parent cfc235a34b
commit c27b9de07c
3 changed files with 67 additions and 72 deletions

View file

@ -1116,8 +1116,8 @@ ScmSendStartCommand(PSERVICE Service,
DPRINT("ScmSendStartCommand() called\n"); DPRINT("ScmSendStartCommand() called\n");
/* Calculate the total length of the start command line */ /* Calculate the total length of the start command line */
PacketSize = sizeof(SCM_CONTROL_PACKET); PacketSize = sizeof(SCM_CONTROL_PACKET) +
PacketSize += (wcslen(Service->lpServiceName) + 1) * sizeof(WCHAR); (wcslen(Service->lpServiceName) + 1) * sizeof(WCHAR);
/* Calculate the required packet size for the start arguments */ /* Calculate the required packet size for the start arguments */
if (argc > 0 && argv != NULL) if (argc > 0 && argv != NULL)
@ -1140,7 +1140,9 @@ ScmSendStartCommand(PSERVICE Service,
return ERROR_NOT_ENOUGH_MEMORY; return ERROR_NOT_ENOUGH_MEMORY;
ControlPacket->dwSize = PacketSize; ControlPacket->dwSize = PacketSize;
ControlPacket->dwControl = SERVICE_CONTROL_START; ControlPacket->dwControl = (Service->Status.dwServiceType & SERVICE_WIN32_OWN_PROCESS)
? SERVICE_CONTROL_START_OWN
: SERVICE_CONTROL_START_SHARE;
ControlPacket->hServiceStatus = (SERVICE_STATUS_HANDLE)Service; ControlPacket->hServiceStatus = (SERVICE_STATUS_HANDLE)Service;
ControlPacket->dwServiceNameOffset = sizeof(SCM_CONTROL_PACKET); ControlPacket->dwServiceNameOffset = sizeof(SCM_CONTROL_PACKET);

View file

@ -47,6 +47,7 @@ typedef struct _ACTIVE_SERVICE
LPHANDLER_FUNCTION_EX HandlerFunctionEx; LPHANDLER_FUNCTION_EX HandlerFunctionEx;
LPVOID HandlerContext; LPVOID HandlerContext;
BOOL bUnicode; BOOL bUnicode;
BOOL bOwnProcess;
} ACTIVE_SERVICE, *PACTIVE_SERVICE; } ACTIVE_SERVICE, *PACTIVE_SERVICE;
@ -142,6 +143,9 @@ ScLookupServiceByServiceName(LPCWSTR lpServiceName)
TRACE("ScLookupServiceByServiceName(%S) called\n", lpServiceName); TRACE("ScLookupServiceByServiceName(%S) called\n", lpServiceName);
if (lpActiveServices[0].bOwnProcess)
return &lpActiveServices[0];
for (i = 0; i < dwActiveServiceCount; i++) for (i = 0; i < dwActiveServiceCount; i++)
{ {
TRACE("Checking %S\n", lpActiveServices[i].ServiceName.Buffer); TRACE("Checking %S\n", lpActiveServices[i].ServiceName.Buffer);
@ -488,10 +492,9 @@ ScControlService(PACTIVE_SERVICE lpService,
static BOOL static BOOL
ScServiceDispatcher(HANDLE hPipe, ScServiceDispatcher(HANDLE hPipe,
PUCHAR lpBuffer, PSCM_CONTROL_PACKET ControlPacket,
DWORD dwBufferSize) DWORD dwBufferSize)
{ {
PSCM_CONTROL_PACKET ControlPacket;
DWORD Count; DWORD Count;
BOOL bResult; BOOL bResult;
DWORD dwRunningServices = 0; DWORD dwRunningServices = 0;
@ -502,18 +505,12 @@ ScServiceDispatcher(HANDLE hPipe,
TRACE("ScDispatcherLoop() called\n"); TRACE("ScDispatcherLoop() called\n");
ControlPacket = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
1024);
if (ControlPacket == NULL)
return FALSE;
while (TRUE) while (TRUE)
{ {
/* Read command from the control pipe */ /* Read command from the control pipe */
bResult = ReadFile(hPipe, bResult = ReadFile(hPipe,
ControlPacket, ControlPacket,
1024, dwBufferSize,
&Count, &Count,
NULL); NULL);
if (bResult == FALSE) if (bResult == FALSE)
@ -525,13 +522,17 @@ ScServiceDispatcher(HANDLE hPipe,
lpServiceName = (LPWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset); lpServiceName = (LPWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset);
TRACE("Service: %S\n", lpServiceName); TRACE("Service: %S\n", lpServiceName);
if (ControlPacket->dwControl == SERVICE_CONTROL_START_OWN)
lpActiveServices[0].bOwnProcess = TRUE;
lpService = ScLookupServiceByServiceName(lpServiceName); lpService = ScLookupServiceByServiceName(lpServiceName);
if (lpService != NULL) if (lpService != NULL)
{ {
/* Execute command */ /* Execute command */
switch (ControlPacket->dwControl) switch (ControlPacket->dwControl)
{ {
case SERVICE_CONTROL_START: case SERVICE_CONTROL_START_SHARE:
case SERVICE_CONTROL_START_OWN:
TRACE("Start command - recieved SERVICE_CONTROL_START\n"); TRACE("Start command - recieved SERVICE_CONTROL_START\n");
dwError = ScStartService(lpService, ControlPacket); dwError = ScStartService(lpService, ControlPacket);
if (dwError == ERROR_SUCCESS) if (dwError == ERROR_SUCCESS)
@ -832,12 +833,14 @@ SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus,
* @implemented * @implemented
*/ */
BOOL WINAPI BOOL WINAPI
StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA * lpServiceStartTable) StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA *lpServiceStartTable)
{ {
ULONG i; ULONG i;
HANDLE hPipe; HANDLE hPipe;
DWORD dwError; DWORD dwError;
PUCHAR lpMessageBuffer; PSCM_CONTROL_PACKET ControlPacket;
DWORD dwBufSize;
BOOL bRet = TRUE;
TRACE("StartServiceCtrlDispatcherA() called\n"); TRACE("StartServiceCtrlDispatcherA() called\n");
@ -864,50 +867,40 @@ StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA * lpServiceStartTable)
lpActiveServices[i].ThreadParams.A.lpServiceMain = lpServiceStartTable[i].lpServiceProc; lpActiveServices[i].ThreadParams.A.lpServiceMain = lpServiceStartTable[i].lpServiceProc;
lpActiveServices[i].hServiceStatus = 0; lpActiveServices[i].hServiceStatus = 0;
lpActiveServices[i].bUnicode = FALSE; lpActiveServices[i].bUnicode = FALSE;
lpActiveServices[i].bOwnProcess = FALSE;
} }
dwError = ScConnectControlPipe(&hPipe); dwError = ScConnectControlPipe(&hPipe);
if (dwError != ERROR_SUCCESS) if (dwError != ERROR_SUCCESS)
{ {
/* Free the service table */ bRet = FALSE;
for (i = 0; i < dwActiveServiceCount; i++) goto done;
{
RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
}
RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
lpActiveServices = NULL;
dwActiveServiceCount = 0;
return FALSE;
} }
lpMessageBuffer = RtlAllocateHeap(RtlGetProcessHeap(), dwBufSize = sizeof(SCM_CONTROL_PACKET) +
HEAP_ZERO_MEMORY, (MAX_SERVICE_NAME_LENGTH + 1) * sizeof(WCHAR);
256);
if (lpMessageBuffer == NULL) ControlPacket = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
dwBufSize);
if (ControlPacket == NULL)
{ {
/* Free the service table */ bRet = FALSE;
for (i = 0; i < dwActiveServiceCount; i++) goto done;
{
RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
}
RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
lpActiveServices = NULL;
dwActiveServiceCount = 0;
CloseHandle(hPipe);
return FALSE;
} }
ScCreateStatusBinding(); ScCreateStatusBinding();
ScServiceDispatcher(hPipe, lpMessageBuffer, 256); ScServiceDispatcher(hPipe, ControlPacket, dwBufSize);
ScDestroyStatusBinding(); ScDestroyStatusBinding();
CloseHandle(hPipe); CloseHandle(hPipe);
/* Free the message buffer */ /* Free the control packet */
RtlFreeHeap(RtlGetProcessHeap(), 0, lpMessageBuffer); RtlFreeHeap(RtlGetProcessHeap(), 0, ControlPacket);
done:
/* Free the service table */ /* Free the service table */
for (i = 0; i < dwActiveServiceCount; i++) for (i = 0; i < dwActiveServiceCount; i++)
{ {
@ -917,7 +910,7 @@ StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA * lpServiceStartTable)
lpActiveServices = NULL; lpActiveServices = NULL;
dwActiveServiceCount = 0; dwActiveServiceCount = 0;
return TRUE; return bRet;
} }
@ -927,12 +920,14 @@ StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA * lpServiceStartTable)
* @implemented * @implemented
*/ */
BOOL WINAPI BOOL WINAPI
StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW * lpServiceStartTable) StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW *lpServiceStartTable)
{ {
ULONG i; ULONG i;
HANDLE hPipe; HANDLE hPipe;
DWORD dwError; DWORD dwError;
PUCHAR lpMessageBuffer; PSCM_CONTROL_PACKET ControlPacket;
DWORD dwBufSize;
BOOL bRet = TRUE;
TRACE("StartServiceCtrlDispatcherW() called\n"); TRACE("StartServiceCtrlDispatcherW() called\n");
@ -959,50 +954,40 @@ StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW * lpServiceStartTable)
lpActiveServices[i].ThreadParams.W.lpServiceMain = lpServiceStartTable[i].lpServiceProc; lpActiveServices[i].ThreadParams.W.lpServiceMain = lpServiceStartTable[i].lpServiceProc;
lpActiveServices[i].hServiceStatus = 0; lpActiveServices[i].hServiceStatus = 0;
lpActiveServices[i].bUnicode = TRUE; lpActiveServices[i].bUnicode = TRUE;
lpActiveServices[i].bOwnProcess = FALSE;
} }
dwError = ScConnectControlPipe(&hPipe); dwError = ScConnectControlPipe(&hPipe);
if (dwError != ERROR_SUCCESS) if (dwError != ERROR_SUCCESS)
{ {
/* Free the service table */ bRet = FALSE;
for (i = 0; i < dwActiveServiceCount; i++) goto done;
{
RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
}
RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
lpActiveServices = NULL;
dwActiveServiceCount = 0;
return FALSE;
} }
lpMessageBuffer = RtlAllocateHeap(RtlGetProcessHeap(), dwBufSize = sizeof(SCM_CONTROL_PACKET) +
HEAP_ZERO_MEMORY, (MAX_SERVICE_NAME_LENGTH + 1) * sizeof(WCHAR);
256);
if (lpMessageBuffer == NULL) ControlPacket = RtlAllocateHeap(RtlGetProcessHeap(),
HEAP_ZERO_MEMORY,
dwBufSize);
if (ControlPacket == NULL)
{ {
/* Free the service table */ bRet = FALSE;
for (i = 0; i < dwActiveServiceCount; i++) goto done;
{
RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
}
RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
lpActiveServices = NULL;
dwActiveServiceCount = 0;
CloseHandle(hPipe);
return FALSE;
} }
ScCreateStatusBinding(); ScCreateStatusBinding();
ScServiceDispatcher(hPipe, lpMessageBuffer, 256); ScServiceDispatcher(hPipe, ControlPacket, dwBufSize);
ScDestroyStatusBinding(); ScDestroyStatusBinding();
CloseHandle(hPipe); CloseHandle(hPipe);
/* Free the message buffer */ /* Free the control packet */
RtlFreeHeap(RtlGetProcessHeap(), 0, lpMessageBuffer); RtlFreeHeap(RtlGetProcessHeap(), 0, ControlPacket);
done:
/* Free the service table */ /* Free the service table */
for (i = 0; i < dwActiveServiceCount; i++) for (i = 0; i < dwActiveServiceCount; i++)
{ {
@ -1012,7 +997,7 @@ StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW * lpServiceStartTable)
lpActiveServices = NULL; lpActiveServices = NULL;
dwActiveServiceCount = 0; dwActiveServiceCount = 0;
return TRUE; return bRet;
} }
/* EOF */ /* EOF */

View file

@ -9,7 +9,15 @@
#ifndef __SERVICES_SERVICES_H__ #ifndef __SERVICES_SERVICES_H__
#define __SERVICES_SERVICES_H__ #define __SERVICES_SERVICES_H__
#define SERVICE_CONTROL_START 0 /*
* Internal control codes.
* Neither in the range of public control codes (1-10 and 11-14 or 16 or 32 or 64)
* nor in the range of user-defined control codes (128-255).
*/
/* Start a service that shares a process with other services */
#define SERVICE_CONTROL_START_SHARE 80
/* Start a service that runs in its own process */
#define SERVICE_CONTROL_START_OWN 81
typedef struct _SCM_CONTROL_PACKET typedef struct _SCM_CONTROL_PACKET
{ {