Kmode subsystem no more hardwired.
Modified: trunk/reactos/subsys/smss/initss.c
Modified: trunk/reactos/subsys/smss/smapiexec.c
Modified: trunk/reactos/subsys/smss/smss.h

Modified: trunk/reactos/subsys/smss/initss.c
--- trunk/reactos/subsys/smss/initss.c	2005-03-02 21:54:58 UTC (rev 13799)
+++ trunk/reactos/subsys/smss/initss.c	2005-03-02 22:09:53 UTC (rev 13800)
@@ -32,6 +32,10 @@
 #define NDEBUG
 #include <debug.h>
 
+/* SM handle for its own \SmApiPort */
+HANDLE hSmApiPort = (HANDLE) 0;
+
+
 /* TODO: this file should be totally rewritten
  *
  * a) look if a special option is set for smss.exe in
@@ -40,9 +44,6 @@
  * b) make smss register with itself for IMAGE_SUBSYSTEM_NATIVE
  *    (programmatically)
  *
- * c) make smss load win32k.sys as set in Kmode key
- *    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems
- *
  * d) make smss initialize Debug (DBGSS) and Windows (CSRSS) as described
  *    in the registry key Required="Debug Windows"
  *    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems
@@ -56,30 +57,41 @@
 NTSTATUS
 SmLoadSubsystems(VOID)
 {
-  SYSTEM_LOAD_AND_CALL_IMAGE ImageInfo;
-  NTSTATUS Status;
+	SYSTEM_LOAD_AND_CALL_IMAGE ImageInfo;
+	NTSTATUS                   Status = STATUS_SUCCESS;
+	WCHAR                      Data [MAX_PATH + 1];
+	ULONG                      DataLength = sizeof Data;
+	ULONG                      DataType = 0;
 
-  DPRINT("SM: loading subsystems\n");
+
+	DPRINT("SM: loading subsystems\n");
  
-  /* Load kernel mode subsystem (aka win32k.sys) */
-  RtlRosInitUnicodeStringFromLiteral(&ImageInfo.ModuleName,
-		       L"\\SystemRoot\\system32\\win32k.sys");
+	/* Load Kmode subsystem (aka win32k.sys) */
+	Status = SmLookupSubsystem (L"Kmode",
+				    Data,
+				    & DataLength,
+				    & DataType,
+				    TRUE);
+	if((STATUS_SUCCESS == Status) && (DataLength > sizeof Data[0]))
+	{
+		WCHAR ImagePath [MAX_PATH + 1] = {0};
 
-  Status = NtSetSystemInformation(SystemLoadAndCallImage,
-				  &ImageInfo,
-				  sizeof(SYSTEM_LOAD_AND_CALL_IMAGE));
-
-  DPRINT("SMSS: Loaded win32k.sys (Status %lx)\n", Status);
-#if 0
-  if (!NT_SUCCESS(Status))
-    {
-      return(Status);
-    }
-#endif
-
-  /* FIXME: load more subsystems (csrss!) */
-
-  return(Status);
+		wcscpy (ImagePath, L"\\??\\");
+		wcscat (ImagePath, Data);
+		RtlZeroMemory (& ImageInfo, sizeof ImageInfo);
+		RtlInitUnicodeString (& ImageInfo.ModuleName, ImagePath);
+		Status = NtSetSystemInformation(SystemLoadAndCallImage,
+					  & ImageInfo,
+					  sizeof ImageInfo);
+		if(!NT_SUCCESS(Status))
+		{
+			DPRINT("SM: loading Kmode failed (Status=0x%08lx)\n",
+				Status);
+			return Status;
+		}
+	}
+	/* TODO: load Required subsystems (Debug Windows) */
+	return Status;
 }
 
 NTSTATUS

Modified: trunk/reactos/subsys/smss/smapiexec.c
--- trunk/reactos/subsys/smss/smapiexec.c	2005-03-02 21:54:58 UTC (rev 13799)
+++ trunk/reactos/subsys/smss/smapiexec.c	2005-03-02 22:09:53 UTC (rev 13800)
@@ -1,13 +1,29 @@
-/* $Id: $
+/* $Id$
  *
  * smapiexec.c - SM_API_EXECUTE_PROGRAM
  *
  * Reactos Session Manager
  *
+ * --------------------------------------------------------------------
+ *
+ * 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"
-#include <rosrtl/string.h>
 
 #define NDEBUG
 #include <debug.h>
@@ -100,14 +116,204 @@
 }
 
 /**********************************************************************
+ * NAME
+ *	SmLookupSubsystem/5
+ *
+ * DESCRIPTION
+ * 	Read from the registry key
+ * 	\Registry\SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems
+ * 	the value which name is Name.
+ *
+ * ARGUMENTS
+ * 	Name: name of the program to run, that is a value's name in
+ * 	      the SM registry key Subsystems;
+ * 	Data: what the registry gived back for Name;
+ * 	DataLength: how much Data the registry retruns;
+ * 	DataType: what is Data?
+ * 	Expand: set it TRUE if you want this function to use the env
+ * 	      to possibly expand Data before giving it back.
+ */
+NTSTATUS STDCALL
+SmLookupSubsystem (IN     PWSTR   Name,
+		   IN OUT PWSTR   Data,
+		   IN OUT PULONG  DataLength,
+		   IN OUT PULONG  DataType,
+		   IN     BOOLEAN Expand)
+{
+	NTSTATUS           Status = STATUS_SUCCESS;
+	UNICODE_STRING     usKeyName = {0};
+	OBJECT_ATTRIBUTES  Oa = {0};
+	HANDLE             hKey = (HANDLE) 0;
+
+	DPRINT("SM: %s called\n", __FUNCTION__);
+	/*
+	 * Prepare the key name to scan and
+	 * related object attributes.
+	 */
+	RtlInitUnicodeString (& usKeyName,
+		L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\SubSystems");
+
+	InitializeObjectAttributes (& Oa,
+				    & usKeyName,
+				    OBJ_CASE_INSENSITIVE,
+				    NULL,
+				    NULL);
+	/*
+	 * Open the key. This MUST NOT fail, if the
+	 * request is for a legitimate subsystem.
+	 */
+	Status = NtOpenKey (& hKey,
+			      MAXIMUM_ALLOWED,
+			      & Oa);
+	if(NT_SUCCESS(Status))
+	{
+		UNICODE_STRING usValueName = {0};
+		WCHAR          KeyValueInformation [1024] = {L'\0'};
+		ULONG          ResultLength = 0L;
+		PKEY_VALUE_PARTIAL_INFORMATION
+			       kvpi = (PKEY_VALUE_PARTIAL_INFORMATION) KeyValueInformation;
+
+		
+		RtlInitUnicodeString (& usValueName, Name);
+		Status = NtQueryValueKey (hKey,
+					  & usValueName,
+					  KeyValuePartialInformation,
+					  KeyValueInformation,
+					  sizeof KeyValueInformation,
+					  & ResultLength);
+		if(NT_SUCCESS(Status))
+		{
+			DPRINT("nkvpi.TitleIndex = %ld\n", kvpi->TitleIndex);
+			DPRINT("kvpi.Type        = %ld\n", kvpi->Type);
+			DPRINT("kvpi.DataLength  = %ld\n", kvpi->DataLength);
+
+			if((NULL != Data) && (NULL != DataLength) && (NULL != DataType))
+			{
+				*DataType = kvpi->Type;
+				if((Expand) && (REG_EXPAND_SZ == *DataType))
+				{
+					UNICODE_STRING Source;
+					WCHAR          DestinationBuffer [2048] = {0};
+					UNICODE_STRING Destination;
+					ULONG          Length = 0;
+
+					DPRINT("SM: %s: value will be expanded\n", __FUNCTION__);
+
+					Source.Length        = kvpi->DataLength;
+					Source.MaximumLength = kvpi->DataLength;
+					Source.Buffer        = (PWCHAR) & kvpi->Data;
+
+					Destination.Length        = 0;
+					Destination.MaximumLength = sizeof DestinationBuffer;
+					Destination.Buffer        = DestinationBuffer;
+
+					Status = RtlExpandEnvironmentStrings_U (SmSystemEnvironment,
+										& Source,
+										& Destination,
+										& Length);
+					if(NT_SUCCESS(Status))
+					{
+						*DataLength = min(*DataLength, Destination.Length);
+						RtlCopyMemory (Data, Destination.Buffer, *DataLength);				
+					}
+							
+				}else{
+					DPRINT("SM: %s: value won't be expanded\n", __FUNCTION__);
+					*DataLength = min(*DataLength, kvpi->DataLength);
+					RtlCopyMemory (Data, & kvpi->Data, *DataLength);
+				}
+				*DataType = kvpi->Type;
+			}else{
+				DPRINT1("SM: %s: Data or DataLength or DataType is NULL!\n", __FUNCTION__);
+				Status = STATUS_INVALID_PARAMETER;
+			}
+		}else{
+			DPRINT1("%s: NtQueryValueKey failed (Status=0x%08lx)\n", __FUNCTION__, Status);
+		}
+		NtClose (hKey);
+	}else{
+		DPRINT1("%s: NtOpenKey failed (Status=0x%08lx)\n", __FUNCTION__, Status);
+	}
+	return Status;
+}
+
+
+/**********************************************************************
  * SmExecPgm/1							API
  */
 SMAPI(SmExecPgm)
 {
+	PSM_PORT_MESSAGE_EXECPGM ExecPgm = NULL;
+	WCHAR                    Name [SM_EXEXPGM_MAX_LENGTH + 1];
+	NTSTATUS                 Status = STATUS_SUCCESS;
+
 	DPRINT("SM: %s called\n",__FUNCTION__);
-	Request->Status = STATUS_NOT_IMPLEMENTED;
-	return STATUS_SUCCESS;
+
+	if(NULL == Request)
+	{
+		DPRINT1("SM: %s: Request == NULL!\n", __FUNCTION__);
+		return STATUS_INVALID_PARAMETER;
+	}
+	DPRINT("SM: %s called from CID(%lx|%lx)\n",
+		__FUNCTION__, Request->Header.ClientId.UniqueProcess,
+		Request->Header.ClientId.UniqueThread);
+	ExecPgm = & Request->ExecPgm;
+	/* Check if the name lenght is valid */
+	if((ExecPgm->NameLength > 0) &&
+	   (ExecPgm->NameLength <= SM_EXEXPGM_MAX_LENGTH) &&
+	   TRUE /* TODO: check LPC payload size */)
+	{
+		
+		RtlZeroMemory (Name, sizeof Name);
+		RtlCopyMemory (Name,
+			       ExecPgm->Name,
+			       (sizeof ExecPgm->Name[0] * ExecPgm->NameLength));
+		DPRINT("SM: %s: Name=[%wZ]\n", __FUNCTION__, Name);
+		/*
+		 * Check if program name is internal
+		 * (Is this correct? Debug is in the registry too)
+		 */
+		if(0 == _wcsicmp(L"DEBUG", Name))
+		{
+			/*
+			 * Initialize DBGSS.
+			 * NOTE: probably in early prototypes it was an
+			 * independent process; now it is embedded in the
+			 * SM for performance or security.
+			 */
+			Request->Status = SmInitializeDbgSs();
+		}
+		else
+		{
+			WCHAR ImagePath [1024] = {0};
+			ULONG ImagePathLength = sizeof ImagePath;
+			ULONG ImagePathType = REG_EXPAND_SZ;
+
+			/* Lookup Name in the registry */
+			Status = SmLookupSubsystem (Name,
+						    ImagePath,
+						    & ImagePathLength,
+						    & ImagePathType,
+						    TRUE); /* expand */
+			if(NT_SUCCESS(Status))
+			{
+				/* Create native process */
+				Request->Status = SmCreateUserProcess(ImagePath,
+								      L"", /* FIXME */
+								      FALSE, /* wait */
+				      				      NULL,
+			      					      FALSE, /* terminate */
+			      					      NULL);
+			}else{
+				Request->Status = Status;
+			}
+		}
+	}
+	else
+	{
+		Request->Status = Status = STATUS_INVALID_PARAMETER;
+	}
+	return Status;
 }
 
-
 /* EOF */

Modified: trunk/reactos/subsys/smss/smss.h
--- trunk/reactos/subsys/smss/smss.h	2005-03-02 21:54:58 UTC (rev 13799)
+++ trunk/reactos/subsys/smss/smss.h	2005-03-02 22:09:53 UTC (rev 13800)
@@ -63,6 +63,12 @@
 				     PLARGE_INTEGER Timeout OPTIONAL,
 				     BOOLEAN TerminateIt,
 				     PRTL_PROCESS_INFO ProcessInfo OPTIONAL);
+NTSTATUS STDCALL
+SmLookupSubsystem (IN     PWSTR   Name,
+		   IN OUT PWSTR   Data,
+		   IN OUT PULONG  DataLength,
+		   IN OUT PULONG  DataType,
+		   IN     BOOLEAN Expand);
 NTSTATUS FASTCALL SmExecPgm(PSM_PORT_MESSAGE);
 
 /* smapicomp.c */