[SERVICES/ADVAPI32]

Rewrite the command packet transfer code between the service control manager (services.exe) and the service control dispatcher (advapi32.dll). The service name is no longer stored in an array of WCHARs at the end of the command packet. The service name is now stored behind the fixed size command packet header using an offset value in the header to determine the start of the string. The same method will be used to store start arguments to the service dispatcher, but it is not fully implemented yet.

svn path=/trunk/; revision=53358
This commit is contained in:
Eric Kohl 2011-08-21 15:35:19 +00:00
parent fd133d9dca
commit bfd0ce90f1
5 changed files with 101 additions and 45 deletions

View file

@ -918,33 +918,43 @@ ScmControlService(PSERVICE Service,
DWORD dwWriteCount = 0; DWORD dwWriteCount = 0;
DWORD dwReadCount = 0; DWORD dwReadCount = 0;
DWORD TotalLength; DWORD PacketSize;
PWSTR Ptr;
DWORD dwError = ERROR_SUCCESS; DWORD dwError = ERROR_SUCCESS;
DPRINT("ScmControlService() called\n"); DPRINT("ScmControlService() called\n");
EnterCriticalSection(&ControlServiceCriticalSection); EnterCriticalSection(&ControlServiceCriticalSection);
TotalLength = wcslen(Service->lpServiceName) + 1; /* Calculate the total length of the start command line */
PacketSize = sizeof(SCM_CONTROL_PACKET);
PacketSize += (wcslen(Service->lpServiceName) + 1) * sizeof(WCHAR);
ControlPacket = (SCM_CONTROL_PACKET*)HeapAlloc(GetProcessHeap(), ControlPacket = (SCM_CONTROL_PACKET*)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, HEAP_ZERO_MEMORY,
sizeof(SCM_CONTROL_PACKET) + (TotalLength * sizeof(WCHAR))); PacketSize);
if (ControlPacket == NULL) if (ControlPacket == NULL)
{ {
LeaveCriticalSection(&ControlServiceCriticalSection); LeaveCriticalSection(&ControlServiceCriticalSection);
return ERROR_NOT_ENOUGH_MEMORY; return ERROR_NOT_ENOUGH_MEMORY;
} }
ControlPacket->dwSize = PacketSize;
ControlPacket->dwControl = dwControl; ControlPacket->dwControl = dwControl;
ControlPacket->dwSize = TotalLength;
ControlPacket->hServiceStatus = (SERVICE_STATUS_HANDLE)Service; ControlPacket->hServiceStatus = (SERVICE_STATUS_HANDLE)Service;
wcscpy(&ControlPacket->szArguments[0], Service->lpServiceName);
ControlPacket->dwServiceNameOffset = sizeof(SCM_CONTROL_PACKET);
Ptr = (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset);
wcscpy(Ptr, Service->lpServiceName);
ControlPacket->dwArgumentsCount = 0;
ControlPacket->dwArgumentsOffset = 0;
/* Send the control packet */ /* Send the control packet */
WriteFile(Service->lpImage->hControlPipe, WriteFile(Service->lpImage->hControlPipe,
ControlPacket, ControlPacket,
sizeof(SCM_CONTROL_PACKET) + (TotalLength * sizeof(WCHAR)), PacketSize,
&dwWriteCount, &dwWriteCount,
NULL); NULL);
@ -986,9 +996,7 @@ ScmSendStartCommand(PSERVICE Service,
{ {
PSCM_CONTROL_PACKET ControlPacket; PSCM_CONTROL_PACKET ControlPacket;
SCM_REPLY_PACKET ReplyPacket; SCM_REPLY_PACKET ReplyPacket;
DWORD TotalLength; DWORD PacketSize;
DWORD ArgsLength = 0;
DWORD Length;
PWSTR Ptr; PWSTR Ptr;
DWORD dwWriteCount = 0; DWORD dwWriteCount = 0;
DWORD dwReadCount = 0; DWORD dwReadCount = 0;
@ -998,52 +1006,59 @@ 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 */
TotalLength = wcslen(Service->lpServiceName) + 1; PacketSize = sizeof(SCM_CONTROL_PACKET);
if (argc > 0) PacketSize += (wcslen(Service->lpServiceName) + 1) * sizeof(WCHAR);
/* Calculate the required packet size for the start arguments */
if (argc > 0 && argv != NULL)
{ {
PacketSize = ALIGN_UP(PacketSize, LPWSTR);
DPRINT("Argc: %lu\n", argc);
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)
{ {
DPRINT("Arg: %S\n", argv[i]); DPRINT("Argv[%lu]: %S\n", i, argv[i]);
Length = wcslen(argv[i]) + 1; PacketSize += (wcslen(argv[i]) + 1) * sizeof(WCHAR) + sizeof(PWSTR);
TotalLength += Length;
ArgsLength += Length;
} }
} }
TotalLength++;
DPRINT("ArgsLength: %ld TotalLength: %ld\n", ArgsLength, TotalLength);
/* Allocate a control packet */ /* Allocate a control packet */
ControlPacket = (SCM_CONTROL_PACKET*)HeapAlloc(GetProcessHeap(), ControlPacket = (SCM_CONTROL_PACKET*)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, HEAP_ZERO_MEMORY,
sizeof(SCM_CONTROL_PACKET) + (TotalLength - 1) * sizeof(WCHAR)); PacketSize);
if (ControlPacket == NULL) if (ControlPacket == NULL)
return ERROR_NOT_ENOUGH_MEMORY; return ERROR_NOT_ENOUGH_MEMORY;
ControlPacket->dwSize = PacketSize;
ControlPacket->dwControl = SERVICE_CONTROL_START; ControlPacket->dwControl = SERVICE_CONTROL_START;
ControlPacket->hServiceStatus = (SERVICE_STATUS_HANDLE)Service; ControlPacket->hServiceStatus = (SERVICE_STATUS_HANDLE)Service;
ControlPacket->dwSize = TotalLength; ControlPacket->dwServiceNameOffset = sizeof(SCM_CONTROL_PACKET);
Ptr = &ControlPacket->szArguments[0];
Ptr = (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset);
wcscpy(Ptr, Service->lpServiceName); wcscpy(Ptr, Service->lpServiceName);
Ptr += (wcslen(Service->lpServiceName) + 1);
ControlPacket->dwArgumentsCount = 0;
ControlPacket->dwArgumentsOffset = 0;
/* Copy argument list */ /* Copy argument list */
if (argc > 0) if (argc > 0 && argv != NULL)
{ {
UNIMPLEMENTED; // Ptr += wcslen(Service->lpServiceName) + 1;
DPRINT1("Arguments sent to service ignored!\n"); // Ptr = ALIGN_UP_POINTER(Ptr, LPWSTR);
// ControlPacket->dwArgumentsOffset = (DWORD)((INT_PTR)Ptr - (INT_PTR)ControlPacket);
#if 0 #if 0
memcpy(Ptr, Arguments, ArgsLength); memcpy(Ptr, Arguments, ArgsLength);
Ptr += ArgsLength; Ptr += ArgsLength;
#endif #endif
} }
/* Terminate the argument list */
*Ptr = 0;
/* Send the start command */ /* Send the start command */
WriteFile(Service->lpImage->hControlPipe, WriteFile(Service->lpImage->hControlPipe,
ControlPacket, ControlPacket,
sizeof(SCM_CONTROL_PACKET) + (TotalLength - 1) * sizeof(WCHAR), PacketSize,
&dwWriteCount, &dwWriteCount,
NULL); NULL);

View file

@ -11,7 +11,6 @@
/* INCLUDES ****************************************************************/ /* INCLUDES ****************************************************************/
#include "services.h" #include "services.h"
#include "svcctl_s.h"
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
@ -2868,8 +2867,17 @@ DWORD RStartServiceW(
DWORD dwError = ERROR_SUCCESS; DWORD dwError = ERROR_SUCCESS;
PSERVICE_HANDLE hSvc; PSERVICE_HANDLE hSvc;
PSERVICE lpService = NULL; PSERVICE lpService = NULL;
DWORD i;
DPRINT("RStartServiceW() called\n"); DPRINT("RStartServiceW(%p %lu %p) called\n", hService, argc, argv);
DPRINT(" argc: %lu\n", argc);
if (argv != NULL)
{
for (i = 0; i < argc; i++)
{
DPRINT(" argv[%lu]: %S\n", i, argv[i]);
}
}
if (ScmShutdown) if (ScmShutdown)
return ERROR_SHUTDOWN_IN_PROGRESS; return ERROR_SHUTDOWN_IN_PROGRESS;
@ -2901,13 +2909,8 @@ DWORD RStartServiceW(
if (lpService->bDeleted) if (lpService->bDeleted)
return ERROR_SERVICE_MARKED_FOR_DELETE; return ERROR_SERVICE_MARKED_FOR_DELETE;
if (argv) {
UNIMPLEMENTED;
argv = NULL;
}
/* Start the service */ /* Start the service */
dwError = ScmStartService(lpService, argc, (LPWSTR *)argv); dwError = ScmStartService(lpService, argc, (LPWSTR*)argv);
return dwError; return dwError;
} }

View file

@ -11,6 +11,7 @@
#include <ndk/obfuncs.h> #include <ndk/obfuncs.h>
#include <ndk/rtlfuncs.h> #include <ndk/rtlfuncs.h>
#include <services/services.h> #include <services/services.h>
#include "svcctl_s.h"
typedef struct _SERVICE_GROUP typedef struct _SERVICE_GROUP

View file

@ -125,14 +125,20 @@ ScLookupServiceByServiceName(LPCWSTR lpServiceName)
{ {
DWORD i; DWORD i;
TRACE("ScLookupServiceByServiceName(%S) called\n", lpServiceName);
for (i = 0; i < dwActiveServiceCount; i++) for (i = 0; i < dwActiveServiceCount; i++)
{ {
TRACE("Checking %S\n", lpActiveServices[i].ServiceName.Buffer);
if (_wcsicmp(lpActiveServices[i].ServiceName.Buffer, lpServiceName) == 0) if (_wcsicmp(lpActiveServices[i].ServiceName.Buffer, lpServiceName) == 0)
{ {
TRACE("Found!\n");
return &lpActiveServices[i]; return &lpActiveServices[i];
} }
} }
TRACE("No service found!\n");
SetLastError(ERROR_SERVICE_DOES_NOT_EXIST); SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
return NULL; return NULL;
@ -344,23 +350,52 @@ ScStartService(PACTIVE_SERVICE lpService,
{ {
HANDLE ThreadHandle; HANDLE ThreadHandle;
DWORD ThreadId; DWORD ThreadId;
PWSTR pServiceName;
PWSTR Ptr;
DWORD dwArgumentsSize;
TRACE("ScStartService() called\n"); TRACE("ScStartService() called\n");
TRACE("Size: %lu\n", ControlPacket->dwSize); TRACE("Size: %lu\n", ControlPacket->dwSize);
TRACE("Service: %S\n", &ControlPacket->szArguments[0]); TRACE("Service: %S\n", (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset));
/* Set the service status handle */ /* Set the service status handle */
lpService->hServiceStatus = ControlPacket->hServiceStatus; lpService->hServiceStatus = ControlPacket->hServiceStatus;
pServiceName = (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset);
/* Get the service name size */
dwArgumentsSize = (wcslen(pServiceName) + 1) * sizeof(WCHAR);
/* Get the size of the service start arguments */
if (ControlPacket->dwArgumentsCount > 0 &&
ControlPacket->dwArgumentsOffset != 0)
{
/* FIXME */
#if 0
dwArgumentSize += (wcslen(...) + 1) * sizeof(WCHAR);
#endif
}
lpService->Arguments = HeapAlloc(GetProcessHeap(), lpService->Arguments = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, HEAP_ZERO_MEMORY,
(ControlPacket->dwSize + 1) * sizeof(WCHAR)); dwArgumentsSize + sizeof(WCHAR));
if (lpService->Arguments == NULL) if (lpService->Arguments == NULL)
return ERROR_OUTOFMEMORY; return ERROR_OUTOFMEMORY;
memcpy(lpService->Arguments, Ptr = lpService->Arguments;
ControlPacket->szArguments,
ControlPacket->dwSize * sizeof(WCHAR)); /* Add the service name as first argument */
wcscpy(Ptr, pServiceName);
Ptr += (wcslen(pServiceName) + 1);
/* Add service start arguments */
if (ControlPacket->dwArgumentsCount > 0 &&
ControlPacket->dwArgumentsOffset != 0)
{
/* FIXME */
}
*Ptr = 0;
/* invoke the services entry point and implement the command loop */ /* invoke the services entry point and implement the command loop */
ThreadHandle = CreateThread(NULL, ThreadHandle = CreateThread(NULL,
@ -385,7 +420,7 @@ ScControlService(PACTIVE_SERVICE lpService,
{ {
TRACE("ScControlService() called\n"); TRACE("ScControlService() called\n");
TRACE("Size: %lu\n", ControlPacket->dwSize); TRACE("Size: %lu\n", ControlPacket->dwSize);
TRACE("Service: %S\n", &ControlPacket->szArguments[0]); TRACE("Service: %S\n", (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset));
if (lpService->HandlerFunction) if (lpService->HandlerFunction)
{ {
@ -446,7 +481,7 @@ ScServiceDispatcher(HANDLE hPipe,
return FALSE; return FALSE;
} }
lpServiceName = &ControlPacket->szArguments[0]; lpServiceName = (LPWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset);
TRACE("Service: %S\n", lpServiceName); TRACE("Service: %S\n", lpServiceName);
lpService = ScLookupServiceByServiceName(lpServiceName); lpService = ScLookupServiceByServiceName(lpServiceName);

View file

@ -13,10 +13,12 @@
typedef struct _SCM_CONTROL_PACKET typedef struct _SCM_CONTROL_PACKET
{ {
DWORD dwSize;
DWORD dwControl; DWORD dwControl;
SERVICE_STATUS_HANDLE hServiceStatus; SERVICE_STATUS_HANDLE hServiceStatus;
DWORD dwSize; DWORD dwServiceNameOffset;
WCHAR szArguments[1]; DWORD dwArgumentsCount;
DWORD dwArgumentsOffset;
} SCM_CONTROL_PACKET, *PSCM_CONTROL_PACKET; } SCM_CONTROL_PACKET, *PSCM_CONTROL_PACKET;
typedef struct _SCM_REPLY_PACKET typedef struct _SCM_REPLY_PACKET