mirror of
https://github.com/reactos/reactos.git
synced 2025-05-16 15:50:24 +00:00
Committed in the hope CVS will shut the hell up and let me branch. Still part of the SEH work
svn path=/trunk/; revision=9865
This commit is contained in:
parent
2708010986
commit
7fa5587882
2 changed files with 708 additions and 0 deletions
291
reactos/lib/rtl/i386/except.s
Normal file
291
reactos/lib/rtl/i386/except.s
Normal file
|
@ -0,0 +1,291 @@
|
|||
/* $Id: except.s,v 1.1 2004/06/25 01:41:19 hyperion 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
|
417
reactos/lib/rtl/i386/exception.c
Normal file
417
reactos/lib/rtl/i386/exception.c
Normal file
|
@ -0,0 +1,417 @@
|
|||
/* $Id: exception.c,v 1.1 2004/06/25 01:41:20 hyperion 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);
|
||||
|
||||
#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)
|
||||
|
||||
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 */
|
||||
ZwContinue(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
|
||||
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 != -1)
|
||||
{
|
||||
EXCEPTION_RECORD er2;
|
||||
|
||||
DPRINT("ERHead 0x%X\n", ERHead);
|
||||
|
||||
if (ERHead == RegistrationFrame)
|
||||
{
|
||||
DPRINT("Continueing execution\n");
|
||||
ZwContinue(&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)
|
||||
ZwContinue(&Context, FALSE);
|
||||
else
|
||||
NtRaiseException(pExceptRec, &Context, 0);
|
||||
}
|
||||
|
||||
/* EOF */
|
Loading…
Reference in a new issue