602 lines
19 KiB
C
602 lines
19 KiB
C
/*++
|
|
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
psctxmip.c
|
|
|
|
Abstract:
|
|
|
|
This module implements function to get and set the context of a thread.
|
|
|
|
Author:
|
|
|
|
David N. Cutler (davec) 1-Oct-1990
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "psp.h"
|
|
|
|
ULONGLONG
|
|
PspGetSavedValue (
|
|
IN PVOID ContextPointer
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function loads the context value specified by the argument
|
|
pointer.
|
|
|
|
N.B. The low bit of the pointer specifies the operand type.
|
|
|
|
Arguments:
|
|
|
|
ContextPointer - Supplies a pointer to the context value that is
|
|
loaded.
|
|
|
|
Return Value:
|
|
|
|
The value specified by the argument pointer.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
|
|
// If the low bit of the argument pointer is zero, then the argument
|
|
// value is 32-bits. Otherwise, the argument value is 64-bits.
|
|
|
|
|
|
if (((ULONG)ContextPointer & 1) != 0) {
|
|
return *((PULONGLONG)((ULONG)ContextPointer & ~1));
|
|
|
|
} else {
|
|
return *((PLONG)ContextPointer);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
PspSetSavedValue (
|
|
IN ULONGLONG ContextValue,
|
|
IN PVOID ContextPointer
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function stores the context value specified in the location
|
|
specified by the argument pointer.
|
|
|
|
N.B. The low bit of the pointer specifies the operand type.
|
|
|
|
Arguments:
|
|
|
|
ContextValue - Supplies the context value to be stored.
|
|
|
|
ContextPointer - Supplies a pointer to the context value that is
|
|
stored.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
|
|
// If the low bit of the argument pointer is zero, then the argument
|
|
// value is 32-bits. Otherwise, the argument value is 64-bits.
|
|
|
|
|
|
if (((ULONG)ContextPointer & 1) != 0) {
|
|
*((PULONGLONG)((ULONG)ContextPointer & ~1)) = ContextValue;
|
|
|
|
} else {
|
|
*((PULONG)ContextPointer) = (ULONG)ContextValue;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
PspGetContext (
|
|
IN PKTRAP_FRAME TrapFrame,
|
|
IN PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
|
|
IN OUT PCONTEXT ContextRecord
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function selectively moves the contents of the specified trap frame
|
|
and nonvolatile context to the specified context record.
|
|
|
|
Arguments:
|
|
|
|
TrapFrame - Supplies a pointer to a trap frame.
|
|
|
|
ContextPointers - Supplies the address of context pointers record.
|
|
|
|
ContextRecord - Supplies the address of a context record.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG ContextFlags;
|
|
LONG Index;
|
|
|
|
|
|
// Get context.
|
|
|
|
|
|
ContextFlags = ContextRecord->ContextFlags;
|
|
if ((ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
|
|
|
|
|
|
// Get integer registers gp, sp, ra, FIR, and PSR.
|
|
|
|
|
|
ContextRecord->Fir = TrapFrame->Fir;
|
|
ContextRecord->Psr = TrapFrame->Psr;
|
|
if ((ContextFlags & CONTEXT_EXTENDED_INTEGER) != CONTEXT_EXTENDED_INTEGER) {
|
|
ContextRecord->IntGp = (ULONG)TrapFrame->XIntGp;
|
|
ContextRecord->IntSp = (ULONG)TrapFrame->XIntSp;
|
|
ContextRecord->IntRa = (ULONG)TrapFrame->XIntRa;
|
|
|
|
} else {
|
|
ContextRecord->XIntGp = TrapFrame->XIntGp;
|
|
ContextRecord->XIntSp = TrapFrame->XIntSp;
|
|
ContextRecord->XIntRa = TrapFrame->XIntRa;
|
|
}
|
|
}
|
|
|
|
if ((ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
|
|
|
|
|
|
// Get integer registers zero, and, at - t9, k0, k1, lo, and hi.
|
|
|
|
|
|
if ((ContextFlags & CONTEXT_EXTENDED_INTEGER) != CONTEXT_EXTENDED_INTEGER) {
|
|
ContextRecord->IntZero = 0;
|
|
ContextRecord->IntAt = (ULONG)TrapFrame->XIntAt;
|
|
ContextRecord->IntV0 = (ULONG)TrapFrame->XIntV0;
|
|
ContextRecord->IntV1 = (ULONG)TrapFrame->XIntV1;
|
|
ContextRecord->IntA0 = (ULONG)TrapFrame->XIntA0;
|
|
ContextRecord->IntA1 = (ULONG)TrapFrame->XIntA1;
|
|
ContextRecord->IntA2 = (ULONG)TrapFrame->XIntA2;
|
|
ContextRecord->IntA3 = (ULONG)TrapFrame->XIntA3;
|
|
ContextRecord->IntT0 = (ULONG)TrapFrame->XIntT0;
|
|
ContextRecord->IntT1 = (ULONG)TrapFrame->XIntT1;
|
|
ContextRecord->IntT2 = (ULONG)TrapFrame->XIntT2;
|
|
ContextRecord->IntT3 = (ULONG)TrapFrame->XIntT3;
|
|
ContextRecord->IntT4 = (ULONG)TrapFrame->XIntT4;
|
|
ContextRecord->IntT5 = (ULONG)TrapFrame->XIntT5;
|
|
ContextRecord->IntT6 = (ULONG)TrapFrame->XIntT6;
|
|
ContextRecord->IntT7 = (ULONG)TrapFrame->XIntT7;
|
|
ContextRecord->IntT8 = (ULONG)TrapFrame->XIntT8;
|
|
ContextRecord->IntT9 = (ULONG)TrapFrame->XIntT9;
|
|
ContextRecord->IntK0 = 0;
|
|
ContextRecord->IntK1 = 0;
|
|
ContextRecord->IntLo = (ULONG)TrapFrame->XIntLo;
|
|
ContextRecord->IntHi = (ULONG)TrapFrame->XIntHi;
|
|
|
|
} else {
|
|
ContextRecord->XIntZero = 0;
|
|
ContextRecord->XIntAt = TrapFrame->XIntAt;
|
|
ContextRecord->XIntV0 = TrapFrame->XIntV0;
|
|
ContextRecord->XIntV1 = TrapFrame->XIntV1;
|
|
ContextRecord->XIntA0 = TrapFrame->XIntA0;
|
|
ContextRecord->XIntA1 = TrapFrame->XIntA1;
|
|
ContextRecord->XIntA2 = TrapFrame->XIntA2;
|
|
ContextRecord->XIntA3 = TrapFrame->XIntA3;
|
|
ContextRecord->XIntT0 = TrapFrame->XIntT0;
|
|
ContextRecord->XIntT1 = TrapFrame->XIntT1;
|
|
ContextRecord->XIntT2 = TrapFrame->XIntT2;
|
|
ContextRecord->XIntT3 = TrapFrame->XIntT3;
|
|
ContextRecord->XIntT4 = TrapFrame->XIntT4;
|
|
ContextRecord->XIntT5 = TrapFrame->XIntT5;
|
|
ContextRecord->XIntT6 = TrapFrame->XIntT6;
|
|
ContextRecord->XIntT7 = TrapFrame->XIntT7;
|
|
ContextRecord->XIntT8 = TrapFrame->XIntT8;
|
|
ContextRecord->XIntT9 = TrapFrame->XIntT9;
|
|
ContextRecord->XIntK0 = 0;
|
|
ContextRecord->XIntK1 = 0;
|
|
ContextRecord->XIntLo = TrapFrame->XIntLo;
|
|
ContextRecord->XIntHi = TrapFrame->XIntHi;
|
|
}
|
|
|
|
|
|
// Get nonvolatile integer registers s0 - s7, and s8.
|
|
|
|
|
|
if ((ContextFlags & CONTEXT_EXTENDED_INTEGER) != CONTEXT_EXTENDED_INTEGER) {
|
|
Index = 7;
|
|
do {
|
|
if (TrapFrame->SavedFlag == 0) {
|
|
(&ContextRecord->IntS0)[Index] =
|
|
(ULONG)PspGetSavedValue((&ContextPointers->XIntS0)[Index]);
|
|
|
|
} else {
|
|
(&ContextRecord->IntS0)[Index] = (ULONG)(&TrapFrame->XIntS0)[Index];
|
|
}
|
|
|
|
Index -= 1;
|
|
} while (Index >= 0);
|
|
ContextRecord->IntS8 = (ULONG)TrapFrame->XIntS8;
|
|
|
|
} else {
|
|
Index = 7;
|
|
do {
|
|
if (TrapFrame->SavedFlag == 0) {
|
|
(&ContextRecord->XIntS0)[Index] =
|
|
PspGetSavedValue((&ContextPointers->XIntS0)[Index]);
|
|
|
|
} else {
|
|
(&ContextRecord->XIntS0)[Index] = (&TrapFrame->XIntS0)[Index];
|
|
}
|
|
|
|
Index -= 1;
|
|
} while (Index >= 0);
|
|
ContextRecord->XIntS8 = TrapFrame->XIntS8;
|
|
}
|
|
}
|
|
|
|
if ((ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) {
|
|
|
|
|
|
// Get volatile floating registers f0 - f19.
|
|
|
|
|
|
RtlMoveMemory(&ContextRecord->FltF0, &TrapFrame->FltF0,
|
|
sizeof(ULONG) * (20));
|
|
|
|
|
|
// Get nonvolatile floating registers f20 - f31.
|
|
|
|
|
|
ContextRecord->FltF20 = *ContextPointers->FltF20;
|
|
ContextRecord->FltF21 = *ContextPointers->FltF21;
|
|
ContextRecord->FltF22 = *ContextPointers->FltF22;
|
|
ContextRecord->FltF23 = *ContextPointers->FltF23;
|
|
ContextRecord->FltF24 = *ContextPointers->FltF24;
|
|
ContextRecord->FltF25 = *ContextPointers->FltF25;
|
|
ContextRecord->FltF26 = *ContextPointers->FltF26;
|
|
ContextRecord->FltF27 = *ContextPointers->FltF27;
|
|
ContextRecord->FltF28 = *ContextPointers->FltF28;
|
|
ContextRecord->FltF29 = *ContextPointers->FltF29;
|
|
ContextRecord->FltF30 = *ContextPointers->FltF30;
|
|
ContextRecord->FltF31 = *ContextPointers->FltF31;
|
|
|
|
|
|
// Get floating status register.
|
|
|
|
|
|
ContextRecord->Fsr = TrapFrame->Fsr;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
PspSetContext (
|
|
IN OUT PKTRAP_FRAME TrapFrame,
|
|
IN PKNONVOLATILE_CONTEXT_POINTERS ContextPointers,
|
|
IN PCONTEXT ContextRecord,
|
|
IN KPROCESSOR_MODE ProcessorMode
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function selectively moves the contents of the specified context
|
|
record to the specified trap frame and nonvolatile context.
|
|
|
|
Arguments:
|
|
|
|
TrapFrame - Supplies the address of a trap frame.
|
|
|
|
ContextPointers - Supplies the address of a context pointers record.
|
|
|
|
ContextRecord - Supplies the address of a context record.
|
|
|
|
ProcessorMode - Supplies the processor mode to use when sanitizing
|
|
the PSR and FSR.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
ULONG ContextFlags;
|
|
LONG Index;
|
|
|
|
|
|
// Set context.
|
|
|
|
|
|
ContextFlags = ContextRecord->ContextFlags;
|
|
if ((ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
|
|
|
|
|
|
// Set integer registers gp, sp, ra, FIR, and PSR.
|
|
|
|
|
|
TrapFrame->Fir = ContextRecord->Fir;
|
|
TrapFrame->Psr = SANITIZE_PSR(ContextRecord->Psr, ProcessorMode);
|
|
if ((ContextFlags & CONTEXT_EXTENDED_INTEGER) != CONTEXT_EXTENDED_INTEGER) {
|
|
TrapFrame->XIntGp = (LONG)ContextRecord->IntGp;
|
|
TrapFrame->XIntSp = (LONG)ContextRecord->IntSp;
|
|
TrapFrame->XIntRa = (LONG)ContextRecord->IntRa;
|
|
|
|
} else {
|
|
TrapFrame->XIntGp = ContextRecord->XIntGp;
|
|
TrapFrame->XIntSp = ContextRecord->XIntSp;
|
|
TrapFrame->XIntRa = ContextRecord->XIntRa;
|
|
}
|
|
}
|
|
|
|
if ((ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
|
|
|
|
|
|
// Set integer registers at - t9, lo, and hi.
|
|
|
|
|
|
if ((ContextFlags & CONTEXT_EXTENDED_INTEGER) != CONTEXT_EXTENDED_INTEGER) {
|
|
TrapFrame->XIntAt = (LONG)ContextRecord->IntAt;
|
|
TrapFrame->XIntV0 = (LONG)ContextRecord->IntV0;
|
|
TrapFrame->XIntV1 = (LONG)ContextRecord->IntV1;
|
|
TrapFrame->XIntA0 = (LONG)ContextRecord->IntA0;
|
|
TrapFrame->XIntA1 = (LONG)ContextRecord->IntA1;
|
|
TrapFrame->XIntA2 = (LONG)ContextRecord->IntA2;
|
|
TrapFrame->XIntA3 = (LONG)ContextRecord->IntA3;
|
|
TrapFrame->XIntT0 = (LONG)ContextRecord->IntT0;
|
|
TrapFrame->XIntT1 = (LONG)ContextRecord->IntT1;
|
|
TrapFrame->XIntT2 = (LONG)ContextRecord->IntT2;
|
|
TrapFrame->XIntT3 = (LONG)ContextRecord->IntT3;
|
|
TrapFrame->XIntT4 = (LONG)ContextRecord->IntT4;
|
|
TrapFrame->XIntT5 = (LONG)ContextRecord->IntT5;
|
|
TrapFrame->XIntT6 = (LONG)ContextRecord->IntT6;
|
|
TrapFrame->XIntT7 = (LONG)ContextRecord->IntT7;
|
|
TrapFrame->XIntT8 = (LONG)ContextRecord->IntT8;
|
|
TrapFrame->XIntT9 = (LONG)ContextRecord->IntT9;
|
|
TrapFrame->XIntLo = (LONG)ContextRecord->IntLo;
|
|
TrapFrame->XIntHi = (LONG)ContextRecord->IntHi;
|
|
|
|
} else {
|
|
TrapFrame->XIntAt = ContextRecord->XIntAt;
|
|
TrapFrame->XIntV0 = ContextRecord->XIntV0;
|
|
TrapFrame->XIntV1 = ContextRecord->XIntV1;
|
|
TrapFrame->XIntA0 = ContextRecord->XIntA0;
|
|
TrapFrame->XIntA1 = ContextRecord->XIntA1;
|
|
TrapFrame->XIntA2 = ContextRecord->XIntA2;
|
|
TrapFrame->XIntA3 = ContextRecord->XIntA3;
|
|
TrapFrame->XIntT0 = ContextRecord->XIntT0;
|
|
TrapFrame->XIntT1 = ContextRecord->XIntT1;
|
|
TrapFrame->XIntT2 = ContextRecord->XIntT2;
|
|
TrapFrame->XIntT3 = ContextRecord->XIntT3;
|
|
TrapFrame->XIntT4 = ContextRecord->XIntT4;
|
|
TrapFrame->XIntT5 = ContextRecord->XIntT5;
|
|
TrapFrame->XIntT6 = ContextRecord->XIntT6;
|
|
TrapFrame->XIntT7 = ContextRecord->XIntT7;
|
|
TrapFrame->XIntT8 = ContextRecord->XIntT8;
|
|
TrapFrame->XIntT9 = ContextRecord->XIntT9;
|
|
TrapFrame->XIntLo = ContextRecord->XIntLo;
|
|
TrapFrame->XIntHi = ContextRecord->XIntHi;
|
|
}
|
|
|
|
|
|
// Set nonvolatile integer registers s0 - s7, and s8.
|
|
|
|
|
|
if ((ContextFlags & CONTEXT_EXTENDED_INTEGER) != CONTEXT_EXTENDED_INTEGER) {
|
|
Index = 7;
|
|
do {
|
|
if (TrapFrame->SavedFlag == 0) {
|
|
PspSetSavedValue((LONG)(&ContextRecord->IntS0)[Index],
|
|
(&ContextPointers->XIntS0)[Index]);
|
|
|
|
} else {
|
|
(&TrapFrame->XIntS0)[Index] = (LONG)(&ContextRecord->IntS0)[Index];
|
|
}
|
|
|
|
Index -= 1;
|
|
} while (Index >= 0);
|
|
TrapFrame->XIntS8 = (LONG)ContextRecord->IntS8;
|
|
|
|
} else {
|
|
Index = 7;
|
|
do {
|
|
if (TrapFrame->SavedFlag == 0) {
|
|
PspSetSavedValue((&ContextRecord->XIntS0)[Index],
|
|
(&ContextPointers->XIntS0)[Index]);
|
|
|
|
} else {
|
|
(&TrapFrame->XIntS0)[Index] = (&ContextRecord->XIntS0)[Index];
|
|
}
|
|
|
|
Index -= 1;
|
|
} while (Index >= 0);
|
|
TrapFrame->XIntS8 = ContextRecord->XIntS8;
|
|
}
|
|
}
|
|
|
|
if ((ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) {
|
|
|
|
|
|
// Set volatile floating registers f0 - f19.
|
|
|
|
|
|
RtlMoveMemory(&TrapFrame->FltF0, &ContextRecord->FltF0,
|
|
sizeof(ULONG) * (20));
|
|
|
|
|
|
// Set nonvolatile floating registers f20 - f31.
|
|
|
|
|
|
*ContextPointers->FltF20 = ContextRecord->FltF20;
|
|
*ContextPointers->FltF21 = ContextRecord->FltF21;
|
|
*ContextPointers->FltF22 = ContextRecord->FltF22;
|
|
*ContextPointers->FltF23 = ContextRecord->FltF23;
|
|
*ContextPointers->FltF24 = ContextRecord->FltF24;
|
|
*ContextPointers->FltF25 = ContextRecord->FltF25;
|
|
*ContextPointers->FltF26 = ContextRecord->FltF26;
|
|
*ContextPointers->FltF27 = ContextRecord->FltF27;
|
|
*ContextPointers->FltF28 = ContextRecord->FltF28;
|
|
*ContextPointers->FltF29 = ContextRecord->FltF29;
|
|
*ContextPointers->FltF30 = ContextRecord->FltF30;
|
|
*ContextPointers->FltF31 = ContextRecord->FltF31;
|
|
|
|
|
|
// Set floating status register.
|
|
|
|
|
|
TrapFrame->Fsr = SANITIZE_FSR(ContextRecord->Fsr, ProcessorMode);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
PspGetSetContextSpecialApc (
|
|
IN PKAPC Apc,
|
|
IN PKNORMAL_ROUTINE *NormalRoutine,
|
|
IN PVOID *NormalContext,
|
|
IN PVOID *SystemArgument1,
|
|
IN PVOID *SystemArgument2
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function either captures the user mode state of the current
|
|
thread, or sets the user mode state of the current thread. The
|
|
operation type is determined by the value of SystemArgument1. A
|
|
zero value is used for get context, and a nonzero value is used
|
|
for set context.
|
|
|
|
Arguments:
|
|
|
|
Apc - Supplies a pointer to the APC control object that caused entry
|
|
into this routine.
|
|
|
|
NormalRoutine - Supplies a pointer to the normal routine function that
|
|
was specified when the APC was initialized. This parameter is not
|
|
used.
|
|
|
|
NormalContext - Supplies a pointer to an arbitrary data structure that
|
|
was specified when the APC was initialized. This parameter is not
|
|
used.
|
|
|
|
SystemArgument1, SystemArgument2 - Supplies a set of two pointer to two
|
|
arguments that contain untyped data. These parameters are not used.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PGETSETCONTEXT ContextBlock;
|
|
KNONVOLATILE_CONTEXT_POINTERS ContextPointers;
|
|
CONTEXT ContextRecord;
|
|
ULONG ControlPc;
|
|
ULONG EstablisherFrame;
|
|
PRUNTIME_FUNCTION FunctionEntry;
|
|
BOOLEAN InFunction;
|
|
PETHREAD Thread;
|
|
ULONG TrapFrame1;
|
|
ULONG TrapFrame2;
|
|
|
|
|
|
// Get the address of the context block and compute the address of the
|
|
// system entry trap frame.
|
|
|
|
|
|
ContextBlock = CONTAINING_RECORD(Apc, GETSETCONTEXT, Apc);
|
|
Thread = PsGetCurrentThread();
|
|
TrapFrame1 = (ULONG)Thread->Tcb.InitialStack - KTRAP_FRAME_LENGTH;
|
|
TrapFrame2 = (ULONG)Thread->Tcb.InitialStack - KTRAP_FRAME_LENGTH - KTRAP_FRAME_ARGUMENTS;
|
|
|
|
|
|
// Capture the current thread context and set the initial control PC
|
|
// value.
|
|
|
|
|
|
RtlCaptureContext(&ContextRecord);
|
|
ControlPc = (ULONG)ContextRecord.XIntRa;
|
|
|
|
|
|
// Initialize context pointers for the nonvolatile integer and floating
|
|
// registers.
|
|
|
|
|
|
ContextPointers.XIntS0 = &ContextRecord.XIntS0;
|
|
ContextPointers.XIntS1 = &ContextRecord.XIntS1;
|
|
ContextPointers.XIntS2 = &ContextRecord.XIntS2;
|
|
ContextPointers.XIntS3 = &ContextRecord.XIntS3;
|
|
ContextPointers.XIntS4 = &ContextRecord.XIntS4;
|
|
ContextPointers.XIntS5 = &ContextRecord.XIntS5;
|
|
ContextPointers.XIntS6 = &ContextRecord.XIntS6;
|
|
ContextPointers.XIntS7 = &ContextRecord.XIntS7;
|
|
|
|
ContextPointers.FltF20 = &ContextRecord.FltF20;
|
|
ContextPointers.FltF21 = &ContextRecord.FltF21;
|
|
ContextPointers.FltF22 = &ContextRecord.FltF22;
|
|
ContextPointers.FltF23 = &ContextRecord.FltF23;
|
|
ContextPointers.FltF24 = &ContextRecord.FltF24;
|
|
ContextPointers.FltF25 = &ContextRecord.FltF25;
|
|
ContextPointers.FltF26 = &ContextRecord.FltF26;
|
|
ContextPointers.FltF27 = &ContextRecord.FltF27;
|
|
ContextPointers.FltF28 = &ContextRecord.FltF28;
|
|
ContextPointers.FltF29 = &ContextRecord.FltF29;
|
|
ContextPointers.FltF30 = &ContextRecord.FltF30;
|
|
ContextPointers.FltF31 = &ContextRecord.FltF31;
|
|
|
|
// Start with the frame specified by the context record and virtually
|
|
// unwind call frames until the system entry trap frame is encountered.
|
|
|
|
do {
|
|
// Lookup the function table entry using the point at which control left the procedure.
|
|
FunctionEntry = RtlLookupFunctionEntry(ControlPc);
|
|
|
|
// If there is a function table entry for the routine, then virtually
|
|
// unwind to the caller of the current routine to obtain the address
|
|
// where control left the caller. Otherwise, the function is a leaf
|
|
// function and the return address register contains the address of where control left the caller.
|
|
if (FunctionEntry != NULL) {
|
|
ControlPc = RtlVirtualUnwind(ControlPc | 1, FunctionEntry, &ContextRecord, &InFunction, &EstablisherFrame, &ContextPointers);
|
|
} else {
|
|
ControlPc = (ULONG)ContextRecord.XIntRa;
|
|
}
|
|
} while (((ULONG)ContextRecord.XIntSp != TrapFrame1) && (((ULONG)ContextRecord.XIntSp != TrapFrame2) || (ControlPc < PCR->SystemServiceDispatchStart) || (ControlPc >= PCR->SystemServiceDispatchEnd)));
|
|
|
|
// If system argument one is nonzero, then set the context of the current thread. Otherwise, get the context of the current thread.
|
|
if (Apc->SystemArgument1 != 0) {
|
|
// Set context of current thread.
|
|
PspSetContext((PKTRAP_FRAME)TrapFrame1, &ContextPointers, &ContextBlock->Context, ContextBlock->Mode);
|
|
} else {
|
|
// Get context of current thread.
|
|
PspGetContext((PKTRAP_FRAME)TrapFrame1, &ContextPointers, &ContextBlock->Context);
|
|
}
|
|
|
|
KeSetEvent(&ContextBlock->OperationComplete, 0, FALSE);
|
|
return;
|
|
} |