Initial OS level SEH support.

svn path=/trunk/; revision=2256
This commit is contained in:
Casper Hornstrup 2001-09-24 00:51:17 +00:00
parent 2eb7adef67
commit 0948ab6596
19 changed files with 1424 additions and 92 deletions

View file

@ -1,3 +1,442 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: include/types.h
* PURPOSE: Types used by all the parts of the system
* PROGRAMMER: David Welch <welch@cwcom.net>
* DEFINES: _WIN64: 64-bit architecture
* _WIN32: 32-bit architecture (default)
* UPDATE HISTORY:
* 27/06/00: Created
* 01/05/01: Portabillity changes
*/
#ifndef __INCLUDE_ACPI_TYPES_H
#define __INCLUDE_ACPI_TYPES_H
/* Fixed precision types */
typedef signed char INT8, *PINT8;
typedef signed short INT16, *PINT16;
#if 0
typedef signed int INT32, *PINT32;
#endif
typedef signed long long INT64, *PINT64;
#if 0
typedef unsigned char UINT8, *PUINT8;
typedef unsigned short UINT16, *PUINT16;
typedef unsigned int UINT32, *PUINT32;
typedef unsigned long long UINT64, *PUINT64;
#endif
typedef signed long int LONG32, *PLONG32;
typedef unsigned long int ULONG32, *PULONG32;
typedef unsigned long int DWORD32, *PDWORD32;
#ifdef _WIN64
/* 64-bit architecture */
typedef INT64 INT, *PINT;
typedef LONG64 LONG, *PLONG;
typedef DWORD64 DWORD, *PDWORD;
typedef UINT64 UINT, *PUINT;
typedef ULONG64 ULONG, *PULONG;
/* Pointer precision types */
typedef long long INT_PTR, *PINT_PTR;
typedef unsigned long long UINT_PTR, *PUINT_PTR;
typedef long long LONG_PTR, *PLONG_PTR;
typedef unsigned long long ULONG_PTR, *PULONG_PTR;
typedef unsigned long long HANDLE_PTR;
typedef unsigned int UHALF_PTR, *PUHALF_PTR;
typedef int HALF_PTR, *PHALF_PTR;
#else /* _WIN64 */
/* 32-bit architecture */
typedef INT32 INT, *PINT;
typedef LONG32 LONG, *PLONG;
typedef DWORD32 DWORD, *PDWORD;
typedef UINT32 UINT, *PUINT;
typedef ULONG32 ULONG, *PULONG;
/* Pointer precision types */
typedef int INT_PTR, *PINT_PTR;
typedef unsigned int UINT_PTR, *PUINT_PTR;
typedef long LONG_PTR, *PLONG_PTR;
typedef unsigned long ULONG_PTR, *PULONG_PTR;
typedef unsigned short UHALF_PTR, *PUHALF_PTR;
typedef short HALF_PTR, *PHALF_PTR;
typedef unsigned long HANDLE_PTR;
#endif /* _WIN64 */
typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR;
typedef long long LONG64, *PLONG64;
typedef unsigned long long ULONG64, *PULONG64;
typedef unsigned long long DWORD64, *PDWORD64;
#if 0
typedef unsigned char UCHAR;
#endif
typedef unsigned short USHORT;
typedef unsigned short WCHAR;
typedef unsigned short WORD;
typedef int BOOL;
#if 0
typedef unsigned char BOOLEAN;
#endif
typedef BOOLEAN* PBOOLEAN;
typedef unsigned short *LPWSTR;
typedef unsigned short *PWSTR;
typedef unsigned char *PUCHAR;
typedef unsigned short *PUSHORT;
typedef void *PVOID;
typedef unsigned char BYTE;
typedef void *LPVOID;
typedef float *PFLOAT;
typedef unsigned short *PWCH;
typedef unsigned short *PWORD;
typedef long long LONGLONG;
typedef unsigned long long ULONGLONG;
typedef long long *PLONGLONG;
typedef unsigned long long *PULONGLONG;
/* Check VOID before defining CHAR, SHORT */
#ifndef VOID
#define VOID void
typedef char CHAR;
typedef short SHORT;
#endif
typedef CHAR *PCHAR;
typedef CHAR *PCH;
typedef void *HANDLE;
typedef char CCHAR;
typedef CCHAR *PCCHAR;
#if 0
#define FALSE 0
#define TRUE 1
#endif
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void*)0)
#endif /* __cplusplus */
#endif /* NULL */
typedef const unsigned short *PCWSTR;
typedef char* PCSZ;
typedef union _LARGE_INTEGER
{
struct
{
DWORD LowPart;
LONG HighPart;
} u;
#ifdef ANONYMOUSUNIONS
struct
{
DWORD LowPart;
LONG HighPart;
};
#endif /* ANONYMOUSUNIONS */
LONGLONG QuadPart;
} LARGE_INTEGER, *PLARGE_INTEGER;
typedef union _ULARGE_INTEGER
{
struct
{
DWORD LowPart;
DWORD HighPart;
} u;
#ifdef ANONYMOUSUNIONS
struct
{
DWORD LowPart;
DWORD HighPart;
};
#endif /* ANONYMOUSUNIONS */
ULONGLONG QuadPart;
} ULARGE_INTEGER, *PULARGE_INTEGER;
typedef struct _FILETIME
{
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME, *LPFILETIME, *PFILETIME;
#define CONST const
#ifdef i386
#define STDCALL __attribute__ ((stdcall))
#define CDECL __attribute((cdecl))
#define CALLBACK WINAPI
#define PASCAL WINAPI
#else
#define STDCALL
#define CDECL
#define CALLBACK
#define PASCAL
#endif
typedef struct _LIST_ENTRY {
struct _LIST_ENTRY *Flink;
struct _LIST_ENTRY *Blink;
} LIST_ENTRY, *PLIST_ENTRY;
typedef struct _SINGLE_LIST_ENTRY {
struct _SINGLE_LIST_ENTRY *Next;
} SINGLE_LIST_ENTRY, *PSINGLE_LIST_ENTRY;
typedef DWORD STDCALL (*PTHREAD_START_ROUTINE) (LPVOID);
typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE;
typedef unsigned short *PWCHAR;
#ifdef __PPC__
#define CONTEXT_CONTROL 1L
#define CONTEXT_FLOATING_POINT 2L
#define CONTEXT_INTEGER 4L
#define CONTEXT_DEBUG_REGISTERS 8L
#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_FLOATING_POINT | CONTEXT_INTEGER)
#define CONTEXT_DEBUGGER (CONTEXT_FULL)
#else /* x86 */
/* The doc refered me to winnt.h, so I had to look... */
#define SIZE_OF_80387_REGISTERS 80
/* Values for contextflags */
#define CONTEXT_i386 0x10000
#define CONTEXT_CONTROL (CONTEXT_i386 | 1)
#define CONTEXT_INTEGER (CONTEXT_i386 | 2)
#define CONTEXT_SEGMENTS (CONTEXT_i386 | 4)
#define CONTEXT_FLOATING_POINT (CONTEXT_i386 | 8)
#define CONTEXT_DEBUG_REGISTERS (CONTEXT_i386 | 0x10)
#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS)
/* our own invention */
#define FLAG_TRACE_BIT 0x100
#define CONTEXT_DEBUGGER (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
#endif
#ifdef __i386__
typedef struct _FLOATING_SAVE_AREA {
DWORD ControlWord;
DWORD StatusWord;
DWORD TagWord;
DWORD ErrorOffset;
DWORD ErrorSelector;
DWORD DataOffset;
DWORD DataSelector;
BYTE RegisterArea[80];
DWORD Cr0NpxState;
} FLOATING_SAVE_AREA;
typedef struct _CONTEXT {
DWORD ContextFlags;
DWORD Dr0;
DWORD Dr1;
DWORD Dr2;
DWORD Dr3;
DWORD Dr6;
DWORD Dr7;
FLOATING_SAVE_AREA FloatSave;
DWORD SegGs;
DWORD SegFs;
DWORD SegEs;
DWORD SegDs;
DWORD Edi;
DWORD Esi;
DWORD Ebx;
DWORD Edx;
DWORD Ecx;
DWORD Eax;
DWORD Ebp;
DWORD Eip;
DWORD SegCs;
DWORD EFlags;
DWORD Esp;
DWORD SegSs;
} CONTEXT, *PCONTEXT, *LPCONTEXT;
#else /* __ppc__ */
typedef struct
{
/* Floating point registers returned when CONTEXT_FLOATING_POINT is set */
double Fpr0;
double Fpr1;
double Fpr2;
double Fpr3;
double Fpr4;
double Fpr5;
double Fpr6;
double Fpr7;
double Fpr8;
double Fpr9;
double Fpr10;
double Fpr11;
double Fpr12;
double Fpr13;
double Fpr14;
double Fpr15;
double Fpr16;
double Fpr17;
double Fpr18;
double Fpr19;
double Fpr20;
double Fpr21;
double Fpr22;
double Fpr23;
double Fpr24;
double Fpr25;
double Fpr26;
double Fpr27;
double Fpr28;
double Fpr29;
double Fpr30;
double Fpr31;
double Fpscr;
/* Integer registers returned when CONTEXT_INTEGER is set. */
DWORD Gpr0;
DWORD Gpr1;
DWORD Gpr2;
DWORD Gpr3;
DWORD Gpr4;
DWORD Gpr5;
DWORD Gpr6;
DWORD Gpr7;
DWORD Gpr8;
DWORD Gpr9;
DWORD Gpr10;
DWORD Gpr11;
DWORD Gpr12;
DWORD Gpr13;
DWORD Gpr14;
DWORD Gpr15;
DWORD Gpr16;
DWORD Gpr17;
DWORD Gpr18;
DWORD Gpr19;
DWORD Gpr20;
DWORD Gpr21;
DWORD Gpr22;
DWORD Gpr23;
DWORD Gpr24;
DWORD Gpr25;
DWORD Gpr26;
DWORD Gpr27;
DWORD Gpr28;
DWORD Gpr29;
DWORD Gpr30;
DWORD Gpr31;
DWORD Cr; /* Condition register */
DWORD Xer; /* Fixed point exception register */
/* The following are set when CONTEXT_CONTROL is set. */
DWORD Msr; /* Machine status register */
DWORD Iar; /* Instruction address register */
DWORD Lr; /* Link register */
DWORD Ctr; /* Control register */
/* Control which context values are returned */
DWORD ContextFlags;
DWORD Fill[3];
/* Registers returned if CONTEXT_DEBUG_REGISTERS is set. */
DWORD Dr0; /* Breakpoint Register 1 */
DWORD Dr1; /* Breakpoint Register 2 */
DWORD Dr2; /* Breakpoint Register 3 */
DWORD Dr3; /* Breakpoint Register 4 */
DWORD Dr4; /* Breakpoint Register 5 */
DWORD Dr5; /* Breakpoint Register 6 */
DWORD Dr6; /* Debug Status Register */
DWORD Dr7; /* Debug Control Register */
} CONTEXT, *PCONTEXT, *LPCONTEXT;
#endif
typedef HANDLE *PHANDLE;
typedef struct value_ent {
LPWSTR ve_valuename;
DWORD ve_valuelen;
DWORD ve_valueptr;
DWORD ve_type;
} WVALENT, *PWVALENT;
typedef const void *LPCVOID;
typedef BYTE *LPBYTE, *PBYTE;
typedef BOOL *PBOOL;
typedef DWORD LCID;
typedef DWORD *PLCID;
typedef const char *LPCSTR;
typedef char *LPSTR;
typedef const unsigned short *LPCWSTR;
typedef unsigned short RTL_ATOM;
typedef unsigned short *PRTL_ATOM;
typedef WORD ATOM;
typedef struct _COORD {
SHORT X;
SHORT Y;
} COORD;
typedef struct _SMALL_RECT {
SHORT Left;
SHORT Top;
SHORT Right;
SHORT Bottom;
} SMALL_RECT, *PSMALL_RECT;
typedef
VOID
(*PTIMERAPCROUTINE)(
LPVOID lpArgToCompletionRoutine,
DWORD dwTimerLowValue,
DWORD dwTimerHighValue
);
#include <ntos/except.h>
#endif /* __INCLUDE_ACPI_TYPES_H */
#if 0
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -308,17 +747,6 @@ typedef struct value_ent {
DWORD ve_type;
} WVALENT, *PWVALENT;
#define EXCEPTION_MAXIMUM_PARAMETERS (15)
typedef struct _EXCEPTION_RECORD {
DWORD ExceptionCode;
DWORD ExceptionFlags;
struct _EXCEPTION_RECORD *ExceptionRecord;
PVOID ExceptionAddress;
DWORD NumberParameters;
DWORD ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
} EXCEPTION_RECORD, *PEXCEPTION_RECORD, *LPEXCEPTION_RECORD;
typedef long *PLONG;
typedef const void *LPCVOID;
@ -360,4 +788,8 @@ VOID
DWORD dwTimerHighValue
);
#include <ntos/except.h>
#endif /* __INCLUDE_ACPI_TYPES_H */
#endif

View file

@ -1,4 +1,4 @@
/* $Id: rtl.h,v 1.57 2001/09/01 15:36:43 chorns Exp $
/* $Id: rtl.h,v 1.58 2001/09/24 00:51:15 chorns Exp $
*
*/
@ -1830,10 +1830,10 @@ RtlUnlockHeap (
VOID
STDCALL
RtlUnwind (
ULONG Unknown1,
ULONG Unknown2,
ULONG Unknown3,
ULONG Unknown4
PEXCEPTION_REGISTRATION RegistrationFrame,
PVOID ReturnAddress,
PEXCEPTION_RECORD ExceptionRecord,
DWORD EaxValue
);
WCHAR

View file

@ -373,22 +373,12 @@ typedef struct
typedef HANDLE *PHANDLE;
typedef struct value_ent {
LPWSTR ve_valuename;
DWORD ve_valuelen;
DWORD ve_valueptr;
DWORD ve_type;
LPWSTR ve_valuename;
DWORD ve_valuelen;
DWORD ve_valueptr;
DWORD ve_type;
} WVALENT, *PWVALENT;
#define EXCEPTION_MAXIMUM_PARAMETERS (15)
typedef struct _EXCEPTION_RECORD {
DWORD ExceptionCode;
DWORD ExceptionFlags;
struct _EXCEPTION_RECORD *ExceptionRecord;
PVOID ExceptionAddress;
DWORD NumberParameters;
DWORD ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
} EXCEPTION_RECORD, *PEXCEPTION_RECORD, *LPEXCEPTION_RECORD;
typedef const void *LPCVOID;
typedef BYTE *LPBYTE, *PBYTE;
@ -428,4 +418,6 @@ typedef VOID STDCALL
DWORD dwTimerHighValue
);
#include "except.h"
#endif /* __INCLUDE_TYPES_H */

View file

@ -1872,11 +1872,6 @@ typedef struct tagEVENTMSG {
HWND hwnd;
} EVENTMSG;
typedef struct _EXCEPTION_POINTERS {
PEXCEPTION_RECORD ExceptionRecord;
PCONTEXT ContextRecord;
} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS, *LPEXCEPTION_POINTERS;
typedef struct _EXT_BUTTON {
WORD idCommand;
WORD idsHelp;

View file

@ -1,13 +1,5 @@
#include <windows.h>
typedef enum _EXCEPTION_DISPOSITION {
ExceptionContinueExecution,
ExceptionContinueSearch,
ExceptionNestedException,
ExceptionCollidedUnwind
} EXCEPTION_DISPOSITION;
EXCEPTION_DISPOSITION
_except_handler2(
struct _EXCEPTION_RECORD *ExceptionRecord,

View file

@ -1,13 +1,5 @@
#include <windows.h>
typedef enum _EXCEPTION_DISPOSITION {
ExceptionContinueExecution,
ExceptionContinueSearch,
ExceptionNestedException,
ExceptionCollidedUnwind
} EXCEPTION_DISPOSITION;
EXCEPTION_DISPOSITION
_except_handler3(
struct _EXCEPTION_RECORD *ExceptionRecord,

View file

@ -1,4 +1,4 @@
/* $Id: exception.c,v 1.6 2001/06/17 20:05:10 ea Exp $
/* $Id: exception.c,v 1.7 2001/09/24 00:51:16 chorns Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -64,10 +64,10 @@ RtlRaiseStatus(NTSTATUS Status)
VOID STDCALL
RtlUnwind(ULONG Unknown1,
ULONG Unknown2,
ULONG Unknown3,
ULONG Unknown4)
RtlUnwind(PEXCEPTION_REGISTRATION RegistrationFrame,
PVOID ReturnAddress,
PEXCEPTION_RECORD ExceptionRecord,
DWORD EaxValue)
{
}

View file

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.54 2001/09/06 20:26:36 dwelch Exp $
# $Id: Makefile,v 1.55 2001/09/24 00:51:16 chorns Exp $
#
# ReactOS Operating System
#
@ -94,6 +94,7 @@ OBJECTS_RTL = \
rtl/nls.o \
rtl/qsort.o \
rtl/regio.o \
rtl/seh.o \
rtl/sprintf.o \
rtl/stdlib.o \
rtl/string.o \

View file

@ -183,7 +183,7 @@ NtEarlyInitVdm(VOID);
VOID
KiAddProfileEvent(KPROFILE_SOURCE Source, ULONG Eip);
VOID
KiDispatchException(PEXCEPTION_RECORD Er,
KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
PCONTEXT Context,
PKTRAP_FRAME Tf,
KPROCESSOR_MODE PreviousMode,

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: catch.c,v 1.15 2001/07/04 20:40:21 chorns Exp $
/* $Id: catch.c,v 1.16 2001/09/24 00:51:16 chorns Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/catch.c
@ -31,19 +31,173 @@
#include <internal/ldr.h>
#include <internal/ps.h>
#define NDEBUG
#include <internal/debug.h>
/* FUNCTIONS ****************************************************************/
EXCEPTION_DISPOSITION
RtlpExecuteHandlerForException(
PEXCEPTION_RECORD ExceptionRecord,
PEXCEPTION_REGISTRATION ExceptionRegistration,
PCONTEXT Context,
PVOID DispatcherContext,
PEXCEPTION_HANDLER Handler);
#ifndef NDEBUG
VOID RtlpDumpExceptionRegistrations(VOID)
{
PEXCEPTION_REGISTRATION Current;
PKTHREAD Thread;
DbgPrint("Dumping exception registrations:\n");
Thread = KeGetCurrentThread();
assert(Thread);
assert(Thread->TrapFrame);
Current = Thread->TrapFrame->ExceptionList;
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 */
EXCEPTION_DISPOSITION
RtlpDispatchException(
PEXCEPTION_RECORD ExceptionRecord,
PCONTEXT Context)
{
PEXCEPTION_REGISTRATION RegistrationFrame;
DWORD DispatcherContext;
DWORD ReturnValue;
PKPCR KPCR;
PKTHREAD Thread;
DPRINT("RtlpDispatchException() called\n");
#ifndef NDEBUG
RtlpDumpExceptionRegistrations();
#endif /* NDEBUG */
Thread = KeGetCurrentThread();
DPRINT("Thread is 0x%X\n", Thread);
KPCR = KeGetCurrentKPCR();
RegistrationFrame = Thread->TrapFrame->ExceptionList;
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 (Thread->KernelStack > RegistrationFrameEnd)
{
ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
return ExceptionDismiss;
}
// FIXME: Correct?
if (Thread->StackLimit < RegistrationFrameEnd)
{
ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
return ExceptionDismiss;
}
// Make sure stack is DWORD aligned
if ((ULONG_PTR)RegistrationFrame & 3)
{
ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
return ExceptionDismiss;
}
#endif
DPRINT("Calling handler at 0x%X\n", RegistrationFrame->handler);
ReturnValue = RtlpExecuteHandlerForException(
ExceptionRecord,
RegistrationFrame,
Context,
&DispatcherContext,
RegistrationFrame->handler);
if (RegistrationFrame == NULL)
{
ExceptionRecord->ExceptionFlags &= ~EXCEPTION_NESTED_CALL; // Turn off flag
}
if (ReturnValue == ExceptionContinueExecution)
{
/* Copy the changed context back to the trap frame and return */
NtContinue(Context, FALSE);
return ExceptionContinueExecution;
}
else if (ReturnValue == ExceptionDismiss)
{
if (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE)
{
ExceptionRecord2.ExceptionRecord = ExceptionRecord;
ExceptionRecord2.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION;
ExceptionRecord2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
ExceptionRecord2.NumberParameters = 0;
RtlRaiseException(&ExceptionRecord2);
}
/* Else continue search */
}
else if (ReturnValue == ExceptionNestedException)
{
ExceptionRecord->ExceptionFlags |= EXCEPTION_EXIT_UNWIND;
if (DispatcherContext > Temp)
Temp = DispatcherContext;
}
else if (ReturnValue == ExceptionCollidedUnwind)
{
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 */
return ExceptionDismiss;
}
VOID
KiDispatchException(PEXCEPTION_RECORD Er,
KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
PCONTEXT Context,
PKTRAP_FRAME Tf,
KPROCESSOR_MODE PreviousMode,
BOOLEAN SearchFrames)
{
EXCEPTION_DISPOSITION Value;
CONTEXT TContext;
DPRINT("KiDispatchException() called \n");
/* PCR->KeExceptionDispatchCount++; */
if (Context == NULL)
@ -59,7 +213,7 @@ KiDispatchException(PEXCEPTION_RECORD Er,
Context = &TContext;
}
if (Er->ExceptionCode == STATUS_BREAKPOINT)
if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT)
{
Context->Eip--;
}
@ -91,7 +245,7 @@ KiDispatchException(PEXCEPTION_RECORD Er,
Stack[1] = (ULONG)&Stack[3];
/* Pointer to CONTEXT structure */
Stack[2] = (ULONG)&Stack[CDest];
memcpy(&Stack[3], Er, sizeof(EXCEPTION_RECORD));
memcpy(&Stack[3], ExceptionRecord, sizeof(EXCEPTION_RECORD));
memcpy(&Stack[CDest], Context, sizeof(CONTEXT));
Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
@ -103,14 +257,24 @@ KiDispatchException(PEXCEPTION_RECORD Er,
/* FIXME: Forward the exception to the process exception port */
/* Terminate the offending thread */
ZwTerminateThread(NtCurrentThread(), Er->ExceptionCode);
ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
/* If that fails then bugcheck */
DbgPrint("Could not terminate thread\n");
KeBugCheck(KMODE_EXCEPTION_NOT_HANDLED);
}
else
{
KeBugCheck(KMODE_EXCEPTION_NOT_HANDLED);
/* PreviousMode == KernelMode */
Value = RtlpDispatchException(ExceptionRecord, Context);
DPRINT("RtlpDispatchException() returned with 0x%X\n", Value);
/* If RtlpDispatchException() does not handle the exception then bugcheck */
if (Value != ExceptionContinueExecution)
{
KeBugCheck(KMODE_EXCEPTION_NOT_HANDLED);
}
}
}
@ -129,10 +293,17 @@ ExRaiseDatatypeMisalignment (VOID)
VOID STDCALL
ExRaiseStatus (IN NTSTATUS Status)
{
DbgPrint("ExRaiseStatus(%x)\n",Status);
KeBugCheck(0);
}
EXCEPTION_RECORD ExceptionRecord;
DPRINT("ExRaiseStatus(%x)\n", Status);
ExceptionRecord.ExceptionRecord = NULL;
ExceptionRecord.NumberParameters = 0;
ExceptionRecord.ExceptionCode = Status;
ExceptionRecord.ExceptionFlags = 0;
RtlRaiseException(&ExceptionRecord);
}
NTSTATUS STDCALL
@ -152,17 +323,277 @@ NtRaiseException (IN PEXCEPTION_RECORD ExceptionRecord,
VOID STDCALL
RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord)
{
ZwRaiseException(ExceptionRecord, NULL, TRUE);
}
inline
EXCEPTION_DISPOSITION
RtlpExecuteHandler(
PEXCEPTION_RECORD ExceptionRecord,
PEXCEPTION_REGISTRATION ExceptionRegistration,
PCONTEXT Context,
PVOID DispatcherContext,
PEXCEPTION_HANDLER Handler,
PEXCEPTION_HANDLER RawHandler)
{
EXCEPTION_DISPOSITION Value;
// Set up an EXCEPTION_REGISTRATION
__asm__ ("pushl %0;pushl %%fs:0;movl %%esp,%%fs:0;" : : "g" (RawHandler));
// Invoke the exception callback function
Value = Handler(
ExceptionRecord,
ExceptionRegistration,
Context,
DispatcherContext);
// Remove the minimal EXCEPTION_REGISTRATION frame
//__asm__ ("movl %fs:0,%esp; popl %fs:0");
__asm__ ("movl (%%esp),%%eax;movl %%eax,%%fs:0;addl $8,%%esp;" : : : "%eax");
return Value;
}
EXCEPTION_DISPOSITION
RtlpExceptionHandler(
PEXCEPTION_RECORD ExceptionRecord,
PEXCEPTION_REGISTRATION ExceptionRegistration,
PCONTEXT Context,
PVOID DispatcherContext)
{
// If unwind flag set, return DISPOSITION_CONTINUE_SEARCH, else
// assign DispatcherContext context and return DISPOSITION_NESTED_EXCEPTION
if (ExceptionRecord->ExceptionFlags & EXCEPTION_UNWINDING)
{
DPRINT("RtlpExceptionHandler(). Returning ExceptionContinueSearch\n");
return ExceptionContinueSearch;
}
else
{
DPRINT("RtlpExceptionHandler(). Returning ExceptionNestedException\n");
*(PEXCEPTION_REGISTRATION*)DispatcherContext = ExceptionRegistration->prev;
return ExceptionNestedException;
}
}
EXCEPTION_DISPOSITION
RtlpUnwindHandler(
PEXCEPTION_RECORD ExceptionRecord,
PEXCEPTION_REGISTRATION ExceptionRegistration,
PCONTEXT Context,
PVOID DispatcherContext)
{
// If unwind flag set, return DISPOSITION_CONTINUE_SEARCH, else
// assign DispatcherContext and return DISPOSITION_COLLIDED_UNWIND
if (ExceptionRecord->ExceptionFlags & EXCEPTION_UNWINDING)
{
DPRINT("RtlpUnwindHandler(). Returning ExceptionContinueSearch\n");
return ExceptionContinueSearch;
}
else
{
DPRINT("RtlpUnwindHandler(). Returning ExceptionCollidedUnwind\n");
*(PEXCEPTION_REGISTRATION*)DispatcherContext = ExceptionRegistration->prev;
return ExceptionCollidedUnwind;
}
}
EXCEPTION_DISPOSITION
RtlpExecuteHandlerForException(
PEXCEPTION_RECORD ExceptionRecord,
PEXCEPTION_REGISTRATION ExceptionRegistration,
PCONTEXT Context,
PVOID DispatcherContext,
PEXCEPTION_HANDLER Handler)
{
return RtlpExecuteHandler(
ExceptionRecord,
ExceptionRegistration,
Context,
DispatcherContext,
Handler,
RtlpExceptionHandler);
}
EXCEPTION_DISPOSITION
RtlpExecuteHandlerForUnwind(
PEXCEPTION_RECORD ExceptionRecord,
PEXCEPTION_REGISTRATION ExceptionRegistration,
PCONTEXT Context,
PVOID DispatcherContext,
PEXCEPTION_HANDLER Handler)
{
return RtlpExecuteHandler(
ExceptionRecord,
ExceptionRegistration,
Context,
DispatcherContext,
Handler,
RtlpUnwindHandler);
}
VOID STDCALL
RtlUnwind(ULONG Unknown1,
ULONG Unknown2,
ULONG Unknown3,
ULONG Unknown4)
RtlUnwind(
PEXCEPTION_REGISTRATION RegistrationFrame,
PVOID ReturnAddress,
PEXCEPTION_RECORD ExceptionRecord,
DWORD EaxValue)
{
PEXCEPTION_REGISTRATION ERHead;
PEXCEPTION_RECORD pExceptRec;
EXCEPTION_RECORD TempER;
CONTEXT Context;
//PVOID Stack;
PKTHREAD Thread;
DPRINT("RtlUnwind() called. RegistrationFrame 0x%X\n", RegistrationFrame);
#ifndef NDEBUG
RtlpDumpExceptionRegistrations();
#endif /* NDEBUG */
Thread = KeGetCurrentThread();
ERHead = Thread->TrapFrame->ExceptionList;
if (ExceptionRecord == NULL) // The normal case
{
pExceptRec = &TempER;
pExceptRec->ExceptionFlags = 0;
pExceptRec->ExceptionCode = STATUS_UNWIND;
pExceptRec->ExceptionRecord = NULL;
// FIXME: Find out if NT retrieves the return address from the stack instead
pExceptRec->ExceptionAddress = ReturnAddress;
//pExceptRec->ExceptionInformation[0] = 0;
}
if (RegistrationFrame)
pExceptRec->ExceptionFlags |= EXCEPTION_UNWINDING;
else
pExceptRec->ExceptionFlags |= (EXCEPTION_UNWINDING|EXCEPTION_EXIT_UNWIND);
Context.ContextFlags =
(CONTEXT_i386 | CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS);
KeTrapFrameToContext(Thread->TrapFrame, &Context);
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");
NtContinue(&Context, FALSE);
return;
}
else
{
// If there's an exception frame, but it's lower on the stack
// then 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 ( (KPCR->StackBase <= (PVOID)ERHead ) // Make sure that ERHead
&& (KPCR->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
KeGetCurrentKPCR()->ExceptionList = 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)
NtContinue(&Context, FALSE);
else
NtRaiseException(pExceptRec, &Context, 0);
}
/* EOF */

View file

@ -307,6 +307,61 @@ KiUserTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
}
#endif
ULONG
KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
{
EXCEPTION_RECORD Er;
if (ExceptionNr == 0)
{
Er.ExceptionCode = STATUS_INTEGER_DIVIDE_BY_ZERO;
}
else if (ExceptionNr == 1)
{
Er.ExceptionCode = STATUS_SINGLE_STEP;
}
else if (ExceptionNr == 3)
{
Er.ExceptionCode = STATUS_BREAKPOINT;
}
else if (ExceptionNr == 4)
{
Er.ExceptionCode = STATUS_INTEGER_OVERFLOW;
}
else if (ExceptionNr == 5)
{
Er.ExceptionCode = STATUS_ARRAY_BOUNDS_EXCEEDED;
}
else if (ExceptionNr == 6)
{
Er.ExceptionCode = STATUS_ILLEGAL_INSTRUCTION;
}
else
{
Er.ExceptionCode = STATUS_ACCESS_VIOLATION;
}
Er.ExceptionFlags = 0;
Er.ExceptionRecord = NULL;
Er.ExceptionAddress = (PVOID)Tf->Eip;
if (ExceptionNr == 14)
{
Er.NumberParameters = 2;
Er.ExceptionInformation[0] = Tf->ErrorCode & 0x1;
Er.ExceptionInformation[1] = (ULONG)Cr2;
}
else
{
Er.NumberParameters = 0;
}
KiDispatchException(&Er, 0, Tf, KernelMode, TRUE);
return(0);
}
ULONG
KiUserTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
{
@ -544,13 +599,17 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
* Complete CPU context
*/
{
unsigned int cr2, cr3;
//#define SEH
unsigned int cr2;
#ifndef SEH
unsigned int cr3;
unsigned int i;
ULONG StackLimit;
PULONG Frame;
#endif
// unsigned int j, sym;
NTSTATUS Status;
ULONG Esp0;
ULONG StackLimit;
PULONG Frame;
/* Use the address of the trap frame as approximation to the ring0 esp */
Esp0 = (ULONG)&Tf->Eip;
@ -592,6 +651,7 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
{
return(0);
}
}
/*
@ -601,6 +661,15 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
{
return(KiUserTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
}
else
{
#ifdef SEH
return(KiKernelTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
#endif
}
#ifndef SEH
/*
* Print out the CPU registers
@ -678,6 +747,9 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
}
for(;;);
return 0;
#endif
}
VOID

View file

@ -70,6 +70,9 @@ KeApplicationProcessorInit(VOID)
KPCR->Self = KPCR;
KPCR->Irql = HIGH_LEVEL;
/* Mark the end of the exception handler list */
KPCR->ExceptionList = (PVOID)-1;
/*
* Initialize the GDT
*/
@ -123,6 +126,9 @@ KeInit1(VOID)
KiPcrInitDone = 1;
PcrsAllocated++;
/* Mark the end of the exception handler list */
KPCR->ExceptionList = (PVOID)-1;
Ki386InitializeLdt();
}

View file

@ -1,6 +1,7 @@
#include <roscfg.h>
#include <internal/ntoskrnl.h>
#include <internal/i386/segment.h>
#include <internal/ps.h>
#define KERNEL_BASE (0xc0000000)
@ -265,7 +266,7 @@ _multiboot_entry:
*/
movl $PCR_SELECTOR, %eax
movl %eax, %fs
/*
* Load the initial kernel stack
*/

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: syscall.S,v 1.2 2001/03/18 19:35:13 dwelch Exp $
/* $Id: syscall.S,v 1.3 2001/09/24 00:51:17 chorns Exp $
*
* FILE: ntoskrnl/hal/x86/syscall.s
* PURPOSE: 2E trap handler
@ -52,7 +52,7 @@ _interrupt_handler2e:
/* Save the old exception list */
movl %fs:KPCR_EXCEPTION_LIST, %ebx
pushl %ebx
/* Put the exception handler chain terminator */
/* Set the exception handler chain terminator */
movl $0xffffffff, %fs:KPCR_EXCEPTION_LIST
/* Get a pointer to the current thread */
movl %fs:KPCR_CURRENT_THREAD, %esi

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: trap.s,v 1.10 2001/03/28 14:24:05 dwelch Exp $
/* $Id: trap.s,v 1.11 2001/09/24 00:51:17 chorns Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/i386/trap.s
@ -139,18 +139,22 @@ _KiTrapProlog:
pushl $0 /* XXX: DebugEIP */
pushl $0 /* XXX: DebugEBP */
/* Load the segment registers */
/* Load the segment registers */
movl $KERNEL_DS, %ebx
movl %ebx, %ds
movl %ebx, %es
movl %ebx, %gs
/* Set ES to kernel segment */
movw $KERNEL_DS,%bx
movw %bx,%es
/* Set ES to kernel segment */
movw $KERNEL_DS,%bx
movw %bx,%es
movl %esp, %ebx
/* Save a pointer to the trap frame in the current KTHREAD */
movl %ebx, %ss:KTHREAD_TRAP_FRAME(%edi)
/* Call the C exception handler */
movl %esp, %ebx
pushl %esi
pushl %ebx
call _KiTrapHandler

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: main.c,v 1.106 2001/09/16 13:19:32 chorns Exp $
/* $Id: main.c,v 1.107 2001/09/24 00:51:16 chorns Exp $
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ke/main.c
@ -737,6 +737,172 @@ VOID DumpBIOSMemoryMap(VOID)
#endif /* !NDEBUG */
#if 1
// SEH Test
static ULONG Scratch;
EXCEPTION_DISPOSITION
ExpUnhandledException1(
PEXCEPTION_RECORD ExceptionRecord,
PEXCEPTION_REGISTRATION ExceptionRegistration,
PCONTEXT Context,
PVOID DispatcherContext)
{
DbgPrint("ExpUnhandledException1() called\n");
DbgPrint("ExceptionRecord 0x%X\n", ExceptionRecord);
DbgPrint(" Flags 0x%X\n", ExceptionRecord->ExceptionFlags);
DbgPrint("ExceptionRegistration 0x%X\n", ExceptionRegistration);
DbgPrint("Context 0x%X\n", Context);
DbgPrint("DispatcherContext 0x%X\n", DispatcherContext);
Context->Eax = (ULONG)&Scratch;
return ExceptionContinueExecution;
}
EXCEPTION_DISPOSITION
ExpUnhandledException2(
PEXCEPTION_RECORD ExceptionRecord,
PEXCEPTION_REGISTRATION ExceptionRegistration,
PCONTEXT Context,
PVOID DispatcherContext)
{
DbgPrint("ExpUnhandledException2() called\n");
DbgPrint("ExceptionRecord 0x%X\n", ExceptionRecord);
DbgPrint(" Flags 0x%X\n", ExceptionRecord->ExceptionFlags);
DbgPrint("ExceptionRegistration 0x%X\n", ExceptionRegistration);
DbgPrint("Context 0x%X\n", Context);
DbgPrint("DispatcherContext 0x%X\n", DispatcherContext);
#if 1
Context->Eax = (ULONG)&Scratch;
return ExceptionContinueExecution;
#else
return ExceptionContinueSearch;
#endif
}
#if 1
// Put in mingw headers
extern VOID
CDECL
_local_unwind2(
PEXCEPTION_REGISTRATION RegistrationFrame,
DWORD TryLevel);
extern VOID
CDECL
_global_unwind2(
PVOID RegistrationFrame);
extern EXCEPTION_DISPOSITION
CDECL
_except_handler2(
PEXCEPTION_RECORD ExceptionRecord,
PEXCEPTION_REGISTRATION RegistrationFrame,
PCONTEXT Context,
PVOID DispatcherContext);
extern EXCEPTION_DISPOSITION
CDECL
_except_handler3(
PEXCEPTION_RECORD ExceptionRecord,
PEXCEPTION_REGISTRATION RegistrationFrame,
PCONTEXT Context,
PVOID DispatcherContext);
#endif
PRTL_EXCEPTION_REGISTRATION
CurrentRER(VOID)
{
ULONG Value;
__asm__("movl %%ebp, %0\n\t" : "=a" (Value));
return((PRTL_EXCEPTION_REGISTRATION)Value) - 1;
}
PULONG x;
PRTL_EXCEPTION_REGISTRATION TestER;
SCOPETABLE_ENTRY ScopeTable;
PEXCEPTION_REGISTRATION OSPtr;
DWORD CDECL SEHFilterRoutine(VOID)
{
DbgPrint("Within filter routine.\n");
return EXCEPTION_EXECUTE_HANDLER;
//return EXCEPTION_CONTINUE_EXECUTION;
}
VOID CDECL SEHHandlerRoutine(VOID)
{
DbgPrint("Within exception handler.\n");
DbgPrint("System halted.\n");
for (;;);
}
VOID SEHTest()
{
RTL_EXCEPTION_REGISTRATION ER;
LPEXCEPTION_POINTERS ExceptionPointers;
PVOID StandardESPInFrame;
__asm__ ("movl %%esp,%%eax;" : "=a" (StandardESPInFrame));
DbgPrint("StandardESPInFrame: 0x%X\n", StandardESPInFrame);
ExceptionPointers = NULL;
ER.OS.handler = _except_handler3;
__asm__ ("movl %%fs:0,%%eax;" : "=a" (ER.OS.prev));
DbgPrint("ER.OS.prev: 0x%X\n", ER.OS.prev);
ER.ScopeTable = &ScopeTable;
DbgPrint("ER.ScopeTable: 0x%X\n", ER.ScopeTable);
ER.TryLevel = -1;
__asm__ ("movl %%ebp,%%eax;" : "=a" (ER.Ebp));
DbgPrint("ER.Ebp: 0x%X\n", ER.Ebp);
ScopeTable.PreviousTryLevel = -1;
ScopeTable.FilterRoutine = SEHFilterRoutine;
DbgPrint("ScopeTable.FilterRoutine: 0x%X\n", ScopeTable.FilterRoutine);
ScopeTable.HandlerRoutine = SEHHandlerRoutine;
DbgPrint("ScopeTable.HandlerRoutine: 0x%X\n", ScopeTable.HandlerRoutine);
OSPtr = &ER.OS;
DbgPrint("OSPtr: 0x%X\n", OSPtr);
__asm__ ("movl %0,%%eax;movl %%eax,%%fs:0;" : : "m" (OSPtr));
/*__try1(__except_handler3)*/ if(1) {
ER.TryLevel = 0; // Entered first try... block
DbgPrint("Within guarded section.\n");
x = (PULONG)0xf2000000; *x = 0;
DbgPrint("After exception.\n");
} /* __except1 */ if(0) {
}
DbgPrint("After exception2.\n");
__asm__ ("movl %0,%%eax;movl %%eax,%%fs:0;" : : "m" (ER.OS.prev));
//KeGetCurrentKPCR()->ExceptionList = ER.OS.prev;
DbgPrint("Exiting.\n");
}
#endif
VOID
ExpInitializeExecutive(VOID)
{
@ -994,6 +1160,10 @@ ExpInitializeExecutive(VOID)
*/
InitSystemSharedUserPage ((PUCHAR)KeLoaderBlock.CommandLine);
#if 0
SEHTest();
#endif
/*
* Launch initial process
*/

View file

@ -1,4 +1,4 @@
; $Id: ntoskrnl.def,v 1.114 2001/09/03 20:41:52 ea Exp $
; $Id: ntoskrnl.def,v 1.115 2001/09/24 00:51:16 chorns Exp $
;
; reactos/ntoskrnl/ntoskrnl.def
;
@ -936,10 +936,11 @@ ZwYieldExecution@0
;_aulldiv
;_aullrem
;_aullshr
;_except_handler2
;_global_unwind2
_except_handler2
_except_handler3
_global_unwind2
_itoa
;_local_unwind2
_local_unwind2
;_purecall
_snprintf
_snwprintf

View file

@ -1,4 +1,4 @@
; $Id: ntoskrnl.edf,v 1.100 2001/09/03 20:41:52 ea Exp $
; $Id: ntoskrnl.edf,v 1.101 2001/09/24 00:51:16 chorns Exp $
;
; reactos/ntoskrnl/ntoskrnl.def
;
@ -934,10 +934,11 @@ ZwYieldExecution=ZwYieldExecution@0
;_aulldiv
;_aullrem
;_aullshr
;_except_handler2
;_global_unwind2
_except_handler2
_except_handler3
_global_unwind2
_itoa
;_local_unwind2
_local_unwind2
;_purecall
_snprintf
_snwprintf

242
reactos/ntoskrnl/rtl/seh.c Normal file
View file

@ -0,0 +1,242 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/rtl/seh.c
* PURPOSE: Compiler level Structured Exception Handling
* PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* UPDATE HISTORY:
* 2001/10/10 CSH Created
*/
/* INCLUDES *****************************************************************/
#include <ntddk.h>
#define NDEBUG
#include <debug.h>
/* FUNCTIONS *****************************************************************/
VOID
CDECL
_local_unwind2(
PEXCEPTION_REGISTRATION RegistrationFrame,
DWORD TryLevel)
{
PSCOPETABLE_ENTRY ScopeTableHead;
PRTL_EXCEPTION_REGISTRATION RtlRegistrationFrame =
(PRTL_EXCEPTION_REGISTRATION)RegistrationFrame;
DbgPrint("RegistrationFrame (0x%X) - TryLevel (0x%X)\n",
RegistrationFrame, TryLevel);
return;
ScopeTableHead = RtlRegistrationFrame->ScopeTable;
/* Begin traversing the list of SCOPETABLE_ENTRY */
while ((ULONG_PTR)ScopeTableHead != -1)
{
}
}
VOID
CDECL
_global_unwind2(
PVOID RegistrationFrame)
{
RtlUnwind(RegistrationFrame, &&__return_label, NULL, 0);
__return_label:;
}
#if 1
extern DWORD CDECL SEHFilterRoutine(VOID);
extern VOID CDECL SEHHandlerRoutine(VOID);
#endif
EXCEPTION_DISPOSITION
CDECL
_except_handler2(
PEXCEPTION_RECORD ExceptionRecord,
PEXCEPTION_REGISTRATION RegistrationFrame,
PCONTEXT Context,
PVOID DispatcherContext)
{
/* FIXME: */
return ExceptionContinueSearch;
}
EXCEPTION_DISPOSITION
CDECL
_except_handler3(
PEXCEPTION_RECORD ExceptionRecord,
PEXCEPTION_REGISTRATION RegistrationFrame,
PCONTEXT Context,
PVOID DispatcherContext)
{
DWORD FilterFuncRet;
DWORD TryLevel;
EXCEPTION_POINTERS ExceptionPointers;
//PSCOPETABLE_ENTRY pScopeTable;
PSCOPETABLE_ENTRY ScopeTable;
EXCEPTION_DISPOSITION ReturnValue;
PVOID Handler;
PVOID NewEBP;
PRTL_EXCEPTION_REGISTRATION RtlRegistrationFrame =
(PRTL_EXCEPTION_REGISTRATION)RegistrationFrame;
DPRINT("__except_handler3() called\n");
DPRINT("ExceptionRecord 0x%X\n", ExceptionRecord);
DPRINT(" ExceptionCode 0x%X\n", ExceptionRecord->ExceptionCode);
DPRINT(" ExceptionFlags 0x%X\n", ExceptionRecord->ExceptionFlags);
DPRINT("RegistrationFrame 0x%X\n", RegistrationFrame);
DPRINT("Context 0x%X\n", Context);
DPRINT("DispatcherContext 0x%X\n", DispatcherContext);
// Clear the direction flag (make no assumptions!)
__asm__ ("cld");
// if neither the EXCEPTION_UNWINDING nor EXCEPTION_EXIT_UNWIND bit
// is set... This is true the first time through the handler (the
// non-unwinding case)
if (!(ExceptionRecord->ExceptionFlags
& (EXCEPTION_UNWINDING|EXCEPTION_EXIT_UNWIND)))
{
DPRINT("Exception caught\n");
// Build the EXCEPTION_POINTERS structure on the stack
ExceptionPointers.ExceptionRecord = ExceptionRecord;
ExceptionPointers.ContextRecord = Context;
// Put the pointer to the EXCEPTION_POINTERS 4 bytes below the
// establisher frame
*(PDWORD)((ULONG_PTR)RtlRegistrationFrame - 4) = (ULONG_PTR)&ExceptionPointers;
// Get a pointer to the scopetable array
ScopeTable = RtlRegistrationFrame->ScopeTable;
DPRINT("ScopeTable is at 0x%X\n", ScopeTable);
// Get initial "try-level" value
TryLevel = RtlRegistrationFrame->TryLevel;
DPRINT("TryLevel is 0x%X\n", TryLevel);
search_for_handler:
DPRINT("RtlRegistrationFrame->TryLevel: 0x%X\n",
RtlRegistrationFrame->TryLevel);
if (RtlRegistrationFrame->TryLevel != TRYLEVEL_NONE)
{
if (ScopeTable[TryLevel].FilterRoutine)
{
NewEBP = (PVOID)RtlRegistrationFrame->Ebp;
Handler = (PVOID)ScopeTable[TryLevel].FilterRoutine;
DPRINT("Original EBP is: 0x%X\n", NewEBP);
DPRINT("Calling filter routine at 0x%X\n", Handler);
// Save this frame EBP
__asm__ ("pushl %ebp");
DPRINT("\n");
// Switch to original EBP. This is what allows all locals in the
// frame to have the same value as before the exception occurred.
__asm__ ("movl %0,%%eax; movl %0,%%ebp; call _SEHFilterRoutine;" : : \
"g" (Handler), \
"g" (NewEBP));
DPRINT("\n");
// Call the filter function
//FilterFuncRet = ScopeTable[TryLevel].FilterRoutine();
//FilterFuncRet = SEHFilterRoutine();
DPRINT("\n");
// Restore this frame EBP
__asm__ ("popl %%ebp" : "=a" (FilterFuncRet));
DPRINT("FilterRoutine returned: 0x%X\n", FilterFuncRet);
if (FilterFuncRet != EXCEPTION_CONTINUE_SEARCH)
{
if (FilterFuncRet < 0) // EXCEPTION_CONTINUE_EXECUTION
return ExceptionContinueExecution;
DPRINT("Filter routine said: execute handler\n");
// If we get here, EXCEPTION_EXECUTE_HANDLER was specified
// Does the actual OS cleanup of registration frames
// Causes this function to recurse
_global_unwind2(RtlRegistrationFrame);
_local_unwind2(RegistrationFrame, TryLevel);
// NLG == "non-local-goto" (setjmp/longjmp stuff)
//__NLG_Notify( 1 ); // EAX == scopetable->lpfnHandler
// Set the current trylevel to whatever SCOPETABLE entry
// was being used when a handler was found
RtlRegistrationFrame->TryLevel = ScopeTable->PreviousTryLevel;
// Once we get here, everything is all cleaned up, except
// for the last frame, where we'll continue execution
NewEBP = (PVOID)RtlRegistrationFrame->Ebp;
Handler = (PVOID)ScopeTable[TryLevel].HandlerRoutine;
// Switch to original EBP and call the __except block.
// If the function returns bugcheck the system.
__asm__ ("movl %0,%%eax; movl %0,%%ebp; call _SEHHandlerRoutine;" : : \
"g" (Handler), \
"g" (NewEBP));
KeBugCheck(KMODE_EXCEPTION_NOT_HANDLED);
}
}
ScopeTable = RtlRegistrationFrame->ScopeTable;
DPRINT("ScopeTable is at 0x%X\n", ScopeTable);
TryLevel = ScopeTable->PreviousTryLevel;
DPRINT("TryLevel is 0x%X\n", TryLevel);
goto search_for_handler;
}
else // TryLevel == TRYLEVEL_NONE
{
ReturnValue = ExceptionContinueSearch;
}
}
else // Either EXCEPTION_UNWINDING or EXCEPTION_EXIT_UNWIND flags is set
{
DPRINT("Local unwind\n");
// Save EBP
__asm__ ("pushl %%ebp; movl %0,%%edx;" : : \
"m" (RtlRegistrationFrame));
/* FIXME: Why is "addl $0x10,%%esp" needed? We only push 2*4 bytes, so why pop 16? */
__asm__ ("pushl $-1; pushl %%edx; movl %0,%%ebp; call __local_unwind2; addl $0x10,%%esp;" : : \
"m" (RtlRegistrationFrame->Ebp));
DPRINT("Local unwind3\n");
// Restore EBP for this frame
__asm__ ("popl %ebp");
ReturnValue = ExceptionContinueSearch;
}
DPRINT("ReturnValue 0x%X\n", ReturnValue);
return ReturnValue;
}
/* EOF */