Fix so reactos can boot to gui again Thx W3seek for his small patch
[reactos.git] / reactos / subsys / csrss / init.c
index d5d1e0b..cdffec5 100644 (file)
@@ -1,5 +1,5 @@
-/* $Id: init.c,v 1.23 2003/11/17 02:12:51 hyperion Exp $
- * 
+/* $Id$
+ *
  * reactos/subsys/csrss/init.c
  *
  * Initialize the CSRSS subsystem server process.
 
 /* INCLUDES ******************************************************************/
 
-#include <ddk/ntddk.h>
-#include <ntdll/rtl.h>
-#include <csrss/csrss.h>
-#include <win32k/win32k.h>
-#include <rosrtl/string.h>
-
-#include "api.h"
+#include <csrss.h>
 
 #define NDEBUG
 #include <debug.h>
 
 /* GLOBALS ******************************************************************/
 
-/*
- * Server's named ports.
+HANDLE CsrHeap = (HANDLE) 0;
+
+HANDLE CsrObjectDirectory = (HANDLE) 0;
+
+UNICODE_STRING CsrDirectoryName;
+
+extern HANDLE CsrssApiHeap;
+
+static unsigned InitCompleteProcCount;
+static CSRPLUGIN_INIT_COMPLETE_PROC *InitCompleteProcs = NULL;
+
+HANDLE hSbApiPort = (HANDLE) 0;
+
+HANDLE hBootstrapOk = (HANDLE) 0;
+
+HANDLE hSmApiPort = (HANDLE) 0;
+
+HANDLE hApiPort = (HANDLE) 0;
+
+/**********************************************************************
+ * CsrpAddInitCompleteProc/1
  */
-static HANDLE ApiPortHandle;
+static NTSTATUS FASTCALL
+CsrpAddInitCompleteProc(CSRPLUGIN_INIT_COMPLETE_PROC Proc)
+{
+  CSRPLUGIN_INIT_COMPLETE_PROC *NewProcs;
+
+  DPRINT("CSR: %s called\n", __FUNCTION__);
+
+  NewProcs = RtlAllocateHeap(CsrssApiHeap, 0,
+                             (InitCompleteProcCount + 1)
+                             * sizeof(CSRPLUGIN_INIT_COMPLETE_PROC));
+  if (NULL == NewProcs)
+    {
+      return STATUS_NO_MEMORY;
+    }
+  if (0 != InitCompleteProcCount)
+    {
+      RtlCopyMemory(NewProcs, InitCompleteProcs,
+                    InitCompleteProcCount * sizeof(CSRPLUGIN_INIT_COMPLETE_PROC));
+      RtlFreeHeap(CsrssApiHeap, 0, InitCompleteProcs);
+    }
+  NewProcs[InitCompleteProcCount] = Proc;
+  InitCompleteProcs = NewProcs;
+  InitCompleteProcCount++;
 
+  return STATUS_SUCCESS;
+}
 
-HANDLE CsrInitEvent = INVALID_HANDLE_VALUE;
-HANDLE CsrHeap = INVALID_HANDLE_VALUE;
+/**********************************************************************
+ * CallInitComplete/0
+ */
+static BOOL FASTCALL
+CallInitComplete(void)
+{
+  BOOL Ok;
+  unsigned i;
 
-HANDLE CsrObjectDirectory = INVALID_HANDLE_VALUE;
-HANDLE CsrApiPort = INVALID_HANDLE_VALUE;
-HANDLE CsrSbApiPort = INVALID_HANDLE_VALUE;
+  DPRINT("CSR: %s called\n", __FUNCTION__);
 
-UNICODE_STRING CsrDirectoryName;
+  Ok = TRUE;
+  if (0 != InitCompleteProcCount)
+    {
+      for (i = 0; i < InitCompleteProcCount && Ok; i++)
+        {
+          Ok = (*(InitCompleteProcs[i]))();
+        }
+      RtlFreeHeap(CsrssApiHeap, 0, InitCompleteProcs);
+    }
 
-extern HANDLE CsrssApiHeap;
+  return Ok;
+}
 
 ULONG
 InitializeVideoAddressSpace(VOID);
 
+/**********************************************************************
+ * CsrpCreateObjectDirectory/3
+ */
 static NTSTATUS
-CsrParseCommandLine (
-       ULONG ArgumentCount,
-       PWSTR *ArgumentArray
-       )
+CsrpCreateObjectDirectory (int argc, char ** argv, char ** envp)
 {
    NTSTATUS Status;
    OBJECT_ATTRIBUTES Attributes;
 
-
-   /*   DbgPrint ("Arguments: %ld\n", ArgumentCount);
-   for (i = 0; i < ArgumentCount; i++)
-     {
-       DbgPrint ("Argument %ld: %S\n", i, ArgumentArray[i]);
-       }*/
+  DPRINT("CSR: %s called\n", __FUNCTION__);
 
 
        /* create object directory ('\Windows') */
@@ -66,30 +111,35 @@ CsrParseCommandLine (
 
        InitializeObjectAttributes (&Attributes,
                                    &CsrDirectoryName,
-                                   0,
+                                   OBJ_OPENIF,
                                    NULL,
                                    NULL);
 
-       Status = NtCreateDirectoryObject(&CsrObjectDirectory,
-                                        0xF000F,
-                                        &Attributes);
-
+       Status = NtOpenDirectoryObject(&CsrObjectDirectory,
+                                      0xF000F, /* ea:??? */
+                                      &Attributes);
        return Status;
 }
 
-
-static VOID
-CsrInitVideo(VOID)
+/**********************************************************************
+ * CsrpInitVideo/3
+ *
+ * TODO: we need a virtual device for sessions other than
+ * TODO: the console one
+ */
+static NTSTATUS
+CsrpInitVideo (int argc, char ** argv, char ** envp)
 {
   OBJECT_ATTRIBUTES ObjectAttributes;
-  UNICODE_STRING DeviceName;
+  UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\??\\DISPLAY1");
   IO_STATUS_BLOCK Iosb;
-  HANDLE VideoHandle;
-  NTSTATUS Status;
+  HANDLE VideoHandle = (HANDLE) 0;
+  NTSTATUS Status = STATUS_SUCCESS;
+
+  DPRINT("CSR: %s called\n", __FUNCTION__);
 
   InitializeVideoAddressSpace();
 
-  RtlRosInitUnicodeStringFromLiteral(&DeviceName, L"\\??\\DISPLAY1");
   InitializeObjectAttributes(&ObjectAttributes,
                             &DeviceName,
                             0,
@@ -105,110 +155,470 @@ CsrInitVideo(VOID)
     {
       NtClose(VideoHandle);
     }
+  return Status;
 }
 
+/**********************************************************************
+ * CsrpInitWin32Csr/3
+ *
+ * TODO: this function should be turned more general to load an
+ * TODO: hosted server DLL as received from the command line;
+ * TODO: for instance: ServerDll=winsrv:ConServerDllInitialization,2
+ * TODO:               ^method   ^dll   ^api                       ^sid
+ * TODO:
+ * TODO: CsrpHostServerDll (LPWSTR DllName,
+ * TODO:                    LPWSTR ApiName,
+ * TODO:                    DWORD  ServerId)
+ */
+static NTSTATUS
+CsrpInitWin32Csr (int argc, char ** argv, char ** envp)
+{
+  NTSTATUS Status;
+  UNICODE_STRING DllName;
+  HINSTANCE hInst;
+  ANSI_STRING ProcName;
+  CSRPLUGIN_INITIALIZE_PROC InitProc;
+  CSRSS_EXPORTED_FUNCS Exports;
+  PCSRSS_API_DEFINITION ApiDefinitions;
+  PCSRSS_OBJECT_DEFINITION ObjectDefinitions;
+  CSRPLUGIN_INIT_COMPLETE_PROC InitCompleteProc;
+
+  DPRINT("CSR: %s called\n", __FUNCTION__);
+
+  RtlInitUnicodeString(&DllName, L"win32csr.dll");
+  Status = LdrLoadDll(NULL, 0, &DllName, (PVOID *) &hInst);
+  if (! NT_SUCCESS(Status))
+    {
+      return Status;
+    }
+  RtlInitAnsiString(&ProcName, "Win32CsrInitialization");
+  Status = LdrGetProcedureAddress(hInst, &ProcName, 0, (PVOID *) &InitProc);
+  if (! NT_SUCCESS(Status))
+    {
+      return Status;
+    }
+  Exports.CsrInsertObjectProc = CsrInsertObject;
+  Exports.CsrGetObjectProc = CsrGetObject;
+  Exports.CsrReleaseObjectProc = CsrReleaseObject;
+  if (! (*InitProc)(&ApiDefinitions, &ObjectDefinitions, &InitCompleteProc,
+                    &Exports, CsrssApiHeap))
+    {
+      return STATUS_UNSUCCESSFUL;
+    }
+
+  Status = CsrApiRegisterDefinitions(ApiDefinitions);
+  if (! NT_SUCCESS(Status))
+    {
+      return Status;
+    }
+  Status = CsrRegisterObjectDefinitions(ObjectDefinitions);
+  if (! NT_SUCCESS(Status))
+    {
+      return Status;
+    }
+  if (NULL != InitCompleteProc)
+    {
+      Status = CsrpAddInitCompleteProc(InitCompleteProc);
+    }
+
+  return Status;
+}
+
+CSRSS_API_DEFINITION NativeDefinitions[] =
+  {
+    CSRSS_DEFINE_API(CREATE_PROCESS,               CsrCreateProcess),
+    CSRSS_DEFINE_API(TERMINATE_PROCESS,            CsrTerminateProcess),
+    CSRSS_DEFINE_API(CONNECT_PROCESS,              CsrConnectProcess),
+    CSRSS_DEFINE_API(REGISTER_SERVICES_PROCESS,    CsrRegisterServicesProcess),
+    CSRSS_DEFINE_API(GET_SHUTDOWN_PARAMETERS,      CsrGetShutdownParameters),
+    CSRSS_DEFINE_API(SET_SHUTDOWN_PARAMETERS,      CsrSetShutdownParameters),
+    CSRSS_DEFINE_API(GET_INPUT_HANDLE,             CsrGetInputHandle),
+    CSRSS_DEFINE_API(GET_OUTPUT_HANDLE,            CsrGetOutputHandle),
+    CSRSS_DEFINE_API(CLOSE_HANDLE,                 CsrCloseHandle),
+    CSRSS_DEFINE_API(VERIFY_HANDLE,                CsrVerifyHandle),
+    CSRSS_DEFINE_API(DUPLICATE_HANDLE,             CsrDuplicateHandle),
+    CSRSS_DEFINE_API(GET_INPUT_WAIT_HANDLE,        CsrGetInputWaitHandle),
+    { 0, 0, NULL }
+  };
+
+static NTSTATUS STDCALL
+CsrpCreateListenPort (IN     LPWSTR  Name,
+                     IN OUT PHANDLE Port,
+                     IN     PTHREAD_START_ROUTINE ListenThread)
+{
+       NTSTATUS           Status = STATUS_SUCCESS;
+       OBJECT_ATTRIBUTES  PortAttributes;
+       UNICODE_STRING     PortName;
+
+       DPRINT("CSR: %s called\n", __FUNCTION__);
+
+       RtlInitUnicodeString (& PortName, Name);
+       InitializeObjectAttributes (& PortAttributes,
+                                   & PortName,
+                                   0,
+                                   NULL,
+                                   NULL);
+       Status = NtCreatePort ( Port,
+                               & PortAttributes,
+                               LPC_MAX_DATA_LENGTH, /* TODO: make caller set it*/
+                               LPC_MAX_MESSAGE_LENGTH, /* TODO: make caller set it*/
+                               0); /* TODO: make caller set it*/
+       if(!NT_SUCCESS(Status))
+       {
+               DPRINT1("CSR: %s: NtCreatePort failed (Status=%08lx)\n",
+                       __FUNCTION__, Status);
+               return Status;
+       }
+       Status = RtlCreateUserThread(NtCurrentProcess(),
+                               NULL,
+                               FALSE,
+                               0,
+                               0,
+                               0,
+                               (PTHREAD_START_ROUTINE) ListenThread,
+                               Port,
+                               NULL,
+                               NULL);
+       return Status;
+}
+
+/* === INIT ROUTINES === */
+
+/**********************************************************************
+ * CsrpCreateHeap/3
+ */
+static NTSTATUS
+CsrpCreateHeap (int argc, char ** argv, char ** envp)
+{
+       DPRINT("CSR: %s called\n", __FUNCTION__);
+
+       CsrssApiHeap = RtlCreateHeap(HEAP_GROWABLE,
+                                      NULL,
+                                      65536,
+                                      65536,
+                                      NULL,
+                                      NULL);
+       if (CsrssApiHeap == NULL)
+       {
+               return STATUS_UNSUCCESSFUL;
+       }
+       return STATUS_SUCCESS;
+}
+
+/**********************************************************************
+ * CsrpCreateCallbackPort/3
+ */
+static NTSTATUS
+CsrpCreateCallbackPort (int argc, char ** argv, char ** envp)
+{
+       DPRINT("CSR: %s called\n", __FUNCTION__);
+
+       return CsrpCreateListenPort (L"\\Windows\\SbApiPort",
+                                    & hSbApiPort,
+                                    ServerSbApiPortThread);
+}
+
+/**********************************************************************
+ * CsrpRegisterSubsystem/3
+ */
+static NTSTATUS
+CsrpRegisterSubsystem (int argc, char ** argv, char ** envp)
+{
+       NTSTATUS           Status = STATUS_SUCCESS;
+       OBJECT_ATTRIBUTES  BootstrapOkAttributes;
+       UNICODE_STRING     Name;
+
+       DPRINT("CSR: %s called\n", __FUNCTION__);
+
+       /*
+        * Create the event object the callback port
+        * thread will signal *if* the SM will
+        * authorize us to bootstrap.
+        */
+       RtlInitUnicodeString (& Name, L"\\CsrssBooting");
+       InitializeObjectAttributes(& BootstrapOkAttributes,
+                                  & Name,
+                                  0, NULL, NULL);
+       Status = NtCreateEvent (& hBootstrapOk,
+                               EVENT_ALL_ACCESS,
+                               & BootstrapOkAttributes,
+                               SynchronizationEvent,
+                               FALSE);
+       if(!NT_SUCCESS(Status))
+       {
+               DPRINT("CSR: %s: NtCreateEvent failed (Status=0x%08lx)\n",
+                       __FUNCTION__, Status);
+               return Status;
+       }
+       /*
+        * Let's tell the SM a new environment
+        * subsystem server is in the system.
+        */
+       RtlInitUnicodeString (& Name, L"\\Windows\\SbApiPort");
+       DPRINT("CSR: %s: registering with SM for\n  IMAGE_SUBSYSTEM_WINDOWS_CUI == 3\n", __FUNCTION__);
+       Status = SmConnectApiPort (& Name,
+                                  hSbApiPort,
+                                  IMAGE_SUBSYSTEM_WINDOWS_CUI,
+                                  & hSmApiPort);
+       if(!NT_SUCCESS(Status))
+       {
+               DPRINT("CSR: %s unable to connect to the SM (Status=0x%08lx)\n",
+                       __FUNCTION__, Status);
+               NtClose (hBootstrapOk);
+               return Status;
+       }
+       /*
+        *  Wait for SM to reply OK... If the SM
+        *  won't answer, we hang here forever!
+        */
+       DPRINT("CSR: %s: waiting for SM to OK boot...\n", __FUNCTION__);
+       Status = NtWaitForSingleObject (hBootstrapOk,
+                                       FALSE,
+                                       NULL);
+       NtClose (hBootstrapOk);
+       return Status;
+}
+
+/**********************************************************************
+ *     EnvpToUnicodeString/2
+ */
+static ULONG FASTCALL
+EnvpToUnicodeString (char ** envp, PUNICODE_STRING UnicodeEnv)
+{
+       ULONG        CharCount = 0;
+       ULONG        Index = 0;
+       ANSI_STRING  AnsiEnv;
+
+       UnicodeEnv->Buffer = NULL;
+       
+       for (Index=0; NULL != envp[Index]; Index++)
+       {
+               CharCount += strlen (envp[Index]);
+               ++ CharCount;
+       }
+       ++ CharCount;
+       
+       AnsiEnv.Buffer = RtlAllocateHeap (RtlGetProcessHeap(), 0, CharCount);
+       if (NULL != AnsiEnv.Buffer)
+       {
+
+               PCHAR WritePos = AnsiEnv.Buffer;
+               
+               for (Index=0; NULL != envp[Index]; Index++)
+               {
+                       strcpy (WritePos, envp[Index]);
+                       WritePos += strlen (envp[Index]) + 1;
+               }
+
+      /* FIXME: the last (double) nullterm should perhaps not be included in Length
+       * but only in MaximumLength. -Gunnar */
+               AnsiEnv.Buffer [CharCount-1] = '\0';
+               AnsiEnv.Length             = CharCount;
+               AnsiEnv.MaximumLength      = CharCount;
+      
+               RtlAnsiStringToUnicodeString (UnicodeEnv, & AnsiEnv, TRUE);
+               RtlFreeHeap (RtlGetProcessHeap(), 0, AnsiEnv.Buffer);
+       }
+       return CharCount;
+}
+/**********************************************************************
+ *     CsrpLoadKernelModeDriver/3
+ */
+static NTSTATUS
+CsrpLoadKernelModeDriver (int argc, char ** argv, char ** envp)
+{
+       NTSTATUS        Status = STATUS_SUCCESS;
+       WCHAR           Data [MAX_PATH + 1];
+       ULONG           DataLength = sizeof Data;
+       ULONG           DataType = 0;
+       UNICODE_STRING  Environment;
+
+
+       DPRINT("SM: %s called\n", __FUNCTION__);
+
+
+       EnvpToUnicodeString (envp, & Environment);      
+       Status = SmLookupSubsystem (L"Kmode",
+                                   Data,
+                                   & DataLength,
+                                   & DataType,
+                                   Environment.Buffer);
+       RtlFreeUnicodeString (& Environment);
+       if((STATUS_SUCCESS == Status) && (DataLength > sizeof Data[0]))
+       {
+               WCHAR                      ImagePath [MAX_PATH + 1] = {0};
+               UNICODE_STRING             ModuleName;
+
+               wcscpy (ImagePath, L"\\??\\");
+               wcscat (ImagePath, Data);
+               RtlInitUnicodeString (& ModuleName, ImagePath);
+               Status = NtSetSystemInformation(/* FIXME: SystemLoadAndCallImage */
+                                               SystemExtendServiceTableInformation,
+                                               & ModuleName,
+                                               sizeof ModuleName);
+               if(!NT_SUCCESS(Status))
+               {
+                       DPRINT("WIN: %s: loading Kmode failed (Status=0x%08lx)\n",
+                               __FUNCTION__, Status);
+               }
+       }
+       return Status;
+}
+
+/**********************************************************************
+ * CsrpCreateApiPort/2
+ */
+static NTSTATUS
+CsrpCreateApiPort (int argc, char ** argv, char ** envp)
+{
+       DPRINT("CSR: %s called\n", __FUNCTION__);
+
+       return CsrpCreateListenPort (L"\\Windows\\ApiPort",
+                                    & hApiPort,
+                                    ServerApiPortThread);
+}
+
+/**********************************************************************
+ * CsrpApiRegisterDef/0
+ */
+static NTSTATUS
+CsrpApiRegisterDef (int argc, char ** argv, char ** envp)
+{
+       return CsrApiRegisterDefinitions(NativeDefinitions);
+}
+
+/**********************************************************************
+ * CsrpCCTS/2
+ */
+static NTSTATUS
+CsrpCCTS (int argc, char ** argv, char ** envp)
+{
+    ULONG Dummy;
+    ULONG DummyLength = sizeof(Dummy);
+       return CsrClientConnectToServer(L"\\Windows",
+                       0, &Dummy, &DummyLength, NULL);
+}
+
+/**********************************************************************
+ * CsrpRunWinlogon/0
+ *
+ * Start the logon process (winlogon.exe).
+ *
+ * TODO: this should be moved in CsrpCreateSession/x (one per session)
+ * TODO: in its own desktop (one logon desktop per winstation).
+ */
+static NTSTATUS
+CsrpRunWinlogon (int argc, char ** argv, char ** envp)
+{
+       NTSTATUS                      Status = STATUS_SUCCESS;
+       UNICODE_STRING                ImagePath;
+       UNICODE_STRING                CommandLine;
+       PRTL_USER_PROCESS_PARAMETERS  ProcessParameters = NULL;
+       RTL_USER_PROCESS_INFORMATION  ProcessInfo;
+
+
+       DPRINT("CSR: %s called\n", __FUNCTION__);
+
+       /* initialize the process parameters */
+       RtlInitUnicodeString (& ImagePath, L"\\SystemRoot\\system32\\winlogon.exe");
+       RtlInitUnicodeString (& CommandLine, L"");
+       RtlCreateProcessParameters(& ProcessParameters,
+                                  & ImagePath,
+                                  NULL,
+                                  NULL,
+                                  & CommandLine,
+                                  NULL,
+                                  NULL,
+                                  NULL,
+                                  NULL,
+                                  NULL);
+       /* Create the winlogon process */
+       Status = RtlCreateUserProcess (& ImagePath,
+                                      OBJ_CASE_INSENSITIVE,
+                                      ProcessParameters,
+                                      NULL,
+                                      NULL,
+                                      NULL,
+                                      FALSE,
+                                      NULL,
+                                      NULL,
+                                      & ProcessInfo);
+       /* Cleanup */
+       RtlDestroyProcessParameters (ProcessParameters);
+       if (!NT_SUCCESS(Status))
+       {
+               DPRINT1("SM: %s: loading winlogon.exe failed (Status=%08lx)\n",
+                               __FUNCTION__, Status);
+       }
+   ZwResumeThread(ProcessInfo.ThreadHandle, NULL);
+       return Status;
+}
+
+
+
+typedef NTSTATUS (* CSR_INIT_ROUTINE)(int,char**,char**);
+
+struct {
+       BOOL Required;
+       CSR_INIT_ROUTINE EntryPoint;
+       PCHAR ErrorMessage;
+} InitRoutine [] = {
+       {TRUE, CsrpCreateCallbackPort,   "create the callback port \\Windows\\SbApiPort"},
+       {TRUE, CsrpRegisterSubsystem,    "register with SM"},
+       {TRUE, CsrpCreateHeap,           "create the CSR heap"},
+       {TRUE, CsrpCreateApiPort,        "create the api port \\Windows\\ApiPort"},
+       {TRUE, CsrpCreateObjectDirectory,"create the object directory \\Windows"},
+       {TRUE, CsrpLoadKernelModeDriver, "load Kmode driver"},
+       {TRUE, CsrpInitVideo,            "initialize video"},
+       {TRUE, CsrpApiRegisterDef,       "initialize api definitions"},
+       {TRUE, CsrpCCTS,                 "connect client to server"},
+       {TRUE, CsrpInitWin32Csr,         "load usermode dll"},
+       {TRUE, CsrpRunWinlogon,          "run WinLogon"},
+};
 
 /**********************************************************************
  * NAME
  *     CsrServerInitialization
  *
  * DESCRIPTION
- *     Create a directory object (\windows) and two named LPC ports:
- *
- *     1. \windows\ApiPort
- *     2. \windows\SbApiPort
+ *     Initialize the Win32 environment subsystem server.
  *
  * RETURN VALUE
  *     TRUE: Initialization OK; otherwise FALSE.
  */
-BOOL
-STDCALL
+BOOL STDCALL
 CsrServerInitialization (
-       ULONG ArgumentCount,
-       PWSTR *ArgumentArray
+       int argc,
+       char ** argv,
+       char ** envp
        )
 {
-   NTSTATUS            Status;
-   OBJECT_ATTRIBUTES   ObAttributes;
-   UNICODE_STRING PortName;
-   OBJECT_ATTRIBUTES RefreshEventAttr;
-   UNICODE_STRING RefreshEventName;
-   HANDLE RefreshEventHandle;
-
-   Status = CsrParseCommandLine (ArgumentCount, ArgumentArray);
-   if (!NT_SUCCESS(Status))
-     {
-       DPRINT1("CSR: Unable to parse the command line (Status: %x)\n", Status);
-       return(FALSE);
-     }
-
-   CsrInitVideo();
-
-   /* NEW NAMED PORT: \ApiPort */
-   RtlRosInitUnicodeStringFromLiteral(&PortName, L"\\Windows\\ApiPort");
-   InitializeObjectAttributes(&ObAttributes,
-                             &PortName,
-                             0,
-                             NULL,
-                             NULL);
-
-   Status = NtCreatePort(&ApiPortHandle,
-                        &ObAttributes,
-                        260,
-                        328,
-                        0);
-   if (!NT_SUCCESS(Status))
-     {
-       DPRINT1("CSR: Unable to create \\ApiPort (Status %x)\n", Status);
-       return(FALSE);
-     }
-   CsrssApiHeap = RtlCreateHeap(HEAP_GROWABLE,
-                               NULL,
-                               65536,
-                               65536,
-                               NULL,
-                               NULL);
-   if (CsrssApiHeap == NULL)
-     {
-       DPRINT1("CSR: Failed to create private heap, aborting\n");
-       return FALSE;
-     }
-
-   CsrInitConsoleSupport();
-   Status = RtlCreateUserThread(NtCurrentProcess(),
-                               NULL,
-                               FALSE,
-                               0,
-                               NULL,
-                               NULL,
-                               (PTHREAD_START_ROUTINE)Thread_Api,
-                               ApiPortHandle,
-                               NULL,
-                               NULL);
-   if (!NT_SUCCESS(Status))
-     {
-       DPRINT1("CSR: Unable to create server thread\n");
-       NtClose(ApiPortHandle);
+       UINT       i = 0;
+       NTSTATUS  Status = STATUS_SUCCESS;
+
+       DPRINT("CSR: %s called\n", __FUNCTION__);
+
+       for (i=0; i < (sizeof InitRoutine / sizeof InitRoutine[0]); i++)
+       {
+               Status = InitRoutine[i].EntryPoint(argc,argv,envp);
+               if(!NT_SUCCESS(Status))
+               {
+                       DPRINT1("CSR: %s: failed to %s (Status=%08lx)\n",
+                               __FUNCTION__,
+                               InitRoutine[i].ErrorMessage,
+                               Status);
+                       if (InitRoutine[i].Required)
+                       {
+                               return FALSE;
+                       }
+               }
+       }
+       if (CallInitComplete())
+       {
+               Status = SmCompleteSession (hSmApiPort,hSbApiPort,hApiPort);
+               return TRUE;
+       }
        return FALSE;
-     }
-   RtlRosInitUnicodeStringFromLiteral( &RefreshEventName, L"\\TextConsoleRefreshEvent" );
-   InitializeObjectAttributes( &RefreshEventAttr, &RefreshEventName, 0, NULL, NULL );
-   Status = NtCreateEvent( &RefreshEventHandle, STANDARD_RIGHTS_ALL, &RefreshEventAttr, FALSE, FALSE );
-   if( !NT_SUCCESS( Status ) )
-     {
-       DPRINT1( "CSR: Unable to create refresh event!\n" );
-       return FALSE;
-     }
-   Status = RtlCreateUserThread( NtCurrentProcess(), NULL, FALSE, 0, NULL, NULL, (PTHREAD_START_ROUTINE)Console_Api, (PVOID) RefreshEventHandle, NULL, NULL );
-   if( !NT_SUCCESS( Status ) )
-     {
-       DPRINT1( "CSR: Unable to create console thread\n" );
-       return FALSE;
-     }
-
-   Win32kInitialize();
-
-   return TRUE;
 }
 
 /* EOF */