First shot at CreateServiceW. It crashes due to a bug (aka missing feature) in widl...
[reactos.git] / reactos / subsys / system / services / services.c
index 07eb294..8235c50 100644 (file)
@@ -1,9 +1,8 @@
-/* $Id: services.c,v 1.3 2001/03/26 20:46:52 dwelch Exp $
- *
+/*
  * service control manager
- * 
+ *
  * ReactOS Operating System
- * 
+ *
  * --------------------------------------------------------------------
  *
  * This software is free software; you can redistribute it and/or
@@ -19,7 +18,7 @@
  * You should have received a copy of the GNU General Public License
  * along with this software; see the file COPYING.LIB. If not, write
  * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
- * MA 02139, USA.  
+ * MA 02139, USA.
  *
  */
 
 
 /* INCLUDES *****************************************************************/
 
-#define NTOS_MODE_USER
-#include <ntos.h>
 #include <windows.h>
+#define NTOS_MODE_USER
+#include <ndk/ntndk.h>
+
+#include "services.h"
 
-#include <services/services.h>
+#define NDEBUG
+#include <debug.h>
+
+int WINAPI RegisterServicesProcess(DWORD ServicesProcessId);
 
 /* GLOBALS ******************************************************************/
 
+#define PIPE_BUFSIZE 1024
+#define PIPE_TIMEOUT 1000
 
 
 /* FUNCTIONS *****************************************************************/
 
-void PrintString (char* fmt,...)
+VOID
+PrintString(LPCSTR fmt, ...)
+{
+#ifdef DBG
+  CHAR buffer[512];
+  va_list ap;
+
+  va_start(ap, fmt);
+  vsprintf(buffer, fmt, ap);
+  va_end(ap);
+
+  OutputDebugStringA(buffer);
+#endif
+}
+
+
+BOOL
+ScmCreateStartEvent(PHANDLE StartEvent)
+{
+  HANDLE hEvent;
+
+  hEvent = CreateEvent(NULL,
+                       TRUE,
+                       FALSE,
+                       TEXT("SvcctrlStartEvent_A3725DX"));
+  if (hEvent == NULL)
+  {
+    if (GetLastError() == ERROR_ALREADY_EXISTS)
+    {
+      hEvent = OpenEvent(EVENT_ALL_ACCESS,
+                         FALSE,
+                         TEXT("SvcctrlStartEvent_A3725DX"));
+      if (hEvent == NULL)
+      {
+        return FALSE;
+      }
+    }
+    else
+    {
+      return FALSE;
+    }
+  }
+
+  *StartEvent = hEvent;
+
+  return TRUE;
+}
+
+
+BOOL
+ScmNamedPipeHandleRequest(PVOID Request,
+                         DWORD RequestSize,
+                         PVOID Reply,
+                         LPDWORD ReplySize)
+{
+  DbgPrint("SCM READ: %s\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 fSuccess;
+    HANDLE hPipe;
+
+    hPipe = (HANDLE)Context;
+
+    DPRINT("ScmNamedPipeThread(%x) - Accepting SCM commands through named pipe\n", hPipe);
+
+    for (;;) {
+        fSuccess = ReadFile(hPipe,
+                            &chRequest,
+                            PIPE_BUFSIZE,
+                            &cbBytesRead,
+                            NULL);
+        if (!fSuccess || cbBytesRead == 0) {
+            break;
+        }
+        if (ScmNamedPipeHandleRequest(&chRequest, cbBytesRead, &chReply, &cbReplyBytes)) {
+            fSuccess = WriteFile(hPipe,
+                                 &chReply,
+                                 cbReplyBytes,
+                                 &cbWritten,
+                                 NULL);
+            if (!fSuccess || cbReplyBytes != cbWritten) {
+                break;
+            }
+        }
+    }
+    DPRINT("ScmNamedPipeThread(%x) - Disconnecting named pipe connection\n", hPipe);
+    FlushFileBuffers(hPipe);
+    DisconnectNamedPipe(hPipe);
+    CloseHandle(hPipe);
+    DPRINT("ScmNamedPipeThread(%x) - Done.\n", hPipe);
+    return ERROR_SUCCESS;
+}
+
+
+BOOL
+ScmCreateNamedPipe(VOID)
 {
-   char buffer[512];
-   va_list ap;
+    DWORD dwThreadId;
+    BOOL fConnected;
+    HANDLE hThread;
+    HANDLE hPipe;
+
+    DPRINT("ScmCreateNamedPipe() - CreateNamedPipe(\"\\\\.\\pipe\\Ntsvcs\")\n");
+
+    hPipe = CreateNamedPipe(TEXT("\\\\.\\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 (%d)\n", GetLastError());
+        return FALSE;
+    }
+
+    DPRINT("CreateNamedPipe() - calling ConnectNamedPipe(%x)\n", hPipe);
+    fConnected = ConnectNamedPipe(hPipe,
+                   NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
+    DPRINT("CreateNamedPipe() - ConnectNamedPipe() returned %d\n", fConnected);
+
+    if (fConnected) {
+        DPRINT("Pipe connected\n");
+        hThread = CreateThread(NULL,
+                               0,
+                               ScmNamedPipeThread,
+                               (LPVOID)hPipe,
+                               0,
+                               &dwThreadId);
+        if (!hThread) {
+            DPRINT("Could not create thread (%d)\n", GetLastError());
+            DisconnectNamedPipe(hPipe);
+            CloseHandle(hPipe);
+            DPRINT("CreateNamedPipe() - returning FALSE\n");
+           return FALSE;
+        }
+    } else {
+        DPRINT("Pipe not connected\n");
+        CloseHandle(hPipe);
+        DPRINT("CreateNamedPipe() - returning FALSE\n");
+        return FALSE;
+    }
+    DPRINT("CreateNamedPipe() - returning TRUE\n");
+    return TRUE;
+}
 
-   va_start(ap, fmt);
-   vsprintf(buffer, fmt, ap);
-   va_end(ap);
 
-   OutputDebugString(buffer);
+DWORD WINAPI
+ScmNamedPipeListenerThread(LPVOID Context)
+{
+//    HANDLE hPipe;
+    DPRINT("ScmNamedPipeListenerThread(%x) - 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(%x) - Aborted.\n\n", Context);
+    return ERROR_SUCCESS;
 }
 
 
-BOOL ScmCreateStartEvent(PHANDLE StartEvent)
+BOOL
+StartScmNamedPipeThreadListener(VOID)
 {
-   HANDLE hEvent;
-
-   hEvent = CreateEvent(NULL,
-                       TRUE,
-                       FALSE,
-                       _T("SvcctrlStartEvent_A3725DX"));
-   if (hEvent == NULL)
-     {
-       if (GetLastError() == ERROR_ALREADY_EXISTS)
-         {
-            hEvent = OpenEvent(EVENT_ALL_ACCESS,
-                               FALSE,
-                               "SvcctrlStartEvent_A3725DX");
-            if (hEvent == NULL)
-              {
-                 return FALSE;
-              }
-         }
-       else
-         {
-            return FALSE;
-         }
-     }
-
-   *StartEvent = hEvent;
-
-   return TRUE;
+  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;
+  }
+
+  return TRUE;
+}
+
+
+VOID FASTCALL
+AcquireLoadDriverPrivilege(VOID)
+{
+  HANDLE hToken;
+  TOKEN_PRIVILEGES tkp;
+
+  /* Get a token for this process */
+  if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
+  {
+    /* Get the LUID for the debug privilege */
+    LookupPrivilegeValue(NULL, SE_LOAD_DRIVER_NAME, &tkp.Privileges[0].Luid);
+
+    /* One privilege to set */
+    tkp.PrivilegeCount = 1;
+    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+    /* Get the debug privilege for this process */
+    AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
+  }
 }
 
 
 int STDCALL
 WinMain(HINSTANCE hInstance,
-       HINSTANCE hPrevInstance,
-       LPSTR lpCmdLine,
-       int nShowCmd)
+        HINSTANCE hPrevInstance,
+        LPSTR lpCmdLine,
+        int nShowCmd)
 {
-   HANDLE hScmStartEvent;
-   HANDLE hEvent;
-   
-   PrintString("Service Control Manager\n");
-   
-   /* Create start event */
-   if (!ScmCreateStartEvent(&hScmStartEvent))
-     {
-       PrintString("SERVICES: Failed to create start event\n");
-       ExitThread(0);
-     }
-   
+  HANDLE hScmStartEvent;
+  HANDLE hEvent;
+  NTSTATUS Status;
 
+  DPRINT("SERVICES: Service Control Manager\n");
 
+  /* Acquire privileges to load drivers */
+  AcquireLoadDriverPrivilege();
 
-   /* FIXME: more initialization */
+  /* Create start event */
+  if (!ScmCreateStartEvent(&hScmStartEvent))
+  {
+    DPRINT1("SERVICES: Failed to create start event\n");
+    ExitThread(0);
+  }
 
-   /* FIXME: create service database */
-//   ScmCreateServiceDB();
+  DPRINT("SERVICES: created start event with handle %x.\n", hScmStartEvent);
 
-   /* FIXME: update service database */
-//   ScmGetBootAndSystemDriverState();
+//  ScmInitThreadManager();
 
-   /* FIXME: create pipe "\Pipe\Ntsvcs" */
+  /* FIXME: more initialization */
 
-   /* FIXME: create listener thread for pipe */
 
-   /* FIXME: register process as service process */
-//   RegisterServiceProcess();
+  /* Create the service database */
+  Status = ScmCreateServiceDataBase();
+  if (!NT_SUCCESS(Status))
+  {
+    DPRINT1("SERVICES: failed to create SCM database (Status %lx)\n", Status);
+    ExitThread(0);
+  }
 
-   PrintString("SERVICES: Initialized.\n");
+  /* Update service database */
+  ScmGetBootAndSystemDriverState();
 
-   /* Signal start event */
-   SetEvent(hScmStartEvent);
+  /* Start the RPC server */
+  ScmStartRpcServer();
 
-   /* FIXME: register event handler (used for system shutdown) */
-//   SetConsoleCtrlHandler(...);
+  /* Register service process with CSRSS */
+//  RegisterServicesProcess(GetCurrentProcessId());
 
+  DPRINT("SERVICES: Initialized.\n");
 
-   /* FIXME: start auto-start services */
-//   ScmAutoStartServices();
+  /* Signal start event */
+  SetEvent(hScmStartEvent);
 
-   /* FIXME: more to do ? */
+#if 0
+  /* FIXME: register event handler (used for system shutdown) */
+  SetConsoleCtrlHandler(...);
+#endif
 
+  /* Start auto-start services */
+  ScmAutoStartServices();
 
-   PrintString("SERVICES: Running.\n");
-   
-   hEvent = CreateEvent(NULL,
-                       TRUE,
-                       FALSE,
-                       NULL);
-   WaitForSingleObject(hEvent, INFINITE);
-#if 0
-    for (;;)
-      {
-       NtYieldExecution();
-      }
+  /* FIXME: more to do ? */
+
+
+  DPRINT("SERVICES: Running.\n");
+
+#if 1
+  hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+  WaitForSingleObject(hEvent, INFINITE);
+#else
+  for (;;)
+  {
+    NtYieldExecution();
+  }
 #endif
 
-   PrintString("SERVICES: Finished.\n");
+  DPRINT("SERVICES: Finished.\n");
+
+  ExitThread(0);
 
-   ExitThread (0);
-   return 0;
+  return 0;
 }
 
 /* EOF */