From: Eric Kohl Date: Sat, 27 Feb 2010 21:47:59 +0000 (+0000) Subject: [SERVICES] X-Git-Tag: ReactOS-0.3.11-CLT2010~8^2~68 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=9e6714ef3bc2138e19bca606132e5be02d154b19 [SERVICES] - Generate unique service status handles. Services could set the status information of another service because the status handles were not guaranteed to be unique for all services. - Lock and unlock the service database when getting or setting service status information. svn path=/trunk/; revision=45711 --- diff --git a/reactos/base/system/services/database.c b/reactos/base/system/services/database.c index 2a0ae9859f9..95bc302daac 100644 --- a/reactos/base/system/services/database.c +++ b/reactos/base/system/services/database.c @@ -121,37 +121,6 @@ ScmGetServiceEntryByResumeCount(DWORD dwResumeCount) } -PSERVICE -ScmGetServiceEntryByClientHandle(HANDLE Handle) -{ - PLIST_ENTRY ServiceEntry; - PSERVICE CurrentService; - - DPRINT("ScmGetServiceEntryByClientHandle() called\n"); - DPRINT("looking for %p\n", Handle); - - ServiceEntry = ServiceListHead.Flink; - while (ServiceEntry != &ServiceListHead) - { - CurrentService = CONTAINING_RECORD(ServiceEntry, - SERVICE, - ServiceListEntry); - - if (CurrentService->hClient == Handle) - { - DPRINT("Found service: '%S'\n", CurrentService->lpDisplayName); - return CurrentService; - } - - ServiceEntry = ServiceEntry->Flink; - } - - DPRINT("Couldn't find a matching service\n"); - - return NULL; -} - - DWORD ScmCreateNewServiceRecord(LPCWSTR lpServiceName, PSERVICE *lpServiceRecord) @@ -728,8 +697,8 @@ ScmControlService(PSERVICE Service, return ERROR_NOT_ENOUGH_MEMORY; ControlPacket->dwControl = dwControl; - ControlPacket->hClient = Service->hClient; ControlPacket->dwSize = TotalLength; + ControlPacket->hServiceStatus = (SERVICE_STATUS_HANDLE)Service; wcscpy(&ControlPacket->szArguments[0], Service->lpServiceName); /* Send the control packet */ @@ -793,7 +762,7 @@ ScmSendStartCommand(PSERVICE Service, return ERROR_NOT_ENOUGH_MEMORY; ControlPacket->dwControl = SERVICE_CONTROL_START; - ControlPacket->hClient = Service->hClient; + ControlPacket->hServiceStatus = (SERVICE_STATUS_HANDLE)Service; ControlPacket->dwSize = TotalLength; Ptr = &ControlPacket->szArguments[0]; wcscpy(Ptr, Service->lpServiceName); @@ -850,6 +819,7 @@ ScmStartUserModeService(PSERVICE Service, WCHAR NtControlPipeName[MAX_PATH + 1]; HKEY hServiceCurrentKey = INVALID_HANDLE_VALUE; DWORD KeyDisposition; + DWORD dwProcessId; RtlInitUnicodeString(&ImagePath, NULL); @@ -991,7 +961,7 @@ ScmStartUserModeService(PSERVICE Service, /* Read SERVICE_STATUS_HANDLE from pipe */ if (!ReadFile(Service->ControlPipeHandle, - (LPVOID)&Service->hClient, + (LPVOID)&dwProcessId, sizeof(DWORD), &dwRead, NULL)) @@ -1002,7 +972,7 @@ ScmStartUserModeService(PSERVICE Service, } else { - DPRINT("Received service status %lu\n", Service->hClient); + DPRINT("Received service process ID %lu\n", dwProcessId); /* Send start command */ dwError = ScmSendStartCommand(Service, argc, argv); @@ -1244,4 +1214,25 @@ ScmAutoShutdownServices(VOID) DPRINT("ScmGetBootAndSystemDriverState() done\n"); } + +BOOL +ScmLockDatabaseExclusive(VOID) +{ + return RtlAcquireResourceExclusive(&DatabaseLock, TRUE); +} + + +BOOL +ScmLockDatabaseShared(VOID) +{ + return RtlAcquireResourceShared(&DatabaseLock, TRUE); +} + + +VOID +ScmUnlockDatabase(VOID) +{ + RtlReleaseResource(&DatabaseLock); +} + /* EOF */ diff --git a/reactos/base/system/services/rpcserver.c b/reactos/base/system/services/rpcserver.c index 2262aa55e71..a1085f05fe3 100644 --- a/reactos/base/system/services/rpcserver.c +++ b/reactos/base/system/services/rpcserver.c @@ -978,11 +978,15 @@ DWORD RQueryServiceStatus( return ERROR_INVALID_HANDLE; } + ScmLockDatabaseShared(); + /* Return service status information */ RtlCopyMemory(lpServiceStatus, &lpService->Status, sizeof(SERVICE_STATUS)); + ScmUnlockDatabase(); + return ERROR_SUCCESS; } @@ -1030,7 +1034,7 @@ DWORD RSetServiceStatus( return ERROR_INVALID_HANDLE; } - lpService = ScmGetServiceEntryByClientHandle((HANDLE)hServiceStatus); + lpService = (PSERVICE)hServiceStatus; if (lpService == NULL) { DPRINT("lpService == NULL!\n"); @@ -1059,11 +1063,14 @@ DWORD RSetServiceStatus( return ERROR_INVALID_DATA; } + ScmLockDatabaseExclusive(); RtlCopyMemory(&lpService->Status, lpServiceStatus, sizeof(SERVICE_STATUS)); + ScmUnlockDatabase(); + DPRINT("Set %S to %lu\n", lpService->lpDisplayName, lpService->Status.dwCurrentState); DPRINT("RSetServiceStatus() done\n"); diff --git a/reactos/base/system/services/services.h b/reactos/base/system/services/services.h index 23022dc2c92..811aa001e49 100644 --- a/reactos/base/system/services/services.h +++ b/reactos/base/system/services/services.h @@ -42,7 +42,6 @@ typedef struct _SERVICE DWORD dwResumeCount; DWORD dwRefCount; - CLIENT_HANDLE hClient; SERVICE_STATUS Status; DWORD dwStartType; DWORD dwErrorControl; @@ -112,7 +111,6 @@ DWORD ScmStartService(PSERVICE Service, PSERVICE ScmGetServiceEntryByName(LPCWSTR lpServiceName); PSERVICE ScmGetServiceEntryByDisplayName(LPCWSTR lpDisplayName); PSERVICE ScmGetServiceEntryByResumeCount(DWORD dwResumeCount); -PSERVICE ScmGetServiceEntryByClientHandle(HANDLE Handle); DWORD ScmCreateNewServiceRecord(LPCWSTR lpServiceName, PSERVICE *lpServiceRecord); VOID ScmDeleteServiceRecord(PSERVICE lpService); @@ -122,6 +120,11 @@ DWORD ScmControlService(PSERVICE Service, DWORD dwControl, LPSERVICE_STATUS lpServiceStatus); +BOOL ScmLockDatabaseExclusive(VOID); +BOOL ScmLockDatabaseShared(VOID); +VOID ScmUnlockDatabase(VOID); + + /* driver.c */ DWORD ScmLoadDriver(PSERVICE lpService); diff --git a/reactos/dll/win32/advapi32/service/sctrl.c b/reactos/dll/win32/advapi32/service/sctrl.c index 3094951b911..a88fb2f11b0 100644 --- a/reactos/dll/win32/advapi32/service/sctrl.c +++ b/reactos/dll/win32/advapi32/service/sctrl.c @@ -22,7 +22,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(advapi); typedef struct _ACTIVE_SERVICE { - CLIENT_HANDLE hService; + SERVICE_STATUS_HANDLE hServiceStatus; UNICODE_STRING ServiceName; union { @@ -32,7 +32,6 @@ typedef struct _ACTIVE_SERVICE LPHANDLER_FUNCTION HandlerFunction; LPHANDLER_FUNCTION_EX HandlerFunctionEx; LPVOID HandlerContext; - SERVICE_STATUS ServiceStatus; BOOL bUnicode; LPWSTR Arguments; } ACTIVE_SERVICE, *PACTIVE_SERVICE; @@ -199,6 +198,7 @@ ScConnectControlPipe(HANDLE *hPipe) NTSTATUS Status; WCHAR NtControlPipeName[MAX_PATH + 1]; RTL_QUERY_REGISTRY_TABLE QueryTable[2]; + DWORD dwProcessId; /* Get the service number and create the named pipe */ RtlZeroMemory(&QueryTable, @@ -249,37 +249,34 @@ ScConnectControlPipe(HANDLE *hPipe) return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT; } - /* Share the SERVICE_HANDLE handle with the SCM */ + /* Pass the ProcessId to the SCM */ + dwProcessId = GetCurrentProcessId(); WriteFile(*hPipe, - (DWORD *)&lpActiveServices->hService, - sizeof(CLIENT_HANDLE), + &dwProcessId, + sizeof(DWORD), &dwBytesWritten, NULL); - TRACE("Sent SERVICE_HANDLE %lu\n", lpActiveServices->hService); + TRACE("Sent Process ID %lu\n", dwProcessId); + return ERROR_SUCCESS; } static DWORD -ScStartService(PSCM_CONTROL_PACKET ControlPacket) +ScStartService(PACTIVE_SERVICE lpService, + PSCM_CONTROL_PACKET ControlPacket) { - PACTIVE_SERVICE lpService; HANDLE ThreadHandle; DWORD ThreadId; TRACE("ScStartService() called\n"); - TRACE("client handle: %lu\n", ControlPacket->hClient); TRACE("Size: %lu\n", ControlPacket->dwSize); TRACE("Service: %S\n", &ControlPacket->szArguments[0]); - lpService = (PACTIVE_SERVICE)ControlPacket->hClient; - if (lpService == NULL) - { - TRACE("Service not found\n"); - return ERROR_SERVICE_DOES_NOT_EXIST; - } + /* Set the service status handle */ + lpService->hServiceStatus = ControlPacket->hServiceStatus; lpService->Arguments = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, @@ -309,21 +306,13 @@ ScStartService(PSCM_CONTROL_PACKET ControlPacket) static DWORD -ScControlService(PSCM_CONTROL_PACKET ControlPacket) +ScControlService(PACTIVE_SERVICE lpService, + PSCM_CONTROL_PACKET ControlPacket) { - PACTIVE_SERVICE lpService; - TRACE("ScControlService() called\n"); TRACE("Size: %lu\n", ControlPacket->dwSize); TRACE("Service: %S\n", &ControlPacket->szArguments[0]); - lpService = (PACTIVE_SERVICE)ControlPacket->hClient; - if (lpService == NULL) - { - TRACE("Service not found\n"); - return ERROR_SERVICE_DOES_NOT_EXIST; - } - if (lpService->HandlerFunction) { (lpService->HandlerFunction)(ControlPacket->dwControl); @@ -356,6 +345,8 @@ ScServiceDispatcher(HANDLE hPipe, DWORD Count; BOOL bResult; DWORD dwRunningServices = 0; + LPWSTR lpServiceName; + PACTIVE_SERVICE lpService; TRACE("ScDispatcherLoop() called\n"); @@ -379,25 +370,32 @@ ScServiceDispatcher(HANDLE hPipe, return FALSE; } - /* Execute command */ - switch (ControlPacket->dwControl) + lpServiceName = &ControlPacket->szArguments[0]; + TRACE("Service: %S\n", lpServiceName); + + lpService = ScLookupServiceByServiceName(lpServiceName); + if (lpService != NULL) { - case SERVICE_CONTROL_START: - TRACE("Start command - recieved SERVICE_CONTROL_START\n"); - if (ScStartService(ControlPacket) == ERROR_SUCCESS) - dwRunningServices++; - break; - - case SERVICE_CONTROL_STOP: - TRACE("Stop command - recieved SERVICE_CONTROL_STOP\n"); - if (ScControlService(ControlPacket) == ERROR_SUCCESS) - dwRunningServices--; - break; - - default: - TRACE("Command %lu received", ControlPacket->dwControl); - ScControlService(ControlPacket); - continue; + /* Execute command */ + switch (ControlPacket->dwControl) + { + case SERVICE_CONTROL_START: + TRACE("Start command - recieved SERVICE_CONTROL_START\n"); + if (ScStartService(lpService, ControlPacket) == ERROR_SUCCESS) + dwRunningServices++; + break; + + case SERVICE_CONTROL_STOP: + TRACE("Stop command - recieved SERVICE_CONTROL_STOP\n"); + if (ScControlService(lpService, ControlPacket) == ERROR_SUCCESS) + dwRunningServices--; + break; + + default: + TRACE("Command %lu received", ControlPacket->dwControl); + ScControlService(lpService, ControlPacket); + continue; + } } if (dwRunningServices == 0) @@ -461,9 +459,9 @@ RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName, Service->HandlerFunction = lpHandlerProc; Service->HandlerFunctionEx = NULL; - TRACE("RegisterServiceCtrlHandler returning %lu\n", Service->hService); + TRACE("RegisterServiceCtrlHandler returning %lu\n", Service->hServiceStatus); - return (SERVICE_STATUS_HANDLE)Service->hService; + return Service->hServiceStatus; } @@ -520,9 +518,9 @@ RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName, Service->HandlerFunctionEx = lpHandlerProc; Service->HandlerContext = lpContext; - TRACE("RegisterServiceCtrlHandlerEx returning %lu\n", Service->hService); + TRACE("RegisterServiceCtrlHandlerEx returning %lu\n", Service->hServiceStatus); - return (SERVICE_STATUS_HANDLE)Service->hService; + return Service->hServiceStatus; } @@ -683,7 +681,7 @@ StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA * lpServiceStartTable) RtlCreateUnicodeStringFromAsciiz(&lpActiveServices[i].ServiceName, lpServiceStartTable[i].lpServiceName); lpActiveServices[i].Main.lpFuncA = lpServiceStartTable[i].lpServiceProc; - lpActiveServices[i].hService = (CLIENT_HANDLE)&lpActiveServices[i]; + lpActiveServices[i].hServiceStatus = 0; lpActiveServices[i].bUnicode = FALSE; } @@ -773,7 +771,7 @@ StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW * lpServiceStartTable) RtlCreateUnicodeString(&lpActiveServices[i].ServiceName, lpServiceStartTable[i].lpServiceName); lpActiveServices[i].Main.lpFuncW = lpServiceStartTable[i].lpServiceProc; - lpActiveServices[i].hService = (CLIENT_HANDLE)&lpActiveServices[i]; + lpActiveServices[i].hServiceStatus = 0; lpActiveServices[i].bUnicode = TRUE; } diff --git a/reactos/include/reactos/services/services.h b/reactos/include/reactos/services/services.h index 21a6085bf6c..7c8a972b6e7 100644 --- a/reactos/include/reactos/services/services.h +++ b/reactos/include/reactos/services/services.h @@ -11,12 +11,10 @@ #define SERVICE_CONTROL_START 0 -DECLARE_HANDLE(CLIENT_HANDLE); - typedef struct _SCM_CONTROL_PACKET { DWORD dwControl; - CLIENT_HANDLE hClient; + SERVICE_STATUS_HANDLE hServiceStatus; DWORD dwSize; WCHAR szArguments[1]; } SCM_CONTROL_PACKET, *PSCM_CONTROL_PACKET;