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
*\r
* --------------------------------------------------------------------\r
*/\r
+ \r
\r
#include "smss.h"\r
\r
DPRINT("SmProcessFileRenameList() called\n");\r
\r
/* FIXME: implement it! */\r
+/*\r
+ * open HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\FileRenameOperations\r
+ * for each item in its value\r
+ * clone the old file in the new name,\r
+ * delete the source.\r
+ *\r
+ */\r
\r
DPRINT("SmProcessFileRenameList() done\n");\r
\r
#define NDEBUG\r
#include <debug.h>\r
\r
-HANDLE Children[2] = {0, 0}; /* csrss, winlogon */\r
+//HANDLE Children[2] = {0, 0}; /* csrss, winlogon */\r
\r
\r
/**********************************************************************\r
Status = SmCreateUserProcess (ImagePath,\r
CommandLine,\r
TRUE, /* wait */\r
- NULL,\r
- TRUE, /* terminate */\r
- NULL);\r
-\r
+ NULL, NULL);\r
+ if (!NT_SUCCESS(Status))\r
+ {\r
+ DPRINT1("SM: %s: running '$S' failed (Status=0x%08lx)\n",\r
+ __FUNCTION__, Status);\r
+ }\r
return(STATUS_SUCCESS);\r
}\r
\r
SmpRegisterSmss(VOID)\r
{\r
NTSTATUS Status = STATUS_SUCCESS;\r
- UNICODE_STRING SbApiPortName = {0,0,NULL};\r
+ RTL_PROCESS_INFO ProcessInfo;\r
\r
\r
DPRINT("SM: %s called\n",__FUNCTION__);\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
+ 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
- DPRINT("SM: %s: SMLIB!SmConnectApiPort failed (Status=0x%08lx)\n",\r
- __FUNCTION__,Status);\r
- return Status;\r
+ DPRINT1("SM: %s: SmCreateClient failed (Status=0x%08lx)\n",\r
+ __FUNCTION__, Status);\r
}\r
- DPRINT("SM self registered\n");\r
/*\r
* Note that you don't need to call complete session\r
* because connection handling code autocompletes\r
#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,
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__);
{
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",
*
* 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.
*/\r
SMAPI(SmCompSes)\r
{\r
- NTSTATUS Status = STATUS_SUCCESS;\r
+ NTSTATUS Status = STATUS_SUCCESS;\r
\r
DPRINT("SM: %s called\n", __FUNCTION__);\r
- \r
- Status = SmCompleteClientInitialization (Request->Header.ClientId.UniqueProcess);\r
- if(!NT_SUCCESS(Status))\r
+\r
+ DPRINT("SM: %s: ClientId.UniqueProcess=%lx\n",\r
+ __FUNCTION__, Request->Header.ClientId.UniqueProcess);\r
+ Status = SmCompleteClientInitialization ((ULONG) Request->Header.ClientId.UniqueProcess);\r
+ if (!NT_SUCCESS(Status))\r
{\r
- Request->SmHeader.Status = STATUS_UNSUCCESSFUL;\r
+ DPRINT1("SM: %s: NtQueryInformationProcess failed (Status=0x%08lx)\n",\r
+ __FUNCTION__, Status);\r
}\r
- return Status;\r
+ Request->SmHeader.Status = Status;\r
+ return STATUS_SUCCESS;\r
}\r
\r
\r
/**********************************************************************\r
* SmCreateUserProcess/5\r
*\r
+ * DESCRIPTION\r
+ *\r
+ * ARGUMENTS\r
+ * ImagePath: bsolute path of the image to run;\r
+ * CommandLine: arguments and options for ImagePath;\r
+ * WaitForIt: TRUE for boot time processes and FALSE for\r
+ * subsystems bootstrapping;\r
+ * Timeout: optional: used if WaitForIt==TRUE;\r
+ * ProcessHandle: optional: a duplicated handle for\r
+ the child process (storage provided by the caller).\r
+ *\r
+ * RETURN VALUE\r
+ * NTSTATUS:\r
+ *\r
*/\r
NTSTATUS STDCALL\r
SmCreateUserProcess (LPWSTR ImagePath,\r
LPWSTR CommandLine,\r
BOOLEAN WaitForIt,\r
PLARGE_INTEGER Timeout OPTIONAL,\r
- BOOLEAN TerminateIt,\r
- PRTL_PROCESS_INFO UserProcessInfo OPTIONAL\r
- )\r
+ PRTL_PROCESS_INFO UserProcessInfo OPTIONAL)\r
{\r
UNICODE_STRING ImagePathString = {0};\r
UNICODE_STRING CommandLineString = {0};\r
PRTL_PROCESS_INFO pProcessInfo = & ProcessInfo;\r
NTSTATUS Status = STATUS_SUCCESS;\r
\r
-\r
- DPRINT("SM: %s called\n",__FUNCTION__);\r
+ DPRINT("SM: %s called\n", __FUNCTION__);\r
+ \r
+ if (NULL != UserProcessInfo)\r
+ {\r
+ pProcessInfo = UserProcessInfo;\r
+ }\r
\r
RtlInitUnicodeString (& ImagePathString, ImagePath);\r
RtlInitUnicodeString (& CommandLineString, CommandLine);\r
NULL,\r
NULL);\r
\r
- if(NULL != UserProcessInfo)\r
- {\r
- /* Use caller provided storage */\r
- pProcessInfo = UserProcessInfo;\r
- }\r
-\r
Status = RtlCreateUserProcess (& ImagePathString,\r
OBJ_CASE_INSENSITIVE,\r
ProcessParameters,\r
NULL,\r
pProcessInfo);\r
\r
- RtlDestroyProcessParameters (ProcessParameters);\r
+ RtlDestroyProcessParameters (ProcessParameters);\r
\r
if (!NT_SUCCESS(Status))\r
{\r
__FUNCTION__, ImagePathString.Buffer, Status);\r
return Status;\r
}\r
-\r
- ZwResumeThread(pProcessInfo->ThreadHandle, NULL);\r
-\r
-\r
- /* Wait for process termination */\r
- if(WaitForIt)\r
+ /*\r
+ * It the caller is *not* interested in the child info,\r
+ * resume it immediately.\r
+ */\r
+ if (NULL == UserProcessInfo)\r
{\r
- NtWaitForSingleObject (pProcessInfo->ProcessHandle,\r
- FALSE,\r
- Timeout);\r
+ Status = NtResumeThread (ProcessInfo.ThreadHandle, NULL);\r
+ if(!NT_SUCCESS(Status))\r
+ {\r
+ DPRINT1("SM: %s: NtResumeThread failed (Status=0x%08lx)\n",\r
+ __FUNCTION__, Status);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ HANDLE DupProcessHandle = (HANDLE) 0;\r
+ \r
+ Status = NtDuplicateObject (NtCurrentProcess(),\r
+ pProcessInfo->ProcessHandle,\r
+ NtCurrentProcess(),\r
+ & DupProcessHandle,\r
+ PROCESS_ALL_ACCESS,\r
+ 0, 0);\r
+ if(!NT_SUCCESS(Status))\r
+ {\r
+ DPRINT1("SM: %s: NtDuplicateObject failed (Status=0x%08lx)\n",\r
+ __FUNCTION__, Status);\r
+ }\r
+ pProcessInfo->ProcessHandle = DupProcessHandle;\r
+ \r
}\r
\r
- /* Terminate process */\r
- if(TerminateIt)\r
+ /* Wait for process termination */\r
+ if (WaitForIt)\r
{\r
- NtClose(pProcessInfo->ThreadHandle);\r
- NtClose(pProcessInfo->ProcessHandle);\r
+ Status = NtWaitForSingleObject (pProcessInfo->ProcessHandle,\r
+ FALSE,\r
+ Timeout);\r
+ if (!NT_SUCCESS(Status))\r
+ {\r
+ DPRINT1("SM: %s: NtWaitForSingleObject failed with Status=0x%08lx\n",\r
+ __FUNCTION__, Status);\r
+ }\r
+ \r
}\r
- return STATUS_SUCCESS;\r
+ return Status;\r
}\r
\r
/**********************************************************************\r
(ExecPgm->NameLength <= SM_EXEXPGM_MAX_LENGTH) &&\r
TRUE /* TODO: check LPC payload size */)\r
{\r
+ WCHAR Data [MAX_PATH + 1] = {0};\r
+ ULONG DataLength = sizeof Data;\r
+ ULONG DataType = REG_EXPAND_SZ;\r
+\r
\r
RtlZeroMemory (Name, sizeof Name);\r
RtlCopyMemory (Name,\r
ExecPgm->Name,\r
(sizeof ExecPgm->Name[0] * ExecPgm->NameLength));\r
DPRINT("SM: %s: Name='%S'\n", __FUNCTION__, Name);\r
- /*\r
- * Check if program name is internal\r
- * (Is this correct? Debug is in the registry too)\r
- */\r
- if(0 == _wcsicmp(L"DEBUG", Name))\r
- {\r
- /*\r
- * Initialize DBGSS.\r
- * NOTE: probably in early prototypes it was an\r
- * independent process; now it is embedded in the\r
- * SM for performance or security.\r
- */\r
- Request->SmHeader.Status = SmInitializeDbgSs();\r
- }\r
- else\r
+ /* Lookup Name in the registry */\r
+ Status = SmLookupSubsystem (Name,\r
+ Data,\r
+ & DataLength,\r
+ & DataType,\r
+ TRUE); /* expand */\r
+ if(NT_SUCCESS(Status))\r
{\r
- WCHAR Data [MAX_PATH + 1] = {0};\r
- ULONG DataLength = sizeof Data;\r
- ULONG DataType = REG_EXPAND_SZ;\r
-\r
- /* Lookup Name in the registry */\r
- Status = SmLookupSubsystem (Name,\r
- Data,\r
- & DataLength,\r
- & DataType,\r
- TRUE); /* expand */\r
- if(NT_SUCCESS(Status))\r
+ /* Is the subsystem definition non-empty? */\r
+ if (DataLength > sizeof Data[0])\r
{\r
WCHAR ImagePath [MAX_PATH + 1] = {0};\r
+ PWCHAR CommandLine = ImagePath;\r
+ RTL_PROCESS_INFO ProcessInfo = {0};\r
\r
wcscpy (ImagePath, L"\\??\\");\r
wcscat (ImagePath, Data);\r
- \r
- /* Create native process */\r
- Request->SmHeader.Status = SmCreateUserProcess(ImagePath,\r
- L"", /* FIXME */\r
- FALSE, /* wait */\r
- NULL,\r
- FALSE, /* terminate */\r
- NULL);\r
- }else{\r
- Request->SmHeader.Status = Status;\r
+ /*\r
+ * Look for the beginning of the command line.\r
+ */\r
+ for (; (*CommandLine != L'\0') && (*CommandLine != L' ');\r
+ CommandLine ++);\r
+ for (; *CommandLine == L' '; CommandLine ++)\r
+ {\r
+ *CommandLine = L'\0';\r
+ }\r
+ /*\r
+ * Create a native process (suspended).\r
+ */\r
+ ProcessInfo.Size = sizeof ProcessInfo;\r
+ Request->SmHeader.Status =\r
+ SmCreateUserProcess(ImagePath,\r
+ CommandLine,\r
+ FALSE, /* wait */\r
+ NULL, /* timeout */\r
+ & ProcessInfo);\r
+ if (NT_SUCCESS(Request->SmHeader.Status))\r
+ {\r
+ Status = SmCreateClient (& ProcessInfo, Name);\r
+ if (NT_SUCCESS(Status))\r
+ {\r
+ Status = NtResumeThread (ProcessInfo.ThreadHandle, NULL);\r
+ if (!NT_SUCCESS(Status))\r
+ {\r
+ //Status = SmDestroyClient TODO\r
+ }\r
+ } else {\r
+ DPRINT1("SM: %s: SmCreateClient failed (Status=0x%08lx)\n",\r
+ __FUNCTION__, Status);\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ /*\r
+ * OK, the definition is empty, but check\r
+ * if it is the name of an embedded subsystem.\r
+ */\r
+ if(0 == _wcsicmp(L"DEBUG", Name))\r
+ {\r
+ /*\r
+ * Initialize the embedded DBGSS.\r
+ */\r
+ Request->SmHeader.Status = SmInitializeDbgSs();\r
+ }\r
+ else\r
+ {\r
+ /*\r
+ * Badly defined subsystem. Check the registry!\r
+ */\r
+ Request->SmHeader.Status = STATUS_NOT_FOUND;\r
+ }\r
}\r
+ } else {\r
+ /* It couldn't lookup the Name! */\r
+ Request->SmHeader.Status = Status;\r
}\r
}\r
- else\r
- {\r
- Request->SmHeader.Status = Status = STATUS_INVALID_PARAMETER;\r
- }\r
return Status;\r
}\r
\r
#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);
NULL);
if(NT_SUCCESS(Status))
{
- SmSsProcessId = PBI.UniqueProcessId;
+ SmSsProcessId = (ULONG) PBI.UniqueProcessId;
}
/* Initialize the system */
Status = InitSessionManager();
#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);
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,
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;
+ WORD Unused;
+ ULONG ServerProcessId;
+ HANDLE ServerProcess;
+ HANDLE ApiPort;
+ 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);
-NTSTATUS STDCALL SmCreateClient(PSM_PORT_MESSAGE,PSM_CLIENT_DATA*);
-NTSTATUS STDCALL SmDestroyClient(ULONG);
-NTSTATUS STDCALL SmCompleteClientInitialization (HANDLE hProcess);
+NTSTATUS SmInitializeClientManagement (VOID);
+NTSTATUS STDCALL SmCreateClient (PRTL_PROCESS_INFO,PWSTR);
+NTSTATUS STDCALL SmDestroyClient (ULONG);
+NTSTATUS STDCALL SmBeginClientInitialization (PSM_PORT_MESSAGE,PSM_CLIENT_DATA*);
+NTSTATUS STDCALL SmCompleteClientInitialization (ULONG);
NTSTATUS FASTCALL SmGetClientBasicInformation (PSM_BASIC_INFORMATION);
NTSTATUS FASTCALL SmGetSubSystemInformation (PSM_SUBSYSTEM_INFORMATION);