From bfd0ce90f101c2ee6a3874925cef05caa764abf9 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sun, 21 Aug 2011 15:35:19 +0000 Subject: [PATCH] [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 --- reactos/base/system/services/database.c | 71 +++++++++++++-------- reactos/base/system/services/rpcserver.c | 19 +++--- reactos/base/system/services/services.h | 1 + reactos/dll/win32/advapi32/service/sctrl.c | 49 ++++++++++++-- reactos/include/reactos/services/services.h | 6 +- 5 files changed, 101 insertions(+), 45 deletions(-) diff --git a/reactos/base/system/services/database.c b/reactos/base/system/services/database.c index 1c2cc7eeaa6..8b22e36867e 100644 --- a/reactos/base/system/services/database.c +++ b/reactos/base/system/services/database.c @@ -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); diff --git a/reactos/base/system/services/rpcserver.c b/reactos/base/system/services/rpcserver.c index 6f909a28622..6a7895992de 100644 --- a/reactos/base/system/services/rpcserver.c +++ b/reactos/base/system/services/rpcserver.c @@ -11,7 +11,6 @@ /* INCLUDES ****************************************************************/ #include "services.h" -#include "svcctl_s.h" #define NDEBUG #include @@ -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; } diff --git a/reactos/base/system/services/services.h b/reactos/base/system/services/services.h index 210f8db5219..c22f95a1ccc 100644 --- a/reactos/base/system/services/services.h +++ b/reactos/base/system/services/services.h @@ -11,6 +11,7 @@ #include #include #include +#include "svcctl_s.h" typedef struct _SERVICE_GROUP diff --git a/reactos/dll/win32/advapi32/service/sctrl.c b/reactos/dll/win32/advapi32/service/sctrl.c index 1a1b31e6966..c77f133ee49 100644 --- a/reactos/dll/win32/advapi32/service/sctrl.c +++ b/reactos/dll/win32/advapi32/service/sctrl.c @@ -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); diff --git a/reactos/include/reactos/services/services.h b/reactos/include/reactos/services/services.h index 009c2506b7d..9a46a61ae13 100644 --- a/reactos/include/reactos/services/services.h +++ b/reactos/include/reactos/services/services.h @@ -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