mirror of
https://github.com/reactos/reactos.git
synced 2025-05-24 19:56:38 +00:00
[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
This commit is contained in:
parent
763962665e
commit
9e6714ef3b
5 changed files with 85 additions and 88 deletions
|
@ -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 */
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
/* 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(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(ControlPacket);
|
||||
continue;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue