[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:
Eric Kohl 2010-02-27 21:47:59 +00:00
parent 763962665e
commit 9e6714ef3b
5 changed files with 85 additions and 88 deletions

View file

@ -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 */

View file

@ -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");

View file

@ -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);

View file

@ -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;
}

View file

@ -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;