mirror of
https://github.com/reactos/reactos.git
synced 2025-01-01 03:54:02 +00:00
[SMSS2]: Flesh out the _main function in the new SMSS, including the SEH filter and SmpTerminate support. Instead of launching Winlogon (The "initial command", we launch the ReactOS SMSS for now -- and kill the system if it is ever terminated, as we should). We use the right priority, set the right critical flags, use the correct debug parameters, and acquire/release the correct privileges. Only thing not supported is launching ntsd if the "Debug Initial Command" global flag is set. I promise to implement that once someone implements ntsd ;-)
svn path=/trunk/; revision=55311
This commit is contained in:
parent
4e3bf71826
commit
88cd0f3813
11 changed files with 549 additions and 46 deletions
|
@ -2,12 +2,20 @@
|
|||
include_directories(${REACTOS_SOURCE_DIR}/include/reactos/subsys)
|
||||
|
||||
list(APPEND SOURCE
|
||||
smss.c
|
||||
smss.rc)
|
||||
crashdmp.c
|
||||
pagefile.c
|
||||
sminit.c
|
||||
smloop.c
|
||||
smsbapi.c
|
||||
smsessn.c
|
||||
smsubsys.c
|
||||
smutil.c
|
||||
smss.c
|
||||
smss.rc)
|
||||
|
||||
add_executable(smss2 WIN32 ${SOURCE})
|
||||
|
||||
target_link_libraries(smss2 nt)
|
||||
target_link_libraries(smss2 nt pseh)
|
||||
|
||||
add_pch(smss2 smss.h)
|
||||
|
||||
|
|
17
reactos/base/system/smss2/crashdmp.c
Normal file
17
reactos/base/system/smss2/crashdmp.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Windows-Compatible Session Manager
|
||||
* LICENSE: BSD 2-Clause License
|
||||
* FILE: base/system/smss/smss.c
|
||||
* PURPOSE: Main SMSS Code
|
||||
* PROGRAMMERS: Alex Ionescu
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "smss.h"
|
||||
#define NDEBUG
|
||||
#include "debug.h"
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
17
reactos/base/system/smss2/pagefile.c
Normal file
17
reactos/base/system/smss2/pagefile.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Windows-Compatible Session Manager
|
||||
* LICENSE: BSD 2-Clause License
|
||||
* FILE: base/system/smss/smss.c
|
||||
* PURPOSE: Main SMSS Code
|
||||
* PROGRAMMERS: Alex Ionescu
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "smss.h"
|
||||
#define NDEBUG
|
||||
#include "debug.h"
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
25
reactos/base/system/smss2/sminit.c
Normal file
25
reactos/base/system/smss2/sminit.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Windows-Compatible Session Manager
|
||||
* LICENSE: BSD 2-Clause License
|
||||
* FILE: base/system/smss/smss.c
|
||||
* PURPOSE: Main SMSS Code
|
||||
* PROGRAMMERS: Alex Ionescu
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "smss.h"
|
||||
#define NDEBUG
|
||||
#include "debug.h"
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SmpInit(IN PUNICODE_STRING InitialCommand,
|
||||
OUT PHANDLE ProcessHandle)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
17
reactos/base/system/smss2/smloop.c
Normal file
17
reactos/base/system/smss2/smloop.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Windows-Compatible Session Manager
|
||||
* LICENSE: BSD 2-Clause License
|
||||
* FILE: base/system/smss/smss.c
|
||||
* PURPOSE: Main SMSS Code
|
||||
* PROGRAMMERS: Alex Ionescu
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "smss.h"
|
||||
#define NDEBUG
|
||||
#include "debug.h"
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
17
reactos/base/system/smss2/smsbapi.c
Normal file
17
reactos/base/system/smss2/smsbapi.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Windows-Compatible Session Manager
|
||||
* LICENSE: BSD 2-Clause License
|
||||
* FILE: base/system/smss/smss.c
|
||||
* PURPOSE: Main SMSS Code
|
||||
* PROGRAMMERS: Alex Ionescu
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "smss.h"
|
||||
#define NDEBUG
|
||||
#include "debug.h"
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
17
reactos/base/system/smss2/smsessn.c
Normal file
17
reactos/base/system/smss2/smsessn.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Windows-Compatible Session Manager
|
||||
* LICENSE: BSD 2-Clause License
|
||||
* FILE: base/system/smss/smss.c
|
||||
* PURPOSE: Main SMSS Code
|
||||
* PROGRAMMERS: Alex Ionescu
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "smss.h"
|
||||
#define NDEBUG
|
||||
#include "debug.h"
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
|
@ -28,6 +28,9 @@ ULONG NtInitialUserProcessBufferType = REG_SZ;
|
|||
|
||||
UNICODE_STRING NtSystemRoot;
|
||||
|
||||
ULONG AttachedSessionId = -1;
|
||||
BOOLEAN SmpDebug;
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
|
@ -176,7 +179,7 @@ ExpLoadInitialProcess(IN PINIT_BUFFER InitBuffer,
|
|||
(USHORT)Size);
|
||||
|
||||
/* Append the DLL path to it */
|
||||
RtlAppendUnicodeToString(&Environment, L"Path=" );
|
||||
RtlAppendUnicodeToString(&Environment, L"Path=");
|
||||
RtlAppendUnicodeStringToString(&Environment, &ProcessParams->DllPath);
|
||||
RtlAppendUnicodeStringToString(&Environment, &NullString);
|
||||
|
||||
|
@ -246,19 +249,20 @@ ExpLoadInitialProcess(IN PINIT_BUFFER InitBuffer,
|
|||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
LaunchOldSmss(VOID)
|
||||
LaunchOldSmss(OUT PHANDLE Handles)
|
||||
{
|
||||
PINIT_BUFFER InitBuffer;
|
||||
PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL;
|
||||
PRTL_USER_PROCESS_INFORMATION ProcessInfo;
|
||||
LARGE_INTEGER Timeout;
|
||||
NTSTATUS Status;
|
||||
PCHAR Environment;
|
||||
SIZE_T Size;
|
||||
|
||||
|
||||
/* No handles at first */
|
||||
Handles[0] = Handles[1] = NULL;
|
||||
|
||||
/* Setup system root */
|
||||
RtlInitUnicodeString(&NtSystemRoot, SharedUserData->NtSystemRoot);
|
||||
|
||||
|
||||
/* Allocate the initialization buffer */
|
||||
InitBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(INIT_BUFFER));
|
||||
if (!InitBuffer)
|
||||
|
@ -266,7 +270,7 @@ LaunchOldSmss(VOID)
|
|||
/* Bugcheck */
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
/* Launch initial process */
|
||||
ProcessInfo = &InitBuffer->ProcessInfo;
|
||||
Status = ExpLoadInitialProcess(InitBuffer, &ProcessParameters, &Environment);
|
||||
|
@ -277,51 +281,223 @@ LaunchOldSmss(VOID)
|
|||
return Status;
|
||||
}
|
||||
|
||||
/* Wait 5 seconds for initial process to initialize */
|
||||
Timeout.QuadPart = Int32x32To64(5, -10000000);
|
||||
Status = ZwWaitForSingleObject(ProcessInfo->ProcessHandle, FALSE, &Timeout);
|
||||
if (Status == STATUS_SUCCESS)
|
||||
{
|
||||
/* Failed, display error */
|
||||
DPRINT1("INIT: Session Manager terminated.\n");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* Close process handles */
|
||||
ZwClose(ProcessInfo->ThreadHandle);
|
||||
ZwClose(ProcessInfo->ProcessHandle);
|
||||
|
||||
/* Free the initial process environment */
|
||||
Size = 0;
|
||||
ZwFreeVirtualMemory(NtCurrentProcess(),
|
||||
(PVOID*)&Environment,
|
||||
&Size,
|
||||
MEM_RELEASE);
|
||||
|
||||
/* Free the initial process parameters */
|
||||
Size = 0;
|
||||
ZwFreeVirtualMemory(NtCurrentProcess(),
|
||||
(PVOID*)&ProcessParameters,
|
||||
&Size,
|
||||
MEM_RELEASE);
|
||||
return STATUS_SUCCESS;
|
||||
/* Return the handle and status */
|
||||
Handles[0] = ProcessInfo->ProcessHandle;
|
||||
Handles[1] = ProcessInfo->ProcessHandle;
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SmpTerminate(IN PULONG_PTR Parameters,
|
||||
IN ULONG ParameterMask,
|
||||
IN ULONG ParameterCount)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
BOOLEAN Old;
|
||||
ULONG Response;
|
||||
|
||||
/* Give the shutdown privilege to the thread */
|
||||
if (RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, TRUE, &Old) ==
|
||||
STATUS_NO_TOKEN)
|
||||
{
|
||||
/* Thread doesn't have a token, give it to the entire process */
|
||||
RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &Old);
|
||||
}
|
||||
|
||||
/* Take down the process/machine with a hard error */
|
||||
Status = NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
|
||||
ParameterCount,
|
||||
ParameterMask,
|
||||
Parameters,
|
||||
OptionShutdownSystem,
|
||||
&Response);
|
||||
|
||||
/* Terminate the process if the hard error didn't already */
|
||||
return NtTerminateProcess(NtCurrentProcess(), Status);
|
||||
}
|
||||
|
||||
LONG
|
||||
SmpUnhandledExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo)
|
||||
{
|
||||
ULONG_PTR Parameters[4];
|
||||
UNICODE_STRING DestinationString;
|
||||
|
||||
/* Print and breakpoint into the debugger */
|
||||
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();
|
||||
|
||||
/* Build the hard error and terminate */
|
||||
RtlInitUnicodeString(&DestinationString, L"Unhandled Exception in Session Manager");
|
||||
Parameters[0] = (ULONG_PTR)&DestinationString;
|
||||
Parameters[1] = ExceptionInfo->ExceptionRecord->ExceptionCode;
|
||||
Parameters[2] = (ULONG_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress;
|
||||
Parameters[3] = (ULONG_PTR)ExceptionInfo->ContextRecord;
|
||||
SmpTerminate(Parameters, 1, RTL_NUMBER_OF(Parameters));
|
||||
|
||||
/* We hould never get here */
|
||||
ASSERT(FALSE);
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
__cdecl
|
||||
_main(IN INT argc,
|
||||
IN PCHAR argv[],
|
||||
IN PCHAR envp[],
|
||||
IN ULONG DebugFlag)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Launch the original SMSS */
|
||||
DPRINT1("SMSS-2 Loaded... Launching original SMSS\n");
|
||||
Status = LaunchOldSmss();
|
||||
KPRIORITY SetBasePriority;
|
||||
ULONG_PTR Parameters[4];
|
||||
HANDLE Handles[2];
|
||||
PVOID State;
|
||||
ULONG Flags;
|
||||
PROCESS_BASIC_INFORMATION ProcessInfo;
|
||||
UNICODE_STRING DbgString, InitialCommand;
|
||||
|
||||
/* Terminate this SMSS for now, later we'll have an LPC thread running */
|
||||
return NtTerminateThread(NtCurrentThread(), Status);
|
||||
/* Make us critical */
|
||||
RtlSetProcessIsCritical(TRUE, NULL, FALSE);
|
||||
RtlSetThreadIsCritical(TRUE, NULL, FALSE);
|
||||
|
||||
/* Raise our priority */
|
||||
SetBasePriority = 11;
|
||||
Status = NtSetInformationProcess(NtCurrentProcess(),
|
||||
ProcessBasePriority,
|
||||
(PVOID)&SetBasePriority,
|
||||
sizeof(SetBasePriority));
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
|
||||
/* Save the debug flag if it was passed */
|
||||
if (DebugFlag) SmpDebug = DebugFlag;
|
||||
|
||||
/* Build the hard error parameters */
|
||||
Parameters[0] = (ULONG_PTR)&DbgString;
|
||||
Parameters[1] = Parameters[2] = Parameters[3] = 0;
|
||||
|
||||
/* Enter SEH so we can terminate correctly if anything goes wrong */
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* Initialize SMSS */
|
||||
Status = SmpInit(&InitialCommand, Handles);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("SMSS: SmpInit return failure - Status == %x\n");
|
||||
RtlInitUnicodeString(&DbgString, L"Session Manager Initialization");
|
||||
Parameters[1] = Status;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
/* Get the global flags */
|
||||
Status = NtQuerySystemInformation(SystemFlagsInformation,
|
||||
&Flags,
|
||||
sizeof(Flags),
|
||||
NULL);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
|
||||
/* Before executing the initial command check if the debug flag is on */
|
||||
if (Flags & (FLG_DEBUG_INITIAL_COMMAND | FLG_DEBUG_INITIAL_COMMAND_EX))
|
||||
{
|
||||
/* SMSS should launch ntsd with a few parameters at this point */
|
||||
DPRINT1("Global Flags Set to SMSS Debugging: Not yet supported\n");
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Execute the initial command (Winlogon.exe) */
|
||||
Status = SmpExecuteInitialCommand(0, &InitialCommand, &Handles[1], NULL);
|
||||
#else
|
||||
/* Launch the original SMSS */
|
||||
DPRINT1("SMSS-2 Loaded... Launching original SMSS\n");
|
||||
Status = LaunchOldSmss(Handles);
|
||||
#endif
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Fail and raise a hard error */
|
||||
DPRINT1("SMSS: Execute Initial Command failed\n");
|
||||
RtlInitUnicodeString(&DbgString,
|
||||
L"Session Manager ExecuteInitialCommand");
|
||||
Parameters[1] = Status;
|
||||
_SEH2_LEAVE;
|
||||
}
|
||||
|
||||
/* Check if we're already attached to a session */
|
||||
Status = SmpAcquirePrivilege(SE_LOAD_DRIVER_PRIVILEGE, &State);
|
||||
if (AttachedSessionId != -1)
|
||||
{
|
||||
/* Detach from it, we should be in no session right now */
|
||||
Status = NtSetSystemInformation(SystemSessionDetach,
|
||||
&AttachedSessionId,
|
||||
sizeof(AttachedSessionId));
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
AttachedSessionId = -1;
|
||||
}
|
||||
SmpReleasePrivilege(State);
|
||||
|
||||
/* Wait on either CSRSS or Winlogon to die */
|
||||
Status = NtWaitForMultipleObjects(RTL_NUMBER_OF(Handles),
|
||||
Handles,
|
||||
WaitAny,
|
||||
FALSE,
|
||||
NULL);
|
||||
if (Status == STATUS_WAIT_0)
|
||||
{
|
||||
/* CSRSS is dead, get exit code and prepare for the hard error */
|
||||
RtlInitUnicodeString(&DbgString, L"Windows SubSystem");
|
||||
Status = NtQueryInformationProcess(Handles[0],
|
||||
ProcessBasicInformation,
|
||||
&ProcessInfo,
|
||||
sizeof(ProcessInfo),
|
||||
NULL);
|
||||
DPRINT1("SMSS: Windows subsystem terminated when it wasn't supposed to.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The initial command is dead or we have another failure */
|
||||
RtlInitUnicodeString(&DbgString, L"Windows Logon Process");
|
||||
if (Status == STATUS_WAIT_1)
|
||||
{
|
||||
/* Winlogon.exe got terminated, get its exit code */
|
||||
Status = NtQueryInformationProcess(Handles[1],
|
||||
ProcessBasicInformation,
|
||||
&ProcessInfo,
|
||||
sizeof(ProcessInfo),
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Something else satisfied our wait, so set the wait status */
|
||||
ProcessInfo.ExitStatus = Status;
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
DPRINT1("SMSS: Initial command '%wZ' terminated when it wasn't supposed to.\n",
|
||||
&InitialCommand);
|
||||
}
|
||||
|
||||
/* Check if NtQueryInformationProcess was successful */
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Then we must have a valid exit status in the structure, use it */
|
||||
Parameters[1] = ProcessInfo.ExitStatus;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We really don't know what happened, so set a generic error */
|
||||
Parameters[1] = STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
_SEH2_EXCEPT(SmpUnhandledExceptionFilter(_SEH2_GetExceptionInformation()))
|
||||
{
|
||||
/* The filter should never return here */
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
_SEH2_END;
|
||||
|
||||
/* Something in the init loop failed, terminate SMSS */
|
||||
return SmpTerminate(Parameters, 1, RTL_NUMBER_OF(Parameters));
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -1,4 +1,53 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Windows-Compatible Session Manager
|
||||
* LICENSE: BSD 2-Clause License
|
||||
* FILE: base/system/smss/smss.h
|
||||
* PURPOSE: Main SMSS Header
|
||||
* PROGRAMMERS: Alex Ionescu
|
||||
*/
|
||||
|
||||
/* DEPENDENCIES ***************************************************************/
|
||||
|
||||
//
|
||||
// Native Headers
|
||||
//
|
||||
#define WIN32_NO_STATUS
|
||||
#include <windows.h>
|
||||
#include <windows.h> // Should just be using ntdef.h I think
|
||||
#define RTL_NUMBER_OF_V1(A) (sizeof(A)/sizeof((A)[0]))
|
||||
#define RTL_NUMBER_OF_V2(A) RTL_NUMBER_OF_V1(A)
|
||||
#ifdef ENABLE_RTL_NUMBER_OF_V2
|
||||
#define RTL_NUMBER_OF(A) RTL_NUMBER_OF_V2(A)
|
||||
#else
|
||||
#define RTL_NUMBER_OF(A) RTL_NUMBER_OF_V1(A)
|
||||
#endif
|
||||
#define NTOS_MODE_USER
|
||||
#include <ndk/ntndk.h>
|
||||
|
||||
//
|
||||
// SM Protocol Header
|
||||
//
|
||||
#include "sm/smmsg.h"
|
||||
|
||||
/* DEFINES ********************************************************************/
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SmpInit(
|
||||
IN PUNICODE_STRING InitialCommand,
|
||||
OUT PHANDLE ProcessHandle
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SmpAcquirePrivilege(
|
||||
IN ULONG Privilege,
|
||||
OUT PVOID *PrivilegeStat
|
||||
);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
SmpReleasePrivilege(
|
||||
IN PVOID State
|
||||
);
|
||||
|
|
19
reactos/base/system/smss2/smsubsys.c
Normal file
19
reactos/base/system/smss2/smsubsys.c
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Windows-Compatible Session Manager
|
||||
* LICENSE: BSD 2-Clause License
|
||||
* FILE: base/system/smss/smss.c
|
||||
* PURPOSE: Main SMSS Code
|
||||
* PROGRAMMERS: Alex Ionescu
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "smss.h"
|
||||
#define NDEBUG
|
||||
#include "debug.h"
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
/* EOF */
|
141
reactos/base/system/smss2/smutil.c
Normal file
141
reactos/base/system/smss2/smutil.c
Normal file
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Windows-Compatible Session Manager
|
||||
* LICENSE: BSD 2-Clause License
|
||||
* FILE: base/system/smss/smss.c
|
||||
* PURPOSE: Main SMSS Code
|
||||
* PROGRAMMERS: Alex Ionescu
|
||||
*/
|
||||
|
||||
/* INCLUDES *******************************************************************/
|
||||
|
||||
#include "smss.h"
|
||||
#define NDEBUG
|
||||
#include "debug.h"
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
typedef struct _SMP_PRIVILEGE_STATE
|
||||
{
|
||||
HANDLE TokenHandle;
|
||||
PTOKEN_PRIVILEGES OldPrivileges;
|
||||
PTOKEN_PRIVILEGES NewPrivileges;
|
||||
UCHAR OldBuffer[1024];
|
||||
TOKEN_PRIVILEGES NewBuffer;
|
||||
} SMP_PRIVILEGE_STATE, *PSMP_PRIVILEGE_STATE;
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
SmpAcquirePrivilege(IN ULONG Privilege,
|
||||
OUT PVOID *PrivilegeState)
|
||||
{
|
||||
PSMP_PRIVILEGE_STATE State;
|
||||
ULONG Size;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Assume failure */
|
||||
*PrivilegeState = NULL;
|
||||
|
||||
/* Acquire the state structure to hold everything we need */
|
||||
State = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
sizeof(SMP_PRIVILEGE_STATE) +
|
||||
sizeof(TOKEN_PRIVILEGES) +
|
||||
sizeof(LUID_AND_ATTRIBUTES));
|
||||
if (!State) return STATUS_NO_MEMORY;
|
||||
|
||||
/* Open our token */
|
||||
Status = NtOpenProcessToken(NtCurrentProcess(),
|
||||
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
|
||||
&State->TokenHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Fail */
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, State);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Set one privilege in the enabled state */
|
||||
State->NewPrivileges = &State->NewBuffer;
|
||||
State->OldPrivileges = (PTOKEN_PRIVILEGES)&State->OldBuffer;
|
||||
State->NewPrivileges->PrivilegeCount = 1;
|
||||
State->NewPrivileges->Privileges[0].Luid = RtlConvertUlongToLuid(Privilege);
|
||||
State->NewPrivileges->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
|
||||
/* Adjust the privileges in the token */
|
||||
Size = sizeof(State->OldBuffer);
|
||||
Status = NtAdjustPrivilegesToken(State->TokenHandle,
|
||||
FALSE,
|
||||
State->NewPrivileges,
|
||||
Size,
|
||||
State->OldPrivileges,
|
||||
&Size);
|
||||
if (Status == STATUS_BUFFER_TOO_SMALL)
|
||||
{
|
||||
/* Our static buffer is not big enough, allocate a bigger one */
|
||||
State->OldPrivileges = RtlAllocateHeap(RtlGetProcessHeap(), 0, Size);
|
||||
if (!State->OldPrivileges)
|
||||
{
|
||||
/* Out of memory, fail */
|
||||
Status = STATUS_NO_MEMORY;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Now try again */
|
||||
Status = NtAdjustPrivilegesToken(State->TokenHandle,
|
||||
FALSE,
|
||||
State->NewPrivileges,
|
||||
Size,
|
||||
State->OldPrivileges,
|
||||
&Size);
|
||||
}
|
||||
|
||||
/* Normalize failure code and check for success */
|
||||
if (Status == STATUS_NOT_ALL_ASSIGNED) Status = STATUS_PRIVILEGE_NOT_HELD;
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* We got the privilege, return */
|
||||
*PrivilegeState = State;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
Quickie:
|
||||
/* Check if we used a dynamic buffer */
|
||||
if (State->OldPrivileges != (PTOKEN_PRIVILEGES)&State->OldBuffer)
|
||||
{
|
||||
/* Free it */
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, State->OldPrivileges);
|
||||
}
|
||||
|
||||
/* Close the token handle and free the state structure */
|
||||
NtClose(State->TokenHandle);
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, State);
|
||||
return Status;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
SmpReleasePrivilege(IN PVOID PrivState)
|
||||
{
|
||||
PSMP_PRIVILEGE_STATE State = (PSMP_PRIVILEGE_STATE)PrivState;
|
||||
|
||||
/* Adjust the privileges in the token */
|
||||
NtAdjustPrivilegesToken(State->TokenHandle,
|
||||
FALSE,
|
||||
State->OldPrivileges,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
/* Check if we used a dynamic buffer */
|
||||
if (State->OldPrivileges != (PTOKEN_PRIVILEGES)&State->OldBuffer)
|
||||
{
|
||||
/* Free it */
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, State->OldPrivileges);
|
||||
}
|
||||
|
||||
/* Close the token handle and free the state structure */
|
||||
NtClose(State->TokenHandle);
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, State);
|
||||
}
|
Loading…
Reference in a new issue