SM: simplify and fix client (subsystem servers) management.
[reactos.git] / reactos / subsys / smss / initss.c
index bc8f7fa..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
-\r
-#include <rosrtl/string.h>\r
-\r
-#define NDEBUG\r
-#include <debug.h>\r
-\r
-/* SM handle for its own \SmApiPort */\r
-HANDLE hSmApiPort = (HANDLE) 0;\r
-\r
-\r
-/* TODO:\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
-\r
-/**********************************************************************\r
- *     SmpRegisterSmss/0\r
- *\r
- * DESCRIPTION\r
- *     Make smss register with itself for IMAGE_SUBSYSTEM_NATIVE\r
- *     (programmatically). This also opens hSmApiPort to be used\r
- *     in loading required subsystems.\r
- */\r
-\r
-static NTSTATUS\r
-SmpRegisterSmss(VOID)\r
-{\r
-       NTSTATUS Status = STATUS_SUCCESS;\r
-       RTL_PROCESS_INFO ProcessInfo;\r
-\r
-       \r
-       DPRINT("SM: %s called\n",__FUNCTION__);\r
-       \r
-       RtlZeroMemory (& ProcessInfo, sizeof ProcessInfo);\r
-       ProcessInfo.Size = sizeof ProcessInfo;\r
-       ProcessInfo.ProcessHandle = (HANDLE) SmSsProcessId;\r
-       ProcessInfo.ClientId.UniqueProcess = (HANDLE) SmSsProcessId;\r
-       DPRINT("SM: %s: ProcessInfo.ProcessHandle=%lx\n",\r
-               __FUNCTION__,ProcessInfo.ProcessHandle);\r
-       Status = SmCreateClient (& ProcessInfo, L"Session Manager");\r
-       if (NT_SUCCESS(Status))\r
-       {\r
-               UNICODE_STRING SbApiPortName = {0,0,NULL};\r
-               \r
-               RtlInitUnicodeString (& SbApiPortName, L"");    \r
-               Status = SmConnectApiPort(& SbApiPortName,\r
-                                         (HANDLE) -1, /* SM has no SB port */\r
-                                         IMAGE_SUBSYSTEM_NATIVE,\r
-                                         & hSmApiPort);\r
-               if(!NT_SUCCESS(Status))\r
-               {\r
-                       DPRINT("SM: %s: SMLIB!SmConnectApiPort failed (Status=0x%08lx)\n",\r
-                               __FUNCTION__,Status);\r
-                       return Status;\r
-               }\r
-               DPRINT("SM self registered\n");\r
-       }\r
-       else\r
-       {\r
-               DPRINT1("SM: %s: SmCreateClient failed (Status=0x%08lx)\n",\r
-                       __FUNCTION__, Status);\r
-       }\r
-       /*\r
-        * Note that you don't need to call complete session\r
-        * because connection handling code autocompletes\r
-        * the client structure for IMAGE_SUBSYSTEM_NATIVE.\r
-        */\r
-       return Status;\r
-}\r
-\r
-\r
-/**********************************************************************\r
- *     SmpLoadKernelModeSubsystem/0\r
- */\r
-static NTSTATUS\r
-SmpLoadKernelModeSubsystem (VOID)\r
-{\r
-       NTSTATUS  Status = STATUS_SUCCESS;\r
-       WCHAR     Data [MAX_PATH + 1];\r
-       ULONG     DataLength = sizeof Data;\r
-       ULONG     DataType = 0;\r
-\r
-\r
-       DPRINT("SM: %s called\n", __FUNCTION__);\r
-\r
-       Status = SmLookupSubsystem (L"Kmode",\r
-                                   Data,\r
-                                   & DataLength,\r
-                                   & DataType,\r
-                                   TRUE);\r
-       if((STATUS_SUCCESS == Status) && (DataLength > sizeof Data[0]))\r
-       {\r
-               WCHAR                      ImagePath [MAX_PATH + 1] = {0};\r
-               SYSTEM_LOAD_AND_CALL_IMAGE ImageInfo;\r
-\r
-               wcscpy (ImagePath, L"\\??\\");\r
-               wcscat (ImagePath, Data);\r
-               RtlZeroMemory (& ImageInfo, sizeof ImageInfo);\r
-               RtlInitUnicodeString (& ImageInfo.ModuleName, ImagePath);\r
-               Status = NtSetSystemInformation(SystemLoadAndCallImage,\r
-                                               & ImageInfo,\r
-                                               sizeof ImageInfo);\r
-               if(!NT_SUCCESS(Status))\r
-               {\r
-                       DPRINT("SM: %s: loading Kmode failed (Status=0x%08lx)\n",\r
-                               __FUNCTION__, Status);\r
-               }\r
-       }\r
-       return Status;\r
-}\r
-\r
-/**********************************************************************\r
- *     SmpLoadRequiredSubsystems/0\r
- */\r
-static NTSTATUS\r
-SmpLoadRequiredSubsystems (VOID)\r
-{\r
-       NTSTATUS  Status = STATUS_SUCCESS;\r
-       WCHAR     Data [MAX_PATH + 1];\r
-       ULONG     DataLength = sizeof Data;\r
-       ULONG     DataType = 0;\r
-\r
-       \r
-       DPRINT("SM: %s called\n", __FUNCTION__);\r
-\r
-       RtlZeroMemory (Data, DataLength);\r
-       Status = SmLookupSubsystem (L"Required",\r
-                                   Data,\r
-                                   & DataLength,\r
-                                   & DataType,\r
-                                   FALSE);\r
-       if((STATUS_SUCCESS == Status) && (DataLength > sizeof Data[0]))\r
-       {\r
-               PWCHAR Name = NULL;\r
-               ULONG Offset = 0;\r
-               \r
-               for (Name = Data; (Offset < DataLength); )\r
-               {\r
-                       if(L'\0' != *Name)\r
-                       {\r
-                               UNICODE_STRING Program;\r
-\r
-                               /* Run the current program */\r
-                               RtlInitUnicodeString (& Program, Name);\r
-                               Status = SmExecuteProgram (hSmApiPort, & Program);\r
-                               if(!NT_SUCCESS(Status))\r
-                               {\r
-                                       DPRINT1("SM: %s failed to run '%S' program (Status=0x%08lx)\n",\r
-                                               __FUNCTION__, Name, Status);\r
-                               }\r
-                               /* Look for the next program */\r
-                               while ((L'\0' != *Name) && (Offset < DataLength))\r
-                               {\r
-                                       ++ Name;\r
-                                       ++ Offset;\r
-                               }\r
-                       }\r
-                       ++ Name;\r
-                       ++ Offset;\r
-               }\r
-       }\r
-\r
-       return Status;\r
-}\r
-\r
-/**********************************************************************\r
- *     SmLoadSubsystems/0\r
- */\r
-NTSTATUS\r
-SmLoadSubsystems(VOID)\r
-{\r
-       NTSTATUS  Status = STATUS_SUCCESS;\r
-\r
-       \r
-       DPRINT("SM: loading subsystems\n");\r
-\r
-       /* SM self registers */\r
-       Status = SmpRegisterSmss();\r
-       if(!NT_SUCCESS(Status)) return Status;\r
-       /* Load Kmode subsystem (aka win32k.sys) */\r
-       Status = SmpLoadKernelModeSubsystem();\r
-       if(!NT_SUCCESS(Status)) return Status;\r
-       /* Load Required subsystems (Debug Windows) */\r
-       Status = SmpLoadRequiredSubsystems();\r
-       if(!NT_SUCCESS(Status)) return Status;\r
-       /* done */\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 */