test: apcuser.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# apcuser.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1990  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     apcuser.c
    00008
    00009 Abstract:
    00010
    00011     This module implements the machine dependent code necessary to initialize
    00012     a user mode APC.
    00013
    00014 Author:
    00015
    00016     David N. Cutler (davec) 23-Apr-1990
    00017
    00018 Environment:
    00019
    00020     Kernel mode only, IRQL APC_LEVEL.
    00021
    00022 Revision History:
    00023
    00024 --*/
    00025
    00026 #include "ki.h"
    00027
    00028 VOID
    00029 KiInitializeUserApc (
    00030     IN PKEXCEPTION_FRAME ExceptionFrame,
    00031     IN PKTRAP_FRAME TrapFrame,
    00032     IN PKNORMAL_ROUTINE NormalRoutine,
    00033     IN PVOID NormalContext,
    00034     IN PVOID SystemArgument1,
    00035     IN PVOID SystemArgument2
    00036     )
    00037
    00038 /*++
    00039
    00040 Routine Description:
    00041
    00042     This function is called to initialize the context for a user mode APC.
    00043
    00044 Arguments:
    00045
    00046     ExceptionFrame - Supplies a pointer to an exception frame.
    00047
    00048     TrapFrame - Supplies a pointer to a trap frame.
    00049
    00050     NormalRoutine - Supplies a pointer to the user mode APC routine.
    00051
    00052     NormalContext - Supplies a pointer to the user context for the APC
    00053         routine.
    00054
    00055     SystemArgument1 - Supplies the first system supplied value.
    00056
    00057     SystemArgument2 - Supplies the second system supplied value.
    00058
    00059 Return Value:
    00060
    00061     None.
    00062
    00063 --*/
    00064
    00065 {
    00066
    00067     EXCEPTION_RECORD ExceptionRecord;
    00068     CONTEXT ContextFrame;
    00069     LONG Length;
    00070     ULONG UserStack;
    00071
    00072
    00073     //
    00074     // APCs are not defined for V86 mode; however, it is possible a
    00075     // thread is trying to set it's context to V86 mode - this isn't
    00076     // going to work, but we don't want to crash the system so we
    00077     // check for the possibility before hand.
    00078     //
    00079
    00080     if (TrapFrame->EFlags & EFLAGS_V86_MASK) {
    00081         return ;
    00082     }
    00083
    00084     //
    00085     // Move machine state from trap and exception frames to the context frame.
    00086     //
    00087
    00088     ContextFrame.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
    00089     KeContextFromKframes(TrapFrame, ExceptionFrame, &ContextFrame);
    00090
    00091     //
    00092     // Transfer the context information to the user stack, initialize the
    00093     // APC routine parameters, and modify the trap frame so execution will
    00094     // continue in user mode at the user mode APC dispatch routine.
    00095     //
    00096
    00097
    00098     try {
    00099         ASSERT((TrapFrame->SegCs & MODE_MASK) != KernelMode); // Assert usermode frame
    00100
    00101         //
    00102         // Compute length of context record and new aligned user stack pointer.
    00103         //
    00104
    00105         Length = ((sizeof(CONTEXT) + CONTEXT_ROUND) &
    00106                     ~CONTEXT_ROUND) + sizeof(KAPC_RECORD);
    00107         UserStack = (ContextFrame.Esp & ~CONTEXT_ROUND) - Length;
    00108
    00109         //
    00110         // Probe user stack area for writeability and then transfer the
    00111         // context record to the user stack.
    00112         //
    00113
    00114         ProbeForWrite((PCHAR)UserStack, Length, CONTEXT_ALIGN);
    00115         RtlMoveMemory((PULONG)(UserStack + (sizeof(KAPC_RECORD))),
    00116                      &ContextFrame, sizeof(CONTEXT));
    00117
    00118         //
    00119         // Force correct R3 selectors into TrapFrame.
    00120         //
    00121
    00122         TrapFrame->SegCs = SANITIZE_SEG(KGDT_R3_CODE, UserMode);
    00123         TrapFrame->HardwareSegSs = SANITIZE_SEG(KGDT_R3_DATA, UserMode);
    00124         TrapFrame->SegDs = SANITIZE_SEG(KGDT_R3_DATA, UserMode);
    00125         TrapFrame->SegEs = SANITIZE_SEG(KGDT_R3_DATA, UserMode);
    00126         TrapFrame->SegFs = SANITIZE_SEG(KGDT_R3_TEB, UserMode);
    00127         TrapFrame->SegGs = 0;
    00128         TrapFrame->EFlags = SANITIZE_FLAGS( ContextFrame.EFlags, UserMode );
    00129
    00130         //
    00131         // If thread is supposed to have IOPL, then force it on in eflags
    00132         //
    00133
    00134         if (KeGetCurrentThread()->Iopl) {
    00135             TrapFrame->EFlags |= (EFLAGS_IOPL_MASK & -1);  // IOPL = 3
    00136         }
    00137
    00138         //
    00139         // Set the address of the user APC routine, the APC parameters, the
    00140         // new frame pointer, and the new stack pointer in the current trap
    00141         // frame. Set the continuation address so control will be transfered
    00142         // to the user APC dispatcher.
    00143         //
    00144
    00145         TrapFrame->HardwareEsp = UserStack;
    00146         TrapFrame->Eip = (ULONG)KeUserApcDispatcher;
    00147         TrapFrame->ErrCode = 0;
    00148         *((PULONG)UserStack)++ = (ULONG)NormalRoutine;
    00149         *((PULONG)UserStack)++ = (ULONG)NormalContext;
    00150         *((PULONG)UserStack)++ = (ULONG)SystemArgument1;
    00151         *((PULONG)UserStack)++ = (ULONG)SystemArgument2;
    00152     } except (KiCopyInformation(&ExceptionRecord,
    00153                                 (GetExceptionInformation())->ExceptionRecord)) {
    00154
    00155         //
    00156         // Set the address of the exception to the current program address
    00157         // and raise the exception by calling the exception dispatcher.
    00158         //
    00159
    00160         ExceptionRecord.ExceptionAddress = (PVOID)(TrapFrame->Eip);
    00161         KiDispatchException(&ExceptionRecord,
    00162                             ExceptionFrame,
    00163                             TrapFrame,
    00164                             UserMode,
    00165                             TRUE);
    00166     }
    00167     return;
    00168 }
    00169