3 modified files
reactos/lib/ntdll/rtl/i386
diff -N except.s
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ except.s 25 Jun 2004 16:39:41 -0000 1.5
@@ -0,0 +1,291 @@
+/* $Id: except.s,v 1.5 2004/06/25 16:39:41 weiden Exp $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * PURPOSE: User-mode exception support for IA-32
+ * FILE: lib/ntdll/rtl/i386/except.s
+ * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * NOTES: This file is shared with ntoskrnl/rtl/i386/except.s.
+ * Please keep them in sync.
+ */
+
+#define EXCEPTION_UNWINDING 0x02
+
+#define EREC_FLAGS 0x04
+
+#define ExceptionContinueExecution 0
+#define ExceptionContinueSearch 1
+#define ExceptionNestedException 2
+#define ExceptionCollidedUnwind 3
+
+.globl _RtlpExecuteHandlerForException
+.globl _RtlpExecuteHandlerForUnwind
+
+#define CONTEXT_FLAGS 0x00
+#define CONTEXT_SEGGS 0x8C
+#define CONTEXT_SEGFS 0x90
+#define CONTEXT_SEGES 0x94
+#define CONTEXT_SEGDS 0x98
+#define CONTEXT_EDI 0x9C
+#define CONTEXT_ESI 0xA0
+#define CONTEXT_EBX 0xA4
+#define CONTEXT_EDX 0xA8
+#define CONTEXT_ECX 0xAC
+#define CONTEXT_EAX 0xB0
+#define CONTEXT_EBP 0xB4
+#define CONTEXT_EIP 0xB8
+#define CONTEXT_SEGCS 0xBC
+#define CONTEXT_EFLAGS 0xC0
+#define CONTEXT_ESP 0xC4
+#define CONTEXT_SEGSS 0xC8
+
+
+#define RCC_CONTEXT 0x08
+
+// EAX = value to print
+_do_debug:
+ pushal
+ pushl %eax
+ call _AsmDebug@4
+ popal
+ ret
+
+#ifndef __NTOSKRNL__
+
+//
+// VOID
+// RtlpCaptureContext(PCONTEXT pContext);
+//
+// Parameters:
+// [ESP+08h] - PCONTEXT_X86 pContext
+// Registers:
+// None
+// Returns:
+// Nothing
+// Notes:
+// Grabs the current CPU context.
+.globl _RtlpCaptureContext
+_RtlpCaptureContext:
+ pushl %ebp
+ movl %esp, %ebp
+ movl RCC_CONTEXT(%ebp), %edx // EDX = Address of context structure
+
+ cld
+ pushf
+ pop %eax
+ movl %eax, CONTEXT_EFLAGS(%edx)
+ xorl %eax, %eax
+ movl %eax, CONTEXT_EAX(%edx)
+ movl %eax, CONTEXT_EBX(%edx)
+ movl %eax, CONTEXT_ECX(%edx)
+ movl %eax, CONTEXT_EDX(%edx)
+ movl %eax, CONTEXT_ESI(%edx)
+ movl %eax, CONTEXT_EDI(%edx)
+ movl %cs, %eax
+ movl %eax, CONTEXT_SEGCS(%edx)
+ movl %ds, %eax
+ movl %eax, CONTEXT_SEGDS(%edx)
+ movl %es, %eax
+ movl %eax, CONTEXT_SEGES(%edx)
+ movl %fs, %eax
+ movl %eax, CONTEXT_SEGFS(%edx)
+ movl %gs, %eax
+ movl %eax, CONTEXT_SEGGS(%edx)
+ movl %ss, %eax
+ movl %eax, CONTEXT_SEGSS(%edx)
+
+ //
+ // STACK LAYOUT: - (ESP to put in context structure)
+ // - RETURN ADDRESS OF CALLER OF CALLER
+ // - EBP OF CALLER OF CALLER
+ // ...
+ // - RETURN ADDRESS OF CALLER
+ // - EBP OF CALLER
+ // ...
+ //
+
+ // Get return address of the caller of the caller of this function
+ movl %ebp, %ebx
+ //movl 4(%ebx), %eax // EAX = return address of caller
+ movl (%ebx), %ebx // EBX = EBP of caller
+
+ movl 4(%ebx), %eax // EAX = return address of caller of caller
+ movl (%ebx), %ebx // EBX = EBP of caller of caller
+
+ movl %eax, CONTEXT_EIP(%edx) // EIP = return address of caller of caller
+ movl %ebx, CONTEXT_EBP(%edx) // EBP = EBP of caller of caller
+ addl $8, %ebx
+ movl %ebx, CONTEXT_ESP(%edx) // ESP = EBP of caller of caller + 8
+
+ movl %ebp, %esp
+ popl %ebp
+ ret
+
+#endif /* !__NTOSKRNL__ */
+
+#define REH_ERECORD 0x08
+#define REH_RFRAME 0x0C
+#define REH_CONTEXT 0x10
+#define REH_DCONTEXT 0x14
+#define REH_EROUTINE 0x18
+
+// Parameters:
+// None
+// Registers:
+// [EBP+08h] - PEXCEPTION_RECORD ExceptionRecord
+// [EBP+0Ch] - PEXCEPTION_REGISTRATION RegistrationFrame
+// [EBP+10h] - PVOID Context
+// [EBP+14h] - PVOID DispatcherContext
+// [EBP+18h] - PEXCEPTION_HANDLER ExceptionRoutine
+// EDX - Address of protecting exception handler
+// Returns:
+// EXCEPTION_DISPOSITION
+// Notes:
+// Setup the protecting exception handler and call the exception
+// handler in the right context.
+_RtlpExecuteHandler:
+ pushl %ebp
+ movl %esp, %ebp
+ pushl REH_RFRAME(%ebp)
+
+ pushl %edx
+ pushl %fs:0x0
+ movl %esp, %fs:0x0
+
+ // Prepare to call the exception handler
+ pushl REH_DCONTEXT(%ebp)
+ pushl REH_CONTEXT(%ebp)
+ pushl REH_RFRAME(%ebp)
+ pushl REH_ERECORD(%ebp)
+
+ // Now call the exception handler
+ movl REH_EROUTINE(%ebp), %eax
+ call *%eax
+
+ cmpl $-1, %fs:0x0
+ jne .reh_stack_looks_ok
+
+ // This should not happen
+ pushl 0
+ pushl 0
+ pushl 0
+ pushl 0
+ call _RtlAssert@16
+
+.reh_loop:
+ jmp .reh_loop
+
+.reh_stack_looks_ok:
+ movl %fs:0x0, %esp
+
+ // Return to the 'front-end' for this function
+ popl %fs:0x0
+ movl %ebp, %esp
+ popl %ebp
+ ret
+
+
+#define REP_ERECORD 0x04
+#define REP_RFRAME 0x08
+#define REP_CONTEXT 0x0C
+#define REP_DCONTEXT 0x10
+
+// Parameters:
+// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord
+// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
+// [ESP+0Ch] - PCONTEXT Context
+// [ESP+10h] - PVOID DispatcherContext
+// Registers:
+// None
+// Returns:
+// EXCEPTION_DISPOSITION
+// Notes:
+// This exception handler protects the exception handling
+// mechanism by detecting nested exceptions.
+_RtlpExceptionProtector:
+ movl $ExceptionContinueSearch, %eax
+ movl REP_ERECORD(%esp), %ecx
+ testl $EXCEPTION_UNWINDING, EREC_FLAGS(%ecx)
+ jnz .rep_end
+
+ // Unwinding is not taking place, so return ExceptionNestedException
+
+ // Set DispatcherContext field to the exception registration for the
+ // exception handler that executed when a nested exception occurred
+ movl REP_DCONTEXT(%esp), %ecx
+ movl REP_RFRAME(%esp), %eax
+ movl %eax, (%ecx)
+ movl $ExceptionNestedException, %eax
+
+.rep_end:
+ ret
+
+
+// Parameters:
+// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord
+// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
+// [ESP+0Ch] - PCONTEXT Context
+// [ESP+10h] - PVOID DispatcherContext
+// [ESP+14h] - PEXCEPTION_HANDLER ExceptionHandler
+// Registers:
+// None
+// Returns:
+// EXCEPTION_DISPOSITION
+// Notes:
+// Front-end
+_RtlpExecuteHandlerForException:
+ movl $_RtlpExceptionProtector, %edx
+ jmp _RtlpExecuteHandler
+
+
+#define RUP_ERECORD 0x04
+#define RUP_RFRAME 0x08
+#define RUP_CONTEXT 0x0C
+#define RUP_DCONTEXT 0x10
+
+// Parameters:
+// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord
+// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
+// [ESP+0Ch] - PCONTEXT Context
+// [ESP+10h] - PVOID DispatcherContext
+// Registers:
+// None
+// Returns:
+// EXCEPTION_DISPOSITION
+// Notes:
+// This exception handler protects the exception handling
+// mechanism by detecting collided unwinds.
+_RtlpUnwindProtector:
+ movl $ExceptionContinueSearch, %eax
+ movl %ecx, RUP_ERECORD(%esp)
+ testl $EXCEPTION_UNWINDING, EREC_FLAGS(%ecx)
+ jz .rup_end
+
+ // Unwinding is taking place, so return ExceptionCollidedUnwind
+
+ movl RUP_RFRAME(%esp), %ecx
+ movl RUP_DCONTEXT(%esp), %edx
+
+ // Set DispatcherContext field to the exception registration for the
+ // exception handler that executed when a collision occurred
+ movl RUP_RFRAME(%ecx), %eax
+ movl %eax, (%edx)
+ movl $ExceptionCollidedUnwind, %eax
+
+.rup_end:
+ ret
+
+
+// Parameters:
+// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord
+// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
+// [ESP+0Ch] - PCONTEXT Context
+// [ESP+10h] - PVOID DispatcherContext
+// [ESP+14h] - PEXCEPTION_HANDLER ExceptionHandler
+// Registers:
+// None
+// Returns:
+// EXCEPTION_DISPOSITION
+_RtlpExecuteHandlerForUnwind:
+ movl $_RtlpUnwindProtector, %edx
+ jmp _RtlpExecuteHandler
reactos/lib/ntdll/rtl/i386
diff -N exception.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ exception.c 25 Jun 2004 16:39:41 -0000 1.9
@@ -0,0 +1,446 @@
+/* $Id: exception.c,v 1.9 2004/06/25 16:39:41 weiden Exp $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * PURPOSE: User-mode exception support for IA-32
+ * FILE: lib/ntdll/rtl/i386/exception.c
+ * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include <windows.h>
+#include <string.h>
+
+#define NDEBUG
+#include <debug.h>
+
+/* FUNCTIONS ***************************************************************/
+
+/* Implemented in except.s */
+
+VOID
+RtlpCaptureContext(PCONTEXT pContext);
+
+/* Macros that will help streamline the SEH implementations for
+ kernel mode and user mode */
+
+#define SehpGetStackLimits(StackBase, StackLimit) \
+{ \
+ (*(StackBase)) = NtCurrentTeb()->Tib->StackBase; \
+ (*(StackLimit)) = NtCurrentTeb()->Tib->StackLimit; \
+}
+
+#define SehpGetExceptionList() \
+ (PEXCEPTION_REGISTRATION)(NtCurrentTeb()->Tib.ExceptionList)
+
+#define SehpSetExceptionList(NewExceptionList) \
+ NtCurrentTeb()->Tib.ExceptionList = (PVOID)(NewExceptionList)
+
+#define SehpCaptureContext(Context) \
+{ \
+ RtlpCaptureContext(Context); \
+}
+
+#define SehpContinue(Context, TestAlert) \
+ NtContinue(Context, TestAlert)
+
+/*** Code below this line is shared with ntoskrnl/rtl/i386/exception.c - please keep in sync ***/
+
+VOID STDCALL
+AsmDebug(ULONG Value)
+{
+ DbgPrint("Value 0x%.08x\n", Value);
+}
+
+
+/* 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)
+{
+ PEXCEPTION_REGISTRATION Current;
+
+ DbgPrint("Dumping exception registrations:\n");
+
+ Current = SehpGetExceptionList();
+
+ if ((ULONG_PTR)Current != -1)
+ {
+ while ((ULONG_PTR)Current != -1)
+ {
+ 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;
+ DWORD DispatcherContext;
+ DWORD ReturnValue;
+
+ DPRINT("RtlpDispatchException()\n");
+
+#ifndef NDEBUG
+ RtlpDumpExceptionRegistrations();
+#endif /* NDEBUG */
+
+ RegistrationFrame = SehpGetExceptionList();
+
+ DPRINT("RegistrationFrame is 0x%X\n", RegistrationFrame);
+
+ while ((ULONG_PTR)RegistrationFrame != -1)
+ {
+ EXCEPTION_RECORD ExceptionRecord2;
+ DWORD Temp = 0;
+ //PVOID RegistrationFrameEnd = (PVOID)RegistrationFrame + 8;
+
+ // Make sure the registration frame is located within the stack
+
+ 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;
+ }
+
+ // 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 == NULL)
+ {
+ ExceptionRecord->ExceptionFlags &= ~EXCEPTION_NESTED_CALL; // Turn off flag
+ }
+
+ if (ReturnValue == ExceptionContinueExecution)
+ {
+ 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 */
+ SehpContinue(Context, FALSE);
+ return ExceptionContinueExecution;
+ }
+ }
+ else if (ReturnValue == ExceptionContinueSearch)
+ {
+ DPRINT("ReturnValue == ExceptionContinueSearch\n");
+
+ /* Nothing to do here */
+ }
+ else if (ReturnValue == ExceptionNestedException)
+ {
+ DPRINT("ReturnValue == ExceptionNestedException\n");
+
+ ExceptionRecord->ExceptionFlags |= EXCEPTION_EXIT_UNWIND;
+ if (DispatcherContext > Temp)
+ {
+ Temp = DispatcherContext;
+ }
+ }
+ else /* if (ReturnValue == ExceptionCollidedUnwind) */
+ {
+ DPRINT("ReturnValue == ExceptionCollidedUnwind or unknown\n");
+
+ ExceptionRecord2.ExceptionRecord = ExceptionRecord;
+ ExceptionRecord2.ExceptionCode = STATUS_INVALID_DISPOSITION;
+ ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
+ ExceptionRecord2.NumberParameters = 0;
+ RtlRaiseException(&ExceptionRecord2);
+ }
+
+ RegistrationFrame = RegistrationFrame->prev; // Go to previous frame
+ }
+
+ /* No exception handler will handle this exception */
+
+ DPRINT("RtlpDispatchException(): Return ExceptionContinueExecution\n");
+
+ return ExceptionContinueExecution;
+}
+
+/*
+ * @implemented
+ */
+VOID STDCALL
+RtlRaiseStatus(NTSTATUS Status)
+{
+ EXCEPTION_RECORD ExceptionRecord;
+
+ DPRINT("RtlRaiseStatus(Status 0x%.08x)\n", Status);
+
+ ExceptionRecord.ExceptionCode = Status;
+ ExceptionRecord.ExceptionRecord = NULL;
+ ExceptionRecord.NumberParameters = 0;
+ ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
+ RtlRaiseException (& ExceptionRecord);
+}
+
+/*
+ * @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);
+
+ SehpCaptureContext(&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 != -1)
+ {
+ EXCEPTION_RECORD er2;
+
+ DPRINT("ERHead 0x%X\n", ERHead);
+
+ if (ERHead == RegistrationFrame)
+ {
+ DPRINT("Continueing execution\n");
+ SehpContinue(&Context, FALSE);
+ return;
+ }
+ else
+ {
+ // 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))
+ {
+ 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;
+
+ 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 (ReturnValue != ExceptionContinueSearch)
+ {
+ if (ReturnValue != ExceptionCollidedUnwind)
+ {
+ DPRINT("Bad return value\n");
+
+ er2.ExceptionRecord = pExceptRec;
+ er2.NumberParameters = 0;
+ er2.ExceptionCode = STATUS_INVALID_DISPOSITION;
+ er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
+
+ RtlRaiseException(&er2);
+ }
+ else
+ {
+ ERHead = NewERHead;
+ }
+ }
+
+ 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);
+
+ // Unlink the exception handler
+ SehpSetExceptionList(RegistrationFrame->prev);
+ }
+ else // The stack looks goofy! Raise an exception to bail out
+ {
+ DPRINT("Bad stack\n");
+
+ er2.ExceptionRecord = pExceptRec;
+ er2.NumberParameters = 0;
+ er2.ExceptionCode = STATUS_BAD_STACK;
+ er2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
+
+ RtlRaiseException(&er2);
+ }
+ }
+
+ // If we get here, we reached the end of the EXCEPTION_REGISTRATION list.
+ // This shouldn't happen normally.
+
+ DPRINT("Ran out of exception registrations. RegistrationFrame is (0x%X)\n",
+ RegistrationFrame);
+
+ if ((ULONG_PTR)RegistrationFrame == -1)
+ SehpContinue(&Context, FALSE);
+ else
+ NtRaiseException(pExceptRec, &Context, 0);
+}
+
+/* EOF */
reactos/ntoskrnl/rtl/i386
diff -N except.s
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ except.s 25 Jun 2004 16:39:41 -0000 1.4
@@ -0,0 +1,291 @@
+/* $Id: except.s,v 1.4 2004/06/25 16:39:41 weiden Exp $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * PURPOSE: Kernel-mode exception support for IA-32
+ * FILE: ntoskrnl/rtl/i386/except.s
+ * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * NOTES: This file is shared with lib/ntdll/rtl/i386/except.s.
+ * Please keep them in sync.
+ */
+
+#define EXCEPTION_UNWINDING 0x02
+
+#define EREC_FLAGS 0x04
+
+#define ExceptionContinueExecution 0
+#define ExceptionContinueSearch 1
+#define ExceptionNestedException 2
+#define ExceptionCollidedUnwind 3
+
+.globl _RtlpExecuteHandlerForException
+.globl _RtlpExecuteHandlerForUnwind
+
+#define CONTEXT_FLAGS 0x00
+#define CONTEXT_SEGGS 0x8C
+#define CONTEXT_SEGFS 0x90
+#define CONTEXT_SEGES 0x94
+#define CONTEXT_SEGDS 0x98
+#define CONTEXT_EDI 0x9C
+#define CONTEXT_ESI 0xA0
+#define CONTEXT_EBX 0xA4
+#define CONTEXT_EDX 0xA8
+#define CONTEXT_ECX 0xAC
+#define CONTEXT_EAX 0xB0
+#define CONTEXT_EBP 0xB4
+#define CONTEXT_EIP 0xB8
+#define CONTEXT_SEGCS 0xBC
+#define CONTEXT_EFLAGS 0xC0
+#define CONTEXT_ESP 0xC4
+#define CONTEXT_SEGSS 0xC8
+
+
+#define RCC_CONTEXT 0x08
+
+// EAX = value to print
+_do_debug:
+ pushal
+ pushl %eax
+ call _AsmDebug@4
+ popal
+ ret
+
+#ifndef __NTOSKRNL__
+
+//
+// VOID
+// RtlpCaptureContext(PCONTEXT pContext);
+//
+// Parameters:
+// [ESP+08h] - PCONTEXT_X86 pContext
+// Registers:
+// None
+// Returns:
+// Nothing
+// Notes:
+// Grabs the current CPU context.
+.globl _RtlpCaptureContext
+_RtlpCaptureContext:
+ pushl %ebp
+ movl %esp, %ebp
+ movl RCC_CONTEXT(%ebp), %edx // EDX = Address of context structure
+
+ cld
+ pushf
+ pop %eax
+ movl %eax, CONTEXT_EFLAGS(%edx)
+ xorl %eax, %eax
+ movl %eax, CONTEXT_EAX(%edx)
+ movl %eax, CONTEXT_EBX(%edx)
+ movl %eax, CONTEXT_ECX(%edx)
+ movl %eax, CONTEXT_EDX(%edx)
+ movl %eax, CONTEXT_ESI(%edx)
+ movl %eax, CONTEXT_EDI(%edx)
+ movl %cs, %eax
+ movl %eax, CONTEXT_SEGCS(%edx)
+ movl %ds, %eax
+ movl %eax, CONTEXT_SEGDS(%edx)
+ movl %es, %eax
+ movl %eax, CONTEXT_SEGES(%edx)
+ movl %fs, %eax
+ movl %eax, CONTEXT_SEGFS(%edx)
+ movl %gs, %eax
+ movl %eax, CONTEXT_SEGGS(%edx)
+ movl %ss, %eax
+ movl %eax, CONTEXT_SEGSS(%edx)
+
+ //
+ // STACK LAYOUT: - (ESP to put in context structure)
+ // - RETURN ADDRESS OF CALLER OF CALLER
+ // - EBP OF CALLER OF CALLER
+ // ...
+ // - RETURN ADDRESS OF CALLER
+ // - EBP OF CALLER
+ // ...
+ //
+
+ // Get return address of the caller of the caller of this function
+ movl %ebp, %ebx
+ //movl 4(%ebx), %eax // EAX = return address of caller
+ movl (%ebx), %ebx // EBX = EBP of caller
+
+ movl 4(%ebx), %eax // EAX = return address of caller of caller
+ movl (%ebx), %ebx // EBX = EBP of caller of caller
+
+ movl %eax, CONTEXT_EIP(%edx) // EIP = return address of caller of caller
+ movl %ebx, CONTEXT_EBP(%edx) // EBP = EBP of caller of caller
+ addl $8, %ebx
+ movl %ebx, CONTEXT_ESP(%edx) // ESP = EBP of caller of caller + 8
+
+ movl %ebp, %esp
+ popl %ebp
+ ret
+
+#endif /* !__NTOSKRNL__ */
+
+#define REH_ERECORD 0x08
+#define REH_RFRAME 0x0C
+#define REH_CONTEXT 0x10
+#define REH_DCONTEXT 0x14
+#define REH_EROUTINE 0x18
+
+// Parameters:
+// None
+// Registers:
+// [EBP+08h] - PEXCEPTION_RECORD ExceptionRecord
+// [EBP+0Ch] - PEXCEPTION_REGISTRATION RegistrationFrame
+// [EBP+10h] - PVOID Context
+// [EBP+14h] - PVOID DispatcherContext
+// [EBP+18h] - PEXCEPTION_HANDLER ExceptionRoutine
+// EDX - Address of protecting exception handler
+// Returns:
+// EXCEPTION_DISPOSITION
+// Notes:
+// Setup the protecting exception handler and call the exception
+// handler in the right context.
+_RtlpExecuteHandler:
+ pushl %ebp
+ movl %esp, %ebp
+ pushl REH_RFRAME(%ebp)
+
+ pushl %edx
+ pushl %fs:0x0
+ movl %esp, %fs:0x0
+
+ // Prepare to call the exception handler
+ pushl REH_DCONTEXT(%ebp)
+ pushl REH_CONTEXT(%ebp)
+ pushl REH_RFRAME(%ebp)
+ pushl REH_ERECORD(%ebp)
+
+ // Now call the exception handler
+ movl REH_EROUTINE(%ebp), %eax
+ call *%eax
+
+ cmpl $-1, %fs:0x0
+ jne .reh_stack_looks_ok
+
+ // This should not happen
+ pushl 0
+ pushl 0
+ pushl 0
+ pushl 0
+ call _RtlAssert@16
+
+.reh_loop:
+ jmp .reh_loop
+
+.reh_stack_looks_ok:
+ movl %fs:0x0, %esp
+
+ // Return to the 'front-end' for this function
+ popl %fs:0x0
+ movl %ebp, %esp
+ popl %ebp
+ ret
+
+
+#define REP_ERECORD 0x04
+#define REP_RFRAME 0x08
+#define REP_CONTEXT 0x0C
+#define REP_DCONTEXT 0x10
+
+// Parameters:
+// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord
+// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
+// [ESP+0Ch] - PCONTEXT Context
+// [ESP+10h] - PVOID DispatcherContext
+// Registers:
+// None
+// Returns:
+// EXCEPTION_DISPOSITION
+// Notes:
+// This exception handler protects the exception handling
+// mechanism by detecting nested exceptions.
+_RtlpExceptionProtector:
+ movl $ExceptionContinueSearch, %eax
+ movl REP_ERECORD(%esp), %ecx
+ testl $EXCEPTION_UNWINDING, EREC_FLAGS(%ecx)
+ jnz .rep_end
+
+ // Unwinding is not taking place, so return ExceptionNestedException
+
+ // Set DispatcherContext field to the exception registration for the
+ // exception handler that executed when a nested exception occurred
+ movl REP_DCONTEXT(%esp), %ecx
+ movl REP_RFRAME(%esp), %eax
+ movl %eax, (%ecx)
+ movl $ExceptionNestedException, %eax
+
+.rep_end:
+ ret
+
+
+// Parameters:
+// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord
+// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
+// [ESP+0Ch] - PCONTEXT Context
+// [ESP+10h] - PVOID DispatcherContext
+// [ESP+14h] - PEXCEPTION_HANDLER ExceptionHandler
+// Registers:
+// None
+// Returns:
+// EXCEPTION_DISPOSITION
+// Notes:
+// Front-end
+_RtlpExecuteHandlerForException:
+ movl $_RtlpExceptionProtector, %edx
+ jmp _RtlpExecuteHandler
+
+
+#define RUP_ERECORD 0x04
+#define RUP_RFRAME 0x08
+#define RUP_CONTEXT 0x0C
+#define RUP_DCONTEXT 0x10
+
+// Parameters:
+// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord
+// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
+// [ESP+0Ch] - PCONTEXT Context
+// [ESP+10h] - PVOID DispatcherContext
+// Registers:
+// None
+// Returns:
+// EXCEPTION_DISPOSITION
+// Notes:
+// This exception handler protects the exception handling
+// mechanism by detecting collided unwinds.
+_RtlpUnwindProtector:
+ movl $ExceptionContinueSearch, %eax
+ movl %ecx, RUP_ERECORD(%esp)
+ testl $EXCEPTION_UNWINDING, EREC_FLAGS(%ecx)
+ jz .rup_end
+
+ // Unwinding is taking place, so return ExceptionCollidedUnwind
+
+ movl RUP_RFRAME(%esp), %ecx
+ movl RUP_DCONTEXT(%esp), %edx
+
+ // Set DispatcherContext field to the exception registration for the
+ // exception handler that executed when a collision occurred
+ movl RUP_RFRAME(%ecx), %eax
+ movl %eax, (%edx)
+ movl $ExceptionCollidedUnwind, %eax
+
+.rup_end:
+ ret
+
+
+// Parameters:
+// [ESP+04h] - PEXCEPTION_RECORD ExceptionRecord
+// [ESP+08h] - PEXCEPTION_REGISTRATION RegistrationFrame
+// [ESP+0Ch] - PCONTEXT Context
+// [ESP+10h] - PVOID DispatcherContext
+// [ESP+14h] - PEXCEPTION_HANDLER ExceptionHandler
+// Registers:
+// None
+// Returns:
+// EXCEPTION_DISPOSITION
+_RtlpExecuteHandlerForUnwind:
+ movl $_RtlpUnwindProtector, %edx
+ jmp _RtlpExecuteHandler
CVSspam 0.2.8