[NTOSKRNL/USERINIT/WIN32K]
[reactos.git] / reactos / base / system / services / database.c
index f33d437..0d7ec77 100644 (file)
@@ -700,7 +700,10 @@ ScmControlService(PSERVICE Service,
                                                    HEAP_ZERO_MEMORY,
                                                    sizeof(SCM_CONTROL_PACKET) + (TotalLength * sizeof(WCHAR)));
     if (ControlPacket == NULL)
+    {
+        LeaveCriticalSection(&ControlServiceCriticalSection);
         return ERROR_NOT_ENOUGH_MEMORY;
+    }
 
     ControlPacket->dwControl = dwControl;
     ControlPacket->dwSize = TotalLength;
@@ -920,7 +923,7 @@ ScmStartUserModeService(PSERVICE Service,
     /* Create '\\.\pipe\net\NtControlPipeXXX' instance */
     swprintf(NtControlPipeName, L"\\\\.\\pipe\\net\\NtControlPipe%u", ServiceCurrent);
 
-    DPRINT1("Service: %p  ImagePath: %wZ  PipeName: %S\n", Service, &ImagePath, NtControlPipeName);
+    DPRINT("Service: %p  ImagePath: %wZ  PipeName: %S\n", Service, &ImagePath, NtControlPipeName);
 
     Service->ControlPipeHandle = CreateNamedPipeW(NtControlPipeName,
                                                   PIPE_ACCESS_DUPLEX,
@@ -1033,16 +1036,17 @@ ScmStartService(PSERVICE Service, DWORD argc, LPWSTR *argv)
 {
     PSERVICE_GROUP Group = Service->lpGroup;
     DWORD dwError = ERROR_SUCCESS;
+    LPCWSTR ErrorLogStrings[2];
 
     DPRINT("ScmStartService() called\n");
 
-    DPRINT1("Start Service %p (%S)\n", Service, Service->lpServiceName);
+    DPRINT("Start Service %p (%S)\n", Service, Service->lpServiceName);
 
     EnterCriticalSection(&ControlServiceCriticalSection);
 
     if (Service->Status.dwCurrentState != SERVICE_STOPPED)
     {
-        DPRINT1("Service %S is already running!\n", Service->lpServiceName);
+        DPRINT("Service %S is already running!\n", Service->lpServiceName);
         LeaveCriticalSection(&ControlServiceCriticalSection);
         return ERROR_SERVICE_ALREADY_RUNNING;
     }
@@ -1085,15 +1089,20 @@ ScmStartService(PSERVICE Service, DWORD argc, LPWSTR *argv)
             Group->ServicesRunning = TRUE;
         }
     }
-#if 0
     else
     {
-        switch (Service->ErrorControl)
+        if (Service->dwErrorControl != SERVICE_ERROR_IGNORE)
         {
-            case SERVICE_ERROR_NORMAL:
-                /* FIXME: Log error */
-                break;
+            ErrorLogStrings[0] = Service->lpServiceName;
+            ErrorLogStrings[1] = L"Test";
+            ScmLogError(EVENT_SERVICE_START_FAILED,
+                        2,
+                        ErrorLogStrings);
+        }
 
+#if 0
+        switch (Service->dwErrorControl)
+        {
             case SERVICE_ERROR_SEVERE:
                 if (IsLastKnownGood == FALSE)
                 {
@@ -1112,8 +1121,8 @@ ScmStartService(PSERVICE Service, DWORD argc, LPWSTR *argv)
                 }
                 break;
         }
-    }
 #endif
+    }
 
     return dwError;
 }
@@ -1126,14 +1135,65 @@ ScmAutoStartServices(VOID)
     PLIST_ENTRY ServiceEntry;
     PSERVICE_GROUP CurrentGroup;
     PSERVICE CurrentService;
+    WCHAR szSafeBootServicePath[MAX_PATH];
+    DWORD dwError;
+    HKEY hKey;
     ULONG i;
 
-    /* Clear 'ServiceVisited' flag */
+    /* Clear 'ServiceVisited' flag (or set if not to start in Safe Mode) */
     ServiceEntry = ServiceListHead.Flink;
     while (ServiceEntry != &ServiceListHead)
     {
       CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
-      CurrentService->ServiceVisited = FALSE;
+        /* Build the safe boot path */
+        wcscpy(szSafeBootServicePath,
+               L"SYSTEM\\CurrentControlSet\\Control\\SafeBoot");
+        switch(GetSystemMetrics(SM_CLEANBOOT))
+        {
+            /* NOTE: Assumes MINIMAL (1) and DSREPAIR (3) load same items */
+            case 1:
+            case 3: wcscat(szSafeBootServicePath, L"\\Minimal\\"); break;
+            case 2: wcscat(szSafeBootServicePath, L"\\Network\\"); break;
+        }
+        if(GetSystemMetrics(SM_CLEANBOOT))
+        {
+            /* If key does not exist then do not assume safe mode */
+            dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                                    szSafeBootServicePath,
+                                    0,
+                                    KEY_READ,
+                                    &hKey);
+            if(dwError == ERROR_SUCCESS)
+            {
+                RegCloseKey(hKey);
+                /* Finish Safe Boot path off */
+                wcsncat(szSafeBootServicePath,
+                        CurrentService->lpServiceName,
+                        MAX_PATH - wcslen(szSafeBootServicePath));
+                /* Check that the key is in the Safe Boot path */
+                dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                                        szSafeBootServicePath,
+                                        0,
+                                        KEY_READ,
+                                        &hKey);
+                if(dwError != ERROR_SUCCESS)
+                {
+                    /* Mark service as visited so it is not auto-started */
+                    CurrentService->ServiceVisited = TRUE;
+                }
+                else
+                {
+                    /* Must be auto-started in safe mode - mark as unvisited */
+                    RegCloseKey(hKey);
+                    CurrentService->ServiceVisited = FALSE;
+                }
+            }
+            else
+            {
+                DPRINT1("WARNING: Could not open the associated Safe Boot key!");
+                CurrentService->ServiceVisited = FALSE;
+            }
+        }
       ServiceEntry = ServiceEntry->Flink;
     }
 
@@ -1239,6 +1299,9 @@ ScmAutoShutdownServices(VOID)
 
     DPRINT("ScmAutoShutdownServices() called\n");
 
+    /* Lock the service database exclusively */
+    ScmLockDatabaseExclusive();
+
     ServiceEntry = ServiceListHead.Flink;
     while (ServiceEntry != &ServiceListHead)
     {
@@ -1248,13 +1311,17 @@ ScmAutoShutdownServices(VOID)
             CurrentService->Status.dwCurrentState == SERVICE_START_PENDING)
         {
             /* shutdown service */
-            ScmControlService(CurrentService, SERVICE_CONTROL_STOP);
+            DPRINT("Shutdown service: %S\n", CurrentService->szServiceName);
+            ScmControlService(CurrentService, SERVICE_CONTROL_SHUTDOWN);
         }
 
         ServiceEntry = ServiceEntry->Flink;
     }
 
-    DPRINT("ScmGetBootAndSystemDriverState() done\n");
+    /* Unlock the service database */
+    ScmUnlockDatabase();
+
+    DPRINT("ScmAutoShutdownServices() done\n");
 }