[SERVICES]
[reactos.git] / reactos / base / system / services / database.c
index ecc9186..95bc302 100644 (file)
 #define NDEBUG
 #include <debug.h>
 
+/*
+ * Uncomment the line below to start services
+ *  using the SERVICE_START_PENDING state
+ */
+// #define USE_SERVICE_START_PENDING
 
 /* GLOBALS *******************************************************************/
 
@@ -30,7 +35,7 @@ static DWORD dwResumeCount = 1;
 
 
 PSERVICE
-ScmGetServiceEntryByName(LPWSTR lpServiceName)
+ScmGetServiceEntryByName(LPCWSTR lpServiceName)
 {
     PLIST_ENTRY ServiceEntry;
     PSERVICE CurrentService;
@@ -59,7 +64,7 @@ ScmGetServiceEntryByName(LPWSTR lpServiceName)
 
 
 PSERVICE
-ScmGetServiceEntryByDisplayName(LPWSTR lpDisplayName)
+ScmGetServiceEntryByDisplayName(LPCWSTR lpDisplayName)
 {
     PLIST_ENTRY ServiceEntry;
     PSERVICE CurrentService;
@@ -116,39 +121,8 @@ ScmGetServiceEntryByResumeCount(DWORD dwResumeCount)
 }
 
 
-PSERVICE
-ScmGetServiceEntryByClientHandle(ULONG Handle)
-{
-    PLIST_ENTRY ServiceEntry;
-    PSERVICE CurrentService;
-
-    DPRINT("ScmGetServiceEntryByClientHandle() called\n");
-    DPRINT("looking for %lu\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;
@@ -191,7 +165,7 @@ ScmCreateNewServiceRecord(LPWSTR lpServiceName,
 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 &&
@@ -215,17 +189,17 @@ ScmDeleteServiceRecord(PSERVICE lpService)
     /* 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;
@@ -446,6 +420,46 @@ ScmDeleteMarkedServices(VOID)
 }
 
 
+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)
 {
@@ -516,6 +530,9 @@ ScmCreateServiceDatabase(VOID)
 
     RegCloseKey(hServicesKey);
 
+    /* Wait for LSA */
+    WaitForLSA();
+
     /* Delete services that are marked for delete */
     ScmDeleteMarkedServices();
 
@@ -680,11 +697,11 @@ 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 start command */
+    /* Send the control packet */
     WriteFile(Service->ControlPipeHandle,
               ControlPacket,
               sizeof(SCM_CONTROL_PACKET) + (TotalLength * sizeof(WCHAR)),
@@ -745,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);
@@ -802,6 +819,7 @@ ScmStartUserModeService(PSERVICE Service,
     WCHAR NtControlPipeName[MAX_PATH + 1];
     HKEY hServiceCurrentKey = INVALID_HANDLE_VALUE;
     DWORD KeyDisposition;
+    DWORD dwProcessId;
 
     RtlInitUnicodeString(&ImagePath, NULL);
 
@@ -896,8 +914,8 @@ ScmStartUserModeService(PSERVICE Service,
     StartupInfo.cbReserved2 = 0;
     StartupInfo.lpReserved2 = 0;
 
-    Result = CreateProcessW(ImagePath.Buffer,
-                            NULL,
+    Result = CreateProcessW(NULL,
+                            ImagePath.Buffer,
                             NULL,
                             NULL,
                             FALSE,
@@ -943,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))
@@ -954,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);
@@ -995,12 +1013,23 @@ ScmStartService(PSERVICE Service, DWORD argc, LPWSTR *argv)
         /* 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);
@@ -1011,7 +1040,6 @@ ScmStartService(PSERVICE Service, DWORD argc, LPWSTR *argv)
         {
             Group->ServicesRunning = TRUE;
         }
-        Service->Status.dwCurrentState = SERVICE_RUNNING;
     }
 #if 0
     else
@@ -1186,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 */