VOID
KiDispatchException (
IN PEXCEPTION_RECORD ExceptionRecord,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN PKTRAP_FRAME TrapFrame,
IN KPROCESSOR_MODE PreviousMode,
IN BOOLEAN FirstChance
)
{
CONTEXT ContextFrame;
EXCEPTION_RECORD ExceptionRecord1, ExceptionRecord2;
LONG Length;
ULONG UserStack1;
ULONG UserStack2;
KeGetCurrentPrcb()->KeExceptionDispatchCount +=
1;
ContextFrame.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
if ((PreviousMode == UserMode) || KdDebuggerEnabled) {
ContextFrame.ContextFlags |= CONTEXT_FLOATING_POINT;
if (KeI386XMMIPresent) {
ContextFrame.ContextFlags |= CONTEXT_EXTENDED_REGISTERS;
}
}
KeContextFromKframes(TrapFrame, ExceptionFrame, &ContextFrame);
switch (ExceptionRecord->ExceptionCode) {
case STATUS_BREAKPOINT:
ContextFrame.Eip--;
break;
case KI_EXCEPTION_ACCESS_VIOLATION:
ExceptionRecord->ExceptionCode = STATUS_ACCESS_VIOLATION;
if (PreviousMode == UserMode) {
if (KiCheckForAtlThunk(ExceptionRecord,&ContextFrame) != FALSE) {
goto Handled1;
}
if ((SharedUserData->ProcessorFeatures[PF_NX_ENABLED] == TRUE) &&
(ExceptionRecord->ExceptionInformation [
0] == EXCEPTION_EXECUTE_FAULT)) {
if (((KeFeatureBits & KF_GLOBAL_32BIT_EXECUTE) !=
0) ||
(PsGetCurrentProcess()->Pcb.Flags.ExecuteEnable !=
0) ||
(((KeFeatureBits & KF_GLOBAL_32BIT_NOEXECUTE) ==
0) &&
(PsGetCurrentProcess()->Pcb.Flags.ExecuteDisable ==
0))) {
ExceptionRecord->ExceptionInformation [
0] =
0;
}
}
}
break;
}
ASSERT ((
!((PreviousMode == KernelMode) &&
(ContextFrame.EFlags & EFLAGS_V86_MASK))
));
if (PreviousMode == KernelMode) {
if (FirstChance == TRUE) {
if ((KiDebugRoutine != NULL) &&
(((KiDebugRoutine) (TrapFrame,
ExceptionFrame,
ExceptionRecord,
&ContextFrame,
PreviousMode,
FALSE)) != FALSE)) {
goto Handled1;
}
if (RtlDispatchException(ExceptionRecord, &ContextFrame) == TRUE) {
goto Handled1;
}
}
if ((KiDebugRoutine != NULL) &&
(((KiDebugRoutine) (TrapFrame,
ExceptionFrame,
ExceptionRecord,
&ContextFrame,
PreviousMode,
TRUE)) != FALSE)) {
goto Handled1;
}
KeBugCheckEx(
KERNEL_MODE_EXCEPTION_NOT_HANDLED,
ExceptionRecord->ExceptionCode,
(ULONG)ExceptionRecord->ExceptionAddress,
(ULONG)TrapFrame,
0);
}
else {
if (FirstChance == TRUE) {
if ((KiDebugRoutine != NULL) &&
((PsGetCurrentProcess()->DebugPort == NULL &&
!KdIgnoreUmExceptions) ||
(KdIsThisAKdTrap(ExceptionRecord, &ContextFrame, UserMode)))) {
if ((((KiDebugRoutine) (TrapFrame,
ExceptionFrame,
ExceptionRecord,
&ContextFrame,
PreviousMode,
FALSE)) != FALSE)) {
goto Handled1;
}
}
if (DbgkForwardException(ExceptionRecord, TRUE, FALSE)) {
goto Handled2;
}
ExceptionRecord1.ExceptionCode =
0;
repeat:
try {
if (TrapFrame->HardwareSegSs != (KGDT_R3_DATA | RPL_MASK) ||
TrapFrame->EFlags & EFLAGS_V86_MASK ) {
ExceptionRecord2.ExceptionCode = STATUS_ACCESS_VIOLATION;
ExceptionRecord2.ExceptionFlags =
0;
ExceptionRecord2.NumberParameters =
0;
ExRaiseException(&ExceptionRecord2);
}
UserStack1 = (ContextFrame.Esp & ~CONTEXT_ROUND) - CONTEXT_ALIGNED_SIZE;
ProbeForWrite((PCHAR)UserStack1, CONTEXT_ALIGNED_SIZE, CONTEXT_ALIGN);
RtlCopyMemory((PULONG)UserStack1, &ContextFrame,
sizeof(CONTEXT));
Length = (
sizeof(EXCEPTION_RECORD) - (EXCEPTION_MAXIMUM_PARAMETERS -
ExceptionRecord->NumberParameters) *
sizeof(ULONG) +
3) &
(~
3);
UserStack2 = UserStack1 - Length;
ProbeForWrite((PCHAR)(UserStack2 -
8), Length +
8,
sizeof(ULONG));
RtlCopyMemory((PULONG)UserStack2, ExceptionRecord, Length);
*(PULONG)(UserStack2 -
sizeof(ULONG)) = UserStack1;
*(PULONG)(UserStack2 -
2*
sizeof(ULONG)) = UserStack2;
KiSegSsToTrapFrame(TrapFrame, KGDT_R3_DATA);
KiEspToTrapFrame(TrapFrame, (UserStack2 -
sizeof(ULONG)*
2));
TrapFrame->SegCs = SANITIZE_SEG(KGDT_R3_CODE, PreviousMode);
TrapFrame->SegDs = SANITIZE_SEG(KGDT_R3_DATA, PreviousMode);
TrapFrame->SegEs = SANITIZE_SEG(KGDT_R3_DATA, PreviousMode);
TrapFrame->SegFs = SANITIZE_SEG(KGDT_R3_TEB, PreviousMode);
TrapFrame->SegGs =
0;
TrapFrame->Eip = (ULONG)KeUserExceptionDispatcher;
return;
} except (KiCopyInformation(&ExceptionRecord1,
(GetExceptionInformation())->ExceptionRecord)) {
if (ExceptionRecord1.ExceptionCode == STATUS_STACK_OVERFLOW) {
ExceptionRecord1.ExceptionAddress = ExceptionRecord->ExceptionAddress;
RtlCopyMemory((PVOID)ExceptionRecord,
&ExceptionRecord1,
sizeof(EXCEPTION_RECORD));
goto repeat;
}
}
}
if (DbgkForwardException(ExceptionRecord, TRUE, TRUE)) {
goto Handled2;
}
else if (DbgkForwardException(ExceptionRecord, FALSE, TRUE)) {
goto Handled2;
}
else {
ZwTerminateProcess(NtCurrentProcess(), ExceptionRecord->ExceptionCode);
KeBugCheckEx(
KERNEL_MODE_EXCEPTION_NOT_HANDLED,
ExceptionRecord->ExceptionCode,
(ULONG)ExceptionRecord->ExceptionAddress,
(ULONG)TrapFrame,
0);
}
}
Handled1:
KeContextToKframes(TrapFrame, ExceptionFrame, &ContextFrame,
ContextFrame.ContextFlags, PreviousMode);
Handled2:
return;
}