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
--- 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 */
--- 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");
--- 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);
}
--- 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
--- 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.
--- 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;
}
--- 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;
}
--- 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();
--- 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]