exception.c
来自「一个类似windows」· C语言 代码 · 共 357 行
C
357 行
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Run-Time Library
* PURPOSE: User-mode exception support for IA-32
* FILE: lib/rtl/i386/exception.c
* PROGRAMERS: Alex Ionescu (alex@relsoft.net)
* Casper S. Hornstrup (chorns@users.sourceforge.net)
*/
/* INCLUDES *****************************************************************/
#include <rtl.h>
#define NDEBUG
#include <debug.h>
/* PRIVATE FUNCTIONS *********************************************************/
VOID
NTAPI
RtlpGetStackLimits(PULONG_PTR StackBase,
PULONG_PTR StackLimit);
PEXCEPTION_REGISTRATION_RECORD
NTAPI
RtlpGetExceptionList(VOID);
VOID
NTAPI
RtlpSetExceptionList(PEXCEPTION_REGISTRATION_RECORD NewExceptionList);
/* PUBLIC FUNCTIONS **********************************************************/
/*
* @unimplemented
*/
VOID
NTAPI
RtlGetCallersAddress(OUT PVOID *CallersAddress,
OUT PVOID *CallersCaller)
{
UNIMPLEMENTED;
}
/*
* @implemented
*/
BOOLEAN
NTAPI
RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
IN PCONTEXT Context)
{
PEXCEPTION_REGISTRATION_RECORD RegistrationFrame, NestedFrame = NULL;
PEXCEPTION_REGISTRATION_RECORD DispatcherContext;
EXCEPTION_RECORD ExceptionRecord2;
EXCEPTION_DISPOSITION ReturnValue;
ULONG_PTR StackLow, StackHigh;
ULONG_PTR RegistrationFrameEnd;
DPRINT("RtlDispatchException(): %p, %p \n", ExceptionRecord, Context);
/* Get the current stack limits and registration frame */
RtlpGetStackLimits(&StackLow, &StackHigh);
RegistrationFrame = RtlpGetExceptionList();
DPRINT("RegistrationFrame is 0x%p\n", RegistrationFrame);
/* Now loop every frame */
while (RegistrationFrame != EXCEPTION_CHAIN_END)
{
/* Find out where it ends */
RegistrationFrameEnd = (ULONG_PTR)RegistrationFrame +
sizeof(*RegistrationFrame);
/* Make sure the registration frame is located within the stack */
if ((RegistrationFrameEnd > StackHigh) ||
((ULONG_PTR)RegistrationFrame < StackLow) ||
((ULONG_PTR)RegistrationFrame & 0x3))
{
/* Check if this happened in the DPC Stack */
if (RtlpHandleDpcStackException(RegistrationFrame,
RegistrationFrameEnd,
&StackLow,
&StackHigh))
{
/* Use DPC Stack Limits and restart */
continue;
}
/* Set invalid stack and return false */
ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
DPRINT1("Invalid exception frame\n");
return FALSE;
}
/* Check if logging is enabled */
DPRINT("Checking for logging\n");
RtlpCheckLogException(ExceptionRecord,
Context,
RegistrationFrame,
sizeof(*RegistrationFrame));
/* Call the handler */
DPRINT("Executing handler: %p\n", RegistrationFrame->Handler);
ReturnValue = RtlpExecuteHandlerForException(ExceptionRecord,
RegistrationFrame,
Context,
&DispatcherContext,
RegistrationFrame->Handler);
DPRINT("Handler returned: %p\n", (PVOID)ReturnValue);
/* Check if this is a nested frame */
if (RegistrationFrame == NestedFrame)
{
/* Mask out the flag and the nested frame */
ExceptionRecord->ExceptionFlags &= ~EXCEPTION_NESTED_CALL;
NestedFrame = NULL;
}
/* Handle the dispositions */
if (ReturnValue == ExceptionContinueExecution)
{
/* Check if it was non-continuable */
if (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
{
/* Set up the exception record */
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
ExceptionRecord2.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION;
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
ExceptionRecord2.NumberParameters = 0;
/* Raise the exception */
DPRINT("Non-continuable\n");
RtlRaiseException(&ExceptionRecord2);
}
else
{
/* Return to caller */
return TRUE;
}
}
else if (ReturnValue == ExceptionNestedException)
{
/* Turn the nested flag on */
ExceptionRecord->ExceptionFlags |= EXCEPTION_NESTED_CALL;
/* Update the current nested frame */
if (NestedFrame < DispatcherContext) NestedFrame = DispatcherContext;
}
else if (ReturnValue == ExceptionContinueSearch)
{
/* Do nothing */
}
else
{
/* Set up the exception record */
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION;
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
ExceptionRecord2.NumberParameters = 0;
/* Raise the exception */
RtlRaiseException(&ExceptionRecord2);
}
/* Go to the next frame */
RegistrationFrame = RegistrationFrame->Next;
}
/* Unhandled, return false */
DPRINT("FALSE\n");
return FALSE;
}
/*
* @implemented
*/
VOID
NTAPI
RtlUnwind(PVOID RegistrationFrame OPTIONAL,
PVOID ReturnAddress OPTIONAL,
PEXCEPTION_RECORD ExceptionRecord OPTIONAL,
PVOID EaxValue)
{
PEXCEPTION_REGISTRATION_RECORD RegistrationFrame2, OldFrame;
PEXCEPTION_REGISTRATION_RECORD DispatcherContext;
EXCEPTION_RECORD ExceptionRecord2, ExceptionRecord3;
EXCEPTION_DISPOSITION ReturnValue;
ULONG_PTR StackLow, StackHigh;
ULONG_PTR RegistrationFrameEnd;
CONTEXT LocalContext;
PCONTEXT Context;
DPRINT("RtlUnwind(). RegistrationFrame 0x%p\n", RegistrationFrame);
/* Get the current stack limits */
RtlpGetStackLimits(&StackLow, &StackHigh);
/* Check if we don't have an exception record */
if (!ExceptionRecord)
{
/* Overwrite the argument */
ExceptionRecord = &ExceptionRecord3;
/* Setup a local one */
ExceptionRecord3.ExceptionFlags = 0;
ExceptionRecord3.ExceptionCode = STATUS_UNWIND;
ExceptionRecord3.ExceptionRecord = NULL;
ExceptionRecord3.ExceptionAddress = RtlpGetExceptionAddress();
ExceptionRecord3.NumberParameters = 0;
}
/* Check if we have a frame */
if (RegistrationFrame)
{
/* Set it as unwinding */
ExceptionRecord->ExceptionFlags |= EXCEPTION_UNWINDING;
}
else
{
/* Set the Exit Unwind flag as well */
ExceptionRecord->ExceptionFlags |= (EXCEPTION_UNWINDING |
EXCEPTION_EXIT_UNWIND);
}
/* Now capture the context */
Context = &LocalContext;
LocalContext.ContextFlags = CONTEXT_INTEGER |
CONTEXT_CONTROL |
CONTEXT_SEGMENTS;
RtlpCaptureContext(Context);
/* Pop the current arguments off */
Context->Esp += sizeof(RegistrationFrame) +
sizeof(ReturnAddress) +
sizeof(ExceptionRecord) +
sizeof(ReturnValue);
/* Set the new value for EAX */
Context->Eax = (ULONG)EaxValue;
/* Get the current frame */
RegistrationFrame2 = RtlpGetExceptionList();
/* Now loop every frame */
while (RegistrationFrame2 != EXCEPTION_CHAIN_END)
{
DPRINT("RegistrationFrame is 0x%p\n", RegistrationFrame2);
/* If this is the target */
if (RegistrationFrame2 == RegistrationFrame)
{
/* Continue execution */
ZwContinue(Context, FALSE);
}
/* Check if the frame is too low */
if ((RegistrationFrame) && ((ULONG_PTR)RegistrationFrame <
(ULONG_PTR)RegistrationFrame2))
{
/* Create an invalid unwind exception */
ExceptionRecord2.ExceptionCode = STATUS_INVALID_UNWIND_TARGET;
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
ExceptionRecord2.NumberParameters = 0;
/* Raise the exception */
DPRINT1("Frame is invalid\n");
RtlRaiseException(&ExceptionRecord2);
}
/* Find out where it ends */
RegistrationFrameEnd = (ULONG_PTR)RegistrationFrame2 +
sizeof(*RegistrationFrame2);
/* Make sure the registration frame is located within the stack */
if ((RegistrationFrameEnd > StackHigh) ||
((ULONG_PTR)RegistrationFrame < StackLow) ||
((ULONG_PTR)RegistrationFrame & 0x3))
{
/* Check if this happened in the DPC Stack */
if (RtlpHandleDpcStackException(RegistrationFrame,
RegistrationFrameEnd,
&StackLow,
&StackHigh))
{
/* Use DPC Stack Limits and restart */
continue;
}
/* Create an invalid stack exception */
ExceptionRecord2.ExceptionCode = STATUS_BAD_STACK;
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
ExceptionRecord2.NumberParameters = 0;
/* Raise the exception */
DPRINT1("Frame has bad stack\n");
RtlRaiseException(&ExceptionRecord2);
}
else
{
/* Call the handler */
DPRINT("Executing unwind handler: %p\n", RegistrationFrame2->Handler);
ReturnValue = RtlpExecuteHandlerForUnwind(ExceptionRecord,
RegistrationFrame2,
Context,
&DispatcherContext,
RegistrationFrame2->Handler);
DPRINT("Handler returned: %p\n", (PVOID)ReturnValue);
/* Handle the dispositions */
if (ReturnValue == ExceptionContinueSearch)
{
/* Do nothing */
}
else if (ReturnValue == ExceptionCollidedUnwind)
{
/* Get the previous frame */
RegistrationFrame2 = DispatcherContext;
}
else
{
/* Set up the exception record */
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION;
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
ExceptionRecord2.NumberParameters = 0;
/* Raise the exception */
RtlRaiseException(&ExceptionRecord2);
}
/* Go to the next frame */
OldFrame = RegistrationFrame2;
RegistrationFrame2 = RegistrationFrame2->Next;
/* Remove this handler */
if (RegistrationFrame2 != RegistrationFrame)
{
RtlpSetExceptionList(OldFrame);
}
}
}
/* Check if we reached the end */
if (RegistrationFrame == EXCEPTION_CHAIN_END)
{
/* Unwind completed, so we don't exit */
ZwContinue(Context, FALSE);
}
else
{
/* This is an exit_unwind or the frame wasn't present in the list */
ZwRaiseException(ExceptionRecord, Context, FALSE);
}
}
/* EOF */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?