Add information letting us know creation deletion of services has worked.
[reactos.git] / reactos / subsys / csrss / init.c
index 32435fc..4237698 100644 (file)
@@ -1,5 +1,5 @@
-/* $Id: init.c,v 1.2 1999/07/17 23:10:30 ea Exp $
- * 
+/* $Id$
+ *
  * reactos/subsys/csrss/init.c
  *
  * Initialize the CSRSS subsystem server process.
  * ReactOS Operating System
  *
  */
-#define PROTO_LPC
-#include <ddk/ntddk.h>
-#include "csrss.h"
 
+/* INCLUDES ******************************************************************/
+
+#include <csrss.h>
+
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ******************************************************************/
+
+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;
 
-void Thread_Api(void*);
-void Thread_SbApi(void*);
+HANDLE hSmApiPort = (HANDLE) 0;
 
-/*
- * Server's named ports.
+HANDLE hApiPort = (HANDLE) 0;
+
+/**********************************************************************
+ * CsrpAddInitCompleteProc/1
  */
-struct _SERVER_PORTS
-Server =
+static NTSTATUS FASTCALL
+CsrpAddInitCompleteProc(CSRPLUGIN_INIT_COMPLETE_PROC Proc)
 {
-       {INVALID_HANDLE_VALUE,Thread_Api},
-       {INVALID_HANDLE_VALUE,Thread_SbApi}
-};
+  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;
+}
+
 /**********************************************************************
- * NAME
- *     Thread_Api
+ * CallInitComplete/0
+ */
+static BOOL FASTCALL
+CallInitComplete(void)
+{
+  BOOL Ok;
+  unsigned i;
+
+  DPRINT("CSR: %s called\n", __FUNCTION__);
+
+  Ok = TRUE;
+  if (0 != InitCompleteProcCount)
+    {
+      for (i = 0; i < InitCompleteProcCount && Ok; i++)
+        {
+          Ok = (*(InitCompleteProcs[i]))();
+        }
+      RtlFreeHeap(CsrssApiHeap, 0, InitCompleteProcs);
+    }
+
+  return Ok;
+}
+
+ULONG
+InitializeVideoAddressSpace(VOID);
+
+/**********************************************************************
+ * CsrpCreateObjectDirectory/3
+ */
+static NTSTATUS
+CsrpCreateObjectDirectory (int argc, char ** argv, char ** envp)
+{
+   NTSTATUS Status;
+   OBJECT_ATTRIBUTES Attributes;
+
+  DPRINT("CSR: %s called\n", __FUNCTION__);
+
+
+       /* create object directory ('\Windows') */
+       RtlCreateUnicodeString (&CsrDirectoryName,
+                               L"\\Windows");
+
+       InitializeObjectAttributes (&Attributes,
+                                   &CsrDirectoryName,
+                                   OBJ_OPENIF,
+                                   NULL,
+                                   NULL);
+
+       Status = NtOpenDirectoryObject(&CsrObjectDirectory,
+                                      0xF000F, /* ea:??? */
+                                      &Attributes);
+       return Status;
+}
+
+/**********************************************************************
+ * CsrpInitVideo/3
  *
- * DESCRIPTION
- *     Handle connection requests from clients to the port
- *     "\Windows\ApiPort".
+ * TODO: we need a virtual device for sessions other than
+ * TODO: the console one
  */
-static
-void
-Thread_Api(void * pPort)
+static NTSTATUS
+CsrpInitVideo (int argc, char ** argv, char ** envp)
 {
-       NTSTATUS        Status;
-       HANDLE          Port;
-       HANDLE          ConnectedPort;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\??\\DISPLAY1");
+  IO_STATUS_BLOCK Iosb;
+  HANDLE VideoHandle = (HANDLE) 0;
+  NTSTATUS Status = STATUS_SUCCESS;
+
+  DPRINT("CSR: %s called\n", __FUNCTION__);
+
+  InitializeVideoAddressSpace();
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &DeviceName,
+                            0,
+                            NULL,
+                            NULL);
+  Status = NtOpenFile(&VideoHandle,
+                     FILE_ALL_ACCESS,
+                     &ObjectAttributes,
+                     &Iosb,
+                     0,
+                     0);
+  if (NT_SUCCESS(Status))
+    {
+      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,
+                               260, /* TODO: make caller set it*/
+                               328, /* 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__);
 
-       Port = * (HANDLE*) pPort;
-       
        /*
-        * Make the CSR API port listen.
+        * Create the event object the callback port
+        * thread will signal *if* the SM will
+        * authorize us to bootstrap.
         */
-       Status = NtListenPort(
-                       Port,
-                       CSRSS_API_PORT_QUEUE_SIZE
-                       );
-       if (!NT_SUCCESS(Status))
+       RtlInitUnicodeString (& Name, L"\\CsrssBooting");
+       InitializeObjectAttributes(& BootstrapOkAttributes,
+                                  & Name,
+                                  0, NULL, NULL);
+       Status = NtCreateEvent (& hBootstrapOk,
+                               EVENT_ALL_ACCESS,
+                               & BootstrapOkAttributes,
+                               SynchronizationEvent,
+                               FALSE);
+       if(!NT_SUCCESS(Status))
        {
-               /*
-                * FIXME: notify SM we could not 
-                * make the port listen.
-                */
-               return;
+               DPRINT("CSR: %s: NtCreateEvent failed (Status=0x%08lx)\n",
+                       __FUNCTION__, Status);
+               return Status;
        }
        /*
-        * Wait for a client to connect
+        * Let's tell the SM a new environment
+        * subsystem server is in the system.
         */
-       while (TRUE)
+       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))
        {
-               /*
-                * Wait for a connection request;
-                * the new connected port's handle
-                * is stored in ConnectedPort.
-                */
-               Status = NtAcceptConnectPort(
-                               Port,
-                               & ConnectedPort
-                               );
-               if (NT_SUCCESS(Status))
-               {
-                       if (NT_SUCCESS(NtCompleteConnectPort(ConnectedPort)))
-                       {
-                               /* dispatch call */
-                               continue;
-                       }
-                       /* error */
-               }
+               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;
 }
 
-
 /**********************************************************************
- * NAME
- *     Thread_SbApi
- *
- * DESCRIPTION
- *     Handle connection requests from clients to the port
- *     "\Windows\SbApiPort".
+ *     EnvpToUnicodeString/2
  */
-static
-void
-Thread_SbApi(void * pPort)
+static ULONG FASTCALL
+EnvpToUnicodeString (char ** envp, PUNICODE_STRING UnicodeEnv)
 {
-       NTSTATUS        Status;
-       HANDLE          Port;
-       HANDLE          ConnectedPort;
+       ULONG        CharCount = 0;
+       ULONG        Index = 0;
+       ANSI_STRING  AnsiEnv;
 
-       Port = * (HANDLE*) pPort;
+       UnicodeEnv->Buffer = NULL;
        
-       Status = NtListenPort(
-                       Port,
-                       CSRSS_SBAPI_PORT_QUEUE_SIZE
-                       );
-       if (!NT_SUCCESS(Status))
+       for (Index=0; NULL != envp[Index]; Index++)
        {
-               return;
+               CharCount += strlen (envp[Index]);
+               ++ CharCount;
        }
-       /*
-        * Wait for a client to connect
-        */
-       while (TRUE)
+       ++ CharCount;
+       
+       AnsiEnv.Buffer = RtlAllocateHeap (RtlGetProcessHeap(), 0, CharCount);
+       if (NULL != AnsiEnv.Buffer)
        {
-               Status = NtAcceptConnectPort(
-                               Port,
-                               & ConnectedPort
-                               );
-               if (NT_SUCCESS(Status))
+
+               PCHAR WritePos = AnsiEnv.Buffer;
+               
+               for (Index=0; NULL != envp[Index]; Index++)
                {
-                       if (NT_SUCCESS(NtCompleteConnectPort(ConnectedPort)))
-                       {
-                               /* dispatch call */
-                               continue;
-                       }
-                       /* error: Port.CompleteConnect failed */
-                       continue;
+                       strcpy (WritePos, envp[Index]);
+                       WritePos += strlen (envp[Index]) + 1;
                }
-               /* error: Port.AcceptConnect failed */
+
+      /* 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;
 }
-#endif
 
 
+
+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
- *     InitializeServer
+ *     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
-InitializeServer(void)
+BOOL STDCALL
+CsrServerInitialization (
+       int argc,
+       char ** argv,
+       char ** envp
+       )
 {
-       NTSTATUS                Status;
-       OBJECT_ATTRIBUTES       ObAttributes;
+       UINT       i = 0;
+       NTSTATUS  Status = STATUS_SUCCESS;
 
-       
-       /* NEW NAMED PORT: \ApiPort */
-       Status = NtCreatePort(
-                       & Server.Api.Port,      /* New port's handle */
-                       & ObAttributes,         /* Port object's attributes */
-                       ...
-                       );
-       if (!NT_SUCCESS(Status))
-       {
-               return FALSE;
-       }
-       Status = NtCreateThread(
-                       & Server.Api.Thread,
-                       0,                      /* desired access */
-                       & ObAttributes,         /* object attributes */
-                       NtCurrentProcess(),     /* process' handle */
-                       0,                      /* client id */
-                       Thread_ApiPort,
-                       (void*) & Server.Api.Port
-                       );
-       if (!NT_SUCCESS(Status))
-       {
-               NtClose(Server.Api.Port);
-               return FALSE;
-       }
-       /* NEW NAMED PORT: \SbApiPort */
-       Status = NtCreatePort(
-                       & Server.SbApi.Port,
-                       & ObAttributes,
-                       ...
-                       );
-       if (!NT_SUCCESS(Status))
+       DPRINT("CSR: %s called\n", __FUNCTION__);
+
+       for (i=0; i < (sizeof InitRoutine / sizeof InitRoutine[0]); i++)
        {
-               NtClose(Server.Api.Port);
-               return FALSE;
+               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;
+                       }
+               }
        }
-       Status = NtCreateThread(
-                       & Server.SbApi.Thread,
-                       Thread_SbApi,
-                       (void*) & Server.SbApi.Port
-                       );
-       if (!NT_SUCCESS(Status))
+       if (CallInitComplete())
        {
-               NtClose(Server.Api.Port);
-               NtClose(Server.SbApi.Port);
-               return FALSE;
+               Status = SmCompleteSession (hSmApiPort,hSbApiPort,hApiPort);
+               return TRUE;
        }
-       return TRUE;
+       return FALSE;
 }
 
-
 /* EOF */