#define NDEBUG
#include <debug.h>
+/*
+ * Uncomment the line below to start services
+ * using the SERVICE_START_PENDING state
+ */
+// #define USE_SERVICE_START_PENDING
/* GLOBALS *******************************************************************/
static RTL_RESOURCE DatabaseLock;
static DWORD dwResumeCount = 1;
+static CRITICAL_SECTION NamedPipeCriticalSection;
+static CRITICAL_SECTION StartServiceCriticalSection;
/* FUNCTIONS *****************************************************************/
PSERVICE
-ScmGetServiceEntryByName(LPWSTR lpServiceName)
+ScmGetServiceEntryByName(LPCWSTR lpServiceName)
{
PLIST_ENTRY ServiceEntry;
PSERVICE CurrentService;
PSERVICE
-ScmGetServiceEntryByDisplayName(LPWSTR lpDisplayName)
+ScmGetServiceEntryByDisplayName(LPCWSTR lpDisplayName)
{
PLIST_ENTRY ServiceEntry;
PSERVICE CurrentService;
}
-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(LPWSTR lpServiceName,
+ScmCreateNewServiceRecord(LPCWSTR lpServiceName,
PSERVICE *lpServiceRecord)
{
PSERVICE lpService = NULL;
VOID
ScmDeleteServiceRecord(PSERVICE lpService)
{
- DPRINT1("Deleting Service %S\n", lpService->lpServiceName);
+ DPRINT("Deleting Service %S\n", lpService->lpServiceName);
/* Delete the display name */
if (lpService->lpDisplayName != NULL &&
/* Remove the Service from the List */
RemoveEntryList(&lpService->ServiceListEntry);
- DPRINT1("Deleted Service %S\n", lpService->lpServiceName);
+ DPRINT("Deleted Service %S\n", lpService->lpServiceName);
/* Delete the service record */
HeapFree(GetProcessHeap(), 0, lpService);
- DPRINT1("Done\n");
+ DPRINT("Done\n");
}
static DWORD
-CreateServiceListEntry(LPWSTR lpServiceName,
+CreateServiceListEntry(LPCWSTR lpServiceName,
HKEY hServiceKey)
{
PSERVICE lpService = NULL;
}
+VOID
+WaitForLSA(VOID)
+{
+ HANDLE hEvent;
+ DWORD dwError;
+
+ DPRINT("WaitForLSA() called\n");
+
+ hEvent = CreateEventW(NULL,
+ TRUE,
+ FALSE,
+ L"LSA_RPC_SERVER_ACTIVE");
+ if (hEvent == NULL)
+ {
+ dwError = GetLastError();
+ DPRINT1("Failed to create the notication event (Error %lu)\n", dwError);
+
+ if (dwError == ERROR_ALREADY_EXISTS)
+ {
+ hEvent = OpenEventW(SYNCHRONIZE,
+ FALSE,
+ L"LSA_RPC_SERVER_ACTIVE");
+ if (hEvent != NULL)
+ {
+ DPRINT1("Could not open the notification event!\n");
+ return;
+ }
+ }
+ }
+
+ DPRINT("Wait for LSA!\n");
+ WaitForSingleObject(hEvent, INFINITE);
+ DPRINT("LSA is available!\n");
+
+ CloseHandle(hEvent);
+
+ DPRINT("WaitForLSA() done\n");
+}
+
+
DWORD
ScmCreateServiceDatabase(VOID)
{
RegCloseKey(hServicesKey);
+ /* Wait for LSA */
+ WaitForLSA();
+
/* Delete services that are marked for delete */
ScmDeleteMarkedServices();
DWORD
ScmControlService(PSERVICE Service,
- DWORD dwControl,
- LPSERVICE_STATUS lpServiceStatus)
+ DWORD dwControl)
{
PSCM_CONTROL_PACKET ControlPacket;
- DWORD Count;
+ SCM_REPLY_PACKET ReplyPacket;
+
+ DWORD dwWriteCount = 0;
+ DWORD dwReadCount = 0;
DWORD TotalLength;
+ DWORD dwError = ERROR_SUCCESS;
DPRINT("ScmControlService() called\n");
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 start command */
+ EnterCriticalSection(&NamedPipeCriticalSection);
+
+ /* Send the control packet */
WriteFile(Service->ControlPipeHandle,
ControlPacket,
sizeof(SCM_CONTROL_PACKET) + (TotalLength * sizeof(WCHAR)),
- &Count,
+ &dwWriteCount,
NULL);
- /* FIXME: Read the reply */
+ /* Read the reply */
+ ReadFile(Service->ControlPipeHandle,
+ &ReplyPacket,
+ sizeof(SCM_REPLY_PACKET),
+ &dwReadCount,
+ NULL);
+
+ LeaveCriticalSection(&NamedPipeCriticalSection);
/* Release the contol packet */
HeapFree(GetProcessHeap(),
0,
ControlPacket);
- RtlCopyMemory(lpServiceStatus,
- &Service->Status,
- sizeof(SERVICE_STATUS));
+ if (dwReadCount == sizeof(SCM_REPLY_PACKET))
+ {
+ dwError = ReplyPacket.dwError;
+ }
- DPRINT("ScmControlService) done\n");
+ DPRINT("ScmControlService() done\n");
- return ERROR_SUCCESS;
+ return dwError;
}
LPWSTR *argv)
{
PSCM_CONTROL_PACKET ControlPacket;
+ SCM_REPLY_PACKET ReplyPacket;
DWORD TotalLength;
DWORD ArgsLength = 0;
DWORD Length;
PWSTR Ptr;
- DWORD Count;
+ DWORD dwWriteCount = 0;
+ DWORD dwReadCount = 0;
+ DWORD dwError = ERROR_SUCCESS;
+ DWORD i;
DPRINT("ScmSendStartCommand() called\n");
TotalLength = wcslen(Service->lpServiceName) + 1;
if (argc > 0)
{
- for (Count = 0; Count < argc; Count++)
+ for (i = 0; i < argc; i++)
{
- DPRINT("Arg: %S\n", argv[Count]);
- Length = wcslen(argv[Count]) + 1;
+ DPRINT("Arg: %S\n", argv[i]);
+ Length = wcslen(argv[i]) + 1;
TotalLength += Length;
ArgsLength += Length;
}
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);
/* Terminate the argument list */
*Ptr = 0;
+ EnterCriticalSection(&NamedPipeCriticalSection);
+
/* Send the start command */
WriteFile(Service->ControlPipeHandle,
ControlPacket,
sizeof(SCM_CONTROL_PACKET) + (TotalLength - 1) * sizeof(WCHAR),
- &Count,
+ &dwWriteCount,
NULL);
- /* FIXME: Read the reply */
+ /* Read the reply */
+ ReadFile(Service->ControlPipeHandle,
+ &ReplyPacket,
+ sizeof(SCM_REPLY_PACKET),
+ &dwReadCount,
+ NULL);
+
+ LeaveCriticalSection(&NamedPipeCriticalSection);
/* Release the contol packet */
HeapFree(GetProcessHeap(),
0,
ControlPacket);
+ if (dwReadCount == sizeof(SCM_REPLY_PACKET))
+ {
+ dwError = ReplyPacket.dwError;
+ }
+
DPRINT("ScmSendStartCommand() done\n");
- return ERROR_SUCCESS;
+ return dwError;
}
WCHAR NtControlPipeName[MAX_PATH + 1];
HKEY hServiceCurrentKey = INVALID_HANDLE_VALUE;
DWORD KeyDisposition;
+ DWORD dwProcessId;
RtlInitUnicodeString(&ImagePath, NULL);
/* Read SERVICE_STATUS_HANDLE from pipe */
if (!ReadFile(Service->ControlPipeHandle,
- (LPVOID)&Service->hClient,
+ (LPVOID)&dwProcessId,
sizeof(DWORD),
&dwRead,
NULL))
}
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);
PSERVICE_GROUP Group = Service->lpGroup;
DWORD dwError = ERROR_SUCCESS;
+ EnterCriticalSection(&StartServiceCriticalSection);
+
DPRINT("ScmStartService() called\n");
Service->ControlPipeHandle = INVALID_HANDLE_VALUE;
/* Load driver */
dwError = ScmLoadDriver(Service);
if (dwError == ERROR_SUCCESS)
+ {
Service->Status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
+ Service->Status.dwCurrentState = SERVICE_RUNNING;
+ }
}
else
{
/* Start user-mode service */
dwError = ScmStartUserModeService(Service, argc, argv);
+ if (dwError == ERROR_SUCCESS)
+ {
+#ifdef USE_SERVICE_START_PENDING
+ Service->Status.dwCurrentState = SERVICE_START_PENDING;
+#else
+ Service->Status.dwCurrentState = SERVICE_RUNNING;
+#endif
+ }
}
DPRINT("ScmStartService() done (Error %lu)\n", dwError);
+ LeaveCriticalSection(&StartServiceCriticalSection);
if (dwError == ERROR_SUCCESS)
{
{
Group->ServicesRunning = TRUE;
}
- Service->Status.dwCurrentState = SERVICE_RUNNING;
}
#if 0
else
{
PLIST_ENTRY ServiceEntry;
PSERVICE CurrentService;
- SERVICE_STATUS ServiceStatus;
DPRINT("ScmAutoShutdownServices() called\n");
CurrentService->Status.dwCurrentState == SERVICE_START_PENDING)
{
/* shutdown service */
- ScmControlService(CurrentService, SERVICE_CONTROL_STOP, &ServiceStatus);
+ ScmControlService(CurrentService, SERVICE_CONTROL_STOP);
}
ServiceEntry = ServiceEntry->Flink;
DPRINT("ScmGetBootAndSystemDriverState() done\n");
}
+
+BOOL
+ScmLockDatabaseExclusive(VOID)
+{
+ return RtlAcquireResourceExclusive(&DatabaseLock, TRUE);
+}
+
+
+BOOL
+ScmLockDatabaseShared(VOID)
+{
+ return RtlAcquireResourceShared(&DatabaseLock, TRUE);
+}
+
+
+VOID
+ScmUnlockDatabase(VOID)
+{
+ RtlReleaseResource(&DatabaseLock);
+}
+
+
+VOID
+ScmInitNamedPipeCriticalSection(VOID)
+{
+ InitializeCriticalSection(&NamedPipeCriticalSection);
+ InitializeCriticalSection(&StartServiceCriticalSection);
+}
+
+
+VOID
+ScmDeleteNamedPipeCriticalSection(VOID)
+{
+ DeleteCriticalSection(&StartServiceCriticalSection);
+ DeleteCriticalSection(&NamedPipeCriticalSection);
+}
+
/* EOF */