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