From 88cd0f38130e668a2c14f4cdd5fcd7b6c6cf6e30 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Mon, 30 Jan 2012 02:10:39 +0000 Subject: [PATCH] [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 --- reactos/base/system/smss2/CMakeLists.txt | 14 +- reactos/base/system/smss2/crashdmp.c | 17 ++ reactos/base/system/smss2/pagefile.c | 17 ++ reactos/base/system/smss2/sminit.c | 25 +++ reactos/base/system/smss2/smloop.c | 17 ++ reactos/base/system/smss2/smsbapi.c | 17 ++ reactos/base/system/smss2/smsessn.c | 17 ++ reactos/base/system/smss2/smss.c | 260 +++++++++++++++++++---- reactos/base/system/smss2/smss.h | 51 ++++- reactos/base/system/smss2/smsubsys.c | 19 ++ reactos/base/system/smss2/smutil.c | 141 ++++++++++++ 11 files changed, 549 insertions(+), 46 deletions(-) create mode 100644 reactos/base/system/smss2/crashdmp.c create mode 100644 reactos/base/system/smss2/pagefile.c create mode 100644 reactos/base/system/smss2/sminit.c create mode 100644 reactos/base/system/smss2/smloop.c create mode 100644 reactos/base/system/smss2/smsbapi.c create mode 100644 reactos/base/system/smss2/smsessn.c create mode 100644 reactos/base/system/smss2/smsubsys.c create mode 100644 reactos/base/system/smss2/smutil.c diff --git a/reactos/base/system/smss2/CMakeLists.txt b/reactos/base/system/smss2/CMakeLists.txt index 273e5c8c9b6..dfffa88aa0c 100644 --- a/reactos/base/system/smss2/CMakeLists.txt +++ b/reactos/base/system/smss2/CMakeLists.txt @@ -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) diff --git a/reactos/base/system/smss2/crashdmp.c b/reactos/base/system/smss2/crashdmp.c new file mode 100644 index 00000000000..8678afa43b2 --- /dev/null +++ b/reactos/base/system/smss2/crashdmp.c @@ -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 ******************************************************************/ diff --git a/reactos/base/system/smss2/pagefile.c b/reactos/base/system/smss2/pagefile.c new file mode 100644 index 00000000000..8678afa43b2 --- /dev/null +++ b/reactos/base/system/smss2/pagefile.c @@ -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 ******************************************************************/ diff --git a/reactos/base/system/smss2/sminit.c b/reactos/base/system/smss2/sminit.c new file mode 100644 index 00000000000..d0350b9cf22 --- /dev/null +++ b/reactos/base/system/smss2/sminit.c @@ -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; +} diff --git a/reactos/base/system/smss2/smloop.c b/reactos/base/system/smss2/smloop.c new file mode 100644 index 00000000000..8678afa43b2 --- /dev/null +++ b/reactos/base/system/smss2/smloop.c @@ -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 ******************************************************************/ diff --git a/reactos/base/system/smss2/smsbapi.c b/reactos/base/system/smss2/smsbapi.c new file mode 100644 index 00000000000..8678afa43b2 --- /dev/null +++ b/reactos/base/system/smss2/smsbapi.c @@ -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 ******************************************************************/ diff --git a/reactos/base/system/smss2/smsessn.c b/reactos/base/system/smss2/smsessn.c new file mode 100644 index 00000000000..8678afa43b2 --- /dev/null +++ b/reactos/base/system/smss2/smsessn.c @@ -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 ******************************************************************/ diff --git a/reactos/base/system/smss2/smss.c b/reactos/base/system/smss2/smss.c index c880a174c8b..2be1f0c40c6 100644 --- a/reactos/base/system/smss2/smss.c +++ b/reactos/base/system/smss2/smss.c @@ -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 */ diff --git a/reactos/base/system/smss2/smss.h b/reactos/base/system/smss2/smss.h index 9fc8944ded7..61843994bee 100644 --- a/reactos/base/system/smss2/smss.h +++ b/reactos/base/system/smss2/smss.h @@ -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 +#include // 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 + +// +// 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 +); diff --git a/reactos/base/system/smss2/smsubsys.c b/reactos/base/system/smss2/smsubsys.c new file mode 100644 index 00000000000..4ad4fe75429 --- /dev/null +++ b/reactos/base/system/smss2/smsubsys.c @@ -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 */ diff --git a/reactos/base/system/smss2/smutil.c b/reactos/base/system/smss2/smutil.c new file mode 100644 index 00000000000..5d4dfa8ba56 --- /dev/null +++ b/reactos/base/system/smss2/smutil.c @@ -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); +}