/*
- * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
+ * PROJECT: ReactOS Kernel
+ * LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/ke/i386/exp.c
- * PURPOSE: Handling exceptions
- *
- * PROGRAMMERS: David Welch (welch@cwcom.net)
+ * PURPOSE: Exception Dispatching and Context<->Trap Frame Conversion
+ * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
+ * Gregor Anich
* Skywing (skywing@valhallalegends.com)
*/
-/* INCLUDES *****************************************************************/
+/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
-
#define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
-/*
- * FIXMES:
- * - Put back VEH.
- * - Clean up file.
- * - Sanitize some context fields.
- * - Add PSEH handler when an exception occurs in an exception (KiCopyExceptionRecord).
- * - Implement official stack trace functions (exported) and remove stuff here.
- * - Forward exceptions to user-mode debugger.
- */
+/* GLOBALS *******************************************************************/
+
+/* DR Registers in the CONTEXT structure */
+UCHAR KiDebugRegisterContextOffsets[9] =
+{
+ FIELD_OFFSET(CONTEXT, Dr0),
+ FIELD_OFFSET(CONTEXT, Dr1),
+ FIELD_OFFSET(CONTEXT, Dr2),
+ FIELD_OFFSET(CONTEXT, Dr3),
+ 0,
+ 0,
+ FIELD_OFFSET(CONTEXT, Dr6),
+ FIELD_OFFSET(CONTEXT, Dr7),
+ 0,
+};
+
+/* DR Registers in the KTRAP_FRAME structure */
+UCHAR KiDebugRegisterTrapOffsets[9] =
+{
+ FIELD_OFFSET(KTRAP_FRAME, Dr0),
+ FIELD_OFFSET(KTRAP_FRAME, Dr1),
+ FIELD_OFFSET(KTRAP_FRAME, Dr2),
+ FIELD_OFFSET(KTRAP_FRAME, Dr3),
+ 0,
+ 0,
+ FIELD_OFFSET(KTRAP_FRAME, Dr6),
+ FIELD_OFFSET(KTRAP_FRAME, Dr7),
+ 0,
+};
+
+/* FUNCTIONS *****************************************************************/
VOID
+INIT_FUNCTION
NTAPI
-Ki386AdjustEsp0(IN PKTRAP_FRAME TrapFrame);
-
-/* GLOBALS *****************************************************************/
-
-#define FLAG_IF (1<<9)
-
-#define _STR(x) #x
-#define STR(x) _STR(x)
-
-#ifndef ARRAY_SIZE
-# define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0]))
-#endif
-
-extern void KiSystemService(void);
-extern void KiDebugService(void);
-
-extern VOID KiTrap0(VOID);
-extern VOID KiTrap1(VOID);
-extern VOID KiTrap2(VOID);
-extern VOID KiTrap3(VOID);
-extern VOID KiTrap4(VOID);
-extern VOID KiTrap5(VOID);
-extern VOID KiTrap6(VOID);
-extern VOID KiTrap7(VOID);
-extern VOID KiTrap8(VOID);
-extern VOID KiTrap9(VOID);
-extern VOID KiTrap10(VOID);
-extern VOID KiTrap11(VOID);
-extern VOID KiTrap12(VOID);
-extern VOID KiTrap13(VOID);
-extern VOID KiTrap14(VOID);
-extern VOID KiTrap15(VOID);
-extern VOID KiTrap16(VOID);
-extern VOID KiTrap17(VOID);
-extern VOID KiTrap18(VOID);
-extern VOID KiTrap19(VOID);
-extern VOID KiTrapUnknown(VOID);
-
-extern ULONG init_stack;
-extern ULONG init_stack_top;
-
-extern BOOLEAN Ke386NoExecute;
-
-static char *ExceptionTypeStrings[] =
- {
- "Divide Error",
- "Debug Trap",
- "NMI",
- "Breakpoint",
- "Overflow",
- "BOUND range exceeded",
- "Invalid Opcode",
- "No Math Coprocessor",
- "Double Fault",
- "Unknown(9)",
- "Invalid TSS",
- "Segment Not Present",
- "Stack Segment Fault",
- "General Protection",
- "Page Fault",
- "Reserved(15)",
- "Math Fault",
- "Alignment Check",
- "Machine Check",
- "SIMD Fault"
- };
-
-NTSTATUS ExceptionToNtStatus[] =
- {
- STATUS_INTEGER_DIVIDE_BY_ZERO,
- STATUS_SINGLE_STEP,
- STATUS_ACCESS_VIOLATION,
- STATUS_BREAKPOINT,
- STATUS_INTEGER_OVERFLOW,
- STATUS_ARRAY_BOUNDS_EXCEEDED,
- STATUS_ILLEGAL_INSTRUCTION,
- STATUS_FLOAT_INVALID_OPERATION,
- STATUS_ACCESS_VIOLATION,
- STATUS_ACCESS_VIOLATION,
- STATUS_ACCESS_VIOLATION,
- STATUS_ACCESS_VIOLATION,
- STATUS_STACK_OVERFLOW,
- STATUS_ACCESS_VIOLATION,
- STATUS_ACCESS_VIOLATION,
- STATUS_ACCESS_VIOLATION, /* RESERVED */
- STATUS_FLOAT_INVALID_OPERATION, /* Should not be used, the FPU can give more specific info */
- STATUS_DATATYPE_MISALIGNMENT,
- STATUS_ACCESS_VIOLATION,
- STATUS_FLOAT_MULTIPLE_TRAPS,
- };
-
-/* FUNCTIONS ****************************************************************/
-
-BOOLEAN STDCALL
-KiRosPrintAddress(PVOID address)
+KeInitExceptions(VOID)
{
- PLIST_ENTRY current_entry;
- PLDR_DATA_TABLE_ENTRY current;
- extern LIST_ENTRY ModuleListHead;
- ULONG_PTR RelativeAddress;
- ULONG i = 0;
-
- do
- {
- current_entry = ModuleListHead.Flink;
-
- while (current_entry != &ModuleListHead)
- {
- current =
- CONTAINING_RECORD(current_entry, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);
-
- if (address >= (PVOID)current->DllBase &&
- address < (PVOID)((ULONG_PTR)current->DllBase + current->SizeOfImage))
- {
- RelativeAddress = (ULONG_PTR) address - (ULONG_PTR) current->DllBase;
- DbgPrint("<%wZ: %x>", ¤t->FullDllName, RelativeAddress);
- return(TRUE);
- }
- current_entry = current_entry->Flink;
- }
+ ULONG i;
+ USHORT FlippedSelector;
+ extern KIDTENTRY KiIdt[MAXIMUM_IDTVECTOR];
- address = (PVOID)((ULONG_PTR)address & ~(ULONG_PTR)MmSystemRangeStart);
- } while(++i <= 1);
+ /* Loop the IDT */
+ for (i = 0; i <= MAXIMUM_IDTVECTOR; i++)
+ {
+ /* Save the current Selector */
+ FlippedSelector = KiIdt[i].Selector;
- return(FALSE);
+ /* Flip Selector and Extended Offset */
+ KiIdt[i].Selector = KiIdt[i].ExtendedOffset;
+ KiIdt[i].ExtendedOffset = FlippedSelector;
+ }
}
ULONG
-KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
+FASTCALL
+KiUpdateDr7(IN ULONG Dr7)
{
- EXCEPTION_RECORD Er;
-
- Er.ExceptionFlags = 0;
- Er.ExceptionRecord = NULL;
- Er.ExceptionAddress = (PVOID)Tf->Eip;
+ ULONG DebugMask = KeGetCurrentThread()->DispatcherHeader.DebugActive;
- if (ExceptionNr == 14)
+ /* Check if debugging is enabled */
+ if (DebugMask & DR_MASK(DR7_OVERRIDE_V))
{
- Er.ExceptionCode = STATUS_ACCESS_VIOLATION;
- Er.NumberParameters = 2;
- Er.ExceptionInformation[0] = Tf->ErrorCode & 0x1;
- Er.ExceptionInformation[1] = (ULONG)Cr2;
+ /* Sanity checks */
+ ASSERT((DebugMask & DR_REG_MASK) != 0);
+ ASSERT((Dr7 & ~DR7_RESERVED_MASK) == DR7_OVERRIDE_MASK);
+ return 0;
}
- else
- {
- if (ExceptionNr < ARRAY_SIZE(ExceptionToNtStatus))
- {
- Er.ExceptionCode = ExceptionToNtStatus[ExceptionNr];
- }
- else
- {
- Er.ExceptionCode = STATUS_ACCESS_VIOLATION;
- }
- Er.NumberParameters = 0;
- }
-
- /* FIXME: Which exceptions are noncontinuable? */
- Er.ExceptionFlags = 0;
-
- KiDispatchException(&Er, NULL, Tf, KernelMode, TRUE);
- return(0);
+ /* Return DR7 itself */
+ return Dr7;
}
-VOID
-KiDoubleFaultHandler(VOID)
+BOOLEAN
+FASTCALL
+KiRecordDr7(OUT PULONG Dr7Ptr,
+ OUT PULONG DrMask)
{
- unsigned int cr2;
- ULONG StackLimit;
- ULONG StackBase;
- ULONG Esp0;
- ULONG ExceptionNr = 8;
- KTSS* OldTss;
- PULONG Frame;
- ULONG OldCr3;
-#if 0
- ULONG i, j;
- static PVOID StackTrace[MM_STACK_SIZE / sizeof(PVOID)];
- static ULONG StackRepeatCount[MM_STACK_SIZE / sizeof(PVOID)];
- static ULONG StackRepeatLength[MM_STACK_SIZE / sizeof(PVOID)];
- ULONG TraceLength;
- BOOLEAN FoundRepeat;
-#endif
-
- OldTss = KeGetCurrentKPCR()->TSS;
- Esp0 = OldTss->Esp;
-
- /* Get CR2 */
- cr2 = Ke386GetCr2();
- if (PsGetCurrentThread() != NULL &&
- PsGetCurrentThread()->ThreadsProcess != NULL)
+ ULONG NewMask, Mask;
+ UCHAR Result;
+
+ /* Check if the caller gave us a mask */
+ if (!DrMask)
{
- OldCr3 = (ULONG)
- PsGetCurrentThread()->ThreadsProcess->Pcb.DirectoryTableBase.QuadPart;
+ /* He didn't, use the one from the thread */
+ Mask = KeGetCurrentThread()->DispatcherHeader.DebugActive;
}
- else
+ else
{
- OldCr3 = 0xBEADF0AL;
+ /* He did, read it */
+ Mask = *DrMask;
}
- /*
- * Check for stack underflow
- */
- if (PsGetCurrentThread() != NULL &&
- Esp0 < (ULONG)PsGetCurrentThread()->Tcb.StackLimit)
- {
- DbgPrint("Stack underflow (tf->esp %x Limit %x)\n",
- Esp0, (ULONG)PsGetCurrentThread()->Tcb.StackLimit);
- ExceptionNr = 12;
- }
-
- /*
- * Print out the CPU registers
- */
- if (ExceptionNr < ARRAY_SIZE(ExceptionTypeStrings))
- {
- DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
- ExceptionNr, 0);
- }
- else
- {
- DbgPrint("Exception: %d(%x)\n", ExceptionNr, 0);
- }
- DbgPrint("CS:EIP %x:%x ", OldTss->Cs, OldTss->Eip);
- KeRosPrintAddress((PVOID)OldTss->Eip);
- DbgPrint("\n");
- DbgPrint("cr2 %x cr3 %x ", cr2, OldCr3);
- DbgPrint("Proc: %x ",PsGetCurrentProcess());
- if (PsGetCurrentProcess() != NULL)
- {
- DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId);
- DbgPrint("%.16s> ", PsGetCurrentProcess()->ImageFileName);
- }
- if (PsGetCurrentThread() != NULL)
- {
- DbgPrint("Thrd: %x Tid: %x",
- PsGetCurrentThread(),
- PsGetCurrentThread()->Cid.UniqueThread);
- }
- DbgPrint("\n");
- DbgPrint("DS %x ES %x FS %x GS %x\n", OldTss->Ds, OldTss->Es,
- OldTss->Fs, OldTss->Gs);
- DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", OldTss->Eax, OldTss->Ebx,
- OldTss->Ecx);
- DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\nESP: %.8x ", OldTss->Edx,
- OldTss->Ebp, OldTss->Esi, Esp0);
- DbgPrint("EDI: %.8x EFLAGS: %.8x ", OldTss->Edi, OldTss->Eflags);
- if (OldTss->Cs == KGDT_R0_CODE)
- {
- DbgPrint("kESP %.8x ", Esp0);
- if (PsGetCurrentThread() != NULL)
- {
- DbgPrint("kernel stack base %x\n",
- PsGetCurrentThread()->Tcb.StackLimit);
-
- }
- }
- else
- {
- DbgPrint("User ESP %.8x\n", OldTss->Esp);
- }
- if ((OldTss->Cs & 0xffff) == KGDT_R0_CODE)
+ /* Sanity check */
+ ASSERT((*Dr7Ptr & DR7_RESERVED_MASK) == 0);
+
+ /* Check if DR7 is empty */
+ NewMask = Mask;
+ if (!(*Dr7Ptr))
{
- if (PsGetCurrentThread() != NULL)
- {
- StackLimit = (ULONG)PsGetCurrentThread()->Tcb.StackBase;
- StackBase = (ULONG)PsGetCurrentThread()->Tcb.StackLimit;
- }
- else
- {
- StackLimit = (ULONG)init_stack_top;
- StackBase = (ULONG)init_stack;
- }
-
- /*
- Change to an #if 0 to reduce the amount of information printed on
- a recursive stack trace.
- */
-#if 1
- DbgPrint("Frames: ");
- Frame = (PULONG)OldTss->Ebp;
- while (Frame != NULL && (ULONG)Frame >= StackBase)
- {
- KeRosPrintAddress((PVOID)Frame[1]);
- Frame = (PULONG)Frame[0];
- DbgPrint("\n");
- }
-#else
- DbgPrint("Frames: ");
- i = 0;
- Frame = (PULONG)OldTss->Ebp;
- while (Frame != NULL && (ULONG)Frame >= StackBase)
- {
- StackTrace[i] = (PVOID)Frame[1];
- Frame = (PULONG)Frame[0];
- i++;
- }
- TraceLength = i;
-
- i = 0;
- while (i < TraceLength)
- {
- StackRepeatCount[i] = 0;
- j = i + 1;
- FoundRepeat = FALSE;
- while ((j - i) <= (TraceLength - j) && FoundRepeat == FALSE)
- {
- if (memcmp(&StackTrace[i], &StackTrace[j],
- (j - i) * sizeof(PVOID)) == 0)
- {
- StackRepeatCount[i] = 2;
- StackRepeatLength[i] = j - i;
- FoundRepeat = TRUE;
- }
- else
- {
- j++;
- }
- }
- if (FoundRepeat == FALSE)
- {
- i++;
- continue;
- }
- j = j + StackRepeatLength[i];
- while ((TraceLength - j) >= StackRepeatLength[i] &&
- FoundRepeat == TRUE)
- {
- if (memcmp(&StackTrace[i], &StackTrace[j],
- StackRepeatLength[i] * sizeof(PVOID)) == 0)
- {
- StackRepeatCount[i]++;
- j = j + StackRepeatLength[i];
- }
- else
- {
- FoundRepeat = FALSE;
- }
- }
- i = j;
- }
-
- i = 0;
- while (i < TraceLength)
- {
- if (StackRepeatCount[i] == 0)
- {
- KeRosPrintAddress(StackTrace[i]);
- i++;
- }
- else
- {
- DbgPrint("{");
- if (StackRepeatLength[i] == 0)
- {
- for(;;);
- }
- for (j = 0; j < StackRepeatLength[i]; j++)
- {
- KeRosPrintAddress(StackTrace[i + j]);
- }
- DbgPrint("}*%d", StackRepeatCount[i]);
- i = i + StackRepeatLength[i] * StackRepeatCount[i];
- }
- }
-#endif
- }
+ /* Assume failure */
+ Result = FALSE;
- DbgPrint("\n");
- for(;;);
-}
+ /* Check the DR mask */
+ NewMask &= ~(DR_MASK(7));
+ if (NewMask & DR_REG_MASK)
+ {
+ /* Set the active mask */
+ NewMask |= DR_MASK(DR7_OVERRIDE_V);
-VOID
-NTAPI
-KiDumpTrapFrame(PKTRAP_FRAME Tf, ULONG Parameter1, ULONG Parameter2)
-{
- ULONG cr3_;
- ULONG StackLimit;
- ULONG Esp0;
- ULONG ExceptionNr = (ULONG)Tf->DebugArgMark;
- ULONG cr2 = (ULONG)Tf->DebugPointer;
-
- Esp0 = (ULONG)Tf;
-
- /*
- * Print out the CPU registers
- */
- if (ExceptionNr < ARRAY_SIZE(ExceptionTypeStrings))
- {
- DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
- ExceptionNr, Tf->ErrorCode&0xffff);
- }
- else
- {
- DbgPrint("Exception: %d(%x)\n", ExceptionNr, Tf->ErrorCode&0xffff);
- }
- DbgPrint("Processor: %d CS:EIP %x:%x ", KeGetCurrentProcessorNumber(),
- Tf->Cs&0xffff, Tf->Eip);
- KeRosPrintAddress((PVOID)Tf->Eip);
- DbgPrint("\n");
- Ke386GetPageTableDirectory(cr3_);
- DbgPrint("cr2 %x cr3 %x ", cr2, cr3_);
- DbgPrint("Proc: %x ",PsGetCurrentProcess());
- if (PsGetCurrentProcess() != NULL)
- {
- DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId);
- DbgPrint("%.16s> ", PsGetCurrentProcess()->ImageFileName);
- }
- if (PsGetCurrentThread() != NULL)
- {
- DbgPrint("Thrd: %x Tid: %x",
- PsGetCurrentThread(),
- PsGetCurrentThread()->Cid.UniqueThread);
- }
- DbgPrint("\n");
- DbgPrint("DS %x ES %x FS %x GS %x\n", Tf->Ds&0xffff, Tf->Es&0xffff,
- Tf->Fs&0xffff, Tf->Gs&0xfff);
- DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", Tf->Eax, Tf->Ebx, Tf->Ecx);
- DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x ESP: %.8x\n", Tf->Edx,
- Tf->Ebp, Tf->Esi, Esp0);
- DbgPrint("EDI: %.8x EFLAGS: %.8x ", Tf->Edi, Tf->Eflags);
- if ((Tf->Cs&0xffff) == KGDT_R0_CODE)
- {
- DbgPrint("kESP %.8x ", Esp0);
- if (PsGetCurrentThread() != NULL)
- {
- DbgPrint("kernel stack base %x\n",
- PsGetCurrentThread()->Tcb.StackLimit);
-
- }
- }
-
- if (PsGetCurrentThread() != NULL)
- {
- StackLimit = (ULONG)PsGetCurrentThread()->Tcb.StackBase;
- }
- else
- {
- StackLimit = (ULONG)init_stack_top;
- }
-
- /*
- * Dump the stack frames
- */
- KeDumpStackFrames((PULONG)Tf->Ebp);
-}
+ /* Set DR7 override */
+ *Dr7Ptr |= DR7_OVERRIDE_MASK;
+ }
+ else
+ {
+ /* Sanity check */
+ ASSERT(NewMask == 0);
+ }
+ }
+ else
+ {
+ /* Check if we have a mask or not */
+ Result = NewMask ? TRUE: FALSE;
-ULONG
-KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
-/*
- * FUNCTION: Called by the lowlevel execption handlers to print an amusing
- * message and halt the computer
- * ARGUMENTS:
- * Complete CPU context
- */
-{
- ULONG_PTR cr2;
- NTSTATUS Status;
- ULONG Esp0;
-
- ASSERT(ExceptionNr != 14);
-
- /* Store the exception number in an unused field in the trap frame. */
- Tf->DebugArgMark = ExceptionNr;
-
- /* Use the address of the trap frame as approximation to the ring0 esp */
- Esp0 = (ULONG)&Tf->Eip;
-
- /* Get CR2 */
- cr2 = Ke386GetCr2();
- Tf->DebugPointer = cr2;
-
- /*
- * If this was a V86 mode exception then handle it specially
- */
- if (Tf->Eflags & (1 << 17))
- {
- DPRINT("Tf->Eflags, %x, Tf->Eip %x, ExceptionNr: %d\n", Tf->Eflags, Tf->Eip, ExceptionNr);
- return(KeV86Exception(ExceptionNr, Tf, cr2));
- }
-
- /*
- * Check for stack underflow, this may be obsolete
- */
- if (PsGetCurrentThread() != NULL &&
- Esp0 < (ULONG)PsGetCurrentThread()->Tcb.StackLimit)
- {
- DPRINT1("Stack underflow (tf->esp %x Limit %x Eip %x)\n",
- Esp0, (ULONG)PsGetCurrentThread()->Tcb.StackLimit, Tf->Eip);
- ExceptionNr = 12;
- }
-
- if (ExceptionNr == 15)
- {
- /*
- * FIXME:
- * This exception should never occur. The P6 has a bug, which does sometimes deliver
- * the apic spurious interrupt as exception 15. On an athlon64, I get one exception
- * in the early boot phase in apic mode (using the smp build). I've looked to the linux
- * sources. Linux does ignore this exception.
- *
- * Hartmut Birr
- */
- DPRINT1("Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
- return(0);
- }
-
- /*
- * Check for a breakpoint that was only for the attention of the debugger.
- */
- if (ExceptionNr == 3 && Tf->Eip == ((ULONG)DbgBreakPointNoBugCheck) + 1)
- {
- /*
- EIP is already adjusted by the processor to point to the instruction
- after the breakpoint.
- */
- return(0);
- }
-
- /*
- * Try to handle device-not-present, math-fault and xmm-fault exceptions.
- */
- if (ExceptionNr == 7 || ExceptionNr == 16 || ExceptionNr == 19)
- {
- Status = KiHandleFpuFault(Tf, ExceptionNr);
- if (NT_SUCCESS(Status))
- {
- return(0);
- }
- }
-
- /*
- * Handle user exceptions differently
- */
- if ((Tf->Cs & 0xFFFF) == (KGDT_R3_CODE | RPL_MASK))
- {
- return(KiUserTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
- }
- else
+ /* Update the mask to disable debugging */
+ NewMask &= ~(DR_MASK(DR7_OVERRIDE_V));
+ NewMask |= DR_MASK(7);
+ }
+
+ /* Check if caller wants the new mask */
+ if (DrMask)
+ {
+ /* Update it */
+ *DrMask = NewMask;
+ }
+ else
{
- return(KiKernelTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
+ /* Check if the mask changed */
+ if (Mask != NewMask)
+ {
+ /* Update it */
+ KeGetCurrentThread()->DispatcherHeader.DebugActive =
+ (BOOLEAN)NewMask;
+ }
}
+
+ /* Return the result */
+ return Result;
}
ULONG
KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
{
/* Check if this is user-mode or V86 */
- if ((TrapFrame->Cs & 1) || (TrapFrame->Eflags & X86_EFLAGS_VM))
+ if ((TrapFrame->SegCs & MODE_MASK) ||
+ (TrapFrame->EFlags & EFLAGS_V86_MASK))
{
/* Return it directly */
- return TrapFrame->Esp;
+ return TrapFrame->HardwareEsp;
}
else
{
/* Edited frame */
- if (!(TrapFrame->Cs & FRAME_EDITED))
+ if (!(TrapFrame->SegCs & FRAME_EDITED))
{
/* Return edited value */
return TrapFrame->TempEsp;
else
{
/* Virgin frame, calculate */
- return (ULONG)&TrapFrame->Esp;
+ return (ULONG)&TrapFrame->HardwareEsp;
}
}
}
KiEspToTrapFrame(IN PKTRAP_FRAME TrapFrame,
IN ULONG Esp)
{
- ULONG Previous = KiEspFromTrapFrame(TrapFrame);
+ KIRQL OldIrql;
+ ULONG Previous;
+
+ /* Raise to APC_LEVEL if needed */
+ OldIrql = KeGetCurrentIrql();
+ if (OldIrql < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
+
+ /* Get the old ESP */
+ Previous = KiEspFromTrapFrame(TrapFrame);
/* Check if this is user-mode or V86 */
- if ((TrapFrame->Cs & MODE_MASK) || (TrapFrame->Eflags & X86_EFLAGS_VM))
+ if ((TrapFrame->SegCs & MODE_MASK) ||
+ (TrapFrame->EFlags & EFLAGS_V86_MASK))
{
/* Write it directly */
- TrapFrame->Esp = Esp;
+ TrapFrame->HardwareEsp = Esp;
}
else
{
/* Don't allow ESP to be lowered, this is illegal */
- if (Esp < Previous)
- {
- KeBugCheck(SET_OF_INVALID_CONTEXT);
- }
+ if (Esp < Previous) KeBugCheckEx(SET_OF_INVALID_CONTEXT,
+ Esp,
+ Previous,
+ (ULONG_PTR)TrapFrame,
+ 0);
/* Create an edit frame, check if it was alrady */
- if (!(TrapFrame->Cs & FRAME_EDITED))
+ if (!(TrapFrame->SegCs & FRAME_EDITED))
{
/* Update the value */
TrapFrame->TempEsp = Esp;
if (Previous != Esp)
{
/* Save CS */
- TrapFrame->TempCs = TrapFrame->Cs;
- TrapFrame->Cs &= ~FRAME_EDITED;
+ TrapFrame->TempSegCs = TrapFrame->SegCs;
+ TrapFrame->SegCs &= ~FRAME_EDITED;
/* Save ESP */
TrapFrame->TempEsp = Esp;
}
}
}
+
+ /* Restore IRQL */
+ if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql);
}
ULONG
NTAPI
KiSsFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
{
- /* If this was V86 Mode */
- if (TrapFrame->Eflags & X86_EFLAGS_VM)
+ /* Check if this was V86 Mode */
+ if (TrapFrame->EFlags & EFLAGS_V86_MASK)
{
/* Just return it */
- return TrapFrame->Ss;
+ return TrapFrame->HardwareSegSs;
}
- else if (TrapFrame->Cs & MODE_MASK)
+ else if (TrapFrame->SegCs & MODE_MASK)
{
- /* Usermode, return the User SS */
- return TrapFrame->Ss | RPL_MASK;
+ /* User mode, return the User SS */
+ return TrapFrame->HardwareSegSs | RPL_MASK;
}
else
{
Ss &= 0xFFFF;
/* If this was V86 Mode */
- if (TrapFrame->Eflags & X86_EFLAGS_VM)
+ if (TrapFrame->EFlags & EFLAGS_V86_MASK)
{
/* Just write it */
- TrapFrame->Ss = Ss;
+ TrapFrame->HardwareSegSs = Ss;
}
- else if (TrapFrame->Cs & MODE_MASK)
+ else if (TrapFrame->SegCs & MODE_MASK)
{
/* Usermode, save the User SS */
- TrapFrame->Ss = Ss | RPL_MASK;
+ TrapFrame->HardwareSegSs = Ss | RPL_MASK;
}
}
-BOOLEAN
+USHORT
+NTAPI
+KiTagWordFnsaveToFxsave(USHORT TagWord)
+{
+ INT FxTagWord = ~TagWord;
+
+ /*
+ * Empty is now 00, any 2 bits containing 1 mean valid
+ * Now convert the rest (11->0 and the rest to 1)
+ */
+ FxTagWord = (FxTagWord | (FxTagWord >> 1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
+ FxTagWord = (FxTagWord | (FxTagWord >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
+ FxTagWord = (FxTagWord | (FxTagWord >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
+ FxTagWord = (FxTagWord | (FxTagWord >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
+ return FxTagWord;
+}
+
+VOID
NTAPI
KeContextToTrapFrame(IN PCONTEXT Context,
IN OUT PKEXCEPTION_FRAME ExceptionFrame,
IN OUT PKTRAP_FRAME TrapFrame,
+ IN ULONG ContextFlags,
IN KPROCESSOR_MODE PreviousMode)
{
+ PFX_SAVE_AREA FxSaveArea;
+ ULONG i;
BOOLEAN V86Switch = FALSE;
+ KIRQL OldIrql;
+ ULONG DrMask = 0;
+ PVOID SafeDr;
+
+ /* Do this at APC_LEVEL */
+ OldIrql = KeGetCurrentIrql();
+ if (OldIrql < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
/* Start with the basic Registers */
- if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
+ if ((ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
{
/* Check if we went through a V86 switch */
- if ((Context->EFlags & X86_EFLAGS_VM) !=
- (TrapFrame->Eflags & X86_EFLAGS_VM))
+ if ((Context->EFlags & EFLAGS_V86_MASK) !=
+ (TrapFrame->EFlags & EFLAGS_V86_MASK))
{
/* We did, remember this for later */
V86Switch = TRUE;
}
- /* Copy EFLAGS. FIXME: Needs to be sanitized */
- TrapFrame->Eflags = Context->EFlags;
+ /* Copy EFLAGS and sanitize them*/
+ TrapFrame->EFlags = Ke386SanitizeFlags(Context->EFlags, PreviousMode);
/* Copy EBP and EIP */
TrapFrame->Ebp = Context->Ebp;
TrapFrame->Eip = Context->Eip;
/* Check if we were in V86 Mode */
- if (TrapFrame->Eflags & X86_EFLAGS_VM)
+ if (TrapFrame->EFlags & EFLAGS_V86_MASK)
{
/* Simply copy the CS value */
- TrapFrame->Cs = Context->SegCs;
+ TrapFrame->SegCs = Context->SegCs;
}
else
{
- /* We weren't in V86, so sanitize the CS (FIXME!) */
- TrapFrame->Cs = Context->SegCs;
+ /* We weren't in V86, so sanitize the CS */
+ TrapFrame->SegCs = Ke386SanitizeSeg(Context->SegCs, PreviousMode);
/* Don't let it under 8, that's invalid */
- if ((PreviousMode != KernelMode) && (TrapFrame->Cs < 8))
+ if ((PreviousMode != KernelMode) && (TrapFrame->SegCs < 8))
{
/* Force it to User CS */
- TrapFrame->Cs = (KGDT_R3_CODE | RPL_MASK);
+ TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK;
}
}
}
/* Process the Integer Registers */
- if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
+ if ((ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
{
+ /* Copy them manually */
TrapFrame->Eax = Context->Eax;
TrapFrame->Ebx = Context->Ebx;
TrapFrame->Ecx = Context->Ecx;
}
/* Process the Context Segments */
- if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
+ if ((ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
{
/* Check if we were in V86 Mode */
- if (TrapFrame->Eflags & X86_EFLAGS_VM)
+ if (TrapFrame->EFlags & EFLAGS_V86_MASK)
{
- /* Copy the V86 Segments directlry */
- TrapFrame->V86_Ds = Context->SegDs;
- TrapFrame->V86_Es = Context->SegEs;
- TrapFrame->V86_Fs = Context->SegFs;
- TrapFrame->V86_Gs = Context->SegGs;
+ /* Copy the V86 Segments directly */
+ TrapFrame->V86Ds = Context->SegDs;
+ TrapFrame->V86Es = Context->SegEs;
+ TrapFrame->V86Fs = Context->SegFs;
+ TrapFrame->V86Gs = Context->SegGs;
}
- else if (!(TrapFrame->Cs & MODE_MASK))
+ else if (!(TrapFrame->SegCs & MODE_MASK))
{
- /* For user mode, write the values directly */
- TrapFrame->Ds = KGDT_R3_DATA | RPL_MASK;
- TrapFrame->Es = KGDT_R3_DATA | RPL_MASK;
- TrapFrame->Fs = Context->SegFs;
- TrapFrame->Gs = 0;
+ /* For kernel mode, write the standard values */
+ TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK;
+ TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK;
+ TrapFrame->SegFs = Ke386SanitizeSeg(Context->SegFs, PreviousMode);
+ TrapFrame->SegGs = 0;
}
else
{
- /* For kernel-mode, return the values */
- TrapFrame->Ds = Context->SegDs;
- TrapFrame->Es = Context->SegEs;
- TrapFrame->Fs = Context->SegFs;
+ /* For user mode, return the values directly */
+ TrapFrame->SegDs = Context->SegDs;
+ TrapFrame->SegEs = Context->SegEs;
+ TrapFrame->SegFs = Context->SegFs;
/* Handle GS specially */
- if (TrapFrame->Cs == (KGDT_R3_CODE | RPL_MASK))
+ if (TrapFrame->SegCs == (KGDT_R3_CODE | RPL_MASK))
{
/* Don't use it, if user */
- TrapFrame->Gs = 0;
+ TrapFrame->SegGs = 0;
}
else
{
/* Copy it if kernel */
- TrapFrame->Gs = Context->SegGs;
+ TrapFrame->SegGs = Context->SegGs;
+ }
+ }
+ }
+
+ /* Handle the extended registers */
+ if (((ContextFlags & CONTEXT_EXTENDED_REGISTERS) ==
+ CONTEXT_EXTENDED_REGISTERS) && (TrapFrame->SegCs & MODE_MASK))
+ {
+ /* Get the FX Area */
+ FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
+
+ /* Check if NPX is present */
+ if (KeI386NpxPresent)
+ {
+ /* Flush the NPX State */
+ KiFlushNPXState(NULL);
+
+ /* Copy the FX State */
+ RtlCopyMemory(&FxSaveArea->U.FxArea,
+ &Context->ExtendedRegisters[0],
+ MAXIMUM_SUPPORTED_EXTENSION);
+
+ /* Remove reserved bits from MXCSR */
+ FxSaveArea->U.FxArea.MXCsr &= KiMXCsrMask;
+
+ /* Mask out any invalid flags */
+ FxSaveArea->Cr0NpxState &= ~(CR0_EM | CR0_MP | CR0_TS);
+
+ /* Check if this is a VDM app */
+ if (PsGetCurrentProcess()->VdmObjects)
+ {
+ /* Allow the EM flag */
+ FxSaveArea->Cr0NpxState |= Context->FloatSave.Cr0NpxState &
+ (CR0_EM | CR0_MP);
}
}
}
+ /* Handle the floating point state */
+ if (((ContextFlags & CONTEXT_FLOATING_POINT) ==
+ CONTEXT_FLOATING_POINT) && (TrapFrame->SegCs & MODE_MASK))
+ {
+ /* Get the FX Area */
+ FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
+
+ /* Check if NPX is present */
+ if (KeI386NpxPresent)
+ {
+ /* Flush the NPX State */
+ KiFlushNPXState(NULL);
+
+ /* Check if we have Fxsr support */
+ if (KeI386FxsrPresent)
+ {
+ /* Convert the Fn Floating Point state to Fx */
+ FxSaveArea->U.FxArea.ControlWord =
+ (USHORT)Context->FloatSave.ControlWord;
+ FxSaveArea->U.FxArea.StatusWord =
+ (USHORT)Context->FloatSave.StatusWord;
+ FxSaveArea->U.FxArea.TagWord =
+ KiTagWordFnsaveToFxsave((USHORT)Context->FloatSave.TagWord);
+ FxSaveArea->U.FxArea.ErrorOpcode =
+ (USHORT)((Context->FloatSave.ErrorSelector >> 16) & 0xFFFF);
+ FxSaveArea->U.FxArea.ErrorOffset =
+ Context->FloatSave.ErrorOffset;
+ FxSaveArea->U.FxArea.ErrorSelector =
+ Context->FloatSave.ErrorSelector & 0xFFFF;
+ FxSaveArea->U.FxArea.DataOffset =
+ Context->FloatSave.DataOffset;
+ FxSaveArea->U.FxArea.DataSelector =
+ Context->FloatSave.DataSelector;
+
+ /* Clear out the Register Area */
+ RtlZeroMemory(&FxSaveArea->U.FxArea.RegisterArea[0],
+ SIZE_OF_FX_REGISTERS);
+
+ /* Loop the 8 floating point registers */
+ for (i = 0; i < 8; i++)
+ {
+ /* Copy from Fn to Fx */
+ RtlCopyMemory(FxSaveArea->U.FxArea.RegisterArea + (i * 16),
+ Context->FloatSave.RegisterArea + (i * 10),
+ 10);
+ }
+ }
+ else
+ {
+ /* Copy the structure */
+ FxSaveArea->U.FnArea.ControlWord = Context->FloatSave.
+ ControlWord;
+ FxSaveArea->U.FnArea.StatusWord = Context->FloatSave.
+ StatusWord;
+ FxSaveArea->U.FnArea.TagWord = Context->FloatSave.TagWord;
+ FxSaveArea->U.FnArea.ErrorOffset = Context->FloatSave.
+ ErrorOffset;
+ FxSaveArea->U.FnArea.ErrorSelector = Context->FloatSave.
+ ErrorSelector;
+ FxSaveArea->U.FnArea.DataOffset = Context->FloatSave.
+ DataOffset;
+ FxSaveArea->U.FnArea.DataSelector = Context->FloatSave.
+ DataSelector;
+
+ /* Loop registers */
+ for (i = 0; i < SIZE_OF_80387_REGISTERS; i++)
+ {
+ /* Copy registers */
+ FxSaveArea->U.FnArea.RegisterArea[i] =
+ Context->FloatSave.RegisterArea[i];
+ }
+ }
+
+ /* Mask out any invalid flags */
+ FxSaveArea->Cr0NpxState &= ~(CR0_EM | CR0_MP | CR0_TS);
+
+ /* Check if this is a VDM app */
+ if (PsGetCurrentProcess()->VdmObjects)
+ {
+ /* Allow the EM flag */
+ FxSaveArea->Cr0NpxState |= Context->FloatSave.Cr0NpxState &
+ (CR0_EM | CR0_MP);
+ }
+ }
+ else
+ {
+ /* FIXME: Handle FPU Emulation */
+ //ASSERT(FALSE);
+ }
+ }
+
/* Handle the Debug Registers */
- if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
+ if ((ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
{
- /* FIXME: All these should be sanitized */
- TrapFrame->Dr0 = Context->Dr0;
- TrapFrame->Dr1 = Context->Dr1;
- TrapFrame->Dr2 = Context->Dr2;
- TrapFrame->Dr3 = Context->Dr3;
- TrapFrame->Dr6 = Context->Dr6;
- TrapFrame->Dr7 = Context->Dr7;
-
- /* Check if usermode */
+ /* Loop DR registers */
+ for (i = 0; i < 4; i++)
+ {
+ /* Sanitize the context DR Address */
+ SafeDr = Ke386SanitizeDr(KiDrFromContext(i, Context), PreviousMode);
+
+ /* Save it in the trap frame */
+ *KiDrFromTrapFrame(i, TrapFrame) = SafeDr;
+
+ /* Check if this DR address is active and add it in the DR mask */
+ if (SafeDr) DrMask |= DR_MASK(i);
+ }
+
+ /* Now save and sanitize DR6 */
+ TrapFrame->Dr6 = Context->Dr6 & DR6_LEGAL;
+ if (TrapFrame->Dr6) DrMask |= DR_MASK(6);
+
+ /* Save and sanitize DR7 */
+ TrapFrame->Dr7 = Context->Dr7 & DR7_LEGAL;
+ KiRecordDr7(&TrapFrame->Dr7, &DrMask);
+
+ /* If we're in user-mode */
if (PreviousMode != KernelMode)
{
- /* Set the Debug Flag */
- KeGetCurrentThread()->DispatcherHeader.DebugActive = (Context->Dr7 & DR7_ACTIVE);
+ /* Save the mask */
+ KeGetCurrentThread()->DispatcherHeader.DebugActive = DrMask;
}
}
- /* Handle FPU and Extended Registers */
- return KiContextToFxSaveArea((PFX_SAVE_AREA)(TrapFrame + 1), Context);
+ /* Check if thread has IOPL and force it enabled if so */
+ if (KeGetCurrentThread()->Iopl) TrapFrame->EFlags |= EFLAGS_IOPL;
+
+ /* Restore IRQL */
+ if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql);
}
VOID
IN PKEXCEPTION_FRAME ExceptionFrame,
IN OUT PCONTEXT Context)
{
- PFX_SAVE_AREA FxSaveArea = NULL;
+ PFX_SAVE_AREA FxSaveArea;
+ struct _AlignHack
+ {
+ UCHAR Hack[15];
+ FLOATING_SAVE_AREA UnalignedArea;
+ } FloatSaveBuffer;
+ FLOATING_SAVE_AREA *FloatSaveArea;
+ KIRQL OldIrql;
+ ULONG i;
+
+ /* Do this at APC_LEVEL */
+ OldIrql = KeGetCurrentIrql();
+ if (OldIrql < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
/* Start with the Control flags */
if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
/* EBP, EIP and EFLAGS */
Context->Ebp = TrapFrame->Ebp;
Context->Eip = TrapFrame->Eip;
- Context->EFlags = TrapFrame->Eflags;
+ Context->EFlags = TrapFrame->EFlags;
/* Return the correct CS */
- if (!(TrapFrame->Cs & FRAME_EDITED) &&
- !(TrapFrame->Eflags & X86_EFLAGS_VM))
+ if (!(TrapFrame->SegCs & FRAME_EDITED) &&
+ !(TrapFrame->EFlags & EFLAGS_V86_MASK))
{
/* Get it from the Temp location */
- Context->SegCs = TrapFrame->TempCs & 0xFFFF;
+ Context->SegCs = TrapFrame->TempSegCs & 0xFFFF;
}
else
{
/* Return it directly */
- Context->SegCs = TrapFrame->Cs & 0xFFFF;
+ Context->SegCs = TrapFrame->SegCs & 0xFFFF;
}
/* Get the Ss and ESP */
if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
{
/* Do V86 Mode first */
- if (TrapFrame->Eflags & X86_EFLAGS_VM)
+ if (TrapFrame->EFlags & EFLAGS_V86_MASK)
{
/* Return from the V86 location */
- Context->SegGs = TrapFrame->V86_Gs & 0xFFFF;
- Context->SegFs = TrapFrame->V86_Fs & 0xFFFF;
- Context->SegEs = TrapFrame->V86_Es & 0xFFFF;
- Context->SegDs = TrapFrame->V86_Ds & 0xFFFF;
+ Context->SegGs = TrapFrame->V86Gs & 0xFFFF;
+ Context->SegFs = TrapFrame->V86Fs & 0xFFFF;
+ Context->SegEs = TrapFrame->V86Es & 0xFFFF;
+ Context->SegDs = TrapFrame->V86Ds & 0xFFFF;
}
else
{
/* Check if this was a Kernel Trap */
- if (TrapFrame->Cs == KGDT_R0_CODE)
+ if (TrapFrame->SegCs == KGDT_R0_CODE)
{
/* Set valid selectors */
- TrapFrame->Gs = 0;
- TrapFrame->Fs = KGDT_R0_PCR;
- TrapFrame->Es = KGDT_R3_DATA | RPL_MASK;
- TrapFrame->Ds = KGDT_R3_DATA | RPL_MASK;
+ TrapFrame->SegGs = 0;
+ TrapFrame->SegFs = KGDT_R0_PCR;
+ TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK;
+ TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK;
}
/* Return the segments */
- Context->SegGs = TrapFrame->Gs & 0xFFFF;
- Context->SegFs = TrapFrame->Fs & 0xFFFF;
- Context->SegEs = TrapFrame->Es & 0xFFFF;
- Context->SegDs = TrapFrame->Ds & 0xFFFF;
+ Context->SegGs = TrapFrame->SegGs & 0xFFFF;
+ Context->SegFs = TrapFrame->SegFs & 0xFFFF;
+ Context->SegEs = TrapFrame->SegEs & 0xFFFF;
+ Context->SegDs = TrapFrame->SegDs & 0xFFFF;
}
}
Context->Edi = TrapFrame->Edi;
}
- if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
+ /* Handle extended registers */
+ if (((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) ==
+ CONTEXT_EXTENDED_REGISTERS) && (TrapFrame->SegCs & MODE_MASK))
{
- /*
- * FIXME: Implement this case
- */
- Context->ContextFlags &= (~CONTEXT_DEBUG_REGISTERS) | CONTEXT_i386;
- }
- if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
- {
- FxSaveArea = KiGetFpuState(KeGetCurrentThread());
- if (FxSaveArea != NULL)
- {
- KiFxSaveAreaToFloatingSaveArea(&Context->FloatSave, FxSaveArea);
- }
- else
+ /* Get the FX Save Area */
+ FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
+
+ /* Make sure NPX is present */
+ if (KeI386NpxPresent)
{
- Context->ContextFlags &= (~CONTEXT_FLOATING_POINT) | CONTEXT_i386;
+ /* Flush the NPX State */
+ KiFlushNPXState(NULL);
+
+ /* Copy the registers */
+ RtlCopyMemory(&Context->ExtendedRegisters[0],
+ &FxSaveArea->U.FxArea,
+ MAXIMUM_SUPPORTED_EXTENSION);
}
}
- if ((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS)
+
+ /* Handle Floating Point */
+ if (((Context->ContextFlags & CONTEXT_FLOATING_POINT) ==
+ CONTEXT_FLOATING_POINT) && (TrapFrame->SegCs & MODE_MASK))
+ {
+ /* Get the FX Save Area */
+ FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
+
+ /* Make sure we have an NPX */
+ if (KeI386NpxPresent)
+ {
+ /* Check if we have Fxsr support */
+ if (KeI386FxsrPresent)
+ {
+ /* Align the floating area to 16-bytes */
+ FloatSaveArea = (FLOATING_SAVE_AREA*)
+ ((ULONG_PTR)&FloatSaveBuffer.UnalignedArea &~ 0xF);
+
+ /* Get the State */
+ KiFlushNPXState(FloatSaveArea);
+ }
+ else
+ {
+ /* We don't, use the FN area and flush the NPX State */
+ FloatSaveArea = (FLOATING_SAVE_AREA*)&FxSaveArea->U.FnArea;
+ KiFlushNPXState(NULL);
+ }
+
+ /* Copy structure */
+ Context->FloatSave.ControlWord = FloatSaveArea->ControlWord;
+ Context->FloatSave.StatusWord = FloatSaveArea->StatusWord;
+ Context->FloatSave.TagWord = FloatSaveArea->TagWord;
+ Context->FloatSave.ErrorOffset = FloatSaveArea->ErrorOffset;
+ Context->FloatSave.ErrorSelector = FloatSaveArea->ErrorSelector;
+ Context->FloatSave.DataOffset = FloatSaveArea->DataOffset;
+ Context->FloatSave.DataSelector = FloatSaveArea->DataSelector;
+ Context->FloatSave.Cr0NpxState = FxSaveArea->Cr0NpxState;
+
+ /* Loop registers */
+ for (i = 0; i < SIZE_OF_80387_REGISTERS; i++)
+ {
+ /* Copy them */
+ Context->FloatSave.RegisterArea[i] =
+ FloatSaveArea->RegisterArea[i];
+ }
+ }
+ else
+ {
+ /* FIXME: Handle Emulation */
+ ASSERT(FALSE);
+ }
+ }
+
+ /* Handle debug registers */
+ if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) ==
+ CONTEXT_DEBUG_REGISTERS)
{
- if (FxSaveArea == NULL)
- FxSaveArea = KiGetFpuState(KeGetCurrentThread());
- if (FxSaveArea != NULL)
+ /* Make sure DR7 is valid */
+ if (TrapFrame->Dr7 & ~DR7_RESERVED_MASK)
{
- memcpy(Context->ExtendedRegisters, &FxSaveArea->U.FxArea,
- min(sizeof (Context->ExtendedRegisters), sizeof (FxSaveArea->U.FxArea)) );
+ /* Copy the debug registers */
+ Context->Dr0 = TrapFrame->Dr0;
+ Context->Dr1 = TrapFrame->Dr1;
+ Context->Dr2 = TrapFrame->Dr2;
+ Context->Dr3 = TrapFrame->Dr3;
+ Context->Dr6 = TrapFrame->Dr6;
+
+ /* Update DR7 */
+ Context->Dr7 = KiUpdateDr7(TrapFrame->Dr7);
}
else
{
- Context->ContextFlags &= (~CONTEXT_EXTENDED_REGISTERS) | CONTEXT_i386;
+ /* Otherwise clear DR registers */
+ Context->Dr0 =
+ Context->Dr1 =
+ Context->Dr3 =
+ Context->Dr6 =
+ Context->Dr7 = 0;
}
}
-}
-VOID
-NTAPI
-KeDumpStackFrames(PULONG Frame)
-{
- PULONG StackBase, StackEnd;
- MEMORY_BASIC_INFORMATION mbi;
- ULONG ResultLength = sizeof(mbi);
- NTSTATUS Status;
-
- DbgPrint("Frames:\n");
- _SEH_TRY
- {
- Status = MiQueryVirtualMemory (
- (HANDLE)-1,
- Frame,
- MemoryBasicInformation,
- &mbi,
- sizeof(mbi),
- &ResultLength );
- if ( !NT_SUCCESS(Status) )
- {
- DPRINT1("Can't dump stack frames: MiQueryVirtualMemory() failed: %x\n", Status );
- return;
- }
-
- StackBase = Frame;
- StackEnd = (PULONG)((ULONG_PTR)mbi.BaseAddress + mbi.RegionSize);
-
- while ( Frame >= StackBase && Frame < StackEnd )
- {
- ULONG Addr = Frame[1];
- if (!KeRosPrintAddress((PVOID)Addr))
- DbgPrint("<%X>", Addr);
- if ( Addr == 0 || Addr == 0xDEADBEEF )
- break;
- StackBase = Frame;
- Frame = (PULONG)Frame[0];
- DbgPrint("\n");
- }
- }
- _SEH_HANDLE
- {
- }
- _SEH_END;
- DbgPrint("\n");
+ /* Restore IRQL */
+ if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql);
}
-VOID STDCALL
-KeRosDumpStackFrames ( PULONG Frame, ULONG FrameCount )
+BOOLEAN
+FASTCALL
+KeInvalidAccessAllowed(IN PVOID TrapInformation OPTIONAL)
{
- ULONG i=0;
- PULONG StackBase, StackEnd;
- MEMORY_BASIC_INFORMATION mbi;
- ULONG ResultLength = sizeof(mbi);
- NTSTATUS Status;
-
- DbgPrint("Frames: ");
- _SEH_TRY
- {
- if ( !Frame )
- {
-#if defined __GNUC__
- __asm__("mov %%ebp, %0" : "=r" (Frame) : );
-#elif defined(_MSC_VER)
- __asm mov [Frame], ebp
-#endif
- //Frame = (PULONG)Frame[0]; // step out of KeRosDumpStackFrames
- }
-
- Status = MiQueryVirtualMemory (
- (HANDLE)-1,
- Frame,
- MemoryBasicInformation,
- &mbi,
- sizeof(mbi),
- &ResultLength );
- if ( !NT_SUCCESS(Status) )
- {
- DPRINT1("Can't dump stack frames: MiQueryVirtualMemory() failed: %x\n", Status );
- return;
- }
-
- StackBase = Frame;
- StackEnd = (PULONG)((ULONG_PTR)mbi.BaseAddress + mbi.RegionSize);
-
- while ( Frame >= StackBase && Frame < StackEnd && i++ < FrameCount )
- {
- ULONG Addr = Frame[1];
- if (!KeRosPrintAddress((PVOID)Addr))
- DbgPrint("<%X>", Addr);
- if ( Addr == 0 || Addr == 0xDEADBEEF )
- break;
- StackBase = Frame;
- Frame = (PULONG)Frame[0];
- DbgPrint(" ");
- }
- }
- _SEH_HANDLE
- {
- }
- _SEH_END;
- DbgPrint("\n");
-}
+ ULONG Eip;
+ PKTRAP_FRAME TrapFrame = TrapInformation;
+ VOID NTAPI ExpInterlockedPopEntrySListFault(VOID);
-ULONG STDCALL
-KeRosGetStackFrames ( PULONG Frames, ULONG FrameCount )
-{
- ULONG Count = 0;
- PULONG StackBase, StackEnd, Frame;
- MEMORY_BASIC_INFORMATION mbi;
- ULONG ResultLength = sizeof(mbi);
- NTSTATUS Status;
-
- _SEH_TRY
- {
-#if defined __GNUC__
- __asm__("mov %%ebp, %0" : "=r" (Frame) : );
-#elif defined(_MSC_VER)
- __asm mov [Frame], ebp
-#endif
-
- Status = MiQueryVirtualMemory (
- (HANDLE)-1,
- Frame,
- MemoryBasicInformation,
- &mbi,
- sizeof(mbi),
- &ResultLength );
- if ( !NT_SUCCESS(Status) )
- {
- DPRINT1("Can't get stack frames: MiQueryVirtualMemory() failed: %x\n", Status );
- return 0;
- }
-
- StackBase = Frame;
- StackEnd = (PULONG)((ULONG_PTR)mbi.BaseAddress + mbi.RegionSize);
-
- while ( Count < FrameCount && Frame >= StackBase && Frame < StackEnd )
- {
- Frames[Count++] = Frame[1];
- StackBase = Frame;
- Frame = (PULONG)Frame[0];
- }
- }
- _SEH_HANDLE
- {
- }
- _SEH_END;
- return Count;
-}
+ /* Don't do anything if we didn't get a trap frame */
+ if (!TrapInformation) return FALSE;
-static void
-set_system_call_gate(unsigned int sel, unsigned int func)
-{
- DPRINT("sel %x %d\n",sel,sel);
- KiIdt[sel].a = (((int)func)&0xffff) +
- (KGDT_R0_CODE << 16);
- KiIdt[sel].b = 0xef00 + (((int)func)&0xffff0000);
- DPRINT("idt[sel].b %x\n",KiIdt[sel].b);
-}
+ /* Check where we came from */
+ switch (TrapFrame->SegCs)
+ {
+ /* Kernel mode */
+ case KGDT_R0_CODE:
-static void set_interrupt_gate(unsigned int sel, unsigned int func)
-{
- DPRINT("set_interrupt_gate(sel %d, func %x)\n",sel,func);
- KiIdt[sel].a = (((int)func)&0xffff) +
- (KGDT_R0_CODE << 16);
- KiIdt[sel].b = 0x8e00 + (((int)func)&0xffff0000);
-}
+ /* Allow S-LIST Routine to fail */
+ Eip = (ULONG)&ExpInterlockedPopEntrySListFault;
+ break;
-static void set_trap_gate(unsigned int sel, unsigned int func, unsigned int dpl)
-{
- DPRINT("set_trap_gate(sel %d, func %x, dpl %d)\n",sel, func, dpl);
- ASSERT(dpl <= 3);
- KiIdt[sel].a = (((int)func)&0xffff) +
- (KGDT_R0_CODE << 16);
- KiIdt[sel].b = 0x8f00 + (dpl << 13) + (((int)func)&0xffff0000);
-}
+ /* User code */
+ case KGDT_R3_CODE | RPL_MASK:
-static void
-set_task_gate(unsigned int sel, unsigned task_sel)
-{
- KiIdt[sel].a = task_sel << 16;
- KiIdt[sel].b = 0x8500;
-}
+ /* Allow S-LIST Routine to fail */
+ //Eip = (ULONG)KeUserPopEntrySListFault;
+ Eip = 0;
+ break;
-VOID
-INIT_FUNCTION
-NTAPI
-KeInitExceptions(VOID)
-/*
- * FUNCTION: Initalize CPU exception handling
- */
-{
- int i;
-
- DPRINT("KeInitExceptions()\n");
-
- /*
- * Set up the other gates
- */
- set_trap_gate(0, (ULONG)KiTrap0, 0);
- set_trap_gate(1, (ULONG)KiTrap1, 0);
- set_trap_gate(2, (ULONG)KiTrap2, 0);
- set_trap_gate(3, (ULONG)KiTrap3, 3);
- set_trap_gate(4, (ULONG)KiTrap4, 0);
- set_trap_gate(5, (ULONG)KiTrap5, 0);
- set_trap_gate(6, (ULONG)KiTrap6, 0);
- set_trap_gate(7, (ULONG)KiTrap7, 0);
- set_task_gate(8, KGDT_DF_TSS);
- set_trap_gate(9, (ULONG)KiTrap9, 0);
- set_trap_gate(10, (ULONG)KiTrap10, 0);
- set_trap_gate(11, (ULONG)KiTrap11, 0);
- set_trap_gate(12, (ULONG)KiTrap12, 0);
- set_trap_gate(13, (ULONG)KiTrap13, 0);
- set_interrupt_gate(14, (ULONG)KiTrap14);
- set_trap_gate(15, (ULONG)KiTrap15, 0);
- set_trap_gate(16, (ULONG)KiTrap16, 0);
- set_trap_gate(17, (ULONG)KiTrap17, 0);
- set_trap_gate(18, (ULONG)KiTrap18, 0);
- set_trap_gate(19, (ULONG)KiTrap19, 0);
-
- for (i = 20; i < 256; i++)
- {
- set_trap_gate(i,(int)KiTrapUnknown, 0);
- }
-
- set_system_call_gate(0x2d,(int)KiDebugService);
- set_system_call_gate(0x2e,(int)KiSystemService);
+ default:
+
+ /* Anything else gets a bugcheck */
+ Eip = 0;
+ }
+
+ /* Return TRUE if we want to keep the system up */
+ return (TrapFrame->Eip == Eip) ? TRUE : FALSE;
}
VOID
NTAPI
-KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
- PKEXCEPTION_FRAME ExceptionFrame,
- PKTRAP_FRAME TrapFrame,
- KPROCESSOR_MODE PreviousMode,
- BOOLEAN FirstChance)
+KiDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame,
+ IN KPROCESSOR_MODE PreviousMode,
+ IN BOOLEAN FirstChance)
{
CONTEXT Context;
- KD_CONTINUE_TYPE Action;
- ULONG_PTR Stack, NewStack;
- ULONG Size;
- BOOLEAN UserDispatch = FALSE;
- DPRINT("KiDispatchException() called\n");
+ EXCEPTION_RECORD LocalExceptRecord;
/* Increase number of Exception Dispatches */
KeGetCurrentPrcb()->KeExceptionDispatchCount++;
/* Set the context flags */
Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
- /* Check if User Mode */
- if (PreviousMode == UserMode)
+ /* Check if User Mode or if the debugger is enabled */
+ if ((PreviousMode == UserMode) || (KdDebuggerEnabled))
{
- extern ULONG FxsrSupport;
/* Add the FPU Flag */
Context.ContextFlags |= CONTEXT_FLOATING_POINT;
- if (FxsrSupport)
+
+ /* Check for NPX Support */
+ if (KeI386FxsrPresent)
+ {
+ /* Save those too */
Context.ContextFlags |= CONTEXT_EXTENDED_REGISTERS;
+ }
}
/* Get a Context */
KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context);
+ /* Look at our exception code */
+ switch (ExceptionRecord->ExceptionCode)
+ {
+ /* Breakpoint */
+ case STATUS_BREAKPOINT:
+
+ /* Decrement EIP by one */
+ Context.Eip--;
+ break;
+
+ /* Internal exception */
+ case KI_EXCEPTION_ACCESS_VIOLATION:
+
+ /* Set correct code */
+ ExceptionRecord->ExceptionCode = STATUS_ACCESS_VIOLATION;
+ if (PreviousMode == UserMode)
+ {
+ /* FIXME: Handle no execute */
+ }
+ break;
+ }
+
+ /* Sanity check */
+ ASSERT(!((PreviousMode == KernelMode) &&
+ (Context.EFlags & EFLAGS_V86_MASK)));
+
/* Handle kernel-mode first, it's simpler */
if (PreviousMode == KernelMode)
{
if (FirstChance == TRUE)
{
/* Break into the debugger for the first time */
- Action = KdpEnterDebuggerException(ExceptionRecord,
- PreviousMode,
- &Context,
- TrapFrame,
- TRUE,
- TRUE);
-
- /* If the debugger said continue, then continue */
- if (Action == kdContinue) goto Handled;
-
- /* If the Debugger couldn't handle it, dispatch the exception */
- if (RtlDispatchException(ExceptionRecord, &Context))
+ if (KiDebugRoutine(TrapFrame,
+ ExceptionFrame,
+ ExceptionRecord,
+ &Context,
+ PreviousMode,
+ FALSE))
{
- /* It was handled by an exception handler, continue */
+ /* Exception was handled */
goto Handled;
}
+
+ /* If the Debugger couldn't handle it, dispatch the exception */
+ if (RtlDispatchException(ExceptionRecord, &Context)) goto Handled;
}
/* This is a second-chance exception, only for the debugger */
- Action = KdpEnterDebuggerException(ExceptionRecord,
- PreviousMode,
- &Context,
- TrapFrame,
- FALSE,
- FALSE);
-
- /* If the debugger said continue, then continue */
- if (Action == kdContinue) goto Handled;
+ if (KiDebugRoutine(TrapFrame,
+ ExceptionFrame,
+ ExceptionRecord,
+ &Context,
+ PreviousMode,
+ TRUE))
+ {
+ /* Exception was handled */
+ goto Handled;
+ }
/* Third strike; you're out */
- KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED,
- ExceptionRecord->ExceptionCode,
- (ULONG_PTR)ExceptionRecord->ExceptionAddress,
- ExceptionRecord->ExceptionInformation[0],
- ExceptionRecord->ExceptionInformation[1],
- TrapFrame);
+ KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED,
+ ExceptionRecord->ExceptionCode,
+ (ULONG_PTR)ExceptionRecord->ExceptionAddress,
+ (ULONG_PTR)TrapFrame,
+ 0);
}
else
{
/* User mode exception, was it first-chance? */
if (FirstChance)
{
- /* Enter Debugger if available */
- Action = KdpEnterDebuggerException(ExceptionRecord,
- PreviousMode,
- &Context,
- TrapFrame,
- TRUE,
- TRUE);
-
- /* Exit if we're continuing */
- if (Action == kdContinue) goto Handled;
+ /*
+ * Break into the kernel debugger unless a user mode debugger
+ * is present or user mode exceptions are ignored, unless this is
+ * a breakpoint or a debug service in which case we have to
+ * handle it.
+ */
+ if ((!(PsGetCurrentProcess()->DebugPort) &&
+ !(KdIgnoreUmExceptions)) ||
+ (KdIsThisAKdTrap(ExceptionRecord,
+ &Context,
+ PreviousMode)))
+ {
+ /* Call the kernel debugger */
+ if (KiDebugRoutine(TrapFrame,
+ ExceptionFrame,
+ ExceptionRecord,
+ &Context,
+ PreviousMode,
+ FALSE))
+ {
+ /* Exception was handled */
+ goto Handled;
+ }
+ }
- /* FIXME: Forward exception to user mode debugger */
+ /* Forward exception to user mode debugger */
+ if (DbgkForwardException(ExceptionRecord, TRUE, FALSE)) return;
/* Set up the user-stack */
- _SEH_TRY
+DispatchToUser:
+ _SEH2_TRY
{
+ ULONG Size;
+ ULONG_PTR Stack, NewStack;
+
+ /* Make sure we have a valid SS and that this isn't V86 mode */
+ if ((TrapFrame->HardwareSegSs != (KGDT_R3_DATA | RPL_MASK)) ||
+ (TrapFrame->EFlags & EFLAGS_V86_MASK))
+ {
+ /* Raise an exception instead */
+ LocalExceptRecord.ExceptionCode = STATUS_ACCESS_VIOLATION;
+ LocalExceptRecord.ExceptionFlags = 0;
+ LocalExceptRecord.NumberParameters = 0;
+ RtlRaiseException(&LocalExceptRecord);
+ }
+
/* Align context size and get stack pointer */
Size = (sizeof(CONTEXT) + 3) & ~3;
Stack = (Context.Esp & ~3) - Size;
- DPRINT("Stack: %lx\n", Stack);
/* Probe stack and copy Context */
ProbeForWrite((PVOID)Stack, Size, sizeof(ULONG));
RtlCopyMemory((PVOID)Stack, &Context, sizeof(CONTEXT));
/* Align exception record size and get stack pointer */
- Size = (sizeof(EXCEPTION_RECORD) -
- (EXCEPTION_MAXIMUM_PARAMETERS - ExceptionRecord->NumberParameters) *
- sizeof(ULONG) + 3) & ~3;
+ Size = (sizeof(EXCEPTION_RECORD) -
+ (EXCEPTION_MAXIMUM_PARAMETERS -
+ ExceptionRecord->NumberParameters) *
+ sizeof(ULONG) + 3) & ~3;
NewStack = Stack - Size;
- DPRINT("NewStack: %lx\n", NewStack);
- /* Probe stack and copy exception record. Don't forget to add the two params */
+ /* Probe stack and copy exception record */
ProbeForWrite((PVOID)(NewStack - 2 * sizeof(ULONG_PTR)),
Size + 2 * sizeof(ULONG_PTR),
sizeof(ULONG));
*(PULONG_PTR)(NewStack - 2 * sizeof(ULONG_PTR)) = NewStack;
/* Set new Stack Pointer */
+ KiSsToTrapFrame(TrapFrame, KGDT_R3_DATA);
KiEspToTrapFrame(TrapFrame, NewStack - 2 * sizeof(ULONG_PTR));
- /* Set EIP to the User-mode Dispathcer */
+ /* Force correct segments */
+ TrapFrame->SegCs = Ke386SanitizeSeg(KGDT_R3_CODE, PreviousMode);
+ TrapFrame->SegDs = Ke386SanitizeSeg(KGDT_R3_DATA, PreviousMode);
+ TrapFrame->SegEs = Ke386SanitizeSeg(KGDT_R3_DATA, PreviousMode);
+ TrapFrame->SegFs = Ke386SanitizeSeg(KGDT_R3_TEB, PreviousMode);
+ TrapFrame->SegGs = 0;
+
+ /* Set EIP to the User-mode Dispatcher */
TrapFrame->Eip = (ULONG)KeUserExceptionDispatcher;
- UserDispatch = TRUE;
- _SEH_LEAVE;
+
+ /* Dispatch exception to user-mode */
+ _SEH2_YIELD(return);
}
- _SEH_HANDLE
+ _SEH2_EXCEPT((RtlCopyMemory(&LocalExceptRecord, _SEH2_GetExceptionInformation()->ExceptionRecord, sizeof(EXCEPTION_RECORD)), EXCEPTION_EXECUTE_HANDLER))
{
- /* Do second-chance */
+ /* Check if we got a stack overflow and raise that instead */
+ if ((NTSTATUS)LocalExceptRecord.ExceptionCode ==
+ STATUS_STACK_OVERFLOW)
+ {
+ /* Copy the exception address and record */
+ LocalExceptRecord.ExceptionAddress =
+ ExceptionRecord->ExceptionAddress;
+ RtlCopyMemory(ExceptionRecord,
+ (PVOID)&LocalExceptRecord,
+ sizeof(EXCEPTION_RECORD));
+
+ /* Do the exception again */
+ _SEH2_YIELD(goto DispatchToUser);
+ }
}
- _SEH_END;
+ _SEH2_END;
}
- /* If we dispatch to user, return now */
- if (UserDispatch) return;
-
- /* FIXME: Forward the exception to the debugger for 2nd chance */
+ /* Try second chance */
+ if (DbgkForwardException(ExceptionRecord, TRUE, TRUE))
+ {
+ /* Handled, get out */
+ return;
+ }
+ else if (DbgkForwardException(ExceptionRecord, FALSE, TRUE))
+ {
+ /* Handled, get out */
+ return;
+ }
- /* 3rd strike, kill the thread */
- DPRINT1("Unhandled UserMode exception, terminating thread\n");
- ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
- KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED,
- ExceptionRecord->ExceptionCode,
- (ULONG_PTR)ExceptionRecord->ExceptionAddress,
- ExceptionRecord->ExceptionInformation[0],
- ExceptionRecord->ExceptionInformation[1],
- TrapFrame);
+ /* 3rd strike, kill the process */
+ DPRINT1("Kill %.16s, ExceptionCode: %lx, ExceptionAddress: %lx\n",
+ PsGetCurrentProcess()->ImageFileName,
+ ExceptionRecord->ExceptionCode,
+ ExceptionRecord->ExceptionAddress);
+
+ ZwTerminateProcess(NtCurrentProcess(), ExceptionRecord->ExceptionCode);
+ KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED,
+ ExceptionRecord->ExceptionCode,
+ (ULONG_PTR)ExceptionRecord->ExceptionAddress,
+ (ULONG_PTR)TrapFrame,
+ 0);
}
Handled:
/* Convert the context back into Trap/Exception Frames */
- KeContextToTrapFrame(&Context, NULL, TrapFrame, PreviousMode);
+ KeContextToTrapFrame(&Context,
+ ExceptionFrame,
+ TrapFrame,
+ Context.ContextFlags,
+ PreviousMode);
return;
}
/*
* @implemented
*/
-NTSTATUS STDCALL
+NTSTATUS
+NTAPI
KeRaiseUserException(IN NTSTATUS ExceptionCode)
{
- ULONG OldEip;
- PKTHREAD Thread = KeGetCurrentThread();
-
- _SEH_TRY {
- Thread->Teb->ExceptionCode = ExceptionCode;
- } _SEH_HANDLE {
- return(ExceptionCode);
- } _SEH_END;
-
- OldEip = Thread->TrapFrame->Eip;
- Thread->TrapFrame->Eip = (ULONG_PTR)KeRaiseUserExceptionDispatcher;
- return((NTSTATUS)OldEip);
-}
+ ULONG OldEip;
+ PTEB Teb = KeGetCurrentThread()->Teb;
+ PKTRAP_FRAME TrapFrame = KeGetCurrentThread()->TrapFrame;
+
+ /* Make sure we can access the TEB */
+ _SEH2_TRY
+ {
+ /* Set the exception code */
+ Teb->ExceptionCode = ExceptionCode;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Return the exception code */
+ _SEH2_YIELD(return _SEH2_GetExceptionCode());
+ }
+ _SEH2_END;
+ /* Get the old EIP */
+ OldEip = TrapFrame->Eip;
+
+ /* Change it to the user-mode dispatcher */
+ TrapFrame->Eip = (ULONG_PTR)KeRaiseUserExceptionDispatcher;
+
+ /* Return the old EIP */
+ return (NTSTATUS)OldEip;
+}