VOID NTAPI Ke386SetIOPL(VOID) { PKTHREAD Thread = KeGetCurrentThread(); PKPROCESS Process = Thread->ApcState.Process; PKTRAP_FRAME TrapFrame; CONTEXT Context; /* IOPL was enabled for this process/thread */ Process->Iopl = TRUE; Thread->Iopl = TRUE; /* Get the trap frame on exit */ TrapFrame = KeGetTrapFrame(Thread); /* Convert to a context */ Context.ContextFlags = CONTEXT_CONTROL; KeTrapFrameToContext(TrapFrame, NULL, &Context); /* Set the IOPL flag */ Context.EFlags |= EFLAGS_IOPL; /* Convert back to a trap frame */ KeContextToTrapFrame(&Context, NULL, TrapFrame, CONTEXT_CONTROL, UserMode); }
NTSTATUS NTAPI KiContinue(IN PCONTEXT Context, IN PKEXCEPTION_FRAME ExceptionFrame, IN PKTRAP_FRAME TrapFrame) { NTSTATUS Status = STATUS_SUCCESS; KIRQL OldIrql = APC_LEVEL; KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); /* Raise to APC_LEVEL, only if needed */ if (KeGetCurrentIrql() < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql); /* Set up SEH to validate the context */ _SEH2_TRY { /* Check the previous mode */ if (PreviousMode != KernelMode) { /* Validate from user-mode */ KiContinuePreviousModeUser(Context, ExceptionFrame, TrapFrame); } else { /* Convert the context into Exception/Trap Frames */ KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame, Context->ContextFlags, KernelMode); } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Save the exception code */ Status = _SEH2_GetExceptionCode(); } _SEH2_END; /* Lower the IRQL if needed */ if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql); /* Return status */ return Status; }
VOID NTAPI KiContinuePreviousModeUser(IN PCONTEXT Context, IN PKEXCEPTION_FRAME ExceptionFrame, IN PKTRAP_FRAME TrapFrame) { CONTEXT LocalContext; /* We'll have to make a copy and probe it */ ProbeForRead(Context, sizeof(CONTEXT), sizeof(ULONG)); RtlCopyMemory(&LocalContext, Context, sizeof(CONTEXT)); Context = &LocalContext; /* Convert the context into Exception/Trap Frames */ KeContextToTrapFrame(&LocalContext, ExceptionFrame, TrapFrame, LocalContext.ContextFlags, UserMode); }
/* FIXME: THIS IS TOTALLY BUSTED NOW */ VOID NTAPI KiInitializeContextThread(IN PKTHREAD Thread, IN PKSYSTEM_ROUTINE SystemRoutine, IN PKSTART_ROUTINE StartRoutine, IN PVOID StartContext, IN PCONTEXT ContextPointer) { PKTRAP_FRAME TrapFrame; PKEXCEPTION_FRAME ExceptionFrame = NULL, CtxSwitchFrame; // // Check if this is a user thread // if (ContextPointer) { // // Setup the initial frame // PKUINIT_FRAME InitFrame; InitFrame = (PKUINIT_FRAME)((ULONG_PTR)Thread->InitialStack - sizeof(KUINIT_FRAME)); // // Setup the Trap Frame and Exception frame // TrapFrame = &InitFrame->TrapFrame; ExceptionFrame = &InitFrame->ExceptionFrame; /// // Zero out the trap frame and exception frame // RtlZeroMemory(TrapFrame, sizeof(KTRAP_FRAME)); RtlZeroMemory(ExceptionFrame, sizeof(KEXCEPTION_FRAME)); // // Set up a trap frame from the context // KeContextToTrapFrame(ContextPointer, ExceptionFrame, TrapFrame, ContextPointer->ContextFlags | CONTEXT_CONTROL, UserMode); // // Set the previous mode as user // //TrapFrame->PreviousMode = UserMode; Thread->PreviousMode = UserMode; // // Clear the return address // ExceptionFrame->Lr = 0; // // Context switch frame to setup below // CtxSwitchFrame = &InitFrame->CtxSwitchFrame; } else { // // Set up the Initial Frame for the system thread // PKKINIT_FRAME InitFrame; InitFrame = (PKKINIT_FRAME)((ULONG_PTR)Thread->InitialStack - sizeof(KKINIT_FRAME)); // // Set the previous mode as kernel // Thread->PreviousMode = KernelMode; // // Context switch frame to setup below // CtxSwitchFrame = &InitFrame->CtxSwitchFrame; } // // Now setup the context switch frame // CtxSwitchFrame->Lr = (ULONG)KiThreadStartup; CtxSwitchFrame->R11 = (ULONG)(ExceptionFrame ? ExceptionFrame : CtxSwitchFrame); // // Set the parameters // CtxSwitchFrame->R4 = (ULONG)ContextPointer; CtxSwitchFrame->R5 = (ULONG)StartContext; CtxSwitchFrame->R6 = (ULONG)StartRoutine; CtxSwitchFrame->R7 = (ULONG)SystemRoutine; // // Save back the new value of the kernel stack // Thread->KernelStack = (PVOID)CtxSwitchFrame; }