https://git.reactos.org/?p=reactos.git;a=commitdiff;h=52d1bb5ec978184473b259...
commit 52d1bb5ec978184473b259e1973a7fa33ab9ba69 Author: Timo Kreuzer timo.kreuzer@reactos.org AuthorDate: Sat Feb 10 19:52:46 2018 +0100 Commit: Timo Kreuzer timo.kreuzer@reactos.org CommitDate: Sat Oct 31 14:23:16 2020 +0100
[NTOS:KE:X64] Simplify KiInitializeUserApc --- ntoskrnl/ke/amd64/usercall.c | 136 +++++++++++++++++++++---------------------- 1 file changed, 65 insertions(+), 71 deletions(-)
diff --git a/ntoskrnl/ke/amd64/usercall.c b/ntoskrnl/ke/amd64/usercall.c index 61861d521b7..38517cb58fc 100644 --- a/ntoskrnl/ke/amd64/usercall.c +++ b/ntoskrnl/ke/amd64/usercall.c @@ -11,32 +11,37 @@ #define NDEBUG #include <debug.h>
-/*! \name KiInitializeUserApc -* -* \brief -* Prepares the current trap frame (which must have come from user mode) -* with the ntdll.KiUserApcDispatcher entrypoint, copying a CONTEXT -* record with the context from the old trap frame to the threads user -* mode stack. -* -* \param ExceptionFrame -* \param TrapFrame -* \param NormalRoutine -* \param NormalContext -* \param SystemArgument1 -* \param SystemArgument2 -* -* \remarks -* This function is called from KiDeliverApc, when the trap frame came -* from user mode. This happens before a systemcall or interrupt exits back -* to usermode or when a thread is started from PspUserThreadstartup. -* The trap exit code will then leave to KiUserApcDispatcher which in turn -* calls the NormalRoutine, passing NormalContext, SystemArgument1 and -* SystemArgument2 as parameters. When that function returns, it calls -* NtContinue to return back to the kernel, where the old context that was -* saved on the usermode stack is restored and execution is transferred -* back to usermode, where the original trap originated from. -* +/*! + * \name KiInitializeUserApc + * + * \brief + * Prepares the current trap frame (which must have come from user mode) + * with the ntdll.KiUserApcDispatcher entrypoint, copying a CONTEXT + * record with the context from the old trap frame to the threads user + * mode stack. + * + * \param ExceptionFrame - Pointer to the Exception Frame + * + * \param TrapFrame Pointer to the Trap Frame. + * + * \param NormalRoutine - Pointer to the NormalRoutine to call. + * + * \param NormalContext - Pointer to the context to send to the Normal Routine. + * + * \param SystemArgument[1-2] + * Pointer to a set of two parameters that contain untyped data. + * + * \remarks + * This function is called from KiDeliverApc, when the trap frame came + * from user mode. This happens before a systemcall or interrupt exits back + * to usermode or when a thread is started from PspUserThreadstartup. + * The trap exit code will then leave to KiUserApcDispatcher which in turn + * calls the NormalRoutine, passing NormalContext, SystemArgument1 and + * SystemArgument2 as parameters. When that function returns, it calls + * NtContinue to return back to the kernel, where the old context that was + * saved on the usermode stack is restored and execution is transferred + * back to usermode, where the original trap originated from. + * *--*/ VOID NTAPI @@ -48,67 +53,56 @@ KiInitializeUserApc( _In_ PVOID SystemArgument1, _In_ PVOID SystemArgument2) { - CONTEXT Context; - ULONG64 AlignedRsp, Stack; - EXCEPTION_RECORD SehExceptRecord; + PCONTEXT Context; + EXCEPTION_RECORD ExceptionRecord;
/* Sanity check, that the trap frame is from user mode */ ASSERT((TrapFrame->SegCs & MODE_MASK) != KernelMode);
- /* Convert the current trap frame to a context */ - Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; - KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context); - - /* We jump to KiUserApcDispatcher in ntdll */ - TrapFrame->Rip = (ULONG64)KeUserApcDispatcher; - - /* Setup Ring 3 segments */ - TrapFrame->SegCs = KGDT64_R3_CODE | RPL_MASK; - TrapFrame->SegDs = KGDT64_R3_DATA | RPL_MASK; - TrapFrame->SegEs = KGDT64_R3_DATA | RPL_MASK; - TrapFrame->SegFs = KGDT64_R3_CMTEB | RPL_MASK; - TrapFrame->SegGs = KGDT64_R3_DATA | RPL_MASK; - TrapFrame->SegSs = KGDT64_R3_DATA | RPL_MASK; - - /* Sanitize EFLAGS, enable interrupts */ - TrapFrame->EFlags = (Context.EFlags & EFLAGS_USER_SANITIZE); - TrapFrame->EFlags |= EFLAGS_INTERRUPT_MASK; - - /* Set parameters for KiUserApcDispatcher */ - Context.P1Home = (ULONG64)NormalContext; - Context.P2Home = (ULONG64)SystemArgument1; - Context.P3Home = (ULONG64)SystemArgument2; - Context.P4Home = (ULONG64)NormalRoutine; - - /* Check if thread has IOPL and force it enabled if so */ - //if (KeGetCurrentThread()->Iopl) TrapFrame->EFlags |= EFLAGS_IOPL; - - /* Align Stack to 16 bytes and allocate space */ - AlignedRsp = Context.Rsp & ~15; - Stack = AlignedRsp - sizeof(CONTEXT); - TrapFrame->Rsp = Stack; - - /* The stack must be 16 byte aligned for KiUserApcDispatcher */ - ASSERT((Stack & 15) == 0); + /* Align the user tack to 16 bytes and allocate space for a CONTEXT structure */ + Context = (PCONTEXT)ALIGN_DOWN_POINTER_BY(TrapFrame->Rsp, 16) - 1;
/* Protect with SEH */ _SEH2_TRY { - /* Probe the stack */ - ProbeForWrite((PCONTEXT)Stack, sizeof(CONTEXT), 8); + /* Probe the context */ + ProbeForWrite(Context, sizeof(CONTEXT), 16); + + /* Convert the current trap frame to a context */ + Context->ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; + KeTrapFrameToContext(TrapFrame, ExceptionFrame, Context);
- /* Copy the context */ - RtlCopyMemory((PCONTEXT)Stack, &Context, sizeof(CONTEXT)); + /* Set parameters for KiUserApcDispatcher */ + Context->P1Home = (ULONG64)NormalContext; + Context->P2Home = (ULONG64)SystemArgument1; + Context->P3Home = (ULONG64)SystemArgument2; + Context->P4Home = (ULONG64)NormalRoutine; } - _SEH2_EXCEPT((RtlCopyMemory(&SehExceptRecord, _SEH2_GetExceptionInformation()->ExceptionRecord, sizeof(EXCEPTION_RECORD)), EXCEPTION_EXECUTE_HANDLER)) + _SEH2_EXCEPT(ExceptionRecord = *_SEH2_GetExceptionInformation()->ExceptionRecord, EXCEPTION_EXECUTE_HANDLER) { /* Dispatch the exception */ - SehExceptRecord.ExceptionAddress = (PVOID)TrapFrame->Rip; - KiDispatchException(&SehExceptRecord, + ExceptionRecord.ExceptionAddress = (PVOID)TrapFrame->Rip; + KiDispatchException(&ExceptionRecord, ExceptionFrame, TrapFrame, UserMode, TRUE); } _SEH2_END; + + /* Set the stack pointer to the context record */ + TrapFrame->Rsp = (ULONG64)Context; + + /* We jump to KiUserApcDispatcher in ntdll */ + TrapFrame->Rip = (ULONG64)KeUserApcDispatcher; + + /* Setup Ring 3 segments */ + TrapFrame->SegCs = KGDT64_R3_CODE | RPL_MASK; + TrapFrame->SegFs = KGDT64_R3_CMTEB | RPL_MASK; + TrapFrame->SegGs = KGDT64_R3_DATA | RPL_MASK; + TrapFrame->SegSs = KGDT64_R3_DATA | RPL_MASK; + + /* Sanitize EFLAGS, enable interrupts */ + TrapFrame->EFlags &= EFLAGS_USER_SANITIZE; + TrapFrame->EFlags |= EFLAGS_INTERRUPT_MASK; }