2 * PROJECT: ReactOS Windows-Compatible Session Manager
3 * LICENSE: BSD 2-Clause License
4 * FILE: base/system/smss/smss.c
5 * PURPOSE: Main SMSS Code
6 * PROGRAMMERS: Alex Ionescu
9 /* INCLUDES *******************************************************************/
15 /* GLOBALS ********************************************************************/
17 typedef struct _INIT_BUFFER
19 WCHAR DebugBuffer
[256];
20 RTL_USER_PROCESS_INFORMATION ProcessInfo
;
21 } INIT_BUFFER
, *PINIT_BUFFER
;
23 /* NT Initial User Application */
24 WCHAR NtInitialUserProcessBuffer
[128] = L
"\\SystemRoot\\System32\\smss.exe";
25 ULONG NtInitialUserProcessBufferLength
= sizeof(NtInitialUserProcessBuffer
) -
27 ULONG NtInitialUserProcessBufferType
= REG_SZ
;
29 UNICODE_STRING SmpSystemRoot
;
30 ULONG AttachedSessionId
= -1;
31 BOOLEAN SmpDebug
, SmpEnableDots
;
33 HANDLE SmpInitialCommandProcessId
;
35 /* FUNCTIONS ******************************************************************/
37 /* GCC's incompetence strikes again */
39 sprintf_nt(IN PCHAR Buffer
,
45 sprintf(Buffer
, Format
, ap
);
51 SmpExecuteImage(IN PUNICODE_STRING FileName
,
52 IN PUNICODE_STRING Directory
,
53 IN PUNICODE_STRING CommandLine
,
56 IN PRTL_USER_PROCESS_INFORMATION ProcessInformation
)
58 PRTL_USER_PROCESS_INFORMATION ProcessInfo
;
60 RTL_USER_PROCESS_INFORMATION LocalProcessInfo
;
61 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
;
62 DPRINT1("Executing image: %wZ\n", FileName
);
64 /* Use the input process information if we have it, otherwise use local */
65 ProcessInfo
= ProcessInformation
;
66 if (!ProcessInfo
) ProcessInfo
= &LocalProcessInfo
;
68 /* Create parameters for the target process */
69 Status
= RtlCreateProcessParameters(&ProcessParameters
,
71 SmpDefaultLibPath
.Length
?
72 &SmpDefaultLibPath
: NULL
,
75 SmpDefaultEnvironment
,
80 if (!NT_SUCCESS(Status
))
82 /* This is a pretty bad failure. ASSERT on checked builds and exit */
83 ASSERTMSG(NT_SUCCESS(Status
), "RtlCreateProcessParameters");
84 DPRINT1("SMSS: RtlCreateProcessParameters failed for %wZ - Status == %lx\n",
89 /* Set the size field as required */
90 ProcessInfo
->Size
= sizeof(RTL_USER_PROCESS_INFORMATION
);
92 /* Check if the debug flag was requested */
93 if (Flags
& SMP_DEBUG_FLAG
)
95 /* Write it in the process parameters */
96 ProcessParameters
->DebugFlags
= 1;
100 /* Otherwise inherit the flag that was passed to SMSS itself */
101 ProcessParameters
->DebugFlags
= SmpDebug
;
104 /* Subsystems get the first 1MB of memory reserved for DOS/IVT purposes */
105 if (Flags
& SMP_SUBSYSTEM_FLAG
)
107 ProcessParameters
->Flags
|= RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB
;
110 /* And always force NX for anything that SMSS launches */
111 ProcessParameters
->Flags
|= RTL_USER_PROCESS_PARAMETERS_NX
;
113 /* Now create the process */
114 Status
= RtlCreateUserProcess(FileName
,
115 OBJ_CASE_INSENSITIVE
,
124 RtlDestroyProcessParameters(ProcessParameters
);
125 if (!NT_SUCCESS(Status
))
127 /* If we couldn't create it, fail back to the caller */
128 DPRINT1("SMSS: Failed load of %wZ - Status == %lx\n",
133 /* Associate a session with this process */
134 Status
= SmpSetProcessMuSessionId(ProcessInfo
->ProcessHandle
, MuSessionId
);
136 /* If the application is deferred (suspended), there's nothing to do */
137 if (Flags
& SMP_DEFERRED_FLAG
) return Status
;
139 /* Otherwise, get ready to start it, but make sure it's a native app */
140 if (ProcessInfo
->ImageInformation
.SubSystemType
== IMAGE_SUBSYSTEM_NATIVE
)
143 NtResumeThread(ProcessInfo
->ThreadHandle
, NULL
);
144 if (!(Flags
& SMP_ASYNC_FLAG
))
146 /* Block on it unless Async was requested */
147 NtWaitForSingleObject(ProcessInfo
->ThreadHandle
, FALSE
, NULL
);
150 /* It's up and running now, close our handles */
151 NtClose(ProcessInfo
->ThreadHandle
);
152 NtClose(ProcessInfo
->ProcessHandle
);
156 /* This image is invalid, so kill it, close our handles, and fail */
157 Status
= STATUS_INVALID_IMAGE_FORMAT
;
158 NtTerminateProcess(ProcessInfo
->ProcessHandle
, Status
);
159 NtWaitForSingleObject(ProcessInfo
->ThreadHandle
, 0, 0);
160 NtClose(ProcessInfo
->ThreadHandle
);
161 NtClose(ProcessInfo
->ProcessHandle
);
162 DPRINT1("SMSS: Not an NT image - %wZ\n", FileName
);
165 /* Return the outcome of the process create */
171 SmpInvokeAutoChk(IN PUNICODE_STRING FileName
,
172 IN PUNICODE_STRING Directory
,
173 IN PUNICODE_STRING Arguments
,
176 ANSI_STRING DestinationString
;
177 CHAR SourceString
[256];
178 UNICODE_STRING Destination
;
180 BOOLEAN BootState
, BootOkay
, ShutdownOkay
;
182 /* Check if autochk should show dots (if the user booted with /SOS) */
183 if (SmpQueryRegistrySosOption()) SmpEnableDots
= FALSE
;
185 /* Make sure autochk was actually found */
186 if (Flags
& SMP_INVALID_PATH
)
188 /* It wasn't, so create an error message to print on the screen */
189 sprintf_nt(SourceString
,
190 "%wZ program not found - skipping AUTOCHECK\n",
192 RtlInitAnsiString(&DestinationString
, SourceString
);
193 if (RtlAnsiStringToUnicodeString(&Destination
,
198 NtDisplayString(&Destination
);
199 RtlFreeUnicodeString(&Destination
);
204 /* Autochk is there, so record the BSD state */
205 BootState
= SmpSaveAndClearBootStatusData(&BootOkay
, &ShutdownOkay
);
207 /* Build the path to autochk and place its arguments */
208 RtlInitEmptyUnicodeString(&Destination
, Buffer
, sizeof(Buffer
));
209 RtlAppendUnicodeStringToString(&Destination
, FileName
);
210 RtlAppendUnicodeToString(&Destination
, L
" ");
211 RtlAppendUnicodeStringToString(&Destination
, Arguments
);
214 SmpExecuteImage(FileName
,
218 Flags
& ~SMP_AUTOCHK_FLAG
,
221 /* Restore the BSD state */
222 if (BootState
) SmpRestoreBootStatusData(BootOkay
, ShutdownOkay
);
225 /* We're all done! */
226 return STATUS_SUCCESS
;
231 SmpExecuteCommand(IN PUNICODE_STRING CommandLine
,
232 IN ULONG MuSessionId
,
233 OUT PHANDLE ProcessId
,
237 UNICODE_STRING Arguments
, Directory
, FileName
;
239 /* There's no longer a debugging subsystem */
240 if (Flags
& SMP_DEBUG_FLAG
) return STATUS_SUCCESS
;
242 /* Parse the command line to see what execution flags are requested */
243 Status
= SmpParseCommandLine(CommandLine
,
248 if (!NT_SUCCESS(Status
))
250 /* Fail if we couldn't do that */
251 DPRINT1("SMSS: SmpParseCommand( %wZ ) failed - Status == %lx\n",
252 CommandLine
, Status
);
256 /* Check if autochk is requested */
257 if (Flags
& SMP_AUTOCHK_FLAG
)
260 Status
= SmpInvokeAutoChk(&FileName
, &Directory
, &Arguments
, Flags
);
262 else if (Flags
& SMP_SUBSYSTEM_FLAG
)
264 Status
= SmpLoadSubSystem(&FileName
,
271 else if (Flags
& SMP_INVALID_PATH
)
273 /* An invalid image was specified, fail */
274 DPRINT1("SMSS: Image file (%wZ) not found\n", &FileName
);
275 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
279 /* An actual image name was present -- execute it */
280 Status
= SmpExecuteImage(&FileName
,
288 /* Free all the token parameters */
289 if (FileName
.Buffer
) RtlFreeHeap(RtlGetProcessHeap(), 0, FileName
.Buffer
);
290 if (Directory
.Buffer
) RtlFreeHeap(RtlGetProcessHeap(), 0, Directory
.Buffer
);
291 if (Arguments
.Buffer
) RtlFreeHeap(RtlGetProcessHeap(), 0, Arguments
.Buffer
);
293 /* Return to the caller */
294 if (!NT_SUCCESS(Status
))
296 DPRINT1("SMSS: Command '%wZ' failed - Status == %x\n",
297 CommandLine
, Status
);
304 SmpExecuteInitialCommand(IN ULONG MuSessionId
,
305 IN PUNICODE_STRING InitialCommand
,
306 IN HANDLE InitialCommandProcess
,
307 OUT PHANDLE ReturnPid
)
310 RTL_USER_PROCESS_INFORMATION ProcessInfo
;
311 UNICODE_STRING Arguments
, ImageFileDirectory
, ImageFileName
;
314 /* Check if we haven't yet connected to ourselves */
317 /* Connect to ourselves, as a client */
318 Status
= SmConnectToSm(0, 0, 0, &SmApiPort
);
319 if (!NT_SUCCESS(Status
))
321 DPRINT1("SMSS: Unable to connect to SM - Status == %lx\n", Status
);
326 /* Parse the initial command line */
327 Status
= SmpParseCommandLine(InitialCommand
,
332 if (Flags
& SMP_INVALID_PATH
)
334 /* Fail if it doesn't exist */
335 DPRINT1("SMSS: Initial command image (%wZ) not found\n", &ImageFileName
);
336 if (ImageFileName
.Buffer
) RtlFreeHeap(RtlGetProcessHeap(), 0, ImageFileName
.Buffer
);
337 return STATUS_OBJECT_NAME_NOT_FOUND
;
340 /* And fail if any other reason is also true */
341 if (!NT_SUCCESS(Status
))
343 DPRINT1("SMSS: SmpParseCommand( %wZ ) failed - Status == %lx\n",
344 InitialCommand
, Status
);
348 /* Execute the initial command -- but defer its full execution */
349 Status
= SmpExecuteImage(&ImageFileName
,
356 /* Free any buffers we had lying around */
357 if (ImageFileName
.Buffer
)
359 RtlFreeHeap(RtlGetProcessHeap(), 0, ImageFileName
.Buffer
);
361 if (ImageFileDirectory
.Buffer
)
363 RtlFreeHeap(RtlGetProcessHeap(), 0, ImageFileDirectory
.Buffer
);
365 if (Arguments
.Buffer
) RtlFreeHeap(RtlGetProcessHeap(), 0, Arguments
.Buffer
);
367 /* Bail out if we couldn't execute the initial command */
368 if (!NT_SUCCESS(Status
)) return Status
;
370 /* Now duplicate the handle to this process */
371 Status
= NtDuplicateObject(NtCurrentProcess(),
372 ProcessInfo
.ProcessHandle
,
374 InitialCommandProcess
,
378 if (!NT_SUCCESS(Status
))
380 /* Kill it utterly if duplication failed */
381 DPRINT1("SMSS: DupObject Failed. Status == %lx\n", Status
);
382 NtTerminateProcess(ProcessInfo
.ProcessHandle
, Status
);
383 NtResumeThread(ProcessInfo
.ThreadHandle
, NULL
);
384 NtClose(ProcessInfo
.ThreadHandle
);
385 NtClose(ProcessInfo
.ProcessHandle
);
389 /* Return PID to the caller, and set this as the initial command PID */
390 if (ReturnPid
) *ReturnPid
= ProcessInfo
.ClientId
.UniqueProcess
;
391 if (!MuSessionId
) SmpInitialCommandProcessId
= ProcessInfo
.ClientId
.UniqueProcess
;
393 /* Now call our server execution function to wrap up its initialization */
394 Status
= SmExecPgm(SmApiPort
, &ProcessInfo
, FALSE
);
395 if (!NT_SUCCESS(Status
)) DPRINT1("SMSS: SmExecPgm Failed. Status == %lx\n", Status
);
401 ExpLoadInitialProcess(IN PINIT_BUFFER InitBuffer
,
402 OUT PRTL_USER_PROCESS_PARAMETERS
*ProcessParameters
,
403 OUT PCHAR
*ProcessEnvironment
)
408 UNICODE_STRING NullString
= RTL_CONSTANT_STRING(L
"");
409 UNICODE_STRING SmssName
, DebugString
;
410 PVOID EnvironmentPtr
= NULL
;
411 PRTL_USER_PROCESS_INFORMATION ProcessInformation
;
412 PRTL_USER_PROCESS_PARAMETERS ProcessParams
= NULL
;
414 NullString
.Length
= sizeof(WCHAR
);
416 /* Use the initial buffer, after the strings */
417 ProcessInformation
= &InitBuffer
->ProcessInfo
;
419 /* Allocate memory for the process parameters */
420 Size
= sizeof(*ProcessParams
) + ((MAX_PATH
* 6) * sizeof(WCHAR
));
421 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(),
422 (PVOID
*)&ProcessParams
,
427 if (!NT_SUCCESS(Status
))
429 /* Failed, display error */
430 p
= InitBuffer
->DebugBuffer
;
433 L
"INIT: Unable to allocate Process Parameters. 0x%lx",
435 RtlInitUnicodeString(&DebugString
, p
);
436 ZwDisplayString(&DebugString
);
438 /* Bugcheck the system */
442 /* Setup the basic header, and give the process the low 1MB to itself */
443 ProcessParams
->Length
= (ULONG
)Size
;
444 ProcessParams
->MaximumLength
= (ULONG
)Size
;
445 ProcessParams
->Flags
= RTL_USER_PROCESS_PARAMETERS_NORMALIZED
|
446 RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB
;
448 /* Allocate a page for the environment */
450 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(),
456 if (!NT_SUCCESS(Status
))
458 /* Failed, display error */
459 p
= InitBuffer
->DebugBuffer
;
462 L
"INIT: Unable to allocate Process Environment. 0x%lx",
464 RtlInitUnicodeString(&DebugString
, p
);
465 ZwDisplayString(&DebugString
);
467 /* Bugcheck the system */
471 /* Write the pointer */
472 ProcessParams
->Environment
= EnvironmentPtr
;
474 /* Make a buffer for the DOS path */
475 p
= (PWSTR
)(ProcessParams
+ 1);
476 ProcessParams
->CurrentDirectory
.DosPath
.Buffer
= p
;
477 ProcessParams
->CurrentDirectory
.DosPath
.MaximumLength
= MAX_PATH
*
480 /* Copy the DOS path */
481 RtlCopyUnicodeString(&ProcessParams
->CurrentDirectory
.DosPath
,
484 /* Make a buffer for the DLL Path */
485 p
= (PWSTR
)((PCHAR
)ProcessParams
->CurrentDirectory
.DosPath
.Buffer
+
486 ProcessParams
->CurrentDirectory
.DosPath
.MaximumLength
);
487 ProcessParams
->DllPath
.Buffer
= p
;
488 ProcessParams
->DllPath
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
490 /* Copy the DLL path and append the system32 directory */
491 RtlCopyUnicodeString(&ProcessParams
->DllPath
,
492 &ProcessParams
->CurrentDirectory
.DosPath
);
493 RtlAppendUnicodeToString(&ProcessParams
->DllPath
, L
"\\System32");
495 /* Make a buffer for the image name */
496 p
= (PWSTR
)((PCHAR
)ProcessParams
->DllPath
.Buffer
+
497 ProcessParams
->DllPath
.MaximumLength
);
498 ProcessParams
->ImagePathName
.Buffer
= p
;
499 ProcessParams
->ImagePathName
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
501 /* Make sure the buffer is a valid string which within the given length */
502 if ((NtInitialUserProcessBufferType
!= REG_SZ
) ||
503 ((NtInitialUserProcessBufferLength
!= MAXULONG
) &&
504 ((NtInitialUserProcessBufferLength
< sizeof(WCHAR
)) ||
505 (NtInitialUserProcessBufferLength
>
506 sizeof(NtInitialUserProcessBuffer
) - sizeof(WCHAR
)))))
508 /* Invalid initial process string, bugcheck */
509 return STATUS_INVALID_PARAMETER
;
512 /* Cut out anything after a space */
513 p
= NtInitialUserProcessBuffer
;
514 while ((*p
) && (*p
!= L
' ')) p
++;
516 /* Set the image path length */
517 ProcessParams
->ImagePathName
.Length
=
518 (USHORT
)((PCHAR
)p
- (PCHAR
)NtInitialUserProcessBuffer
);
520 /* Copy the actual buffer */
521 RtlCopyMemory(ProcessParams
->ImagePathName
.Buffer
,
522 NtInitialUserProcessBuffer
,
523 ProcessParams
->ImagePathName
.Length
);
525 /* Null-terminate it */
526 ProcessParams
->ImagePathName
.Buffer
[ProcessParams
->ImagePathName
.Length
/
527 sizeof(WCHAR
)] = UNICODE_NULL
;
529 /* Make a buffer for the command line */
530 p
= (PWSTR
)((PCHAR
)ProcessParams
->ImagePathName
.Buffer
+
531 ProcessParams
->ImagePathName
.MaximumLength
);
532 ProcessParams
->CommandLine
.Buffer
= p
;
533 ProcessParams
->CommandLine
.MaximumLength
= MAX_PATH
* sizeof(WCHAR
);
535 /* Add the image name to the command line */
536 RtlAppendUnicodeToString(&ProcessParams
->CommandLine
,
537 NtInitialUserProcessBuffer
);
539 /* Create the environment string */
540 ProcessParams
->Environment
= SmpDefaultEnvironment
;
542 /* Create SMSS process */
543 SmssName
= ProcessParams
->ImagePathName
;
544 Status
= RtlCreateUserProcess(&SmssName
,
545 OBJ_CASE_INSENSITIVE
,
546 RtlDeNormalizeProcessParams(ProcessParams
),
554 if (!NT_SUCCESS(Status
))
556 /* Failed, display error */
557 p
= InitBuffer
->DebugBuffer
;
560 L
"INIT: Unable to create Session Manager. 0x%lx",
562 RtlInitUnicodeString(&DebugString
, p
);
563 ZwDisplayString(&DebugString
);
565 /* Bugcheck the system */
569 /* Resume the thread */
570 Status
= ZwResumeThread(ProcessInformation
->ThreadHandle
, NULL
);
571 if (!NT_SUCCESS(Status
))
573 /* Failed, display error */
574 p
= InitBuffer
->DebugBuffer
;
577 L
"INIT: Unable to resume Session Manager. 0x%lx",
579 RtlInitUnicodeString(&DebugString
, p
);
580 ZwDisplayString(&DebugString
);
582 /* Bugcheck the system */
587 *ProcessParameters
= ProcessParams
;
588 *ProcessEnvironment
= EnvironmentPtr
;
589 return STATUS_SUCCESS
;
596 PINIT_BUFFER InitBuffer
;
597 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
= NULL
;
598 PRTL_USER_PROCESS_INFORMATION ProcessInfo
;
602 /* Initialize the system root */
603 RtlInitUnicodeString(&SmpSystemRoot
, SharedUserData
->NtSystemRoot
);
605 /* Allocate the initialization buffer */
606 InitBuffer
= RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(INIT_BUFFER
));
610 return STATUS_NO_MEMORY
;
613 /* Launch initial process */
614 ProcessInfo
= &InitBuffer
->ProcessInfo
;
615 Status
= ExpLoadInitialProcess(InitBuffer
, &ProcessParameters
, &Environment
);
616 if (!NT_SUCCESS(Status
))
618 /* Failed, display error */
619 DPRINT1("INIT: Session Manager failed to load.\n");
623 /* Return the handle and status */
629 SmpTerminate(IN PULONG_PTR Parameters
,
630 IN ULONG ParameterMask
,
631 IN ULONG ParameterCount
)
637 /* Give the shutdown privilege to the thread */
638 if (RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
, TRUE
, TRUE
, &Old
) ==
641 /* Thread doesn't have a token, give it to the entire process */
642 RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
, TRUE
, FALSE
, &Old
);
645 /* Take down the process/machine with a hard error */
646 Status
= NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED
,
650 OptionShutdownSystem
,
653 /* Terminate the process if the hard error didn't already */
654 return NtTerminateProcess(NtCurrentProcess(), Status
);
658 SmpUnhandledExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo
)
660 ULONG_PTR Parameters
[4];
661 UNICODE_STRING DestinationString
;
663 /* Print and breakpoint into the debugger */
664 DbgPrint("SMSS: Unhandled exception - Status == %x IP == %x\n",
665 ExceptionInfo
->ExceptionRecord
->ExceptionCode
,
666 ExceptionInfo
->ExceptionRecord
->ExceptionAddress
);
667 DbgPrint(" Memory Address: %x Read/Write: %x\n",
668 ExceptionInfo
->ExceptionRecord
->ExceptionInformation
[0],
669 ExceptionInfo
->ExceptionRecord
->ExceptionInformation
[1]);
672 /* Build the hard error and terminate */
673 RtlInitUnicodeString(&DestinationString
, L
"Unhandled Exception in Session Manager");
674 Parameters
[0] = (ULONG_PTR
)&DestinationString
;
675 Parameters
[1] = ExceptionInfo
->ExceptionRecord
->ExceptionCode
;
676 Parameters
[2] = (ULONG_PTR
)ExceptionInfo
->ExceptionRecord
->ExceptionAddress
;
677 Parameters
[3] = (ULONG_PTR
)ExceptionInfo
->ContextRecord
;
678 SmpTerminate(Parameters
, 1, RTL_NUMBER_OF(Parameters
));
680 /* We hould never get here */
682 return EXCEPTION_EXECUTE_HANDLER
;
692 KPRIORITY SetBasePriority
;
693 ULONG_PTR Parameters
[4];
697 PROCESS_BASIC_INFORMATION ProcessInfo
;
698 UNICODE_STRING DbgString
, InitialCommand
;
700 /* Make us critical */
701 RtlSetProcessIsCritical(TRUE
, NULL
, FALSE
);
702 RtlSetThreadIsCritical(TRUE
, NULL
, FALSE
);
704 /* Raise our priority */
705 SetBasePriority
= 11;
706 Status
= NtSetInformationProcess(NtCurrentProcess(),
708 (PVOID
)&SetBasePriority
,
709 sizeof(SetBasePriority
));
710 ASSERT(NT_SUCCESS(Status
));
712 /* Save the debug flag if it was passed */
713 if (DebugFlag
) SmpDebug
= DebugFlag
;
715 /* Build the hard error parameters */
716 Parameters
[0] = (ULONG_PTR
)&DbgString
;
717 Parameters
[1] = Parameters
[2] = Parameters
[3] = 0;
719 /* Enter SEH so we can terminate correctly if anything goes wrong */
722 LARGE_INTEGER Infinite
= {{0x80000000, 0x7FFFFFFF}};
724 /* Initialize SMSS */
725 Status
= SmpInit(&InitialCommand
, Handles
);
726 if (!NT_SUCCESS(Status
))
728 DPRINT1("SMSS: SmpInit return failure - Status == %x\n", Status
);
729 RtlInitUnicodeString(&DbgString
, L
"Session Manager Initialization");
730 Parameters
[1] = Status
;
731 DPRINT1("SMSS-2 Loaded... Launching original SMSS\n");
732 //_SEH2_LEAVE; Hack so that setup can work. will go away later
733 Status
= LaunchOldSmss();
734 if (!NT_SUCCESS(Status
)) return Status
;
735 return NtDelayExecution(FALSE
, &Infinite
);
738 /* Get the global flags */
739 Status
= NtQuerySystemInformation(SystemFlagsInformation
,
743 ASSERT(NT_SUCCESS(Status
));
745 /* Before executing the initial command check if the debug flag is on */
746 if (Flags
& (FLG_DEBUG_INITIAL_COMMAND
| FLG_DEBUG_INITIAL_COMMAND_EX
))
748 /* SMSS should launch ntsd with a few parameters at this point */
749 DPRINT1("Global Flags Set to SMSS Debugging: Not yet supported\n");
752 /* Execute the initial command (Winlogon.exe) */
753 Status
= SmpExecuteInitialCommand(0, &InitialCommand
, &Handles
[1], NULL
);
754 if (!NT_SUCCESS(Status
))
756 /* Fail and raise a hard error */
757 DPRINT1("SMSS: Execute Initial Command failed\n");
758 RtlInitUnicodeString(&DbgString
,
759 L
"Session Manager ExecuteInitialCommand");
760 Parameters
[1] = Status
;
762 DPRINT1("SMSS-2 Loaded... Launching original SMSS\n");
763 Status
= LaunchOldSmss();
764 if (!NT_SUCCESS(Status
)) return Status
;
765 return NtDelayExecution(FALSE
, &Infinite
);
768 /* Check if we're already attached to a session */
769 Status
= SmpAcquirePrivilege(SE_LOAD_DRIVER_PRIVILEGE
, &State
);
770 if (AttachedSessionId
!= -1)
772 /* Detach from it, we should be in no session right now */
773 Status
= NtSetSystemInformation(SystemSessionDetach
,
775 sizeof(AttachedSessionId
));
776 ASSERT(NT_SUCCESS(Status
));
777 AttachedSessionId
= -1;
779 SmpReleasePrivilege(State
);
781 /* Wait on either CSRSS or Winlogon to die */
782 Status
= NtWaitForMultipleObjects(RTL_NUMBER_OF(Handles
),
787 if (Status
== STATUS_WAIT_0
)
789 /* CSRSS is dead, get exit code and prepare for the hard error */
790 RtlInitUnicodeString(&DbgString
, L
"Windows SubSystem");
791 Status
= NtQueryInformationProcess(Handles
[0],
792 ProcessBasicInformation
,
796 DPRINT1("SMSS: Windows subsystem terminated when it wasn't supposed to.\n");
800 /* The initial command is dead or we have another failure */
801 RtlInitUnicodeString(&DbgString
, L
"Windows Logon Process");
802 if (Status
== STATUS_WAIT_1
)
804 /* Winlogon.exe got terminated, get its exit code */
805 Status
= NtQueryInformationProcess(Handles
[1],
806 ProcessBasicInformation
,
813 /* Something else satisfied our wait, so set the wait status */
814 ProcessInfo
.ExitStatus
= Status
;
815 Status
= STATUS_SUCCESS
;
817 DPRINT1("SMSS: Initial command '%wZ' terminated when it wasn't supposed to.\n",
821 /* Check if NtQueryInformationProcess was successful */
822 if (NT_SUCCESS(Status
))
824 /* Then we must have a valid exit status in the structure, use it */
825 Parameters
[1] = ProcessInfo
.ExitStatus
;
829 /* We really don't know what happened, so set a generic error */
830 Parameters
[1] = STATUS_UNSUCCESSFUL
;
833 _SEH2_EXCEPT(SmpUnhandledExceptionFilter(_SEH2_GetExceptionInformation()))
835 /* The filter should never return here */
840 /* Something in the init loop failed, terminate SMSS */
841 return SmpTerminate(Parameters
, 1, RTL_NUMBER_OF(Parameters
));