windows-nt/Source/XPSP1/NT/base/ntos/ke/alpha/apcuser.c
2020-09-26 16:20:57 +08:00

149 lines
3.8 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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;
}