SM: simplify and fix client (subsystem servers) management.
Modified: trunk/reactos/subsys/smss/client.c
Modified: trunk/reactos/subsys/smss/debug.c
Modified: trunk/reactos/subsys/smss/initss.c
Modified: trunk/reactos/subsys/smss/smapi.c
Modified: trunk/reactos/subsys/smss/smapiexec.c
Modified: trunk/reactos/subsys/smss/smss.h

Modified: trunk/reactos/subsys/smss/client.c
--- trunk/reactos/subsys/smss/client.c	2005-08-27 04:20:49 UTC (rev 17566)
+++ trunk/reactos/subsys/smss/client.c	2005-08-27 09:55:27 UTC (rev 17567)
@@ -31,12 +31,14 @@
 
 /* Private ADT */
 
+#define SM_MAX_CLIENT_COUNT 16
+#define SM_INVALID_CLIENT_INDEX -1
 
 struct _SM_CLIENT_DIRECTORY
 {
 	RTL_CRITICAL_SECTION  Lock;
 	ULONG                 Count;
-	PSM_CLIENT_DATA       Client;
+	PSM_CLIENT_DATA       Client [SM_MAX_CLIENT_COUNT];
 	PSM_CLIENT_DATA       CandidateClient;
 
 } SmpClientDirectory;
@@ -51,7 +53,7 @@
 	DPRINT("SM: %s called\n", __FUNCTION__);
 	RtlInitializeCriticalSection(& SmpClientDirectory.Lock);
 	SmpClientDirectory.Count = 0;
-	SmpClientDirectory.Client = NULL;
+	RtlZeroMemory (SmpClientDirectory.Client, sizeof SmpClientDirectory.Client);
 	SmpClientDirectory.CandidateClient = NULL;
 	return STATUS_SUCCESS;
 
@@ -66,58 +68,87 @@
 	Client->Flags |= SM_CLIENT_FLAG_INITIALIZED;
 }
 /**********************************************************************
- *	SmpLookupClient/2					PRIVATE
+ * SmpGetFirstFreeClientEntry/0					PRIVATE
  *
+ * NOTE: call it holding SmpClientDirectory.Lock only
+ */
+static INT STDCALL SmpGetFirstFreeClientEntry (VOID)
+{
+	INT ClientIndex = 0;
+
+	DPRINT("SM: %s called\n", __FUNCTION__);
+
+	if (SmpClientDirectory.Count < SM_MAX_CLIENT_COUNT)
+	{
+		for (ClientIndex = 0;
+			(ClientIndex < SM_MAX_CLIENT_COUNT);
+			ClientIndex ++)
+		{
+			if (NULL == SmpClientDirectory.Client[ClientIndex])
+			{
+				DPRINT("SM: %s => %d\n", __FUNCTION__, ClientIndex);
+				return ClientIndex; // found
+			}
+		}
+	}
+	return SM_INVALID_CLIENT_INDEX; // full!		
+}
+/**********************************************************************
+ *	SmpLookupClient/1					PRIVATE
+ *
  * DESCRIPTION
- * 	Lookup the subsystem server descriptor given its image ID.
+ * 	Lookup the subsystem server descriptor (client data) given its
+ * 	base image ID.
  *
  * 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.
+ *	SM_INVALID_CLIENT_INDEX on error;
+ *	otherwise an index in the range (0..SM_MAX_CLIENT_COUNT).
  *
  * WARNING
  * 	SmpClientDirectory.Lock must be held by the caller.
  */
-static PSM_CLIENT_DATA FASTCALL
-SmpLookupClient (USHORT           SubsystemId,
-		 PSM_CLIENT_DATA  * Parent)
+static INT FASTCALL
+SmpLookupClient (USHORT SubsystemId)
 {
-	PSM_CLIENT_DATA Client = NULL;
+	INT  ClientIndex = 0;
 
 	DPRINT("SM: %s(%d) called\n", __FUNCTION__, SubsystemId);
-	
-	if(NULL != Parent)
+
+	if (0 != SmpClientDirectory.Count)
 	{
-		*Parent = NULL;
-	}
-	if (SmpClientDirectory.Count > 0)
-	{
-		Client = SmpClientDirectory.Client;
-		while (NULL != Client)
+		for (ClientIndex = 0; (ClientIndex < SM_MAX_CLIENT_COUNT); ClientIndex ++)
 		{
-			DPRINT("SM: %s: Client==%08lx\n", __FUNCTION__, Client);
-			if (SubsystemId == Client->SubsystemId)
+			if (NULL != SmpClientDirectory.Client[ClientIndex])
 			{
-				DPRINT("SM: %s: FOUND Client==%08lx\n", __FUNCTION__, Client);
-				break;
+				if (SubsystemId == SmpClientDirectory.Client[ClientIndex]->SubsystemId)
+				{
+					return ClientIndex;
+				}
 			}
-			if(NULL != Parent)
-			{
-				*Parent = Client;
-			}
-			Client = Client->Next;
 		}
-	}
-	return Client;
+	}	
+	return SM_INVALID_CLIENT_INDEX;
 }
 /**********************************************************************
+ * 	SmpDestroyClientObject/2				PRIVATE
+ *
+ * WARNING
+ * 	SmpClientDirectory.Lock must be held by the caller.
+ */
+static NTSTATUS STDCALL
+SmpDestroyClientObject (PSM_CLIENT_DATA Client, NTSTATUS DestroyReason)
+{
+	DPRINT("SM:%s(%08lx,%08lx) called\n", __FUNCTION__, DestroyReason);
+	/* TODO: send shutdown to the SB port */
+	NtTerminateProcess (Client->ServerProcess, DestroyReason);
+	RtlFreeHeap (SmpHeap, 0, Client);
+	-- SmpClientDirectory.Count;
+	return STATUS_SUCCESS;
+}
+/**********************************************************************
  * 	SmBeginClientInitialization/1
  *
  * DESCRIPTION
@@ -135,18 +166,20 @@
 SmBeginClientInitialization (IN  PSM_PORT_MESSAGE Request,
 			     OUT PSM_CLIENT_DATA  * ClientData)
 {
-	NTSTATUS Status = STATUS_SUCCESS;
-	PSM_CONNECT_DATA ConnectData = SmpGetConnectData (Request);
-	ULONG SbApiPortNameSize = SM_CONNECT_DATA_SIZE(*Request);
+	NTSTATUS          Status = STATUS_SUCCESS;
+	PSM_CONNECT_DATA  ConnectData = SmpGetConnectData (Request);
+	ULONG             SbApiPortNameSize = SM_CONNECT_DATA_SIZE(*Request);
+	INT               ClientIndex = SM_INVALID_CLIENT_INDEX;
 
 
-	DPRINT("SM: %s called\n", __FUNCTION__);
+	DPRINT("SM: %s(%08lx,%08lx) called\n", __FUNCTION__,
+			Request, ClientData);
 	
 	RtlEnterCriticalSection (& SmpClientDirectory.Lock);
 	/*
 	 * Is there a subsystem bootstrap in progress?
 	 */
-	if (SmpClientDirectory.CandidateClient)
+	if (NULL != SmpClientDirectory.CandidateClient)
 	{
 		PROCESS_BASIC_INFORMATION pbi;
 		
@@ -164,7 +197,6 @@
 	}
 	else
 	{
-		RtlFreeHeap (SmpHeap, 0, SmpClientDirectory.CandidateClient);
 		DPRINT1("SM: %s: subsys booting with no descriptor!\n", __FUNCTION__);
 		Status = STATUS_NOT_FOUND;
 		RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
@@ -173,14 +205,28 @@
 	/*
 	 * Check if a client for the ID already exist.
 	 */
-	if (SmpLookupClient(ConnectData->SubSystemId, NULL))
+	if (SM_INVALID_CLIENT_INDEX != SmpLookupClient(ConnectData->SubSystemId))
 	{
 		DPRINT("SM: %s: attempt to register again subsystem %d.\n",
 			__FUNCTION__,
 			ConnectData->SubSystemId);
+		// TODO something else to do here?
 		RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
 		return STATUS_UNSUCCESSFUL;
 	}
+	/*
+	 * Check if a free entry exists in SmpClientDirectory.Client[].
+	 */
+	ClientIndex = SmpGetFirstFreeClientEntry();
+	if (SM_INVALID_CLIENT_INDEX == ClientIndex)
+	{
+		DPRINT("SM: %s: SM_INVALID_CLIENT_INDEX == ClientIndex ", __FUNCTION__);
+		SmpDestroyClientObject (SmpClientDirectory.CandidateClient, STATUS_NO_MEMORY);
+		SmpClientDirectory.CandidateClient = NULL;
+		return STATUS_NO_MEMORY;
+	}
+
+	/* OK! */
 	DPRINT("SM: %s: registering subsystem ID=%d \n",
 		__FUNCTION__, ConnectData->SubSystemId);
 
@@ -191,12 +237,13 @@
 	/* 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))
+	    ((USHORT)-1 == SmpClientDirectory.CandidateClient->SubsystemId))
 	{
 		SmpSetClientInitialized (SmpClientDirectory.CandidateClient);
 	}
 	if (SbApiPortNameSize > 0)
 	{
+		/* Only external servers have an SB port */
 		RtlCopyMemory (SmpClientDirectory.CandidateClient->SbApiPortName,
 			       ConnectData->SbName,
 			       SbApiPortNameSize);
@@ -205,18 +252,7 @@
 	 * Insert the new descriptor in the
 	 * client directory.
 	 */
-	if (NULL == SmpClientDirectory.Client)
-	{
-		SmpClientDirectory.Client = SmpClientDirectory.CandidateClient;
-	} else {
-		PSM_CLIENT_DATA pCD = NULL;
-
-		for (pCD=SmpClientDirectory.Client;
-			(NULL != pCD->Next);
-			pCD = pCD->Next);
-		pCD->Next = SmpClientDirectory.CandidateClient;
-	}
-	SmpClientDirectory.CandidateClient->Next = NULL;
+	SmpClientDirectory.Client [ClientIndex] = SmpClientDirectory.CandidateClient;
 	/*
 	 * Increment the number of active subsystems.
 	 */
@@ -233,6 +269,7 @@
 	 */
 	SmpClientDirectory.CandidateClient = NULL;
 
+	/* Done */
 	RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
 	
 	return STATUS_SUCCESS;
@@ -247,31 +284,102 @@
 NTSTATUS STDCALL
 SmCompleteClientInitialization (ULONG ProcessId)
 {
-	NTSTATUS        Status = STATUS_NOT_FOUND;
-	PSM_CLIENT_DATA Client = NULL;
+	NTSTATUS  Status = STATUS_NOT_FOUND;
+	INT       ClientIndex = SM_INVALID_CLIENT_INDEX;
 
 	DPRINT("SM: %s(%lu) called\n", __FUNCTION__, ProcessId);
 
 	RtlEnterCriticalSection (& SmpClientDirectory.Lock);
 	if (SmpClientDirectory.Count > 0)
 	{
-		Client = SmpClientDirectory.Client;
-		while (NULL != Client)
-		{
-			if (ProcessId == Client->ServerProcessId)
+		for (ClientIndex = 0; ClientIndex < SM_MAX_CLIENT_COUNT; ClientIndex ++)
+		{		
+			if ((NULL != SmpClientDirectory.Client [ClientIndex]) &&
+				(ProcessId == SmpClientDirectory.Client [ClientIndex]->ServerProcessId))
 			{
-				SmpSetClientInitialized (Client);
+				SmpSetClientInitialized (SmpClientDirectory.Client [ClientIndex]);
 				Status = STATUS_SUCCESS;
 				break;
 			}
-			Client = Client->Next;
 		}
 	}
 	RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
 	return Status;
 }
+/**********************************************************************
+ * 	SmpDestroyClientByClientIndex/1				PRIVATE
+ */
+static NTSTATUS STDCALL
+SmpDestroyClientByClientIndex (INT ClientIndex)
+{
+	NTSTATUS         Status = STATUS_SUCCESS;
+	PSM_CLIENT_DATA  Client = NULL;
 
+	DPRINT("SM: %s(%d) called\n", __FUNCTION__, ClientIndex);
+
+	if (SM_INVALID_CLIENT_INDEX == ClientIndex)
+	{
+		DPRINT1("SM: %s: SM_INVALID_CLIENT_INDEX == ClientIndex!\n",
+			__FUNCTION__);
+		Status = STATUS_NOT_FOUND;
+	}
+	else
+	{
+		Client = SmpClientDirectory.Client [ClientIndex];
+		SmpClientDirectory.Client [ClientIndex] = NULL;
+		if (NULL != Client)
+		{
+			Status = SmpDestroyClientObject (Client, STATUS_SUCCESS);
+		} else {
+			DPRINT("SM:%s: NULL == Client[%d]!\n", __FUNCTION__,
+				ClientIndex);
+			Status = STATUS_UNSUCCESSFUL;
+		}
+	}
+	return Status;
+}
 /**********************************************************************
+ *	SmpTimeoutCandidateClient/1
+ *
+ * DESCRIPTION
+ * 	Give the candidate client time to bootstrap and complete
+ * 	session initialization. If the client fails in any way,
+ * 	drop the pending client and kill the process.
+ *
+ * ARGUMENTS
+ * 	x: HANDLE for the candidate process.
+ *
+ * RETURN VALUE
+ * 	NONE.
+ */
+static VOID STDCALL SmpTimeoutCandidateClient (PVOID x)
+{
+	NTSTATUS       Status = STATUS_SUCCESS;
+	HANDLE         CandidateClientProcessHandle = (HANDLE) x;
+	LARGE_INTEGER  TimeOut;
+
+	DPRINT("SM: %s(%lx) called\n", __FUNCTION__, x);
+
+	TimeOut.QuadPart = (LONGLONG) -300000000L; // 30s
+	Status = NtWaitForSingleObject (CandidateClientProcessHandle,
+					FALSE,
+					& TimeOut);
+	if (STATUS_TIMEOUT == Status)
+	{
+		RtlEnterCriticalSection (& SmpClientDirectory.Lock);
+		if (NULL != SmpClientDirectory.CandidateClient)
+		{
+			DPRINT("SM:%s: destroy candidate %08lx\n", __FUNCTION__,
+					SmpClientDirectory.CandidateClient);
+			Status = SmpDestroyClientObject (SmpClientDirectory.CandidateClient,
+							 STATUS_TIMEOUT);
+			SmpClientDirectory.CandidateClient = NULL;
+		}
+		RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
+	}
+	NtTerminateThread (NtCurrentThread(), Status);
+}
+/**********************************************************************
  *	SmpCreateClient/1
  *
  * DESCRIPTION
@@ -294,9 +402,8 @@
 SmCreateClient (PRTL_USER_PROCESS_INFORMATION ProcessInfo, PWSTR ProgramName)
 {
 	NTSTATUS Status = STATUS_SUCCESS;
-
 	
-	DPRINT("SM: %s(%lx) called\n", __FUNCTION__, ProcessInfo->ProcessHandle);
+	DPRINT("SM: %s(%lx, %S) called\n", __FUNCTION__, ProcessInfo->ProcessHandle, ProgramName);
 
 	RtlEnterCriticalSection (& SmpClientDirectory.Lock);
 	/*
@@ -305,6 +412,16 @@
 	if (NULL == SmpClientDirectory.CandidateClient)
 	{
 		/*
+		 * Check if there exist a free entry in the
+		 * SmpClientDirectory.Client array.
+		 */
+		if (SM_INVALID_CLIENT_INDEX == SmpGetFirstFreeClientEntry())
+		{
+			DPRINT("SM: %s(%lx): out of memory!\n",
+				__FUNCTION__, ProcessInfo->ProcessHandle);
+			Status = STATUS_NO_MEMORY;
+		}
+		/*
 		 * Allocate the storage for client data
 		 */
 		SmpClientDirectory.CandidateClient =
@@ -319,6 +436,8 @@
 		}
 		else
 		{
+			DPRINT("SM:%s(%08lx,%S): candidate is %08lx\n", __FUNCTION__,
+					ProcessInfo, ProgramName, SmpClientDirectory.CandidateClient);
 			/* Initialize the candidate client. */
 			RtlInitializeCriticalSection(& SmpClientDirectory.CandidateClient->Lock);
 			SmpClientDirectory.CandidateClient->ServerProcess =
@@ -333,16 +452,35 @@
 				       SM_SB_NAME_MAX_LENGTH);
 		}
 	} else {
-		DPRINT1("SM: %s: CandidateClient pending!\n", __FUNCTION__);
-		RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
+		DPRINT1("SM: %s: CandidateClient %08lx pending!\n", __FUNCTION__,
+				SmpClientDirectory.CandidateClient);
 		Status = STATUS_DEVICE_BUSY;
 	}
 
 	RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
 
+	/* Create the timeout thread for external subsystems */
+	if (_wcsicmp (ProgramName, L"Session Manager") && _wcsicmp (ProgramName, L"Debug"))
+	{
+		Status = RtlCreateUserThread (NtCurrentProcess(),
+						NULL,
+						FALSE,
+						0,
+						0,
+						0,
+						(PTHREAD_START_ROUTINE) SmpTimeoutCandidateClient,
+						SmpClientDirectory.CandidateClient->ServerProcess,
+						NULL,
+						NULL);
+		if (!NT_SUCCESS(Status))
+		{
+			DPRINT1("SM:%s: RtlCreateUserThread() failed (Status=%08lx)\n",
+				__FUNCTION__, Status);
+		}
+	}
+
 	return Status;
 }
-
 /**********************************************************************
  * 	SmpDestroyClient/1
  *
@@ -353,42 +491,20 @@
 NTSTATUS STDCALL
 SmDestroyClient (ULONG SubsystemId)
 {
-	NTSTATUS         Status = STATUS_SUCCESS;
-	PSM_CLIENT_DATA  Parent = NULL;
-	PSM_CLIENT_DATA  Client = NULL;
+	NTSTATUS  Status = STATUS_SUCCESS;
+	INT       ClientIndex = SM_INVALID_CLIENT_INDEX;
 
-	DPRINT("SM: %s called\n", __FUNCTION__);
+	DPRINT("SM: %s(%lu) called\n", __FUNCTION__, SubsystemId);
 
 	RtlEnterCriticalSection (& SmpClientDirectory.Lock);
-	Client = SmpLookupClient (SubsystemId, & Parent);
-	if(NULL == Client)
+	ClientIndex = SmpLookupClient (SubsystemId);
+	if (SM_INVALID_CLIENT_INDEX == ClientIndex)
 	{
 		DPRINT1("SM: %s: del req for non existent subsystem (id=%d)\n",
 			__FUNCTION__, SubsystemId);
-		Status = STATUS_NOT_FOUND;
+		return STATUS_NOT_FOUND;
 	}
-	else
-	{
-		/* 1st in the list? */
-		if(NULL == Parent)
-		{
-			SmpClientDirectory.Client = Client->Next;
-		}
-		else
-		{
-			if(NULL != Parent)
-			{
-				Parent->Next = Client->Next;
-			} else {
-				DPRINT1("SM: %s: n-th has no parent!\n", __FUNCTION__);
-				Status = STATUS_UNSUCCESSFUL; /* FIXME */
-			}
-		}
-		/* TODO: send shutdown or kill */
-		NtTerminateProcess (Client->ServerProcess, 0); //FIXME
-		RtlFreeHeap (SmpHeap, 0, Client);
-		-- SmpClientDirectory.Count;
-	}
+	Status = SmpDestroyClientByClientIndex (ClientIndex);
 	RtlLeaveCriticalSection (& SmpClientDirectory.Lock);
 	return Status;
 }
@@ -401,10 +517,10 @@
 NTSTATUS FASTCALL
 SmGetClientBasicInformation (PSM_BASIC_INFORMATION i)
 {
-	INT              Index = 0;
-	PSM_CLIENT_DATA  ClientData = NULL;
+	INT  ClientIndex = 0;
+	INT  Index = 0;
 
-	DPRINT("SM: %s called\n", __FUNCTION__);
+	DPRINT("SM: %s(%08lx) called\n", __FUNCTION__, i);
 
 	RtlEnterCriticalSection (& SmpClientDirectory.Lock);
 
@@ -413,13 +529,16 @@
 	
 	if (SmpClientDirectory.Count > 0)
 	{
-		ClientData = SmpClientDirectory.Client;
-		while ((NULL != ClientData) && (Index < SM_QRYINFO_MAX_SS_COUNT))
+		for (ClientIndex = 0; (ClientIndex < SM_MAX_CLIENT_COUNT); ClientIndex ++)
 		{
-			i->SubSystem[Index].Id        = ClientData->SubsystemId;
-			i->SubSystem[Index].Flags     = ClientData->Flags;
-			i->SubSystem[Index].ProcessId = ClientData->ServerProcessId;
-			ClientData = ClientData->Next;
+			if ((NULL != SmpClientDirectory.Client [ClientIndex]) &&
+				(Index < SM_QRYINFO_MAX_SS_COUNT))
+			{
+				i->SubSystem[Index].Id        = SmpClientDirectory.Client [ClientIndex]->SubsystemId;
+				i->SubSystem[Index].Flags     = SmpClientDirectory.Client [ClientIndex]->Flags;
+				i->SubSystem[Index].ProcessId = SmpClientDirectory.Client [ClientIndex]->ServerProcessId;
+				++ Index;
+			}
 		}
 	}
 
@@ -433,23 +552,23 @@
 NTSTATUS FASTCALL
 SmGetSubSystemInformation (PSM_SUBSYSTEM_INFORMATION i)
 {
-	NTSTATUS         Status = STATUS_SUCCESS;
-	PSM_CLIENT_DATA  ClientData = NULL;
+	NTSTATUS  Status = STATUS_SUCCESS;
+	INT       ClientIndex = SM_INVALID_CLIENT_INDEX;
 	
-	DPRINT("SM: %s called\n", __FUNCTION__);
+	DPRINT("SM: %s(%08lx) called\n", __FUNCTION__, i);
 
 	RtlEnterCriticalSection (& SmpClientDirectory.Lock);
-	ClientData = SmpLookupClient (i->SubSystemId, NULL);
-	if (NULL == ClientData)
+	ClientIndex = SmpLookupClient (i->SubSystemId);
+	if (SM_INVALID_CLIENT_INDEX == ClientIndex)
 	{
 		Status = STATUS_NOT_FOUND;
 	}
 	else
 	{
-		i->Flags     = ClientData->Flags;
-		i->ProcessId = ClientData->ServerProcessId;
+		i->Flags     = SmpClientDirectory.Client [ClientIndex]->Flags;
+		i->ProcessId = SmpClientDirectory.Client [ClientIndex]->ServerProcessId;
 		RtlCopyMemory (i->NameSpaceRootNode,
-				ClientData->SbApiPortName,
+				SmpClientDirectory.Client [ClientIndex]->SbApiPortName,
 				(SM_QRYINFO_MAX_ROOT_NODE * sizeof(i->NameSpaceRootNode[0])));
 	}
 	RtlLeaveCriticalSection (& SmpClientDirectory.Lock);

Modified: trunk/reactos/subsys/smss/debug.c
--- trunk/reactos/subsys/smss/debug.c	2005-08-27 04:20:49 UTC (rev 17566)
+++ trunk/reactos/subsys/smss/debug.c	2005-08-27 09:55:27 UTC (rev 17567)
@@ -33,6 +33,7 @@
 
 HANDLE DbgSsApiPort = (HANDLE) 0;
 HANDLE DbgUiApiPort = (HANDLE) 0;
+HANDLE hSmDbgApiPort = (HANDLE) 0;
 
 /* FUNCTIONS *********************************************************/
 
@@ -135,8 +136,21 @@
 	NTSTATUS  Status = STATUS_SUCCESS;
 	HANDLE    hDbgSsApiPortThread = (HANDLE) 0;
 
+
 	DPRINT("SM: %s called\n", __FUNCTION__);
 
+	/* Self register */
+#if 0
+	Status = SmRegisterInternalSubsystem (L"Debug",
+						(USHORT)-1,
+						& hSmDbgApiPort);
+	if (!NT_SUCCESS(Status))
+	{
+		DPRINT1("DBG:%s: SmRegisterInternalSubsystem failed with Status=%08lx\n",
+			__FUNCTION__, Status);
+		return Status;
+	}
+#endif	
 	/* Create the \DbgSsApiPort object (LPC) */
 	Status = SmpCreatePT(& DbgSsApiPort,
 			     SM_DBGSS_PORT_NAME,

Modified: trunk/reactos/subsys/smss/initss.c
--- trunk/reactos/subsys/smss/initss.c	2005-08-27 04:20:49 UTC (rev 17566)
+++ trunk/reactos/subsys/smss/initss.c	2005-08-27 09:55:27 UTC (rev 17567)
@@ -39,61 +39,59 @@
  */
 
 /**********************************************************************
- *	SmpRegisterSmss/0
- *
+ *	SmRegisterInternalSubsystem/3
+ * 
  * DESCRIPTION
- *	Make smss register with itself for IMAGE_SUBSYSTEM_NATIVE
- *	(programmatically). This also opens hSmApiPort to be used
- *	in loading required subsystems.
+ *	Register with itself for ImageSubsystemId
+ *	(programmatically).
  */
-
-static NTSTATUS
-SmpRegisterSmss(VOID)
+NTSTATUS STDCALL SmRegisterInternalSubsystem (LPWSTR PgmName,
+					      USHORT ImageSubsystemId,
+					      PHANDLE ApiPort)
 {
-	NTSTATUS Status = STATUS_SUCCESS;
-	RTL_USER_PROCESS_INFORMATION ProcessInfo;
+	NTSTATUS                      Status = STATUS_SUCCESS;
+	RTL_USER_PROCESS_INFORMATION  ProcessInfo;
 
 	
-	DPRINT("SM: %s called\n",__FUNCTION__);
-	
+	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, L"Session Manager");
+	Status = SmCreateClient (& ProcessInfo, PgmName);
 	if (NT_SUCCESS(Status))
 	{
 		UNICODE_STRING SbApiPortName = {0,0,NULL};
 		
 		RtlInitUnicodeString (& SbApiPortName, L"");	
 		Status = SmConnectApiPort(& SbApiPortName,
-					  (HANDLE) -1, /* SM has no SB port */
-					  IMAGE_SUBSYSTEM_NATIVE,
-					  & hSmApiPort);
+					  (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 self registered\n");
+		DPRINT("SM:%s: %S self registered\n", __FUNCTION__, PgmName);
 	}
 	else
 	{
-		DPRINT1("SM: %s: SmCreateClient failed (Status=0x%08lx)\n",
-			__FUNCTION__, Status);
+		DPRINT1("SM: %s: SmCreateClient(%S) failed (Status=0x%08lx)\n",
+			__FUNCTION__, PgmName, Status);
 	}
 	/*
 	 * Note that you don't need to call complete session
-	 * because connection handling code autocompletes
-	 * the client structure for IMAGE_SUBSYSTEM_NATIVE.
+	 * here because connection handling code autocompletes
+	 * the client structure for IMAGE_SUBSYSTEM_NATIVE and
+	 * -1.
 	 */
 	return Status;
 }
-
-
 /**********************************************************************
  * 	SmpLoadRequiredSubsystems/0
  */
@@ -157,15 +155,27 @@
 	NTSTATUS  Status = STATUS_SUCCESS;
 
 	
-	DPRINT("SM: loading subsystems\n");
+	DPRINT("SM: loading subsystems...\n");
 
-	/* SM self registers */
-	Status = SmpRegisterSmss();
-	if(!NT_SUCCESS(Status)) return Status;
+	/*
+	 *  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)) return Status;
+	if(!NT_SUCCESS(Status))
+	{
+		DPRINT1("SM: SmpLoadRequiredSubsystems failed Status=%08lx\n", __FUNCTION__, Status);
+		return Status;
+	}
 	/* done */
+	DPRINT("SM: done loading subsystems\n");
 	return Status;
 }
 

Modified: trunk/reactos/subsys/smss/smapi.c
--- trunk/reactos/subsys/smss/smapi.c	2005-08-27 04:20:49 UTC (rev 17566)
+++ trunk/reactos/subsys/smss/smapi.c	2005-08-27 09:55:27 UTC (rev 17567)
@@ -71,7 +71,7 @@
 
 	DPRINT("SM: %s called\n", __FUNCTION__);
 
-	if (	(IMAGE_SUBSYSTEM_UNKNOWN == ConnectData->SubSystemId) ||
+	if (	((USHORT)-1 == ConnectData->SubSystemId) ||
 		(IMAGE_SUBSYSTEM_NATIVE  == ConnectData->SubSystemId))
 	{
 		DPRINT("SM: %s: we do not need calling back SM!\n",

Modified: trunk/reactos/subsys/smss/smapiexec.c
--- trunk/reactos/subsys/smss/smapiexec.c	2005-08-27 04:20:49 UTC (rev 17566)
+++ trunk/reactos/subsys/smss/smapiexec.c	2005-08-27 09:55:27 UTC (rev 17567)
@@ -34,7 +34,7 @@
  * DESCRIPTION
  *
  * ARGUMENTS
- *	ImagePath: bsolute path of the image to run;
+ *	ImagePath: absolute path of the image to run;
  *	CommandLine: arguments and options for ImagePath;
  *	WaitForIt: TRUE for boot time processes and FALSE for
  *		subsystems bootstrapping;
@@ -215,6 +215,8 @@
 						Status = NtResumeThread (ProcessInfo.ThreadHandle, NULL);
 						if (!NT_SUCCESS(Status))
 						{
+							DPRINT1("SM: %s: NtResumeThread failed (Status=0x%08lx)\n",
+								__FUNCTION__, Status);
 							//Status = SmDestroyClient TODO
 						}
 					} else {

Modified: trunk/reactos/subsys/smss/smss.h
--- trunk/reactos/subsys/smss/smss.h	2005-08-27 04:20:49 UTC (rev 17566)
+++ trunk/reactos/subsys/smss/smss.h	2005-08-27 09:55:27 UTC (rev 17567)
@@ -48,6 +48,7 @@
 NTSTATUS SmInitializeRegistry(VOID);
 
 /* initss.c */
+NTSTATUS STDCALL SmRegisterInternalSubsystem(LPWSTR,USHORT,PHANDLE);
 NTSTATUS SmLoadSubsystems(VOID);
 
 /* smapi.c */
@@ -89,7 +90,6 @@
   HANDLE	        ApiPortThread;
   HANDLE	        SbApiPort;
   WCHAR	                SbApiPortName [SM_SB_NAME_MAX_LENGTH];
-  struct _SM_CLIENT_DATA * Next;
 
 } SM_CLIENT_DATA, *PSM_CLIENT_DATA;
 NTSTATUS SmInitializeClientManagement (VOID);