157 lines
4.1 KiB
C
157 lines
4.1 KiB
C
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
apcuser.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the machine dependent code necessary to initialize
|
|
a user mode APC.
|
|
|
|
Author:
|
|
|
|
David N. Cutler (davec) 5-May-2000
|
|
|
|
Environment:
|
|
|
|
Kernel mode only, IRQL APC_LEVEL.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "ki.h"
|
|
|
|
VOID
|
|
KiInitializeUserApc (
|
|
IN PKEXCEPTION_FRAME ExceptionFrame,
|
|
IN PKTRAP_FRAME TrapFrame,
|
|
IN PKNORMAL_ROUTINE NormalRoutine,
|
|
IN PVOID NormalContext,
|
|
IN PVOID SystemArgument1,
|
|
IN PVOID SystemArgument2
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called to initialize the context for a user mode APC.
|
|
|
|
Arguments:
|
|
|
|
ExceptionFrame - Supplies a pointer to an exception frame.
|
|
|
|
TrapFrame - Supplies a pointer to a trap frame.
|
|
|
|
NormalRoutine - Supplies a pointer to the user mode APC routine.
|
|
|
|
NormalContext - Supplies a pointer to the user context for the APC
|
|
routine.
|
|
|
|
SystemArgument1 - Supplies the first system supplied value.
|
|
|
|
SystemArgument2 - Supplies the second system supplied value.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
CONTEXT ContextRecord;
|
|
EXCEPTION_RECORD ExceptionRecord;
|
|
PMACHINE_FRAME MachineFrame;
|
|
ULONG64 UserStack;
|
|
|
|
//
|
|
// Move machine state from trap and exception frames to the context frame.
|
|
//
|
|
|
|
ContextRecord.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
|
|
KeContextFromKframes(TrapFrame, ExceptionFrame, &ContextRecord);
|
|
|
|
//
|
|
// Transfer the context information to the user stack, initialize the
|
|
// APC routine parameters, and modify the trap frame so execution will
|
|
// continue in user mode at the user mode APC dispatch routine.
|
|
//
|
|
|
|
try {
|
|
|
|
//
|
|
// Compute address of aligned machine frame, compute address of
|
|
// context record, and probe user stack for writeability.
|
|
//
|
|
|
|
MachineFrame =
|
|
(PMACHINE_FRAME)((ContextRecord.Rsp - sizeof(MACHINE_FRAME)) & ~STACK_ROUND);
|
|
|
|
UserStack = (ULONG64)MachineFrame - CONTEXT_LENGTH;
|
|
ProbeForWriteSmallStructure((PVOID)UserStack,
|
|
sizeof(MACHINE_FRAME) + CONTEXT_LENGTH,
|
|
STACK_ALIGN);
|
|
|
|
//
|
|
// Fill in machine frame information.
|
|
//
|
|
|
|
MachineFrame->Rsp = ContextRecord.Rsp;
|
|
MachineFrame->Rip = ContextRecord.Rip;
|
|
|
|
//
|
|
// Initialize the user APC parameters.
|
|
//
|
|
|
|
ContextRecord.P1Home = (ULONG64)NormalContext;
|
|
ContextRecord.P2Home = (ULONG64)SystemArgument1;
|
|
ContextRecord.P3Home = (ULONG64)SystemArgument2;
|
|
ContextRecord.P4Home = (ULONG64)NormalRoutine;
|
|
|
|
//
|
|
// Copy context record to the user stack.
|
|
//
|
|
|
|
RtlCopyMemory((PVOID)UserStack, &ContextRecord, sizeof(CONTEXT));
|
|
|
|
//
|
|
// Set the address new stack pointer in the current trap frame and
|
|
// the continuation address so control will be transfered to the user
|
|
// APC dispatcher.
|
|
//
|
|
|
|
TrapFrame->Rsp = UserStack;
|
|
TrapFrame->Rip = (ULONG64)KeUserApcDispatcher;
|
|
|
|
} except (KiCopyInformation(&ExceptionRecord,
|
|
(GetExceptionInformation())->ExceptionRecord)) {
|
|
|
|
//
|
|
// Lower the IRQL to PASSIVE_LEVEL, set the exception address to
|
|
// the current program address, and raise an exception by calling
|
|
// the exception dispatcher.
|
|
//
|
|
// N.B. The IRQL is lowered to PASSIVE_LEVEL to allow APC interrupts
|
|
// during the dispatching of the exception. The current thread
|
|
// will be terminated during the dispatching of the exception,
|
|
// but lowering of the IRQL is required to enable the debugger
|
|
// to obtain the context of the current thread.
|
|
//
|
|
|
|
KeLowerIrql(PASSIVE_LEVEL);
|
|
ExceptionRecord.ExceptionAddress = (PVOID)(TrapFrame->Rip);
|
|
KiDispatchException(&ExceptionRecord,
|
|
ExceptionFrame,
|
|
TrapFrame,
|
|
UserMode,
|
|
TRUE);
|
|
}
|
|
|
|
return;
|
|
}
|