[SERVICES][ADVAPI32] Support the security process aka lsass.exe
[reactos.git] / base / system / services / services.c
index 2edb6e7..8172526 100644 (file)
@@ -12,6 +12,8 @@
 
 #include "services.h"
 
+#include <wincon.h>
+
 #define NDEBUG
 #include <debug.h>
 
@@ -19,11 +21,14 @@ int WINAPI RegisterServicesProcess(DWORD ServicesProcessId);
 
 /* GLOBALS ******************************************************************/
 
-#define PIPE_BUFSIZE 1024
-#define PIPE_TIMEOUT 1000
+/* Defined in include/reactos/services/services.h */
+// #define SCM_START_EVENT             L"SvcctrlStartEvent_A3752DX"
+#define SCM_AUTOSTARTCOMPLETE_EVENT L"SC_AutoStartComplete"
 
+BOOL ScmInitialize = FALSE;
 BOOL ScmShutdown = FALSE;
 static HANDLE hScmShutdownEvent = NULL;
+static HANDLE hScmSecurityServicesEvent = NULL;
 
 
 /* FUNCTIONS *****************************************************************/
@@ -44,8 +49,41 @@ PrintString(LPCSTR fmt, ...)
 }
 
 
+DWORD
+SetSecurityServicesEvent(VOID)
+{
+    DWORD dwError;
+
+    if (hScmSecurityServicesEvent != NULL)
+        return ERROR_SUCCESS;
+
+    /* Create or open the SECURITY_SERVICES_STARTED event */
+    hScmSecurityServicesEvent = CreateEventW(NULL,
+                                             TRUE,
+                                             FALSE,
+                                             L"SECURITY_SERVICES_STARTED");
+    if (hScmSecurityServicesEvent == NULL)
+    {
+        dwError = GetLastError();
+        if (dwError != ERROR_ALREADY_EXISTS)
+            return dwError;
+
+        hScmSecurityServicesEvent = OpenEventW(EVENT_MODIFY_STATE,
+                                               FALSE,
+                                               L"SECURITY_SERVICES_STARTED");
+        if (hScmSecurityServicesEvent == NULL)
+            return GetLastError();
+    }
+
+    SetEvent(hScmSecurityServicesEvent);
+
+    return ERROR_SUCCESS;
+}
+
+
 VOID
-ScmLogError(DWORD dwEventId,
+ScmLogEvent(DWORD dwEventId,
+            WORD wType,
             WORD wStrings,
             LPCWSTR *lpStrings)
 {
@@ -60,10 +98,10 @@ ScmLogError(DWORD dwEventId,
     }
 
     if (!ReportEventW(hLog,
-                      EVENTLOG_ERROR_TYPE,
+                      wType,
                       0,
                       dwEventId,
-                      NULL, // Sid,
+                      NULL,
                       wStrings,
                       0,
                       lpStrings,
@@ -76,250 +114,23 @@ ScmLogError(DWORD dwEventId,
 }
 
 
-BOOL
-ScmCreateStartEvent(PHANDLE StartEvent)
-{
-    HANDLE hEvent;
-
-    hEvent = CreateEventW(NULL,
-                          TRUE,
-                          FALSE,
-                          L"SvcctrlStartEvent_A3752DX");
-    if (hEvent == NULL)
-    {
-        if (GetLastError() == ERROR_ALREADY_EXISTS)
-        {
-            hEvent = OpenEventW(EVENT_ALL_ACCESS,
-                                FALSE,
-                                L"SvcctrlStartEvent_A3752DX");
-            if (hEvent == NULL)
-            {
-                return FALSE;
-            }
-        }
-        else
-        {
-            return FALSE;
-        }
-    }
-
-    *StartEvent = hEvent;
-
-    return TRUE;
-}
-
-
 VOID
 ScmWaitForLsa(VOID)
 {
-    HANDLE hEvent;
-    DWORD dwError;
-
-    hEvent = CreateEventW(NULL,
-                          TRUE,
-                          FALSE,
-                          L"LSA_RPC_SERVER_ACTIVE");
+    HANDLE 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 (Error %lu)\n", GetLastError());
-               return;
-            }
-        }
-    }
-
-    DPRINT("Wait for the LSA server!\n");
-    WaitForSingleObject(hEvent, INFINITE);
-    DPRINT("LSA server running!\n");
-
-    CloseHandle(hEvent);
-
-    DPRINT("ScmWaitForLsa() done\n");
-}
-
-
-BOOL
-ScmNamedPipeHandleRequest(PVOID Request,
-                          DWORD RequestSize,
-                          PVOID Reply,
-                          LPDWORD ReplySize)
-{
-    DbgPrint("SCM READ: %p\n", Request);
-
-    *ReplySize = 0;
-    return FALSE;
-}
-
-
-DWORD WINAPI
-ScmNamedPipeThread(LPVOID Context)
-{
-    CHAR chRequest[PIPE_BUFSIZE];
-    CHAR chReply[PIPE_BUFSIZE];
-    DWORD cbReplyBytes;
-    DWORD cbBytesRead;
-    DWORD cbWritten;
-    BOOL bSuccess;
-    HANDLE hPipe;
-
-    hPipe = (HANDLE)Context;
-
-    DPRINT("ScmNamedPipeThread(%p) - Accepting SCM commands through named pipe\n", hPipe);
-
-    for (;;)
-    {
-        bSuccess = ReadFile(hPipe,
-                            &chRequest,
-                            PIPE_BUFSIZE,
-                            &cbBytesRead,
-                            NULL);
-        if (!bSuccess || cbBytesRead == 0)
-        {
-            break;
-        }
-
-        if (ScmNamedPipeHandleRequest(&chRequest, cbBytesRead, &chReply, &cbReplyBytes))
-        {
-            bSuccess = WriteFile(hPipe,
-                                 &chReply,
-                                 cbReplyBytes,
-                                 &cbWritten,
-                                 NULL);
-            if (!bSuccess || cbReplyBytes != cbWritten)
-            {
-                break;
-            }
-        }
-    }
-
-    DPRINT("ScmNamedPipeThread(%p) - Disconnecting named pipe connection\n", hPipe);
-
-    FlushFileBuffers(hPipe);
-    DisconnectNamedPipe(hPipe);
-    CloseHandle(hPipe);
-
-    DPRINT("ScmNamedPipeThread(%p) - Done.\n", hPipe);
-
-    return ERROR_SUCCESS;
-}
-
-
-BOOL
-ScmCreateNamedPipe(VOID)
-{
-    DWORD dwThreadId;
-    BOOL bConnected;
-    HANDLE hThread;
-    HANDLE hPipe;
-
-    DPRINT("ScmCreateNamedPipe() - CreateNamedPipe(\"\\\\.\\pipe\\Ntsvcs\")\n");
-
-    hPipe = CreateNamedPipeW(L"\\\\.\\pipe\\Ntsvcs",
-              PIPE_ACCESS_DUPLEX,
-              PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
-              PIPE_UNLIMITED_INSTANCES,
-              PIPE_BUFSIZE,
-              PIPE_BUFSIZE,
-              PIPE_TIMEOUT,
-              NULL);
-    if (hPipe == INVALID_HANDLE_VALUE)
-    {
-        DPRINT("CreateNamedPipe() failed (%lu)\n", GetLastError());
-        return FALSE;
-    }
-
-    DPRINT("CreateNamedPipe() - calling ConnectNamedPipe(%p)\n", hPipe);
-    bConnected = ConnectNamedPipe(hPipe,
-                                  NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
-    DPRINT("CreateNamedPipe() - ConnectNamedPipe() returned %d\n", bConnected);
-
-    if (bConnected)
-    {
-        DPRINT("Pipe connected\n");
-        hThread = CreateThread(NULL,
-                               0,
-                               ScmNamedPipeThread,
-                               (LPVOID)hPipe,
-                               0,
-                               &dwThreadId);
-        if (!hThread)
-        {
-            DPRINT("Could not create thread (%lu)\n", GetLastError());
-            DisconnectNamedPipe(hPipe);
-            CloseHandle(hPipe);
-            DPRINT("CreateNamedPipe() - returning FALSE\n");
-            return FALSE;
-        }
-
-        CloseHandle(hThread);
+        DPRINT1("Failed to create or open the notification event (Error %lu)\n", GetLastError());
     }
     else
     {
-        DPRINT("Pipe not connected\n");
-        CloseHandle(hPipe);
-        DPRINT("CreateNamedPipe() - returning FALSE\n");
-        return FALSE;
-    }
-    DPRINT("CreateNamedPipe() - returning TRUE\n");
-    return TRUE;
-}
-
-
-DWORD WINAPI
-ScmNamedPipeListenerThread(LPVOID Context)
-{
-//    HANDLE hPipe;
-    DPRINT("ScmNamedPipeListenerThread(%p) - aka SCM.\n", Context);
-
-//    hPipe = (HANDLE)Context;
-    for (;;)
-    {
-        DPRINT("SCM: Waiting for new connection on named pipe...\n");
-        /* Create named pipe */
-        if (!ScmCreateNamedPipe())
-        {
-            DPRINT1("\nSCM: Failed to create named pipe\n");
-            break;
-            //ExitThread(0);
-        }
-        DPRINT("\nSCM: named pipe session created.\n");
-        Sleep(10);
-    }
-    DPRINT("\n\nWARNING: ScmNamedPipeListenerThread(%p) - Aborted.\n\n", Context);
-    return ERROR_SUCCESS;
-}
-
-
-BOOL
-StartScmNamedPipeThreadListener(VOID)
-{
-    DWORD dwThreadId;
-    HANDLE hThread;
-
-    hThread = CreateThread(NULL,
-                           0,
-                           ScmNamedPipeListenerThread,
-                           NULL, /*(LPVOID)hPipe,*/
-                           0,
-                           &dwThreadId);
-    if (!hThread)
-    {
-        DPRINT1("SERVICES: Could not create thread (Status %lx)\n", GetLastError());
-        return FALSE;
+        DPRINT("Wait for the LSA server!\n");
+        WaitForSingleObject(hEvent, INFINITE);
+        DPRINT("LSA server running!\n");
+        CloseHandle(hEvent);
     }
 
-    CloseHandle(hThread);
-
-    return TRUE;
+    DPRINT("ScmWaitForLsa() done\n");
 }
 
 
@@ -336,7 +147,7 @@ ShutdownHandlerRoutine(DWORD dwCtrlType)
         ScmAutoShutdownServices();
         ScmShutdownServiceDatabase();
 
-        /* Set the shutdwon event */
+        /* Set the shutdown event */
         SetEvent(hScmShutdownEvent);
     }
 
@@ -351,26 +162,42 @@ wWinMain(HINSTANCE hInstance,
          int nShowCmd)
 {
     HANDLE hScmStartEvent = NULL;
+    HANDLE hScmAutoStartCompleteEvent = NULL;
     SC_RPC_LOCK Lock = NULL;
     BOOL bCanDeleteNamedPipeCriticalSection = FALSE;
     DWORD dwError;
 
     DPRINT("SERVICES: Service Control Manager\n");
 
-    /* Create start event */
-    if (!ScmCreateStartEvent(&hScmStartEvent))
+    /* Make us critical */
+    RtlSetProcessIsCritical(TRUE, NULL, TRUE);
+
+    /* We are initializing ourselves */
+    ScmInitialize = TRUE;
+
+    /* Create the start event */
+    hScmStartEvent = CreateEventW(NULL, TRUE, FALSE, SCM_START_EVENT);
+    if (hScmStartEvent == NULL)
     {
-        DPRINT1("SERVICES: Failed to create start event\n");
+        DPRINT1("SERVICES: Failed to create the start event\n");
         goto done;
     }
+    DPRINT("SERVICES: Created start event with handle %p.\n", hScmStartEvent);
 
-    DPRINT("SERVICES: created start event with handle %p.\n", hScmStartEvent);
+    /* Create the auto-start complete event */
+    hScmAutoStartCompleteEvent = CreateEventW(NULL, TRUE, FALSE, SCM_AUTOSTARTCOMPLETE_EVENT);
+    if (hScmAutoStartCompleteEvent == NULL)
+    {
+        DPRINT1("SERVICES: Failed to create the auto-start complete event\n");
+        goto done;
+    }
+    DPRINT("SERVICES: created auto-start complete event with handle %p.\n", hScmAutoStartCompleteEvent);
 
     /* Create the shutdown event */
-    hScmShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+    hScmShutdownEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
     if (hScmShutdownEvent == NULL)
     {
-        DPRINT1("SERVICES: Failed to create shutdown event\n");
+        DPRINT1("SERVICES: Failed to create the shutdown event\n");
         goto done;
     }
 
@@ -380,12 +207,15 @@ wWinMain(HINSTANCE hInstance,
 
 //    ScmInitThreadManager();
 
+    ScmInitializeSecurity();
+
     /* FIXME: more initialization */
 
-    /* Read the control set values */
-    if (!ScmGetControlSetValues())
+    /* Create the 'Last Known Good' control set */
+    dwError = ScmCreateLastKnownGoodControlSet();
+    if (dwError != ERROR_SUCCESS)
     {
-        DPRINT1("SERVICES: failed to read the control set values\n");
+        DPRINT1("SERVICES: Failed to create the 'Last Known Good' control set (Error %lu)\n", dwError);
         goto done;
     }
 
@@ -393,64 +223,85 @@ wWinMain(HINSTANCE hInstance,
     dwError = ScmCreateServiceDatabase();
     if (dwError != ERROR_SUCCESS)
     {
-        DPRINT1("SERVICES: failed to create SCM database (Error %lu)\n", dwError);
+        DPRINT1("SERVICES: Failed to create SCM database (Error %lu)\n", dwError);
         goto done;
     }
 
     /* Update the services database */
     ScmGetBootAndSystemDriverState();
 
-    /* Register the Service Control Manager process with CSRSS */
+    /* Register the Service Control Manager process with the ReactOS Subsystem */
     if (!RegisterServicesProcess(GetCurrentProcessId()))
     {
         DPRINT1("SERVICES: Could not register SCM process\n");
         goto done;
     }
 
-    /* Acquire the service start lock until autostart services have been started */
+    /*
+     * Acquire the user service start lock until
+     * auto-start services have been started.
+     */
     dwError = ScmAcquireServiceStartLock(TRUE, &Lock);
     if (dwError != ERROR_SUCCESS)
     {
-        DPRINT1("SERVICES: failed to acquire the service start lock (Error %lu)\n", dwError);
+        DPRINT1("SERVICES: Failed to acquire the service start lock (Error %lu)\n", dwError);
         goto done;
     }
 
     /* Start the RPC server */
     ScmStartRpcServer();
 
-    DPRINT("SERVICES: Initialized.\n");
-
     /* Signal start event */
     SetEvent(hScmStartEvent);
 
+    DPRINT("SERVICES: Initialized.\n");
+
     /* Register event handler (used for system shutdown) */
     SetConsoleCtrlHandler(ShutdownHandlerRoutine, TRUE);
 
-    /* Wait for the LSA server */
-    ScmWaitForLsa();
+    /*
+     * Set our shutdown parameters: we want to shutdown after the maintained
+     * services (that inherit the default shutdown level of 640).
+     */
+    SetProcessShutdownParameters(480, SHUTDOWN_NORETRY);
 
     /* Start auto-start services */
     ScmAutoStartServices();
 
+    /* Signal auto-start complete event */
+    SetEvent(hScmAutoStartCompleteEvent);
+
     /* FIXME: more to do ? */
 
     /* Release the service start lock */
     ScmReleaseServiceStartLock(&Lock);
 
+    /* Initialization finished */
+    ScmInitialize = FALSE;
+
     DPRINT("SERVICES: Running.\n");
 
     /* Wait until the shutdown event gets signaled */
     WaitForSingleObject(hScmShutdownEvent, INFINITE);
 
 done:
+    ScmShutdownSecurity();
+
     /* Delete our communication named pipe's critical section */
-    if (bCanDeleteNamedPipeCriticalSection == TRUE)
+    if (bCanDeleteNamedPipeCriticalSection != FALSE)
         ScmDeleteNamedPipeCriticalSection();
 
+    if (hScmSecurityServicesEvent != NULL)
+        CloseHandle(hScmSecurityServicesEvent);
+
     /* Close the shutdown event */
     if (hScmShutdownEvent != NULL)
         CloseHandle(hScmShutdownEvent);
 
+    /* Close the auto-start complete event */
+    if (hScmAutoStartCompleteEvent != NULL)
+        CloseHandle(hScmAutoStartCompleteEvent);
+
     /* Close the start event */
     if (hScmStartEvent != NULL)
         CloseHandle(hScmStartEvent);
@@ -458,7 +309,6 @@ done:
     DPRINT("SERVICES: Finished.\n");
 
     ExitThread(0);
-
     return 0;
 }