📄 exp.c
字号:
{
/* 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)
{
/* Make sure DR7 is valid */
if (TrapFrame->Dr7 & ~DR7_RESERVED_MASK)
{
/* 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
{
/* Otherwise clear DR registers */
Context->Dr0 =
Context->Dr1 =
Context->Dr3 =
Context->Dr6 =
Context->Dr7 = 0;
}
}
/* Restore IRQL */
if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql);
}
VOID
NTAPI
KiDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN PKTRAP_FRAME TrapFrame,
IN KPROCESSOR_MODE PreviousMode,
IN BOOLEAN FirstChance)
{
CONTEXT Context;
ULONG_PTR Stack, NewStack;
ULONG Size;
EXCEPTION_RECORD LocalExceptRecord;
_SEH_DECLARE_LOCALS(KiCopyInfo);
/* Increase number of Exception Dispatches */
KeGetCurrentPrcb()->KeExceptionDispatchCount++;
/* Set the context flags */
Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
/* Check if User Mode or if the debugger is enabled */
if ((PreviousMode == UserMode) || (KdDebuggerEnabled))
{
/* Add the FPU Flag */
Context.ContextFlags |= CONTEXT_FLOATING_POINT;
/* 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)
{
/* Check if this is a first-chance exception */
if (FirstChance == TRUE)
{
/* Break into the debugger for the first time */
if (KiDebugRoutine(TrapFrame,
ExceptionFrame,
ExceptionRecord,
&Context,
PreviousMode,
FALSE))
{
/* 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 */
if (KiDebugRoutine(TrapFrame,
ExceptionFrame,
ExceptionRecord,
&Context,
PreviousMode,
TRUE))
{
/* Exception was handled */
goto Handled;
}
/* Third strike; you're out */
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 */
if (PsGetCurrentProcess()->DebugPort)
{
/* FIXME : TODO */
//KEBUGCHECK(0);
}
else if (KiDebugRoutine(TrapFrame,
ExceptionFrame,
ExceptionRecord,
&Context,
PreviousMode,
FALSE))
{
/* Exception was handled */
goto Handled;
}
/* Forward exception to user mode debugger */
if (DbgkForwardException(ExceptionRecord, TRUE, FALSE)) goto Exit;
/* Set up the user-stack */
DispatchToUser:
_SEH_TRY
{
/* 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;
/* 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;
NewStack = Stack - Size;
/* Probe stack and copy exception record */
ProbeForWrite((PVOID)(NewStack - 2 * sizeof(ULONG_PTR)),
Size + 2 * sizeof(ULONG_PTR),
sizeof(ULONG));
RtlCopyMemory((PVOID)NewStack, ExceptionRecord, Size);
/* Now write the two params for the user-mode dispatcher */
*(PULONG_PTR)(NewStack - 1 * sizeof(ULONG_PTR)) = Stack;
*(PULONG_PTR)(NewStack - 2 * sizeof(ULONG_PTR)) = NewStack;
/* Set new Stack Pointer */
KiSsToTrapFrame(TrapFrame, KGDT_R3_DATA);
KiEspToTrapFrame(TrapFrame, NewStack - 2 * sizeof(ULONG_PTR));
/* 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;
/* Dispatch exception to user-mode */
_SEH_YIELD(return);
}
_SEH_EXCEPT(KiCopyInformation)
{
/* Check if we got a stack overflow and raise that instead */
if (_SEH_VAR(SehExceptRecord).ExceptionCode ==
STATUS_STACK_OVERFLOW)
{
/* Copy the exception address and record */
_SEH_VAR(SehExceptRecord).ExceptionAddress =
ExceptionRecord->ExceptionAddress;
RtlCopyMemory(ExceptionRecord,
(PVOID)&_SEH_VAR(SehExceptRecord),
sizeof(EXCEPTION_RECORD));
/* Do the exception again */
_SEH_YIELD(goto DispatchToUser);
}
}
_SEH_END;
}
/* Try second chance */
if (DbgkForwardException(ExceptionRecord, TRUE, FALSE))
{
/* Handled, get out */
goto Exit;
}
else if (DbgkForwardException(ExceptionRecord, FALSE, TRUE))
{
/* Handled, get out */
goto Exit;
}
/* 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,
ExceptionFrame,
TrapFrame,
Context.ContextFlags,
PreviousMode);
Exit:
return;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
KeRaiseUserException(IN NTSTATUS ExceptionCode)
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG OldEip;
PTEB Teb = KeGetCurrentThread()->Teb;
PKTRAP_FRAME TrapFrame = KeGetCurrentThread()->TrapFrame;
/* Make sure we can access the TEB */
_SEH_TRY
{
/* Set the exception code */
Teb->ExceptionCode = ExceptionCode;
}
_SEH_HANDLE
{
/* Save exception code */
Status = ExceptionCode;
}
_SEH_END;
if (!NT_SUCCESS(Status)) return Status;
/* 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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -