2018-02-10 17:47:29 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Kernel
|
|
|
|
* LICENSE: GPL - 2.0 + (https ://spdx.org/licenses/GPL-2.0+)
|
|
|
|
* PURPOSE: AMD64 User-mode Callout Mechanisms (APC and Win32K Callbacks)
|
|
|
|
* COPYRIGHT: Timo Kreuzer(timo.kreuzer@reactos.org)
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
|
|
|
|
#include <ntoskrnl.h>
|
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
2018-02-10 18:52:46 +00:00
|
|
|
/*!
|
|
|
|
* \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.
|
|
|
|
*
|
2018-02-10 17:47:29 +00:00
|
|
|
*--*/
|
|
|
|
VOID
|
|
|
|
NTAPI
|
|
|
|
KiInitializeUserApc(
|
|
|
|
_In_ PKEXCEPTION_FRAME ExceptionFrame,
|
|
|
|
_Inout_ PKTRAP_FRAME TrapFrame,
|
|
|
|
_In_ PKNORMAL_ROUTINE NormalRoutine,
|
|
|
|
_In_ PVOID NormalContext,
|
|
|
|
_In_ PVOID SystemArgument1,
|
|
|
|
_In_ PVOID SystemArgument2)
|
|
|
|
{
|
2018-02-10 18:52:46 +00:00
|
|
|
PCONTEXT Context;
|
|
|
|
EXCEPTION_RECORD ExceptionRecord;
|
2018-02-10 17:47:29 +00:00
|
|
|
|
|
|
|
/* Sanity check, that the trap frame is from user mode */
|
|
|
|
ASSERT((TrapFrame->SegCs & MODE_MASK) != KernelMode);
|
|
|
|
|
2018-02-10 18:52:46 +00:00
|
|
|
/* Align the user tack to 16 bytes and allocate space for a CONTEXT structure */
|
|
|
|
Context = (PCONTEXT)ALIGN_DOWN_POINTER_BY(TrapFrame->Rsp, 16) - 1;
|
2018-02-10 17:47:29 +00:00
|
|
|
|
|
|
|
/* Protect with SEH */
|
|
|
|
_SEH2_TRY
|
|
|
|
{
|
2018-02-10 18:52:46 +00:00
|
|
|
/* 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);
|
2018-02-10 17:47:29 +00:00
|
|
|
|
2018-02-10 18:52:46 +00:00
|
|
|
/* Set parameters for KiUserApcDispatcher */
|
|
|
|
Context->P1Home = (ULONG64)NormalContext;
|
|
|
|
Context->P2Home = (ULONG64)SystemArgument1;
|
|
|
|
Context->P3Home = (ULONG64)SystemArgument2;
|
|
|
|
Context->P4Home = (ULONG64)NormalRoutine;
|
2018-02-10 17:47:29 +00:00
|
|
|
}
|
2018-02-10 18:52:46 +00:00
|
|
|
_SEH2_EXCEPT(ExceptionRecord = *_SEH2_GetExceptionInformation()->ExceptionRecord, EXCEPTION_EXECUTE_HANDLER)
|
2018-02-10 17:47:29 +00:00
|
|
|
{
|
|
|
|
/* Dispatch the exception */
|
2018-02-10 18:52:46 +00:00
|
|
|
ExceptionRecord.ExceptionAddress = (PVOID)TrapFrame->Rip;
|
|
|
|
KiDispatchException(&ExceptionRecord,
|
2018-02-10 17:47:29 +00:00
|
|
|
ExceptionFrame,
|
|
|
|
TrapFrame,
|
|
|
|
UserMode,
|
|
|
|
TRUE);
|
|
|
|
}
|
|
|
|
_SEH2_END;
|
2018-02-10 18:52:46 +00:00
|
|
|
|
|
|
|
/* 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;
|
2018-02-10 17:47:29 +00:00
|
|
|
}
|