https://git.reactos.org/?p=reactos.git;a=commitdiff;h=52d1bb5ec978184473b259e1973a7fa33ab9ba69

commit 52d1bb5ec978184473b259e1973a7fa33ab9ba69
Author:     Timo Kreuzer <[email protected]>
AuthorDate: Sat Feb 10 19:52:46 2018 +0100
Commit:     Timo Kreuzer <[email protected]>
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;
 }

Reply via email to