-/* $Id$
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
+ * PROJECT: ReactOS Run-Time Library
* PURPOSE: User-mode exception support for IA-32
- * FILE: lib/ntdll/rtl/i386/exception.c
- * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * FILE: lib/rtl/i386/exception.c
+ * PROGRAMERS: Alex Ionescu (alex@relsoft.net)
+ * Casper S. Hornstrup (chorns@users.sourceforge.net)
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include <debug.h>
-/* FUNCTIONS ***************************************************************/
-
-/* Implemented in except.s */
+/* PRIVATE FUNCTIONS *********************************************************/
VOID
-RtlpCaptureContext(PCONTEXT pContext);
+STDCALL
+RtlpGetStackLimits(PULONG_PTR StackBase,
+ PULONG_PTR StackLimit);
-#define SehpGetStackLimits(StackBase, StackLimit) \
-{ \
- (*(StackBase)) = NtCurrentTeb()->Tib->StackBase; \
- (*(StackLimit)) = NtCurrentTeb()->Tib->StackLimit; \
-}
+PEXCEPTION_REGISTRATION_RECORD
+STDCALL
+RtlpGetExceptionList(VOID);
-#define SehpGetExceptionList() \
- (PEXCEPTION_REGISTRATION)(NtCurrentTeb()->Tib.ExceptionList)
+VOID
+STDCALL
+RtlpSetExceptionList(PEXCEPTION_REGISTRATION_RECORD NewExceptionList);
-#define SehpSetExceptionList(NewExceptionList) \
- NtCurrentTeb()->Tib.ExceptionList = (PVOID)(NewExceptionList)
+/* PUBLIC FUNCTIONS **********************************************************/
-VOID STDCALL
-AsmDebug(ULONG Value)
+/*
+ * @unimplemented
+ */
+VOID
+STDCALL
+RtlGetCallersAddress(OUT PVOID *CallersAddress,
+ OUT PVOID *CallersCaller)
{
- DbgPrint("Value 0x%.08x\n", Value);
+ UNIMPLEMENTED;
}
-
-/* Declare a few prototypes for the functions in except.s */
-
-EXCEPTION_DISPOSITION
-RtlpExecuteHandlerForException(
- PEXCEPTION_RECORD ExceptionRecord,
- PEXCEPTION_REGISTRATION RegistrationFrame,
- PCONTEXT Context,
- PVOID DispatcherContext,
- PEXCEPTION_HANDLER ExceptionHandler);
-
-EXCEPTION_DISPOSITION
-RtlpExecuteHandlerForUnwind(
- PEXCEPTION_RECORD ExceptionRecord,
- PEXCEPTION_REGISTRATION RegistrationFrame,
- PCONTEXT Context,
- PVOID DispatcherContext,
- PEXCEPTION_HANDLER ExceptionHandler);
-
-
-#ifndef NDEBUG
-
-VOID RtlpDumpExceptionRegistrations(VOID)
+/*
+ * @implemented
+ */
+BOOLEAN
+STDCALL
+RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PCONTEXT Context)
{
- PEXCEPTION_REGISTRATION Current;
-
- DbgPrint("Dumping exception registrations:\n");
-
- Current = SehpGetExceptionList();
-
- if ((ULONG_PTR)Current != -1)
- {
- while ((ULONG_PTR)Current != -1)
+ PEXCEPTION_REGISTRATION_RECORD RegistrationFrame, NestedFrame = NULL;
+ PEXCEPTION_REGISTRATION_RECORD DispatcherContext;
+ EXCEPTION_RECORD ExceptionRecord2;
+ EXCEPTION_DISPOSITION ReturnValue;
+ ULONG_PTR StackLow, StackHigh;
+ ULONG_PTR RegistrationFrameEnd;
+ DPRINT1("RtlDispatchException(): %p, %p \n", ExceptionRecord, Context);
+
+ /* Get the current stack limits and registration frame */
+ RtlpGetStackLimits(&StackLow, &StackHigh);
+ RegistrationFrame = RtlpGetExceptionList();
+ DPRINT1("RegistrationFrame is 0x%X\n", RegistrationFrame);
+
+ /* Now loop every frame */
+ while (RegistrationFrame != EXCEPTION_CHAIN_END)
{
- DbgPrint(" (0x%08X) HANDLER (0x%08X)\n", Current, Current->handler);
- Current = Current->prev;
- }
- DbgPrint(" End-Of-List\n");
- } else {
- DbgPrint(" No exception registrations exists.\n");
- }
-}
-
-#endif /* NDEBUG */
-
-ULONG
-RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
- IN PCONTEXT Context)
-{
- PEXCEPTION_REGISTRATION RegistrationFrame, NestedFrame = NULL, DispatcherContext;
- DWORD ReturnValue;
-
- DPRINT("RtlpDispatchException()\n");
-
-#ifndef NDEBUG
- RtlpDumpExceptionRegistrations();
-#endif /* NDEBUG */
-
- RegistrationFrame = SehpGetExceptionList();
+ /* 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;
+ }
- DPRINT("RegistrationFrame is 0x%X\n", RegistrationFrame);
+ /* Check if logging is enabled */
+ DPRINT1("Checking for logging\n");
+ RtlpCheckLogException(ExceptionRecord,
+ Context,
+ RegistrationFrame,
+ sizeof(*RegistrationFrame));
+
+ /* Call the handler */
+ DPRINT1("Executing handler: %p\n", RegistrationFrame->Handler);
+ ReturnValue = RtlpExecuteHandlerForException(ExceptionRecord,
+ RegistrationFrame,
+ Context,
+ &DispatcherContext,
+ RegistrationFrame->Handler);
+ DPRINT1("Handler returned: %lx\n", 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;
+ }
- while ((ULONG_PTR)RegistrationFrame != (ULONG_PTR)-1)
- {
- EXCEPTION_RECORD ExceptionRecord2;
- //PVOID RegistrationFrameEnd = (PVOID)RegistrationFrame + 8;
+ /* 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 */
+ DPRINT1("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;
- // Make sure the registration frame is located within the stack
+ /* Update the current nested frame */
+ if (NestedFrame < DispatcherContext) NestedFrame = DispatcherContext;
+ }
+ else if (ReturnValue == ExceptionContinueSearch)
+ {
+ }
+ 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);
+ }
- DPRINT("Error checking\n");
-#if 0
- if (Teb->Tib.StackBase > RegistrationFrameEnd)
- {
- DPRINT("Teb->Tib.StackBase (0x%.08x) > RegistrationFrameEnd (0x%.08x)\n",
- Teb->Tib.StackBase, RegistrationFrameEnd);
- ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
- return ExceptionContinueExecution;
- }
- // FIXME: Stack top, correct?
- if (Teb->Tib.StackLimit < RegistrationFrameEnd)
- {
- DPRINT("Teb->Tib.StackLimit (0x%.08x) > RegistrationFrameEnd (0x%.08x)\n",
- Teb->Tib.StackLimit, RegistrationFrameEnd);
- ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
- return ExceptionContinueExecution;
+ /* Go to the next frame */
+ RegistrationFrame = RegistrationFrame->Next;
}
- // Make sure stack is DWORD aligned
- if ((ULONG_PTR)RegistrationFrame & 3)
- {
- DPRINT("RegistrationFrameEnd (0x%.08x) is not DWORD aligned.\n",
- RegistrationFrameEnd);
- ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
- return ExceptionContinueExecution;
- }
-#endif
-
-#if 0
- /* FIXME: */
- if (someFlag)
- RtlpLogLastExceptionDisposition( hLog, retValue );
-#endif
-
- DPRINT("Calling handler at 0x%X\n", RegistrationFrame->handler);
- DPRINT("ExceptionRecord 0x%X\n", ExceptionRecord);
- DPRINT("RegistrationFrame 0x%X\n", RegistrationFrame);
- DPRINT("Context 0x%X\n", Context);
- DPRINT("&DispatcherContext 0x%X\n", &DispatcherContext);
-
- ReturnValue = RtlpExecuteHandlerForException(
- ExceptionRecord,
- RegistrationFrame,
- Context,
- &DispatcherContext,
- RegistrationFrame->handler);
-#ifdef DEBUG
- DPRINT("Exception handler said 0x%X\n", ReturnValue);
- DPRINT("RegistrationFrame == 0x%.08x\n", RegistrationFrame);
- {
- PULONG sp = (PULONG)((PVOID)RegistrationFrame - 0x08);
- DPRINT("StandardESP == 0x%.08x\n", sp[0]);
- DPRINT("Exception Pointers == 0x%.08x\n", sp[1]);
- DPRINT("PrevFrame == 0x%.08x\n", sp[2]);
- DPRINT("Handler == 0x%.08x\n", sp[3]);
- DPRINT("ScopeTable == 0x%.08x\n", sp[4]);
- DPRINT("TryLevel == 0x%.08x\n", sp[5]);
- DPRINT("EBP == 0x%.08x\n", sp[6]);
- }
-#endif
- if (RegistrationFrame == NestedFrame)
- {
- ExceptionRecord->ExceptionFlags &= ~EXCEPTION_NESTED_CALL; // Turn off flag
- NestedFrame = NULL;
- }
+ /* Unhandled, return false */
+ DPRINT1("FALSE:(\n");
+ return FALSE;
+}
- if (ReturnValue == ExceptionContinueExecution)
+/*
+ * @implemented
+ */
+VOID
+STDCALL
+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;
+ DPRINT1("RtlUnwind(). RegistrationFrame 0x%X\n", RegistrationFrame);
+
+ /* Get the current stack limits */
+ RtlpGetStackLimits(&StackLow, &StackHigh);
+
+ /* Check if we don't have an exception record */
+ if (!ExceptionRecord)
{
- DPRINT("ReturnValue == ExceptionContinueExecution\n");
- if (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
- {
- DPRINT("(ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE) == TRUE\n");
-
- ExceptionRecord2.ExceptionRecord = ExceptionRecord;
- ExceptionRecord2.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION;
- ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
- ExceptionRecord2.NumberParameters = 0;
- RtlRaiseException(&ExceptionRecord2);
- }
- else
- {
- /* Copy the (possibly changed) context back to the trap frame and return */
- ZwContinue(Context, FALSE);
- return ExceptionContinueExecution;
- }
+ /* 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;
}
- else if (ReturnValue == ExceptionContinueSearch)
- {
- DPRINT("ReturnValue == ExceptionContinueSearch\n");
- /* Nothing to do here */
- }
- else if (ReturnValue == ExceptionNestedException)
+ /* Check if we have a frame */
+ if (RegistrationFrame)
{
- DPRINT("ReturnValue == ExceptionNestedException\n");
-
- ExceptionRecord->ExceptionFlags |= EXCEPTION_NESTED_CALL;
- if (NestedFrame < DispatcherContext)
- {
- NestedFrame = DispatcherContext;
- }
+ /* Set it as unwinding */
+ ExceptionRecord->ExceptionFlags |= EXCEPTION_UNWINDING;
}
- else /* if (ReturnValue == ExceptionCollidedUnwind) */
+ else
{
- DPRINT("ReturnValue == ExceptionCollidedUnwind or unknown\n");
-
- ExceptionRecord2.ExceptionRecord = ExceptionRecord;
- ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION;
- ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
- ExceptionRecord2.NumberParameters = 0;
- RtlRaiseException(&ExceptionRecord2);
+ /* Set the Exit Unwind flag as well */
+ ExceptionRecord->ExceptionFlags |= (EXCEPTION_UNWINDING |
+ EXCEPTION_EXIT_UNWIND);
}
- RegistrationFrame = RegistrationFrame->prev; // Go to previous frame
- }
+ /* Now capture the context */
+ Context = &LocalContext;
+ LocalContext.ContextFlags = CONTEXT_INTEGER |
+ CONTEXT_CONTROL |
+ CONTEXT_SEGMENTS;
+ RtlpCaptureContext(Context);
- /* No exception handler will handle this exception */
+ /* Pop the current arguments off */
+ LocalContext.Esp += sizeof(RegistrationFrame) +
+ sizeof(ReturnAddress) +
+ sizeof(ExceptionRecord) +
+ sizeof(ReturnValue);
- DPRINT("RtlpDispatchException(): Return ExceptionContinueExecution\n");
+ /* Set the new value for EAX */
+ LocalContext.Eax = (ULONG)EaxValue;
- ExceptionRecord->ExceptionFlags = EXCEPTION_NONCONTINUABLE;
+ /* Get the current frame */
+ RegistrationFrame2 = RtlpGetExceptionList();
- return ExceptionContinueExecution;
-}
-
-
-/*
- * @implemented
- */
-VOID STDCALL
-RtlUnwind(PEXCEPTION_REGISTRATION RegistrationFrame,
- PVOID ReturnAddress,
- PEXCEPTION_RECORD ExceptionRecord,
- DWORD EaxValue)
-{
- PEXCEPTION_REGISTRATION ERHead;
- PEXCEPTION_RECORD pExceptRec;
- EXCEPTION_RECORD TempER;
- CONTEXT Context;
-
- DPRINT("RtlUnwind(). RegistrationFrame 0x%X\n", RegistrationFrame);
-
-#ifndef NDEBUG
- RtlpDumpExceptionRegistrations();
-#endif /* NDEBUG */
-
- ERHead = SehpGetExceptionList();
-
- DPRINT("ERHead is 0x%X\n", ERHead);
-
- if (ExceptionRecord == NULL) // The normal case
- {
- DPRINT("ExceptionRecord == NULL (normal)\n");
-
- pExceptRec = &TempER;
- pExceptRec->ExceptionFlags = 0;
- pExceptRec->ExceptionCode = STATUS_UNWIND;
- pExceptRec->ExceptionRecord = NULL;
- pExceptRec->ExceptionAddress = ReturnAddress;
- pExceptRec->ExceptionInformation[0] = 0;
- }
- else
- {
- pExceptRec = ExceptionRecord;
- }
-
- if (RegistrationFrame)
- pExceptRec->ExceptionFlags |= EXCEPTION_UNWINDING;
- else
- pExceptRec->ExceptionFlags |= (EXCEPTION_UNWINDING|EXCEPTION_EXIT_UNWIND);
-
-#ifndef NDEBUG
- DPRINT("ExceptionFlags == 0x%x:\n", pExceptRec->ExceptionFlags);
- if (pExceptRec->ExceptionFlags & EXCEPTION_UNWINDING)
- {
- DPRINT(" * EXCEPTION_UNWINDING (0x%x)\n", EXCEPTION_UNWINDING);
- }
- if (pExceptRec->ExceptionFlags & EXCEPTION_EXIT_UNWIND)
- {
- DPRINT(" * EXCEPTION_EXIT_UNWIND (0x%x)\n", EXCEPTION_EXIT_UNWIND);
- }
-#endif /* NDEBUG */
-
- Context.ContextFlags =
- (CONTEXT_i386 | CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS);
-
- RtlpCaptureContext(&Context);
-
- DPRINT("Context.Eip = 0x%.08x\n", Context.Eip);
- DPRINT("Context.Ebp = 0x%.08x\n", Context.Ebp);
- DPRINT("Context.Esp = 0x%.08x\n", Context.Esp);
-
- Context.Esp += 0x10;
- Context.Eax = EaxValue;
-
- // Begin traversing the list of EXCEPTION_REGISTRATION
- while ((ULONG_PTR)ERHead != (ULONG_PTR)-1 && ERHead != RegistrationFrame)
- {
- EXCEPTION_RECORD er2;
-
- DPRINT("ERHead 0x%X\n", ERHead);
-
- // If there's an exception frame, but it's lower on the stack
- // than the head of the exception list, something's wrong!
- if (RegistrationFrame && (RegistrationFrame <= ERHead))
+ /* Now loop every frame */
+ while (RegistrationFrame2 != EXCEPTION_CHAIN_END)
{
- DPRINT("The exception frame is bad\n");
-
- // Generate an exception to bail out
- er2.ExceptionRecord = pExceptRec;
- er2.NumberParameters = 0;
- er2.ExceptionCode = STATUS_INVALID_UNWIND_TARGET;
- er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
+ DPRINT1("RegistrationFrame is 0x%X\n", RegistrationFrame2);
- RtlRaiseException(&er2);
- }
-
-#if 0
- Stack = ERHead + sizeof(EXCEPTION_REGISTRATION);
- if ( (Teb->Tib.StackBase <= (PVOID)ERHead ) // Make sure that ERHead
- && (Teb->Tib.->StackLimit >= (PVOID)Stack ) // is in range, and a multiple
- && (0 == ((ULONG_PTR)ERHead & 3)) ) // of 4 (i.e., sane)
-#else
- if (1)
-#endif
- {
- PEXCEPTION_REGISTRATION NewERHead;
- PEXCEPTION_REGISTRATION pCurrExceptReg;
- EXCEPTION_DISPOSITION ReturnValue;
-
- DPRINT("Executing handler at 0x%X for unwind\n", ERHead->handler);
-
- ReturnValue = RtlpExecuteHandlerForUnwind(
- pExceptRec,
- ERHead,
- &Context,
- &NewERHead,
- ERHead->handler);
-
- DPRINT("Handler at 0x%X returned 0x%X\n", ERHead->handler, ReturnValue);
+ /* If this is the target */
+ if (RegistrationFrame2 == RegistrationFrame)
+ {
+ /* Continue execution */
+ ZwContinue(Context, FALSE);
+ }
- if (ReturnValue != ExceptionContinueSearch)
- {
- if (ReturnValue != ExceptionCollidedUnwind)
+ /* Check if the frame is too low */
+ if ((RegistrationFrame) && ((ULONG_PTR)RegistrationFrame <
+ (ULONG_PTR)RegistrationFrame2))
{
- DPRINT("Bad return value\n");
+ /* 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);
+ }
- er2.ExceptionRecord = pExceptRec;
- er2.NumberParameters = 0;
- er2.ExceptionCode = STATUS_INVALID_DISPOSITION;
- er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
+ /* Find out where it ends */
+ RegistrationFrameEnd = (ULONG_PTR)RegistrationFrame2 +
+ sizeof(*RegistrationFrame2);
- RtlRaiseException(&er2);
+ /* 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
{
- ERHead = NewERHead;
+ /* Call the handler */
+ DPRINT1("Executing unwind handler: %p\n", RegistrationFrame2->Handler);
+ ReturnValue = RtlpExecuteHandlerForUnwind(ExceptionRecord,
+ RegistrationFrame2,
+ Context,
+ &DispatcherContext,
+ RegistrationFrame2->Handler);
+ DPRINT1("Handler returned: %lx\n", ReturnValue);
+
+ /* Handle the dispositions */
+ if (ReturnValue == ExceptionContinueSearch)
+ {
+ /* Get out of here */
+ break;
+ }
+ 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 */
+ RtlpSetExceptionList(OldFrame);
}
- }
-
- pCurrExceptReg = ERHead;
- ERHead = ERHead->prev;
-
- DPRINT("New ERHead is 0x%X\n", ERHead);
-
- DPRINT("Setting exception registration at 0x%X as current\n",
- /*RegistrationFrame->prev*/ pCurrExceptReg->prev);
+ }
- // Unlink the exception handler
- SehpSetExceptionList(pCurrExceptReg->prev);
+ /* Check if we reached the end */
+ if (RegistrationFrame == EXCEPTION_CHAIN_END)
+ {
+ /* Unwind completed, so we don't exit */
+ ZwContinue(Context, FALSE);
}
- else // The stack looks goofy! Raise an exception to bail out
+ else
{
- DPRINT("Bad stack\n");
-
- er2.ExceptionRecord = pExceptRec;
- er2.NumberParameters = 0;
- er2.ExceptionCode = STATUS_BAD_STACK;
- er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
-
- RtlRaiseException(&er2);
+ /* This is an exit_unwind or the frame wasn't present in the list */
+ ZwRaiseException(ExceptionRecord, Context, FALSE);
}
- }
}
/* EOF */