windows-nt/Source/XPSP1/NT/base/subsys/sm/server/smss.c
2020-09-26 16:20:57 +08:00

320 lines
10 KiB
C

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
smss.c
Abstract:
Author:
Mark Lucovsky (markl) 04-Oct-1989
Revision History:
--*/
#include "smsrvp.h"
#if defined(REMOTE_BOOT)
char SmpFormatKeyword[] = "NETBOOTFORMAT";
char SmpDisconnectedKeyword[] = "NETBOOTDISCONNECTED";
char SmpNetbootKeyword[] = "NETBOOT";
char SmpHalKeyword[] = "NETBOOTHAL";
BOOLEAN SmpAutoFormat = FALSE;
BOOLEAN SmpNetboot = FALSE;
BOOLEAN SmpNetbootDisconnected = FALSE;
char SmpHalName[MAX_HAL_NAME_LENGTH + 1] = "";
#endif // defined(REMOTE_BOOT)
void
SmpTerminate(
ULONG_PTR Parameters[]
);
EXCEPTION_DISPOSITION
SmpUnhandledExceptionFilter(
struct _EXCEPTION_POINTERS *ExceptionInfo,
ULONG_PTR Parameters[]
);
void
__cdecl main(
int argc,
char *argv[],
char *envp[],
ULONG DebugParameter OPTIONAL
)
{
NTSTATUS Status;
KPRIORITY SetBasePriority;
UNICODE_STRING InitialCommand, DebugInitialCommand, UnicodeParameter;
HANDLE ProcessHandles[ 2 ];
ULONG_PTR Parameters[ 4 ];
PROCESS_BASIC_INFORMATION ProcessInfo;
ULONG MuSessionId = 0; // First instance (console) has MuSessionId = 0
#if defined(REMOTE_BOOT)
int TmpArgc;
#endif // defined(REMOTE_BOOT)
RtlSetProcessIsCritical(TRUE, NULL, TRUE);
RtlSetThreadIsCritical(TRUE, NULL, TRUE);
SetBasePriority = FOREGROUND_BASE_PRIORITY+2;
Status = NtSetInformationProcess( NtCurrentProcess(),
ProcessBasePriority,
(PVOID) &SetBasePriority,
sizeof( SetBasePriority )
);
ASSERT(NT_SUCCESS(Status));
#if defined(REMOTE_BOOT)
TmpArgc = 1;
while (TmpArgc < argc) {
if (!strcmp(argv[TmpArgc], SmpFormatKeyword)) {
SmpAutoFormat = TRUE;
}
else if (!strcmp(argv[TmpArgc], SmpNetbootKeyword)) {
SmpNetboot = TRUE;
}
else if (!strcmp(argv[TmpArgc], SmpDisconnectedKeyword)) {
SmpNetbootDisconnected = TRUE;
}
else if (!strcmp(argv[TmpArgc], SmpHalKeyword)) {
TmpArgc++;
if (TmpArgc == argc) {
break;
}
memset(SmpHalName, 0x0, sizeof(SmpHalName));
strcpy(SmpHalName, argv[TmpArgc]);
}
TmpArgc++;
}
#endif // defined(REMOTE_BOOT)
if (ARGUMENT_PRESENT( (PVOID)(ULONG_PTR) DebugParameter )) {
SmpDebug = DebugParameter;
}
try {
Parameters[ 0 ] = (ULONG_PTR)&UnicodeParameter;
Parameters[ 1 ] = 0;
Parameters[ 2 ] = 0;
Parameters[ 3 ] = 0;
Status = SmpInit( &InitialCommand, &ProcessHandles[ 0 ] );
if (!NT_SUCCESS( Status )) {
KdPrint(( "SMSS: SmpInit return failure - Status == %x\n", Status ));
RtlInitUnicodeString( &UnicodeParameter, L"Session Manager Initialization" );
Parameters[ 1 ] = (ULONG)Status;
} else {
SYSTEM_FLAGS_INFORMATION FlagInfo;
NtQuerySystemInformation( SystemFlagsInformation,
&FlagInfo,
sizeof( FlagInfo ),
NULL
);
if (FlagInfo.Flags & (FLG_DEBUG_INITIAL_COMMAND | FLG_DEBUG_INITIAL_COMMAND_EX) ) {
DebugInitialCommand.MaximumLength = InitialCommand.Length + 64;
DebugInitialCommand.Length = 0;
DebugInitialCommand.Buffer = RtlAllocateHeap( RtlProcessHeap(),
MAKE_TAG( INIT_TAG ),
DebugInitialCommand.MaximumLength
);
if (FlagInfo.Flags & FLG_ENABLE_CSRDEBUG) {
RtlAppendUnicodeToString( &DebugInitialCommand, L"ntsd -p -1 -d " );
}
else {
RtlAppendUnicodeToString( &DebugInitialCommand, L"ntsd -d " );
}
if (FlagInfo.Flags & FLG_DEBUG_INITIAL_COMMAND_EX ) {
RtlAppendUnicodeToString( &DebugInitialCommand, L"-g -x " );
}
RtlAppendUnicodeStringToString( &DebugInitialCommand, &InitialCommand );
InitialCommand = DebugInitialCommand;
}
Status = SmpExecuteInitialCommand( 0L, &InitialCommand, &ProcessHandles[ 1 ], NULL );
if (NT_SUCCESS( Status )) {
//
// Detach the session manager from the session space as soon as
// we have executed the initial command (winlogon).
//
PVOID State;
Status = SmpAcquirePrivilege( SE_LOAD_DRIVER_PRIVILEGE, &State );
if (NT_SUCCESS( Status )) {
//
// If we are attached to a session space, leave it
// so we can create a new one
//
if( (AttachedSessionId != (-1)) ) {
Status = NtSetSystemInformation(
SystemSessionDetach,
(PVOID)&AttachedSessionId,
sizeof(MuSessionId)
);
ASSERT(NT_SUCCESS(Status));
AttachedSessionId = (-1);
}
SmpReleasePrivilege( State );
}
}
if (NT_SUCCESS( Status )) {
Status = NtWaitForMultipleObjects( 2,
ProcessHandles,
WaitAny,
FALSE,
NULL
);
}
if (Status == STATUS_WAIT_0) {
RtlInitUnicodeString( &UnicodeParameter, L"Windows SubSystem" );
Status = NtQueryInformationProcess( ProcessHandles[ 0 ],
ProcessBasicInformation,
&ProcessInfo,
sizeof( ProcessInfo ),
NULL
);
KdPrint(( "SMSS: Windows subsystem terminated when it wasn't supposed to.\n" ));
} else {
RtlInitUnicodeString( &UnicodeParameter, L"Windows Logon Process" );
if (Status == STATUS_WAIT_1) {
Status = NtQueryInformationProcess( ProcessHandles[ 1 ],
ProcessBasicInformation,
&ProcessInfo,
sizeof( ProcessInfo ),
NULL
);
} else {
ProcessInfo.ExitStatus = Status;
Status = STATUS_SUCCESS;
}
KdPrint(( "SMSS: Initial command '%wZ' terminated when it wasn't supposed to.\n", &InitialCommand ));
}
if (NT_SUCCESS( Status )) {
Parameters[ 1 ] = (ULONG)ProcessInfo.ExitStatus;
} else {
Parameters[ 1 ] = (ULONG)STATUS_UNSUCCESSFUL;
}
}
} except( SmpUnhandledExceptionFilter( GetExceptionInformation(), Parameters ) ) {
/* not reached */
}
SmpTerminate(Parameters);
/* not reached */
}
void
SmpTerminate(
ULONG_PTR Parameters[]
)
{
NTSTATUS Status;
ULONG Response;
BOOLEAN WasEnabled;
//
// We are hosed, so raise a fatal system error to shutdown the system.
// (Basically a user mode KeBugCheck).
//
Status = RtlAdjustPrivilege( SE_SHUTDOWN_PRIVILEGE,
(BOOLEAN)TRUE,
TRUE,
&WasEnabled
);
if (Status == STATUS_NO_TOKEN) {
//
// No thread token, use the process token.
//
Status = RtlAdjustPrivilege( SE_SHUTDOWN_PRIVILEGE,
(BOOLEAN)TRUE,
FALSE,
&WasEnabled
);
}
Status = NtRaiseHardError( STATUS_SYSTEM_PROCESS_TERMINATED,
4,
1,
Parameters,
OptionShutdownSystem,
&Response
);
//
// If this returns, give up.
//
NtTerminateProcess( NtCurrentProcess(), Status );
}
EXCEPTION_DISPOSITION
SmpUnhandledExceptionFilter(
struct _EXCEPTION_POINTERS *ExceptionInfo,
ULONG_PTR Parameters[]
)
{
UNICODE_STRING ExUnicodeParameter;
#if DBG
DbgPrint( "SMSS: Unhandled exception - Status == %x IP == %x\n",
ExceptionInfo->ExceptionRecord->ExceptionCode,
ExceptionInfo->ExceptionRecord->ExceptionAddress
);
DbgPrint( " Memory Address: %x Read/Write: %x\n",
ExceptionInfo->ExceptionRecord->ExceptionInformation[ 0 ],
ExceptionInfo->ExceptionRecord->ExceptionInformation[ 1 ]
);
DbgBreakPoint();
#endif
RtlInitUnicodeString( &ExUnicodeParameter, L"Unhandled Exception in Session Manager" );
Parameters[ 0 ] = (ULONG_PTR)&ExUnicodeParameter;
Parameters[ 1 ] = (ULONG_PTR)ExceptionInfo->ExceptionRecord->ExceptionCode;
Parameters[ 2 ] = (ULONG_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress;
Parameters[ 3 ] = (ULONG_PTR)ExceptionInfo->ContextRecord;
//
// SmpTerminate will raise a hard error with the exception info still valid.
//
SmpTerminate(Parameters);
// not reached
return EXCEPTION_EXECUTE_HANDLER;
}