Author: ion
Date: Thu Feb 9 02:21:56 2012
New Revision: 55509
URL:
http://svn.reactos.org/svn/reactos?rev=55509&view=rev
Log:
[SMSS2]: Implement SmpCallCsrCreateProcess and SmpLoadSubsystem. We now load CSRSS and
everything works 100%! Winlogon is now launched by SMSS2 and no regressions have been
found.
[SMSS]: Turn off all code other than setting up the pagefile.
There's a lot of debug prints, as soon as things seem stable after a few days, SMSS
will be gone and SMSS2 will take over and DPRINT1s will mostly be gone.
Modified:
trunk/reactos/base/system/smss/init.c
trunk/reactos/base/system/smss2/smsubsys.c
Modified: trunk/reactos/base/system/smss/init.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/smss/init.c?re…
==============================================================================
--- trunk/reactos/base/system/smss/init.c [iso-8859-1] (original)
+++ trunk/reactos/base/system/smss/init.c [iso-8859-1] Thu Feb 9 02:21:56 2012
@@ -24,8 +24,8 @@
} InitRoutine [] = {
{TRUE, SmCreateHeap, "create private heap, aborting"},
// {TRUE, SmCreateObjectDirectories, "create object directories"},
- {TRUE, SmCreateApiPort, "create \\SmApiPort"},
- {TRUE, SmCreateEnvironment, "create the system environment"},
+// {TRUE, SmCreateApiPort, "create \\SmApiPort"},
+// {TRUE, SmCreateEnvironment, "create the system environment"},
// {TRUE, SmSetEnvironmentVariables, "set system environment variables"},
// {TRUE, SmInitDosDevices, "create dos device links"},
// {TRUE, SmRunBootApplications, "run boot applications"},
@@ -34,8 +34,8 @@
// {FALSE, SmLoadKnownDlls, "preload system DLLs"},
{TRUE, SmCreatePagingFiles, "create paging files"},
// {TRUE, SmInitializeRegistry, "initialize the registry"},
- {TRUE, SmInitializeClientManagement, "initialize client management"},
- {TRUE, SmLoadSubsystems, "load subsystems"}
+// {TRUE, SmInitializeClientManagement, "initialize client management"},
+// {TRUE, SmLoadSubsystems, "load subsystems"}
};
NTSTATUS
Modified: trunk/reactos/base/system/smss2/smsubsys.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/smss2/smsubsys…
==============================================================================
--- trunk/reactos/base/system/smss2/smsubsys.c [iso-8859-1] (original)
+++ trunk/reactos/base/system/smss2/smsubsys.c [iso-8859-1] Thu Feb 9 02:21:56 2012
@@ -23,6 +23,24 @@
/* FUNCTIONS ******************************************************************/
+NTSTATUS
+NTAPI
+SmpCallCsrCreateProcess(IN PSB_API_MSG SbApiMsg,
+ IN USHORT MessageLength,
+ IN HANDLE PortHandle)
+{
+ NTSTATUS Status;
+
+ /* Initialize the header and send the message to CSRSS */
+ SbApiMsg->h.u2.ZeroInit = 0;
+ SbApiMsg->h.u1.s1.DataLength = MessageLength + 8;
+ SbApiMsg->h.u1.s1.TotalLength = sizeof(SB_API_MSG);
+ SbApiMsg->ApiNumber = SbpCreateProcess;
+ Status = NtRequestWaitReplyPort(PortHandle, &SbApiMsg->h,
&SbApiMsg->h);
+ if (NT_SUCCESS(Status)) Status = SbApiMsg->ReturnValue;
+ return Status;
+}
+
VOID
NTAPI
SmpDereferenceSubsystem(IN PSMP_SUBSYSTEM SubSystem)
@@ -60,7 +78,7 @@
{
/* Check if this one matches the client ID and is still valid */
Subsystem = CONTAINING_RECORD(NextEntry, SMP_SUBSYSTEM, Entry);
- if ((*(PULONGLONG)&Subsystem->ClientId == *(PULONGLONG)&ClientId)
&&
+ if ((*(PULONGLONG)&Subsystem->ClientId == *(PULONGLONG)ClientId)
&&
!(Subsystem->Terminating))
{
/* Add a reference and return it */
@@ -123,8 +141,378 @@
OUT PHANDLE ProcessId,
IN ULONG Flags)
{
- DPRINT1("Should start subsystem %wZ for Session: %lx\n", FileName,
MuSessionId);
- return STATUS_SUCCESS;
+ PSMP_SUBSYSTEM Subsystem, NewSubsystem, KnownSubsystem = NULL;
+ HANDLE SubSysProcessId;
+ NTSTATUS Status = STATUS_SUCCESS;
+ SB_API_MSG SbApiMsg, SbApiMsg2;
+ RTL_USER_PROCESS_INFORMATION ProcessInformation;
+ LARGE_INTEGER Timeout;
+ PVOID State;
+ PSB_CREATE_PROCESS_MSG CreateProcess = &SbApiMsg.CreateProcess;
+ PSB_CREATE_SESSION_MSG CreateSession = &SbApiMsg.CreateSession;
+ DPRINT1("Loading subsystem: %wZ\n", FileName);
+
+ /* Make sure this is a found subsystem */
+ if (Flags & SMP_INVALID_PATH)
+ {
+ DPRINT1("SMSS: Unable to find subsystem - %wZ\n", FileName);
+ return STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ /* Don't use a session if the flag is set */
+ if (Flags & 0x80) MuSessionId = 0;
+
+ /* Lock the subsystems while we do a look up */
+ RtlEnterCriticalSection(&SmpKnownSubSysLock);
+ while (TRUE)
+ {
+ /* Check if we found a subsystem not yet fully iniitalized */
+ Subsystem = SmpLocateKnownSubSysByType(MuSessionId, -1);
+ if (!Subsystem) break;
+ RtlLeaveCriticalSection(&SmpKnownSubSysLock);
+
+ /* Wait on it to initialize */
+ NtWaitForSingleObject(Subsystem->Event, FALSE, NULL);
+
+ /* Dereference it and try the next one */
+ RtlEnterCriticalSection(&SmpKnownSubSysLock);
+ SmpDereferenceSubsystem(Subsystem);
+ }
+
+ /* Check if this is a POSIX subsystem */
+ if (Flags & SMP_POSIX_FLAG)
+ {
+ /* Do we already have it? */
+ Subsystem = SmpLocateKnownSubSysByType(MuSessionId, IMAGE_SUBSYSTEM_POSIX_CUI);
+ }
+ else if (Flags & SMP_OS2_FLAG)
+ {
+ /* This is an OS/2 subsystem, do we we already have it? */
+ Subsystem = SmpLocateKnownSubSysByType(MuSessionId, IMAGE_SUBSYSTEM_OS2_CUI);
+ }
+
+ /* Check if we already have one of the optional subsystems for the session */
+ if (Subsystem)
+ {
+ /* Dereference and return, no work to do */
+ SmpDereferenceSubsystem(Subsystem);
+ RtlLeaveCriticalSection(&SmpKnownSubSysLock);
+ return STATUS_SUCCESS;
+ }
+
+ /* Allocate a new subsystem! */
+ NewSubsystem = RtlAllocateHeap(SmpHeap, SmBaseTag, sizeof(SMP_SUBSYSTEM));
+ DPRINT1("new subsystem created: %p\n", NewSubsystem);
+ if (!NewSubsystem)
+ {
+ RtlLeaveCriticalSection(&SmpKnownSubSysLock);
+ return STATUS_NO_MEMORY;
+ }
+
+ /* Initialize its header and reference count */
+ NewSubsystem->ReferenceCount = 1;
+ NewSubsystem->MuSessionId = MuSessionId;
+ NewSubsystem->ImageType = -1;
+
+ /* Clear out all the other data for now */
+ NewSubsystem->Terminating = FALSE;
+ NewSubsystem->ProcessHandle = NULL;
+ NewSubsystem->Event = NULL;
+ NewSubsystem->PortHandle = NULL;
+ NewSubsystem->SbApiPort = NULL;
+
+ /* Create the event we'll be wating on for initialization */
+ Status = NtCreateEvent(&NewSubsystem->Event,
+ EVENT_ALL_ACCESS,
+ NULL,
+ NotificationEvent,
+ FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ /* This failed, bail out */
+ RtlFreeHeap(SmpHeap, 0, NewSubsystem);
+ RtlLeaveCriticalSection(&SmpKnownSubSysLock);
+ return STATUS_NO_MEMORY;
+ }
+
+ /* Insert the subsystem and release the lock. It can now be found */
+ InsertTailList(&SmpKnownSubSysHead, &NewSubsystem->Entry);
+ RtlLeaveCriticalSection(&SmpKnownSubSysLock);
+
+ /* The OS/2 and POSIX subsystems are actually Windows applications! */
+ if (Flags & (SMP_POSIX_FLAG | SMP_OS2_FLAG))
+ {
+ /* Locate the Windows subsystem for this session */
+ KnownSubsystem = SmpLocateKnownSubSysByType(MuSessionId,
+ IMAGE_SUBSYSTEM_WINDOWS_GUI);
+ if (!KnownSubsystem)
+ {
+ DPRINT1("SMSS: SmpLoadSubSystem - SmpLocateKnownSubSysByType
Failed\n");
+ goto Quickie2;
+ }
+
+ /* Fill out all the process details and call CSRSS to launch it */
+ CreateProcess->In.ImageName = FileName;
+ CreateProcess->In.CurrentDirectory = Directory;
+ CreateProcess->In.CommandLine = CommandLine;
+ CreateProcess->In.DllPath = SmpDefaultLibPath.Length ?
+ &SmpDefaultLibPath : NULL;
+ CreateProcess->In.Flags = Flags | SMP_DEFERRED_FLAG;
+ CreateProcess->In.DebugFlags = SmpDebug;
+ Status = SmpCallCsrCreateProcess(&SbApiMsg,
+ sizeof(*CreateProcess),
+ KnownSubsystem->SbApiPort);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Handle failures */
+ DPRINT1("SMSS: SmpLoadSubSystem - SmpCallCsrCreateProcess Failed with
Status %lx\n",
+ Status);
+ goto Quickie2;
+ }
+
+ /* Save the process information we'll need for the create session */
+ ProcessInformation.ProcessHandle = CreateProcess->Out.ProcessHandle;
+ ProcessInformation.ThreadHandle = CreateProcess->Out.ThreadHandle;
+ ProcessInformation.ClientId = CreateProcess->Out.ClientId;
+ ProcessInformation.ImageInformation.SubSystemType =
CreateProcess->Out.SubsystemType;
+ }
+ else
+ {
+ /* This must be CSRSS itself, so just launch it and that's it */
+ DPRINT1("Executing CSRSS\n");
+ Status = SmpExecuteImage(FileName,
+ Directory,
+ CommandLine,
+ MuSessionId,
+ Flags | SMP_DEFERRED_FLAG,
+ &ProcessInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Handle failures */
+ DPRINT1("SMSS: SmpLoadSubSystem - SmpExecuteImage Failed with Status
%lx\n",
+ Status);
+ goto Quickie2;
+ }
+ }
+
+ /* Fill out the handle and client ID in the subsystem structure now */
+ NewSubsystem->ProcessHandle = ProcessInformation.ProcessHandle;
+ NewSubsystem->ClientId = ProcessInformation.ClientId;
+
+ /* Check if we launched a native image or a subsystem-backed image */
+ if (ProcessInformation.ImageInformation.SubSystemType == IMAGE_SUBSYSTEM_NATIVE)
+ {
+ /* This must be CSRSS itself, since it's a native subsystem image */
+ SubSysProcessId = ProcessInformation.ClientId.UniqueProcess;
+ if ((ProcessId) && !(*ProcessId)) *ProcessId = SubSysProcessId;
+
+ /* Was this the initial CSRSS on Session 0? */
+ if (!MuSessionId)
+ {
+ /* Then save it in the global variables */
+ SmpWindowsSubSysProcessId = SubSysProcessId;
+ SmpWindowsSubSysProcess = ProcessInformation.ProcessHandle;
+ }
+ ASSERT(NT_SUCCESS(Status));
+ DPRINT1("CSRSS is up and running: %lx %lx\n",
SmpWindowsSubSysProcessId, SmpWindowsSubSysProcess);
+ }
+ else
+ {
+ /* This is the POSIX or OS/2 subsystem process, copy its information */
+ RtlCopyMemory(&CreateSession->ProcessInfo,
+ &ProcessInformation,
+ sizeof(&CreateSession->ProcessInfo));
+
+ /* Not sure these field mean what I think they do -- but clear them */
+ *(PULONGLONG)&CreateSession->ClientId = 0;
+ CreateSession->MuSessionId = 0;
+
+ /* This should find CSRSS because they are POSIX or OS/2 subsystems */
+ Subsystem = SmpLocateKnownSubSysByType(MuSessionId,
+
ProcessInformation.ImageInformation.SubSystemType);
+ if (!Subsystem)
+ {
+ /* Odd failure -- but handle it anyway */
+ Status = STATUS_NO_SUCH_PACKAGE;
+ DPRINT1("SMSS: SmpLoadSubSystem - SmpLocateKnownSubSysByType Failed with
Status %lx for sessionid %ld\n",
+ Status,
+ MuSessionId);
+ goto Quickie;
+ }
+
+ /* Duplicate the parent process handle for the subsystem to have */
+ Status = NtDuplicateObject(NtCurrentProcess(),
+ ProcessInformation.ProcessHandle,
+ Subsystem->ProcessHandle,
+ &CreateSession->ProcessInfo.ProcessHandle,
+ PROCESS_ALL_ACCESS,
+ 0,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Fail since this is critical */
+ DPRINT1("SMSS: SmpLoadSubSystem - NtDuplicateObject Failed with Status
%lx for sessionid %ld\n",
+ Status,
+ MuSessionId);
+ goto Quickie;
+ }
+
+ /* Duplicate the initial thread handle for the subsystem to have */
+ Status = NtDuplicateObject(NtCurrentProcess(),
+ ProcessInformation.ThreadHandle,
+ Subsystem->ProcessHandle,
+ &CreateSession->ProcessInfo.ThreadHandle,
+ THREAD_ALL_ACCESS,
+ 0,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Fail since this is critical */
+ DPRINT1("SMSS: SmpLoadSubSystem - NtDuplicateObject Failed with Status
%lx for sessionid %ld\n",
+ Status,
+ MuSessionId);
+ goto Quickie;
+ }
+
+ /* Allocate an internal Session ID for this subsystem */
+ MuSessionId = SmpAllocateSessionId(Subsystem, 0);
+ CreateSession->SessionId = MuSessionId;
+
+ /* Send the create session message to the subsystem */
+ SbApiMsg2.ReturnValue = STATUS_SUCCESS;
+ SbApiMsg2.h.u2.ZeroInit = 0;
+ SbApiMsg2.h.u1.s1.DataLength = sizeof(SB_CREATE_SESSION_MSG) + 8;
+ SbApiMsg2.h.u1.s1.TotalLength = sizeof(SB_API_MSG);
+ Status = NtRequestWaitReplyPort(Subsystem->SbApiPort,
+ &SbApiMsg2.h,
+ &SbApiMsg2.h);
+ if (NT_SUCCESS(Status)) Status = SbApiMsg2.ReturnValue;
+ if (!NT_SUCCESS(Status))
+ {
+ /* Delete the session and handle failure if the LPC call failed */
+ SmpDeleteSession(CreateSession->SessionId);
+ DPRINT1("SMSS: SmpLoadSubSystem - NtRequestWaitReplyPort Failed with
Status %lx for sessionid %ld\n",
+ Status,
+ CreateSession->SessionId);
+ goto Quickie;
+ }
+ }
+
+ /* Okay, everything looks good to go, initialize this subsystem now! */
+ DPRINT1("Resuming the subsystem!\n");
+ Status = NtResumeThread(ProcessInformation.ThreadHandle, NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ /* That didn't work -- back out of everything */
+ DPRINT1("SMSS: SmpLoadSubSystem - NtResumeThread failed Status %lx\n",
Status);
+ goto Quickie;
+ }
+
+ /* Check if this was the subsystem for a different session */
+ if (MuSessionId)
+ {
+ /* Wait up to 60 seconds for it to initialize */
+ Timeout.QuadPart = -600000000;
+ Status = NtWaitForSingleObject(NewSubsystem->Event, FALSE, &Timeout);
+
+ /* Timeout is done -- does this session still exist? */
+ if (!SmpCheckDuplicateMuSessionId(MuSessionId))
+ {
+ /* Nope, it died. Cleanup should've ocurred in a different path. */
+ DPRINT1("SMSS: SmpLoadSubSystem - session deleted\n");
+ return STATUS_DELETE_PENDING;
+ }
+
+ /* Check if we timed our or there was another error with the wait */
+ if (Status != STATUS_WAIT_0)
+ {
+ /* Something is wrong with the subsystem, so back out of everything */
+ DPRINT1("SMSS: SmpLoadSubSystem - Timeout waiting for subsystem connect
with Status %lx for sessionid %ld\n",
+ Status,
+ MuSessionId);
+ goto Quickie;
+ }
+ }
+ else
+ {
+ /* This a session 0 subsystem, just wait for it to initialize */
+ DPRINT1("Waiting on the subsystem to initialize...\n");
+ NtWaitForSingleObject(NewSubsystem->Event, FALSE, NULL);
+ DPRINT1("Subsystem is ready!!!\n");
+ }
+
+ /* Subsystem is created, resumed, and initialized. Close handles and exit */
+ NtClose(ProcessInformation.ThreadHandle);
+ Status = STATUS_SUCCESS;
+ DPRINT1("Returning success\n");
+ goto Quickie2;
+
+Quickie:
+ /* This is the failure path. First check if we need to detach from session */
+ if ((AttachedSessionId == -1) || (Flags & (SMP_POSIX_FLAG | SMP_OS2_FLAG)))
+ {
+ /* We were not attached, or did not launch subsystems that required it */
+ DPRINT1("SMSS: Did not detach from Session Space: SessionId=%x Flags=%x
Status=%x\n",
+ AttachedSessionId,
+ Flags | SMP_DEFERRED_FLAG,
+ Status);
+ }
+ else
+ {
+ /* Get the privilege we need for detachment */
+ Status = SmpAcquirePrivilege(SE_LOAD_DRIVER_PRIVILEGE, &State);
+ if (!NT_SUCCESS(Status))
+ {
+ /* We can't detach without it */
+ DPRINT1("SMSS: Did not detach from Session Space: SessionId=%x Flags=%x
Status=%x\n",
+ AttachedSessionId,
+ Flags | SMP_DEFERRED_FLAG,
+ Status);
+ }
+ else
+ {
+ /* Now detach from the session */
+ Status = NtSetSystemInformation(SystemSessionDetach,
+ &AttachedSessionId,
+ sizeof(AttachedSessionId));
+ if (!NT_SUCCESS(Status))
+ {
+ /* Failed to detach. Note the DPRINT1 has a typo in Windows */
+ DPRINT1("SMSS: SmpStartCsr, Couldn't Detach from Session Space.
Status=%x\n", Status);
+ ASSERT(NT_SUCCESS(Status));
+ }
+ else
+ {
+ /* Detachment worked, reset our attached session ID */
+ AttachedSessionId = -1;
+ }
+
+ /* And release the privilege we acquired */
+ SmpReleasePrivilege(State);
+ }
+ }
+
+ /* Since this is the failure path, terminate the subsystem process */
+ NtTerminateProcess(ProcessInformation.ProcessHandle, Status);
+ NtClose(ProcessInformation.ThreadHandle);
+
+Quickie2:
+ /* This is the cleanup path -- first dereference our subsystems */
+ RtlEnterCriticalSection(&SmpKnownSubSysLock);
+ if (Subsystem) SmpDereferenceSubsystem(Subsystem);
+ if (KnownSubsystem) SmpDereferenceSubsystem(KnownSubsystem);
+
+ /* In the failure case, destroy the new subsystem we just created */
+ if (!NT_SUCCESS(Status))
+ {
+ RemoveEntryList(&NewSubsystem->Entry);
+ NtSetEvent(NewSubsystem->Event, 0);
+ if (NewSubsystem) SmpDereferenceSubsystem(NewSubsystem);
+ }
+
+ /* Finally, we're all done! */
+ RtlLeaveCriticalSection(&SmpKnownSubSysLock);
+ return Status;
}
NTSTATUS