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

View file

@ -11,7 +11,6 @@
/* INCLUDES ****************************************************************/
#include "services.h"
#include "svcctl_s.h"
#define NDEBUG
#include <debug.h>
@ -2868,8 +2867,17 @@ DWORD RStartServiceW(
DWORD dwError = ERROR_SUCCESS;
PSERVICE_HANDLE hSvc;
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)
return ERROR_SHUTDOWN_IN_PROGRESS;
@ -2901,13 +2909,8 @@ DWORD RStartServiceW(
if (lpService->bDeleted)
return ERROR_SERVICE_MARKED_FOR_DELETE;
if (argv) {
UNIMPLEMENTED;
argv = NULL;
}
/* Start the service */
dwError = ScmStartService(lpService, argc, (LPWSTR *)argv);
dwError = ScmStartService(lpService, argc, (LPWSTR*)argv);
return dwError;
}

View file

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

View file

@ -125,14 +125,20 @@ ScLookupServiceByServiceName(LPCWSTR lpServiceName)
{
DWORD i;
TRACE("ScLookupServiceByServiceName(%S) called\n", lpServiceName);
for (i = 0; i < dwActiveServiceCount; i++)
{
TRACE("Checking %S\n", lpActiveServices[i].ServiceName.Buffer);
if (_wcsicmp(lpActiveServices[i].ServiceName.Buffer, lpServiceName) == 0)
{
TRACE("Found!\n");
return &lpActiveServices[i];
}
}
TRACE("No service found!\n");
SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
return NULL;
@ -344,23 +350,52 @@ ScStartService(PACTIVE_SERVICE lpService,
{
HANDLE ThreadHandle;
DWORD ThreadId;
PWSTR pServiceName;
PWSTR Ptr;
DWORD dwArgumentsSize;
TRACE("ScStartService() called\n");
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 */
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(),
HEAP_ZERO_MEMORY,
(ControlPacket->dwSize + 1) * sizeof(WCHAR));
dwArgumentsSize + sizeof(WCHAR));
if (lpService->Arguments == NULL)
return ERROR_OUTOFMEMORY;
memcpy(lpService->Arguments,
ControlPacket->szArguments,
ControlPacket->dwSize * sizeof(WCHAR));
Ptr = lpService->Arguments;
/* 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 */
ThreadHandle = CreateThread(NULL,
@ -385,7 +420,7 @@ ScControlService(PACTIVE_SERVICE lpService,
{
TRACE("ScControlService() called\n");
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)
{
@ -446,7 +481,7 @@ ScServiceDispatcher(HANDLE hPipe,
return FALSE;
}
lpServiceName = &ControlPacket->szArguments[0];
lpServiceName = (LPWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset);
TRACE("Service: %S\n", lpServiceName);
lpService = ScLookupServiceByServiceName(lpServiceName);

View file

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