149 lines
3.8 KiB
C
149 lines
3.8 KiB
C
/*++
|
||
|
||
Copyright (c) 1990 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) 23-Apr-1990
|
||
|
||
Environment:
|
||
|
||
Kernel mode only, IRQL APC_LEVEL.
|
||
|
||
Revision History:
|
||
|
||
Thomas Van Baak (tvb) 13-May-1992
|
||
|
||
Adapted for Alpha AXP.
|
||
|
||
--*/
|
||
|
||
#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;
|
||
LONG_PTR Length;
|
||
ULONG_PTR UserStack;
|
||
|
||
//
|
||
// Move the user mode state from the trap and exception frames to the
|
||
// context frame.
|
||
//
|
||
|
||
ContextRecord.ContextFlags = CONTEXT_FULL;
|
||
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 length of context record and new aligned user stack pointer.
|
||
//
|
||
|
||
Length = (sizeof(CONTEXT) + 15) & (~15);
|
||
UserStack = ((ULONG_PTR)ContextRecord.IntSp & (~15)) - Length;
|
||
|
||
//
|
||
// Probe user stack area for writeability and then transfer the
|
||
// context record to the user stack.
|
||
//
|
||
|
||
ProbeForWrite((PVOID)UserStack, (ULONG)Length, sizeof(QUAD));
|
||
RtlMoveMemory((PVOID)UserStack, &ContextRecord, sizeof(CONTEXT));
|
||
|
||
//
|
||
// Set the address of the user APC routine, the APC parameters, the
|
||
// new frame pointer, and the new stack pointer in the current trap
|
||
// frame. Set the continuation address so control will be transferred
|
||
// to the user APC dispatcher.
|
||
//
|
||
// N.B. It is not possible to pass 64 bit arguments to the routine.
|
||
// N.B. ULONG becomes canonical longword with (ULONGLONG)(LONG) cast.
|
||
//
|
||
//
|
||
|
||
TrapFrame->IntSp = (ULONGLONG)(LONG_PTR)UserStack;
|
||
TrapFrame->IntFp = (ULONGLONG)(LONG_PTR)UserStack;
|
||
TrapFrame->IntA0 = (ULONGLONG)(LONG_PTR)NormalContext;
|
||
TrapFrame->IntA1 = (ULONGLONG)(LONG_PTR)SystemArgument1;
|
||
TrapFrame->IntA2 = (ULONGLONG)(LONG_PTR)SystemArgument2;
|
||
TrapFrame->IntA3 = (ULONGLONG)(LONG_PTR)NormalRoutine;
|
||
TrapFrame->Fir = (ULONGLONG)(LONG_PTR)KeUserApcDispatcher;
|
||
|
||
//
|
||
// If an exception occurs, then copy the exception information to an
|
||
// exception record and handle the exception.
|
||
//
|
||
|
||
} except (KiCopyInformation(&ExceptionRecord,
|
||
(GetExceptionInformation())->ExceptionRecord)) {
|
||
|
||
//
|
||
// Set the address of the exception to the current program address
|
||
// and raise the exception by calling the exception dispatcher.
|
||
//
|
||
|
||
ExceptionRecord.ExceptionAddress = (PVOID)(TrapFrame->Fir);
|
||
KiDispatchException(&ExceptionRecord,
|
||
ExceptionFrame,
|
||
TrapFrame,
|
||
UserMode,
|
||
TRUE);
|
||
}
|
||
|
||
return;
|
||
}
|