SM: change the way sessions are managed.
(it may be buggy)
Modified: trunk/reactos/subsys/smss/client.c
Modified: trunk/reactos/subsys/smss/initmv.c
Modified: trunk/reactos/subsys/smss/initrun.c
Modified: trunk/reactos/subsys/smss/initss.c
Modified: trunk/reactos/subsys/smss/smapi.c
Modified: trunk/reactos/subsys/smss/smapicomp.c
Modified: trunk/reactos/subsys/smss/smapiexec.c
Modified: trunk/reactos/subsys/smss/smss.c
Modified: trunk/reactos/subsys/smss/smss.h

Modified: trunk/reactos/subsys/smss/client.c
--- trunk/reactos/subsys/smss/client.c	2005-05-22 12:29:10 UTC (rev 15466)
+++ trunk/reactos/subsys/smss/client.c	2005-05-22 15:54:15 UTC (rev 15467)
@@ -39,9 +39,11 @@
 	RTL_CRITICAL_SECTION  Lock;
 	ULONG                 Count;
 	PSM_CLIENT_DATA       Client;
+	PSM_CLIENT_DATA       CandidateClient;
 
 } SmpClientDirectory;
 
+
 /**********************************************************************
  *	SmInitializeClientManagement/0
  */
@@ -52,56 +54,41 @@
 	RtlInitializeCriticalSection(& SmpClientDirectory.Lock);
 	SmpClientDirectory.Count = 0;
 	SmpClientDirectory.Client = NULL;
+	SmpClientDirectory.CandidateClient = NULL;
 	return STATUS_SUCCESS;
 
 }
-
 /**********************************************************************
- *	SmCompleteClientInitialization/1
- *
- * DESCRIPTION
- * 	Lookup the subsystem server descriptor given the process handle
- * 	of the subsystem server process.
+ * SmpSetClientInitialized/1
  */
-NTSTATUS STDCALL
-SmCompleteClientInitialization (HANDLE hProcess)
+VOID FASTCALL
+SmpSetClientInitialized (PSM_CLIENT_DATA Client)
 {
-	NTSTATUS        Status = STATUS_SUCCESS;
-	PSM_CLIENT_DATA Client = NULL;
-
-	DPRINT("SM: %s called\n", __FUNCTION__);
-
-	RtlEnterCriticalSection (& SmpClientDirectory.Lock);
-	if (SmpClientDirectory.Count > 0)
-	{
-		Client = SmpClientDirectory.Client;
-		while (NULL != Client)
-		{
-			if (hProcess == Client->ServerProcess)
-			{
-				Client->Initialized = TRUE;
-				break;
-			}
-			Client = Client->Next;
-		}
-		Status = STATUS_NOT_FOUND;
-	}
-	RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
-	return Status;
+	Client->Flags |= SM_CLIENT_FLAG_INITIALIZED;
 }
-
 /**********************************************************************
- *	SmpLookupClient/1					PRIVATE
+ *	SmpLookupClient/2					PRIVATE
  *
  * DESCRIPTION
  * 	Lookup the subsystem server descriptor given its image ID.
  *
- * SIDE EFFECTS
- * 	SmpClientDirectory.Lock is released only on success.
+ * ARGUMENTS
+ *	SubsystemId: IMAGE_SUBSYSTEM_xxx
+ *	Parent: optional: caller provided storage for the
+ *		the pointer to the SM_CLIENT_DATA which
+ *		Next field contains the value returned by
+ *		the function (on success).
+ *
+ * RETURN VALUES
+ *	NULL on error; otherwise a pointer to the SM_CLIENT_DATA
+ *	looked up object.
+ *
+ * WARNING
+ * 	SmpClientDirectory.Lock must be held by the caller.
  */
 static PSM_CLIENT_DATA FASTCALL
-SmpLookupClientUnsafe (USHORT           SubsystemId,
-		       PSM_CLIENT_DATA  * Parent)
+SmpLookupClient (USHORT           SubsystemId,
+		 PSM_CLIENT_DATA  * Parent)
 {
 	PSM_CLIENT_DATA Client = NULL;
 
@@ -129,72 +116,86 @@
 	}
 	return Client;
 }
-
-static PSM_CLIENT_DATA STDCALL
-SmpLookupClient (USHORT SubsystemId)
-{
-	PSM_CLIENT_DATA Client = NULL;
-
-	DPRINT("SM: %s called\n", __FUNCTION__);
-
-	RtlEnterCriticalSection (& SmpClientDirectory.Lock);
-	Client = SmpLookupClientUnsafe (SubsystemId, NULL);
-	if(NULL != Client)
-	{
-		RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
-	}
-	/*
-	 * Note that we do *not* release SmpClientDirectory.Lock here
-	 * because SmpLookupClient is called to FAIL when SubsystemId
-	 * is not registered yet.
-	 */
-	return Client;
-}
-
 /**********************************************************************
- *	SmpCreateClient/2
+ * 	SmBeginClientInitialization/1
+ *
+ * DESCRIPTION
+ * 	Check if the candidate client matches the begin session
+ * 	message from the subsystem process.
+ *
+ * ARGUMENTS
+ *	Request: message received by \SmApiPort
+ *	ClientData:
+ *		
+ * RETURN VALUES
+ *	NTSTATUS
  */
 NTSTATUS STDCALL
-SmCreateClient(PSM_PORT_MESSAGE Request, PSM_CLIENT_DATA * ClientData)
+SmBeginClientInitialization (IN  PSM_PORT_MESSAGE Request,
+			     OUT PSM_CLIENT_DATA  * ClientData)
 {
-	PSM_CLIENT_DATA pClient = NULL;
+	NTSTATUS Status = STATUS_SUCCESS;
 	PSM_CONNECT_DATA ConnectData = SmpGetConnectData (Request);
 	ULONG SbApiPortNameSize = SM_CONNECT_DATA_SIZE(*Request);
 
+
 	DPRINT("SM: %s called\n", __FUNCTION__);
-
+	
+	RtlEnterCriticalSection (& SmpClientDirectory.Lock);
 	/*
+	 * Is there a subsystem bootstrap in progress?
+	 */
+	if (SmpClientDirectory.CandidateClient)
+	{
+		PROCESS_BASIC_INFORMATION pbi;
+		
+		RtlZeroMemory (& pbi, sizeof pbi);
+		Status = NtQueryInformationProcess (Request->Header.ClientId.UniqueProcess,
+					    	    ProcessBasicInformation,
+						    & pbi,
+						    sizeof pbi,
+						    NULL);
+		if (NT_SUCCESS(Status))
+		{
+			SmpClientDirectory.CandidateClient->ServerProcessId =
+				(ULONG) pbi.UniqueProcessId;
+		}
+	}
+	else
+	{
+		RtlFreeHeap (SmpHeap, 0, SmpClientDirectory.CandidateClient);
+		DPRINT1("SM: %s: subsys booting with no descriptor!\n", __FUNCTION__);
+		Status = STATUS_NOT_FOUND;
+		RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
+		return Status;		
+	}
+	/*
 	 * Check if a client for the ID already exist.
 	 */
-	if (SmpLookupClient(ConnectData->SubSystemId))
+	if (SmpLookupClient(ConnectData->SubSystemId, NULL))
 	{
 		DPRINT("SM: %s: attempt to register again subsystem %d.\n",
 			__FUNCTION__,
 			ConnectData->SubSystemId);
 		return STATUS_UNSUCCESSFUL;
 	}
-	DPRINT("SM: %s: registering subsystem ID=%d \n", __FUNCTION__, ConnectData->SubSystemId);
+	DPRINT("SM: %s: registering subsystem ID=%d \n",
+		__FUNCTION__, ConnectData->SubSystemId);
+
 	/*
-	 * Allocate the storage for client data
+	 * Initialize the client data
 	 */
-	pClient = RtlAllocateHeap (SmpHeap,
-				   HEAP_ZERO_MEMORY,
-				   sizeof (SM_CLIENT_DATA));
-	if (NULL == pClient)
+	SmpClientDirectory.CandidateClient->SubsystemId = ConnectData->SubSystemId;
+	/* SM && DBG auto-initializes; other subsystems are required to call
+	 * SM_API_COMPLETE_SESSION via SMDLL. */
+	if ((IMAGE_SUBSYSTEM_NATIVE == SmpClientDirectory.CandidateClient->SubsystemId) ||
+	    (IMAGE_SUBSYSTEM_UNKNOWN == SmpClientDirectory.CandidateClient->SubsystemId))
 	{
-		DPRINT("SM: %s: out of memory!\n",__FUNCTION__);
-		return STATUS_NO_MEMORY;
+		SmpSetClientInitialized (SmpClientDirectory.CandidateClient);
 	}
-	/*
-	 * Initialize the client data
-	 */
-	pClient->SubsystemId = ConnectData->SubSystemId;
-	/* SM auto-initializes; other subsystems are required to call
-	 * SM_API_COMPLETE_SESSION via SMDLL. */
-	pClient->Initialized = (IMAGE_SUBSYSTEM_NATIVE == pClient->SubsystemId);
 	if (SbApiPortNameSize > 0)
 	{
-		RtlCopyMemory (pClient->SbApiPortName,
+		RtlCopyMemory (SmpClientDirectory.CandidateClient->SbApiPortName,
 			       ConnectData->SbName,
 			       SbApiPortNameSize);
 	}
@@ -204,30 +205,134 @@
 	 */
 	if (NULL == SmpClientDirectory.Client)
 	{
-		SmpClientDirectory.Client = pClient;
+		SmpClientDirectory.Client = SmpClientDirectory.CandidateClient;
 	} else {
 		PSM_CLIENT_DATA pCD = NULL;
 
 		for (pCD=SmpClientDirectory.Client;
 			(NULL != pCD->Next);
 			pCD = pCD->Next);
-		pCD->Next = pClient;
+		pCD->Next = SmpClientDirectory.CandidateClient;
 	}
-	pClient->Next = NULL;
+	SmpClientDirectory.CandidateClient->Next = NULL;
+	/*
+	 * Increment the number of active subsystems.
+	 */
 	++ SmpClientDirectory.Count;
 	/*
-	 * Note we unlock the client directory here, because
-	 * it was locked by SmpLookupClient on failure.
+	 * Notify to the caller the reference to the client data.
 	 */
-	RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
 	if (ClientData) 
 	{
-		*ClientData = pClient;
+		*ClientData = SmpClientDirectory.CandidateClient;
 	}
+	/*
+	 * Free the slot for the candidate subsystem.
+	 */
+	SmpClientDirectory.CandidateClient = NULL;
+
+	RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
+	
 	return STATUS_SUCCESS;
 }
+/**********************************************************************
+ *	SmCompleteClientInitialization/1
+ *
+ * DESCRIPTION
+ * 	Lookup the subsystem server descriptor given the process ID
+ * 	of the subsystem server process.
+ */
+NTSTATUS STDCALL
+SmCompleteClientInitialization (ULONG ProcessId)
+{
+	NTSTATUS        Status = STATUS_SUCCESS;
+	PSM_CLIENT_DATA Client = NULL;
 
+	DPRINT("SM: %s called\n", __FUNCTION__);
+
+	RtlEnterCriticalSection (& SmpClientDirectory.Lock);
+	if (SmpClientDirectory.Count > 0)
+	{
+		Client = SmpClientDirectory.Client;
+		while (NULL != Client)
+		{
+			if (ProcessId == Client->ServerProcessId)
+			{
+				SmpSetClientInitialized (Client);
+				break;
+			}
+			Client = Client->Next;
+		}
+		Status = STATUS_NOT_FOUND;
+	}
+	RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
+	return Status;
+}
+
 /**********************************************************************
+ *	SmpCreateClient/1
+ *
+ * DESCRIPTION
+ * 	Create a "candidate" client. Client descriptor will enter the
+ * 	client directory only at the end of the registration
+ * 	procedure. Otherwise, we will kill the associated process.
+ *
+ * ARGUMENTS
+ * 	ProcessHandle: handle of the subsystem server process.
+ *
+ * RETURN VALUE
+ * 	NTSTATUS:
+ */
+NTSTATUS STDCALL
+SmCreateClient (PRTL_PROCESS_INFO ProcessInfo, PWSTR ProgramName)
+{
+	NTSTATUS Status = STATUS_SUCCESS;
+
+	
+	DPRINT("SM: %s(%lx) called\n", __FUNCTION__, ProcessInfo->ProcessHandle);
+	RtlEnterCriticalSection (& SmpClientDirectory.Lock);
+	/*
+	 * Check if the candidate client slot is empty.
+	 */
+	if (NULL != SmpClientDirectory.CandidateClient)
+	{
+		DPRINT1("SM: %s: CandidateClient pending!\n", __FUNCTION__);
+		RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
+		return STATUS_UNSUCCESSFUL;
+	}
+	/*
+	 * Allocate the storage for client data
+	 */
+	SmpClientDirectory.CandidateClient =
+		RtlAllocateHeap (SmpHeap,
+				 HEAP_ZERO_MEMORY,
+				 sizeof (SM_CLIENT_DATA));
+	if (NULL == SmpClientDirectory.CandidateClient)
+	{
+		DPRINT("SM: %s(%lx): out of memory!\n",
+			__FUNCTION__, ProcessInfo->ProcessHandle);
+		Status = STATUS_NO_MEMORY;
+	}
+	else
+	{
+		/* Initialize the candidate client. */
+		RtlInitializeCriticalSection(& SmpClientDirectory.CandidateClient->Lock);
+		SmpClientDirectory.CandidateClient->ServerProcess =
+			(HANDLE) ProcessInfo->ProcessHandle;
+		SmpClientDirectory.CandidateClient->ServerProcessId = 
+			(ULONG) ProcessInfo->ClientId.UniqueProcess;
+	}
+	/*
+	 * Copy the program name
+	 */
+	RtlCopyMemory (SmpClientDirectory.CandidateClient->ProgramName,
+		       ProgramName,
+		       SM_SB_NAME_MAX_LENGTH);
+	RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
+	return Status;
+}
+
+/**********************************************************************
  * 	SmpDestroyClient/1
  *
  * 	1. close any handle
@@ -244,7 +349,7 @@
 	DPRINT("SM: %s called\n", __FUNCTION__);
 
 	RtlEnterCriticalSection (& SmpClientDirectory.Lock);
-	Client = SmpLookupClientUnsafe (SubsystemId, & Parent);
+	Client = SmpLookupClient (SubsystemId, & Parent);
 	if(NULL == Client)
 	{
 		DPRINT1("SM: %s: del req for non existent subsystem (id=%d)\n",
@@ -269,6 +374,7 @@
 			}
 		}
 		/* TODO: send shutdown or kill */
+		NtTerminateProcess (Client->ServerProcess, 0); //FIXME
 		RtlFreeHeap (SmpHeap, 0, Client);
 		-- SmpClientDirectory.Count;
 	}
@@ -285,7 +391,7 @@
 SmGetClientBasicInformation (PSM_BASIC_INFORMATION i)
 {
 	INT              Index = 0;
-	PSM_CLIENT_DATA  Client = NULL;
+	PSM_CLIENT_DATA  ClientData = NULL;
 
 	DPRINT("SM: %s called\n", __FUNCTION__);
 
@@ -296,13 +402,13 @@
 	
 	if (SmpClientDirectory.Count > 0)
 	{
-		Client = SmpClientDirectory.Client;
-		while ((NULL != Client) && (Index < SM_QRYINFO_MAX_SS_COUNT))
+		ClientData = SmpClientDirectory.Client;
+		while ((NULL != ClientData) && (Index < SM_QRYINFO_MAX_SS_COUNT))
 		{
-			i->SubSystem[Index].Id        = Client->SubsystemId;
-			i->SubSystem[Index].Flags     = 0; /* TODO */
-			i->SubSystem[Index].ProcessId = 0; /* TODO */
-			Client = Client->Next;
+			i->SubSystem[Index].Id        = ClientData->SubsystemId;
+			i->SubSystem[Index].Flags     = ClientData->Flags;
+			i->SubSystem[Index].ProcessId = ClientData->ServerProcessId;
+			ClientData = ClientData->Next;
 		}
 	}
 
@@ -316,9 +422,27 @@
 NTSTATUS FASTCALL
 SmGetSubSystemInformation (PSM_SUBSYSTEM_INFORMATION i)
 {
+	NTSTATUS         Status = STATUS_SUCCESS;
+	PSM_CLIENT_DATA  ClientData = NULL;
+	
 	DPRINT("SM: %s called\n", __FUNCTION__);
 
-	return STATUS_NOT_IMPLEMENTED;
+	RtlEnterCriticalSection (& SmpClientDirectory.Lock);
+	ClientData = SmpLookupClient (i->SubSystemId, NULL);
+	if (NULL == ClientData)
+	{
+		Status = STATUS_NOT_FOUND;
+	}
+	else
+	{
+		i->Flags     = ClientData->Flags;
+		i->ProcessId = ClientData->ServerProcessId;
+		RtlCopyMemory (i->NameSpaceRootNode,
+				ClientData->SbApiPortName,
+				(SM_QRYINFO_MAX_ROOT_NODE * sizeof(i->NameSpaceRootNode[0])));
+	}
+	RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
+	return Status;
 }
 
 /* EOF */

Modified: trunk/reactos/subsys/smss/initmv.c
--- trunk/reactos/subsys/smss/initmv.c	2005-05-22 12:29:10 UTC (rev 15466)
+++ trunk/reactos/subsys/smss/initmv.c	2005-05-22 15:54:15 UTC (rev 15467)
@@ -23,6 +23,7 @@
  *
  * --------------------------------------------------------------------
  */
+ 
 
 #include "smss.h"
 
@@ -35,6 +36,13 @@
   DPRINT("SmProcessFileRenameList() called\n");
 
   /* FIXME: implement it! */
+/*
+ * open HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\FileRenameOperations
+ * for each item in its value
+ *     clone the old file in the new name,
+ *     delete the source.
+ *
+ */
 
   DPRINT("SmProcessFileRenameList() done\n");
 

Modified: trunk/reactos/subsys/smss/initrun.c
--- trunk/reactos/subsys/smss/initrun.c	2005-05-22 12:29:10 UTC (rev 15466)
+++ trunk/reactos/subsys/smss/initrun.c	2005-05-22 15:54:15 UTC (rev 15467)
@@ -29,7 +29,7 @@
 #define NDEBUG
 #include <debug.h>
 
-HANDLE Children[2] = {0, 0}; /* csrss, winlogon */
+//HANDLE Children[2] = {0, 0}; /* csrss, winlogon */
 
 
 /**********************************************************************
@@ -99,10 +99,12 @@
   Status = SmCreateUserProcess (ImagePath,
 		  		CommandLine,
 				TRUE, /* wait */
-				NULL,
-				TRUE, /* terminate */
-				NULL);
-
+				NULL, NULL);
+  if (!NT_SUCCESS(Status))
+  {
+		DPRINT1("SM: %s: running '$S' failed (Status=0x%08lx)\n",
+			__FUNCTION__, Status);
+  }
   return(STATUS_SUCCESS);
 }
 

Modified: trunk/reactos/subsys/smss/initss.c
--- trunk/reactos/subsys/smss/initss.c	2005-05-22 12:29:10 UTC (rev 15466)
+++ trunk/reactos/subsys/smss/initss.c	2005-05-22 15:54:15 UTC (rev 15467)
@@ -55,23 +55,40 @@
 SmpRegisterSmss(VOID)
 {
 	NTSTATUS Status = STATUS_SUCCESS;
-	UNICODE_STRING SbApiPortName = {0,0,NULL};
+	RTL_PROCESS_INFO ProcessInfo;
 
 	
 	DPRINT("SM: %s called\n",__FUNCTION__);
-
-	RtlInitUnicodeString (& SbApiPortName, L"");	
-	Status = SmConnectApiPort(& SbApiPortName,
-				  (HANDLE) -1, /* SM has no SB port */
-				  IMAGE_SUBSYSTEM_NATIVE,
-				  & hSmApiPort);
-	if(!NT_SUCCESS(Status))
+	
+	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, L"Session Manager");
+	if (NT_SUCCESS(Status))
 	{
-		DPRINT("SM: %s: SMLIB!SmConnectApiPort failed (Status=0x%08lx)\n",
-			__FUNCTION__,Status);
-		return Status;
+		UNICODE_STRING SbApiPortName = {0,0,NULL};
+		
+		RtlInitUnicodeString (& SbApiPortName, L"");	
+		Status = SmConnectApiPort(& SbApiPortName,
+					  (HANDLE) -1, /* SM has no SB port */
+					  IMAGE_SUBSYSTEM_NATIVE,
+					  & hSmApiPort);
+		if(!NT_SUCCESS(Status))
+		{
+			DPRINT("SM: %s: SMLIB!SmConnectApiPort failed (Status=0x%08lx)\n",
+				__FUNCTION__,Status);
+			return Status;
+		}
+		DPRINT("SM self registered\n");
 	}
-	DPRINT("SM self registered\n");
+	else
+	{
+		DPRINT1("SM: %s: SmCreateClient failed (Status=0x%08lx)\n",
+			__FUNCTION__, Status);
+	}
 	/*
 	 * Note that you don't need to call complete session
 	 * because connection handling code autocompletes

Modified: trunk/reactos/subsys/smss/smapi.c
--- trunk/reactos/subsys/smss/smapi.c	2005-05-22 12:29:10 UTC (rev 15466)
+++ trunk/reactos/subsys/smss/smapi.c	2005-05-22 15:54:15 UTC (rev 15467)
@@ -52,12 +52,13 @@
 #endif
 
 /**********************************************************************
- * SmpCallback/2
+ * SmpCallbackServer/2
  *
- * The SM calls back a previously connected subsystem process to
- * authorizes it to bootstrap (initialize). The SM connects to a
- * named LPC port which name was sent in the connection data by the
- * candidate subsystem server process.
+ * DESCRIPTION
+ *	The SM calls back a previously connected subsystem process to
+ *	authorize it to bootstrap (initialize). The SM connects to a
+ *	named LPC port which name was sent in the connection data by
+ *	the candidate subsystem server process.
  */
 static NTSTATUS
 SmpCallbackServer (PSM_PORT_MESSAGE Request,
@@ -72,7 +73,8 @@
 
 	DPRINT("SM: %s called\n", __FUNCTION__);
 
-	if(IMAGE_SUBSYSTEM_NATIVE == ConnectData->SubSystemId)
+	if (	(IMAGE_SUBSYSTEM_UNKNOWN == ConnectData->SubSystemId) ||
+		(IMAGE_SUBSYSTEM_NATIVE  == ConnectData->SubSystemId))
 	{
 		DPRINT("SM: %s: we do not need calling back SM!\n",
 				__FUNCTION__);
@@ -210,12 +212,10 @@
 			{
 				DPRINT("SM: %s: id = %d\n", __FUNCTION__, ConnectData->SubSystemId);
 				/*
-				 * SmCreateClient/2 is called here explicitly to *fail*.
-				 * If it succeeds, there is something wrong in the
-				 * connection request. An environment subsystem *never*
-				 * registers twice. (security issue)
+				 * SmBeginClientInitialization/2 will succeed only if there
+				 * is a candidate client ready.
 				 */
-				Status = SmCreateClient (Request, & ClientData);
+				Status = SmBeginClientInitialization (Request, & ClientData);
 				if(STATUS_SUCCESS == Status)
 				{
 					DPRINT("SM: %s: ClientData = 0x%08lx\n",
@@ -310,7 +310,7 @@
  *
  * DECRIPTION
  * 	Due to differences in LPC implementation between NT and ROS,
- * 	we need a thread to listen for connection request that
+ * 	we need a thread to listen to for connection request that
  * 	creates a new thread for each connected port. This is not
  * 	necessary in NT LPC, because server side connected ports are
  * 	never used to receive requests.

Modified: trunk/reactos/subsys/smss/smapicomp.c
--- trunk/reactos/subsys/smss/smapicomp.c	2005-05-22 12:29:10 UTC (rev 15466)
+++ trunk/reactos/subsys/smss/smapicomp.c	2005-05-22 15:54:15 UTC (rev 15467)
@@ -34,16 +34,20 @@
  */
 SMAPI(SmCompSes)
 {
-	NTSTATUS Status = STATUS_SUCCESS;
+	NTSTATUS                  Status = STATUS_SUCCESS;
 
 	DPRINT("SM: %s called\n", __FUNCTION__);
-	
-	Status = SmCompleteClientInitialization (Request->Header.ClientId.UniqueProcess);
-	if(!NT_SUCCESS(Status))
+
+	DPRINT("SM: %s: ClientId.UniqueProcess=%lx\n",
+		__FUNCTION__, Request->Header.ClientId.UniqueProcess);
+	Status = SmCompleteClientInitialization ((ULONG) Request->Header.ClientId.UniqueProcess);
+	if (!NT_SUCCESS(Status))
 	{
-		Request->SmHeader.Status = STATUS_UNSUCCESSFUL;
+		DPRINT1("SM: %s: NtQueryInformationProcess failed (Status=0x%08lx)\n",
+			__FUNCTION__, Status);
 	}
-	return Status;
+	Request->SmHeader.Status = Status;
+	return STATUS_SUCCESS;
 }
 
 

Modified: trunk/reactos/subsys/smss/smapiexec.c
--- trunk/reactos/subsys/smss/smapiexec.c	2005-05-22 12:29:10 UTC (rev 15466)
+++ trunk/reactos/subsys/smss/smapiexec.c	2005-05-22 15:54:15 UTC (rev 15467)
@@ -31,15 +31,27 @@
 /**********************************************************************
  * SmCreateUserProcess/5
  *
+ * DESCRIPTION
+ *
+ * ARGUMENTS
+ *	ImagePath: bsolute path of the image to run;
+ *	CommandLine: arguments and options for ImagePath;
+ *	WaitForIt: TRUE for boot time processes and FALSE for
+ *		subsystems bootstrapping;
+ *	Timeout: optional: used if WaitForIt==TRUE;
+ *	ProcessHandle: optional: a duplicated handle for
+ 		the child process (storage provided by the caller).
+ *
+ * RETURN VALUE
+ * 	NTSTATUS:
+ *
  */
 NTSTATUS STDCALL
 SmCreateUserProcess (LPWSTR ImagePath,
 		     LPWSTR CommandLine,
 		     BOOLEAN WaitForIt,
 		     PLARGE_INTEGER Timeout OPTIONAL,
-		     BOOLEAN TerminateIt,
-		     PRTL_PROCESS_INFO UserProcessInfo OPTIONAL
-		     )
+		     PRTL_PROCESS_INFO UserProcessInfo OPTIONAL)
 {
 	UNICODE_STRING			ImagePathString = {0};
 	UNICODE_STRING			CommandLineString = {0};
@@ -48,9 +60,13 @@
 	PRTL_PROCESS_INFO		pProcessInfo = & ProcessInfo;
 	NTSTATUS			Status = STATUS_SUCCESS;
 
+	DPRINT("SM: %s called\n", __FUNCTION__);
+	
+	if (NULL != UserProcessInfo)
+	{
+		pProcessInfo = UserProcessInfo;
+	}
 
-	DPRINT("SM: %s called\n",__FUNCTION__);
-
 	RtlInitUnicodeString (& ImagePathString, ImagePath);
 	RtlInitUnicodeString (& CommandLineString, CommandLine);
 
@@ -65,12 +81,6 @@
 				   NULL,
 				   NULL);
 
-	if(NULL != UserProcessInfo)
-	{
-		/* Use caller provided storage */
-		pProcessInfo = UserProcessInfo;
-	}
-
 	Status = RtlCreateUserProcess (& ImagePathString,
 				       OBJ_CASE_INSENSITIVE,
 				       ProcessParameters,
@@ -82,7 +92,7 @@
 				       NULL,
 				       pProcessInfo);
                    
-   RtlDestroyProcessParameters (ProcessParameters);
+	RtlDestroyProcessParameters (ProcessParameters);
    
 	if (!NT_SUCCESS(Status))
 	{
@@ -90,25 +100,52 @@
 			__FUNCTION__, ImagePathString.Buffer, Status);
 		return Status;
 	}
-
-   ZwResumeThread(pProcessInfo->ThreadHandle, NULL);
-
-
-	/* Wait for process termination */
-	if(WaitForIt)
+	/*
+	 * It the caller is *not* interested in the child info,
+	 * resume it immediately.
+	 */
+	if (NULL == UserProcessInfo)
 	{
-		NtWaitForSingleObject (pProcessInfo->ProcessHandle,
-				       FALSE,
-				       Timeout);
+		Status = NtResumeThread (ProcessInfo.ThreadHandle, NULL);
+		if(!NT_SUCCESS(Status))
+		{
+			DPRINT1("SM: %s: NtResumeThread failed (Status=0x%08lx)\n",
+				__FUNCTION__, Status);
+		}
 	}
+	else
+	{
+		HANDLE DupProcessHandle = (HANDLE) 0;
+		
+		Status = NtDuplicateObject (NtCurrentProcess(),
+					    pProcessInfo->ProcessHandle,
+					    NtCurrentProcess(),
+					    & DupProcessHandle,
+					    PROCESS_ALL_ACCESS,
+					    0, 0);
+		if(!NT_SUCCESS(Status))
+		{
+			DPRINT1("SM: %s: NtDuplicateObject failed (Status=0x%08lx)\n",
+				__FUNCTION__, Status);
+		}
+		pProcessInfo->ProcessHandle = DupProcessHandle;
+		
+	}
 
-	/* Terminate process */
-	if(TerminateIt)
+	/* Wait for process termination */
+	if (WaitForIt)
 	{
-		NtClose(pProcessInfo->ThreadHandle);
-		NtClose(pProcessInfo->ProcessHandle);
+		Status = NtWaitForSingleObject (pProcessInfo->ProcessHandle,
+						FALSE,
+						Timeout);
+		if (!NT_SUCCESS(Status))
+		{
+			DPRINT1("SM: %s: NtWaitForSingleObject failed with Status=0x%08lx\n",
+				__FUNCTION__, Status);
+		}
+		
 	}
-	return STATUS_SUCCESS;
+	return Status;
 }
 
 /**********************************************************************
@@ -259,61 +296,94 @@
 	   (ExecPgm->NameLength <= SM_EXEXPGM_MAX_LENGTH) &&
 	   TRUE /* TODO: check LPC payload size */)
 	{
+		WCHAR Data [MAX_PATH + 1] = {0};
+		ULONG DataLength = sizeof Data;
+		ULONG DataType = REG_EXPAND_SZ;
+
 		
 		RtlZeroMemory (Name, sizeof Name);
 		RtlCopyMemory (Name,
 			       ExecPgm->Name,
 			       (sizeof ExecPgm->Name[0] * ExecPgm->NameLength));
 		DPRINT("SM: %s: Name='%S'\n", __FUNCTION__, Name);
-		/*
-		 * Check if program name is internal
-		 * (Is this correct? Debug is in the registry too)
-		 */
-		if(0 == _wcsicmp(L"DEBUG", Name))
+		/* Lookup Name in the registry */
+		Status = SmLookupSubsystem (Name,
+					    Data,
+					    & DataLength,
+					    & DataType,
+					    TRUE); /* expand */
+		if(NT_SUCCESS(Status))
 		{
-			/*
-			 * Initialize DBGSS.
-			 * NOTE: probably in early prototypes it was an
-			 * independent process; now it is embedded in the
-			 * SM for performance or security.
-			 */
-			Request->SmHeader.Status = SmInitializeDbgSs();
-		}
-		else
-		{
-			WCHAR Data [MAX_PATH + 1] = {0};
-			ULONG DataLength = sizeof Data;
-			ULONG DataType = REG_EXPAND_SZ;
-
-			/* Lookup Name in the registry */
-			Status = SmLookupSubsystem (Name,
-						    Data,
-						    & DataLength,
-						    & DataType,
-						    TRUE); /* expand */
-			if(NT_SUCCESS(Status))
+			/* Is the subsystem definition non-empty? */
+			if (DataLength > sizeof Data[0])
 			{
 				WCHAR ImagePath [MAX_PATH + 1] = {0};
+				PWCHAR CommandLine = ImagePath;
+				RTL_PROCESS_INFO ProcessInfo = {0};
 
 				wcscpy (ImagePath, L"\\??\\");
 				wcscat (ImagePath, Data);
-			
-				/* Create native process */
-				Request->SmHeader.Status = SmCreateUserProcess(ImagePath,
-								      L"", /* FIXME */
-								      FALSE, /* wait */
-				      				      NULL,
-			      					      FALSE, /* terminate */
-			      					      NULL);
-			}else{
-				Request->SmHeader.Status = Status;
+				/*
+				 * Look for the beginning of the command line.
+				 */
+				for (;	(*CommandLine != L'\0') && (*CommandLine != L' ');
+					CommandLine ++);
+				for (; *CommandLine == L' '; CommandLine ++)
+				{
+					*CommandLine = L'\0';
+				}
+				/*
+				 * Create a native process (suspended).
+				 */
+				ProcessInfo.Size = sizeof ProcessInfo;
+				Request->SmHeader.Status =
+					SmCreateUserProcess(ImagePath,
+							      CommandLine,
+							      FALSE, /* wait */
+				      			      NULL, /* timeout */
+			      				      & ProcessInfo);
+				if (NT_SUCCESS(Request->SmHeader.Status))
+				{
+					Status = SmCreateClient (& ProcessInfo, Name);
+					if (NT_SUCCESS(Status))
+					{
+						Status = NtResumeThread (ProcessInfo.ThreadHandle, NULL);
+						if (!NT_SUCCESS(Status))
+						{
+							//Status = SmDestroyClient TODO
+						}
+					} else {
+						DPRINT1("SM: %s: SmCreateClient failed (Status=0x%08lx)\n",
+							__FUNCTION__, Status);
+					}
+				}
 			}
+			else
+			{
+				/*
+				 * OK, the definition is empty, but check
+				 * if it is the name of an embedded subsystem.
+				 */
+				if(0 == _wcsicmp(L"DEBUG", Name))
+				{
+					/*
+					 * Initialize the embedded DBGSS.
+					 */
+					Request->SmHeader.Status = SmInitializeDbgSs();
+				}
+				else
+				{
+					/*
+					 * Badly defined subsystem. Check the registry!
+					 */
+					Request->SmHeader.Status = STATUS_NOT_FOUND;
+				}
+			}
+		} else {
+			/* It couldn't lookup the Name! */
+			Request->SmHeader.Status = Status;
 		}
 	}
-	else
-	{
-		Request->SmHeader.Status = Status = STATUS_INVALID_PARAMETER;
-	}
 	return Status;
 }
 

Modified: trunk/reactos/subsys/smss/smss.c
--- trunk/reactos/subsys/smss/smss.c	2005-05-22 12:29:10 UTC (rev 15466)
+++ trunk/reactos/subsys/smss/smss.c	2005-05-22 15:54:15 UTC (rev 15467)
@@ -30,16 +30,18 @@
 #define NDEBUG
 #include <debug.h>
 
-HANDLE SmSsProcessId = 0;
+ULONG SmSsProcessId = 0;
 
 /* Native image's entry point */
 
 VOID STDCALL
 NtProcessStartup(PPEB Peb)
 {
-  NTSTATUS Status;
+  NTSTATUS Status = STATUS_SUCCESS;
   PROCESS_BASIC_INFORMATION PBI = {0};
 
+PrintString("*** EXPERIMENTAL ***\n");
+  
   PrintString("ReactOS Session Manager %s (Build %s)\n",
 	     KERNEL_RELEASE_STR,
 	     KERNEL_VERSION_BUILD_STR);
@@ -52,7 +54,7 @@
       				      NULL);
   if(NT_SUCCESS(Status))
   {
-	  SmSsProcessId = PBI.UniqueProcessId;
+	  SmSsProcessId = (ULONG) PBI.UniqueProcessId;
   }
   /* Initialize the system */
   Status = InitSessionManager();

Modified: trunk/reactos/subsys/smss/smss.h
--- trunk/reactos/subsys/smss/smss.h	2005-05-22 12:29:10 UTC (rev 15466)
+++ trunk/reactos/subsys/smss/smss.h	2005-05-22 15:54:15 UTC (rev 15467)
@@ -6,11 +6,8 @@
 #include <sm/api.h>
 #include <sm/helper.h>
 
-#define CHILD_CSRSS     0
-#define CHILD_WINLOGON  1
-
 /* smss.c */
-extern HANDLE SmSsProcessId;
+extern ULONG SmSsProcessId;
 
 /* init.c */
 NTSTATUS InitSessionManager(VOID);
@@ -63,8 +60,7 @@
 				     LPWSTR CommandLine,
 				     BOOLEAN WaitForIt,
 				     PLARGE_INTEGER Timeout OPTIONAL,
-				     BOOLEAN TerminateIt,
-				     PRTL_PROCESS_INFO ProcessInfo OPTIONAL);
+				     PRTL_PROCESS_INFO UserProcessInfo OPTIONAL);
 NTSTATUS STDCALL
 SmLookupSubsystem (IN     PWSTR   Name,
 		   IN OUT PWSTR   Data,
@@ -80,22 +76,30 @@
 NTSTATUS FASTCALL SmQryInfo(PSM_PORT_MESSAGE);
 
 /* client.c */
+#define SM_CLIENT_FLAG_CANDIDATE   0x8000
+#define SM_CLIENT_FLAG_INITIALIZED 0x0001
+#define SM_CLIENT_FLAG_REQUIRED    0x0002
 typedef struct _SM_CLIENT_DATA
 {
-	USHORT	SubsystemId;
-	BOOL	Initialized;
-	HANDLE	ServerProcess;
-	HANDLE	ApiPort;
-	HANDLE	ApiPortThread;
-	HANDLE	SbApiPort;
-	WCHAR	SbApiPortName [SM_SB_NAME_MAX_LENGTH];
-	struct _SM_CLIENT_DATA * Next;
+  RTL_CRITICAL_SECTION  Lock;
+  WCHAR                 ProgramName [SM_SB_NAME_MAX_LENGTH];
+  USHORT                SubsystemId;
+  WORD                  Flags;
[truncated at 1000 lines; 22 more skipped]