SM: simplify and fix client (subsystem servers) management.
[reactos.git] / reactos / subsys / smss / initss.c
index 0f80456..656b139 100644 (file)
-/* $Id: init.c 13449 2005-02-06 21:55:07Z ea $\r
- *\r
- * initss.c - Load the subsystems\r
- * \r
- * ReactOS Operating System\r
- * \r
- * --------------------------------------------------------------------\r
- *\r
- * This software is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU General Public License as\r
- * published by the Free Software Foundation; either version 2 of the\r
- * License, or (at your option) any later version.\r
- *\r
- * This software is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this software; see the file COPYING.LIB. If not, write\r
- * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,\r
- * MA 02139, USA.  \r
- *\r
- * --------------------------------------------------------------------\r
- */\r
-\r
-\r
-#include "smss.h"\r
-#include <rosrtl/string.h>\r
-\r
-#define NDEBUG\r
-#include <debug.h>\r
-\r
-/* TODO: this file should be totally rewritten\r
- *\r
- * a) look if a special option is set for smss.exe in\r
- *    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\r
- *\r
- * b) make smss register with itself for IMAGE_SUBSYSTEM_NATIVE\r
- *    (programmatically)\r
- *\r
- * c) make smss load win32k.sys as set in Kmode key\r
- *    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems\r
- *\r
- * d) make smss initialize Debug (DBGSS) and Windows (CSRSS) as described\r
- *    in the registry key Required="Debug Windows"\r
- *    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems\r
- *\r
- * e) make optional subsystems loadable (again: they must be described in the registry\r
- *    key Optional="Posix Os2" to be allowed to run)\r
- */\r
-NTSTATUS\r
-SmLoadSubsystems(VOID)\r
-{\r
-  SYSTEM_LOAD_AND_CALL_IMAGE ImageInfo;\r
-  NTSTATUS Status;\r
-\r
-  DPRINT("SM: loading subsystems\n");\r
-\r
-  /* Load kernel mode subsystem (aka win32k.sys) */\r
-  RtlRosInitUnicodeStringFromLiteral(&ImageInfo.ModuleName,\r
-                      L"\\SystemRoot\\system32\\win32k.sys");\r
-\r
-  Status = NtSetSystemInformation(SystemLoadAndCallImage,\r
-                                 &ImageInfo,\r
-                                 sizeof(SYSTEM_LOAD_AND_CALL_IMAGE));\r
-\r
-  DPRINT("SMSS: Loaded win32k.sys (Status %lx)\n", Status);\r
-#if 0\r
-  if (!NT_SUCCESS(Status))\r
-    {\r
-      return(Status);\r
-    }\r
-#endif\r
-\r
-  /* FIXME: load more subsystems (csrss!) */\r
-\r
-  return(Status);\r
-}\r
-\r
-NTSTATUS\r
-SmRunCsrss(VOID)\r
-{\r
-  NTSTATUS Status;\r
-  UNICODE_STRING UnicodeString;\r
-  OBJECT_ATTRIBUTES ObjectAttributes;\r
-  PRTL_USER_PROCESS_PARAMETERS ProcessParameters;\r
-  RTL_PROCESS_INFO ProcessInfo;\r
-  HANDLE CsrssInitEvent;\r
-  WCHAR UnicodeBuffer[MAX_PATH];\r
-\r
-  DPRINT("SM: initializing csrss\n");\r
-\r
-  /* Run csrss.exe */\r
-  RtlRosInitUnicodeStringFromLiteral(&UnicodeString,\r
-                                 L"\\CsrssInitDone");\r
-  InitializeObjectAttributes(&ObjectAttributes,\r
-                            &UnicodeString,\r
-                            EVENT_ALL_ACCESS,\r
-                            0,\r
-                            NULL);\r
-  Status = NtCreateEvent(&CsrssInitEvent,\r
-                        EVENT_ALL_ACCESS,\r
-                        &ObjectAttributes,\r
-                        NotificationEvent,\r
-                        FALSE);\r
-  if (!NT_SUCCESS(Status))\r
-    {\r
-      DbgPrint("Failed to create csrss notification event\n");\r
-    }\r
-\r
-  /*\r
-   * Start the Win32 subsystem (csrss.exe)\r
-   */\r
-\r
-  /* initialize executable path */\r
-  wcscpy(UnicodeBuffer, L"\\??\\");\r
-  wcscat(UnicodeBuffer, SharedUserData->NtSystemRoot);\r
-  wcscat(UnicodeBuffer, L"\\system32\\csrss.exe");\r
-  RtlInitUnicodeString(&UnicodeString,\r
-                      UnicodeBuffer);\r
-\r
-  RtlCreateProcessParameters(&ProcessParameters,\r
-                            &UnicodeString,\r
-                            NULL,\r
-                            NULL,\r
-                            NULL,\r
-                            SmSystemEnvironment,\r
-                            NULL,\r
-                            NULL,\r
-                            NULL,\r
-                            NULL);\r
-\r
-  Status = RtlCreateUserProcess(&UnicodeString,\r
-                               OBJ_CASE_INSENSITIVE,\r
-                               ProcessParameters,\r
-                               NULL,\r
-                               NULL,\r
-                               NULL,\r
-                               FALSE,\r
-                               NULL,\r
-                               NULL,\r
-                               &ProcessInfo);\r
-\r
-  RtlDestroyProcessParameters (ProcessParameters);\r
-\r
-  if (!NT_SUCCESS(Status))\r
-    {\r
-      DPRINT("SM: %s: Loading csrss.exe failed!\n", __FUNCTION__);\r
-      return(Status);\r
-    }\r
-\r
-  Status = NtWaitForSingleObject(CsrssInitEvent,\r
-                       FALSE,\r
-                       NULL);\r
-\r
-  Children[CHILD_CSRSS] = ProcessInfo.ProcessHandle;\r
-\r
-  return Status;\r
-}\r
-\r
-NTSTATUS\r
-SmRunWinlogon(VOID)\r
-{\r
-  NTSTATUS Status;\r
-  UNICODE_STRING UnicodeString;\r
-  PRTL_USER_PROCESS_PARAMETERS ProcessParameters;\r
-  RTL_PROCESS_INFO ProcessInfo;\r
-  WCHAR UnicodeBuffer[MAX_PATH];\r
-\r
-  /*\r
-   * Start the logon process (winlogon.exe)\r
-   */\r
-\r
-  DPRINT("SM: starting winlogon\n");\r
-\r
-  /* initialize executable path */\r
-  wcscpy(UnicodeBuffer, L"\\??\\");\r
-  wcscat(UnicodeBuffer, SharedUserData->NtSystemRoot);\r
-  wcscat(UnicodeBuffer, L"\\system32\\winlogon.exe");\r
-  RtlInitUnicodeString(&UnicodeString,\r
-                      UnicodeBuffer);\r
-\r
-  RtlCreateProcessParameters(&ProcessParameters,\r
-                            &UnicodeString,\r
-                            NULL,\r
-                            NULL,\r
-                            NULL,\r
-                            SmSystemEnvironment,\r
-                            NULL,\r
-                            NULL,\r
-                            NULL,\r
-                            NULL);\r
-\r
-  Status = RtlCreateUserProcess(&UnicodeString,\r
-                               OBJ_CASE_INSENSITIVE,\r
-                               ProcessParameters,\r
-                               NULL,\r
-                               NULL,\r
-                               NULL,\r
-                               FALSE,\r
-                               NULL,\r
-                               NULL,\r
-                               &ProcessInfo);\r
-\r
-  RtlDestroyProcessParameters(ProcessParameters);\r
-\r
-  if (!NT_SUCCESS(Status))\r
-    {\r
-      DPRINT("SM: %s: Loading winlogon.exe failed!\n", __FUNCTION__);\r
-      NtTerminateProcess(Children[CHILD_CSRSS],\r
-                        0);\r
-      return(Status);\r
-    }\r
-  Children[CHILD_WINLOGON] = ProcessInfo.ProcessHandle;\r
-\r
-  return Status;\r
-}\r
-\r
-/* EOF */\r
+/* $Id$
+ *
+ * initss.c - Load the subsystems
+ * 
+ * ReactOS Operating System
+ * 
+ * --------------------------------------------------------------------
+ *
+ * This software is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * 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.  
+ *
+ * --------------------------------------------------------------------
+ */
+#include "smss.h"
+
+#define NDEBUG
+#include <debug.h>
+
+/* SM handle for its own \SmApiPort */
+HANDLE hSmApiPort = (HANDLE) 0;
+
+
+/* TODO:
+ *
+ * a) look if a special option is set for smss.exe in
+ *    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
+ */
+
+/**********************************************************************
+ *     SmRegisterInternalSubsystem/3
+ * 
+ * DESCRIPTION
+ *     Register with itself for ImageSubsystemId
+ *     (programmatically).
+ */
+NTSTATUS STDCALL SmRegisterInternalSubsystem (LPWSTR PgmName,
+                                             USHORT ImageSubsystemId,
+                                             PHANDLE ApiPort)
+{
+       NTSTATUS                      Status = STATUS_SUCCESS;
+       RTL_USER_PROCESS_INFORMATION  ProcessInfo;
+
+       
+       DPRINT("SM: %s(%S,%d) called\n",__FUNCTION__, PgmName, ImageSubsystemId);
+
+       RtlZeroMemory (& ProcessInfo, sizeof ProcessInfo);
+       ProcessInfo.Size = sizeof ProcessInfo;
+       ProcessInfo.ProcessHandle = (HANDLE) SmSsProcessId;
+       ProcessInfo.ClientId.UniqueProcess = (HANDLE) SmSsProcessId;
+       DPRINT("SM: %s: ProcessInfo.ProcessHandle=%lx\n",
+               __FUNCTION__,ProcessInfo.ProcessHandle);
+       Status = SmCreateClient (& ProcessInfo, PgmName);
+       if (NT_SUCCESS(Status))
+       {
+               UNICODE_STRING SbApiPortName = {0,0,NULL};
+               
+               RtlInitUnicodeString (& SbApiPortName, L"");    
+               Status = SmConnectApiPort(& SbApiPortName,
+                                         (HANDLE) -1, /* internal SS have no SB port */
+                                         ImageSubsystemId,
+                                         ApiPort);
+               if(!NT_SUCCESS(Status))
+               {
+                       DPRINT("SM: %s: SMLIB!SmConnectApiPort failed (Status=0x%08lx)\n",
+                               __FUNCTION__,Status);
+                       return Status;
+               }
+               DPRINT("SM:%s: %S self registered\n", __FUNCTION__, PgmName);
+       }
+       else
+       {
+               DPRINT1("SM: %s: SmCreateClient(%S) failed (Status=0x%08lx)\n",
+                       __FUNCTION__, PgmName, Status);
+       }
+       /*
+        * Note that you don't need to call complete session
+        * here because connection handling code autocompletes
+        * the client structure for IMAGE_SUBSYSTEM_NATIVE and
+        * -1.
+        */
+       return Status;
+}
+/**********************************************************************
+ *     SmpLoadRequiredSubsystems/0
+ */
+static NTSTATUS
+SmpLoadRequiredSubsystems (VOID)
+{
+       NTSTATUS  Status = STATUS_SUCCESS;
+       WCHAR     Data [MAX_PATH + 1];
+       ULONG     DataLength = sizeof Data;
+       ULONG     DataType = 0;
+
+       
+       DPRINT("SM: %s called\n", __FUNCTION__);
+
+       RtlZeroMemory (Data, DataLength);
+       Status = SmLookupSubsystem (L"Required",
+                                   Data,
+                                   & DataLength,
+                                   & DataType,
+                                   NULL);
+       if((STATUS_SUCCESS == Status) && (DataLength > sizeof Data[0]))
+       {
+               PWCHAR Name = NULL;
+               ULONG Offset = 0;
+               
+               for (Name = Data; (Offset < DataLength); )
+               {
+                       if(L'\0' != *Name)
+                       {
+                               UNICODE_STRING Program;
+
+                               /* Run the current program */
+                               RtlInitUnicodeString (& Program, Name);
+                               Status = SmExecuteProgram (hSmApiPort, & Program);
+                               if(!NT_SUCCESS(Status))
+                               {
+                                       DPRINT1("SM: %s failed to run '%S' program (Status=0x%08lx)\n",
+                                               __FUNCTION__, Name, Status);
+                               }
+                               /* Look for the next program */
+                               while ((L'\0' != *Name) && (Offset < DataLength))
+                               {
+                                       ++ Name;
+                                       ++ Offset;
+                               }
+                       }
+                       ++ Name;
+                       ++ Offset;
+               }
+       }
+
+       return Status;
+}
+
+/**********************************************************************
+ *     SmLoadSubsystems/0
+ */
+NTSTATUS
+SmLoadSubsystems(VOID)
+{
+       NTSTATUS  Status = STATUS_SUCCESS;
+
+       
+       DPRINT("SM: loading subsystems...\n");
+
+       /*
+        *  SM self registers: this also opens hSmApiPort to be used
+        * in loading required subsystems.
+        */
+       Status = SmRegisterInternalSubsystem (L"Session Manager", IMAGE_SUBSYSTEM_NATIVE, & hSmApiPort);
+       if(!NT_SUCCESS(Status)) 
+       {
+               DPRINT1("SM: SmRegisterInternalSubsystem failed Status=%08lx\n", __FUNCTION__, Status);
+               return Status;
+       }
+       /* Load Required subsystems (Debug Windows) */
+       Status = SmpLoadRequiredSubsystems();
+       if(!NT_SUCCESS(Status))
+       {
+               DPRINT1("SM: SmpLoadRequiredSubsystems failed Status=%08lx\n", __FUNCTION__, Status);
+               return Status;
+       }
+       /* done */
+       DPRINT("SM: done loading subsystems\n");
+       return Status;
+}
+
+/* EOF */