diff --git a/reactos/drivers/bus/acpi/include/platform/types.h b/reactos/drivers/bus/acpi/include/platform/types.h index 48565bd3692..58faac91fac 100644 --- a/reactos/drivers/bus/acpi/include/platform/types.h +++ b/reactos/drivers/bus/acpi/include/platform/types.h @@ -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 + * 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 + +#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 + #endif /* __INCLUDE_ACPI_TYPES_H */ + +#endif \ No newline at end of file diff --git a/reactos/include/ddk/rtl.h b/reactos/include/ddk/rtl.h index 2dfc5056c4f..c64a7dc159d 100644 --- a/reactos/include/ddk/rtl.h +++ b/reactos/include/ddk/rtl.h @@ -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 diff --git a/reactos/include/ntos/types.h b/reactos/include/ntos/types.h index a13e88eddbb..b0411ab4b4e 100644 --- a/reactos/include/ntos/types.h +++ b/reactos/include/ntos/types.h @@ -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 */ diff --git a/reactos/include/structs.h b/reactos/include/structs.h index 1021e95fbd4..5fb0add5ccd 100644 --- a/reactos/include/structs.h +++ b/reactos/include/structs.h @@ -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; diff --git a/reactos/lib/msvcrt/except/exhand2.c b/reactos/lib/msvcrt/except/exhand2.c index b9f8b365502..406aeeff7d0 100644 --- a/reactos/lib/msvcrt/except/exhand2.c +++ b/reactos/lib/msvcrt/except/exhand2.c @@ -1,13 +1,5 @@ #include -typedef enum _EXCEPTION_DISPOSITION { - ExceptionContinueExecution, - ExceptionContinueSearch, - ExceptionNestedException, - ExceptionCollidedUnwind -} EXCEPTION_DISPOSITION; - - EXCEPTION_DISPOSITION _except_handler2( struct _EXCEPTION_RECORD *ExceptionRecord, diff --git a/reactos/lib/msvcrt/except/exhand3.c b/reactos/lib/msvcrt/except/exhand3.c index 5f426475273..d17bacf1fd3 100644 --- a/reactos/lib/msvcrt/except/exhand3.c +++ b/reactos/lib/msvcrt/except/exhand3.c @@ -1,13 +1,5 @@ #include -typedef enum _EXCEPTION_DISPOSITION { - ExceptionContinueExecution, - ExceptionContinueSearch, - ExceptionNestedException, - ExceptionCollidedUnwind -} EXCEPTION_DISPOSITION; - - EXCEPTION_DISPOSITION _except_handler3( struct _EXCEPTION_RECORD *ExceptionRecord, diff --git a/reactos/lib/ntdll/rtl/exception.c b/reactos/lib/ntdll/rtl/exception.c index dabeb704772..65ad667218e 100644 --- a/reactos/lib/ntdll/rtl/exception.c +++ b/reactos/lib/ntdll/rtl/exception.c @@ -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) { } diff --git a/reactos/ntoskrnl/Makefile b/reactos/ntoskrnl/Makefile index 42d76a84bbb..23c030a911c 100644 --- a/reactos/ntoskrnl/Makefile +++ b/reactos/ntoskrnl/Makefile @@ -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 \ diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index e9d70218438..50b45704733 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -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, diff --git a/reactos/ntoskrnl/ke/catch.c b/reactos/ntoskrnl/ke/catch.c index 38f84a9e6cd..f06d420b5f4 100644 --- a/reactos/ntoskrnl/ke/catch.c +++ b/reactos/ntoskrnl/ke/catch.c @@ -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 #include +#define NDEBUG #include /* 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 */ diff --git a/reactos/ntoskrnl/ke/i386/exp.c b/reactos/ntoskrnl/ke/i386/exp.c index 89d116ce259..1440bfb47dd 100644 --- a/reactos/ntoskrnl/ke/i386/exp.c +++ b/reactos/ntoskrnl/ke/i386/exp.c @@ -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 diff --git a/reactos/ntoskrnl/ke/i386/kernel.c b/reactos/ntoskrnl/ke/i386/kernel.c index 2d23c1f31e8..a9574a50a5a 100644 --- a/reactos/ntoskrnl/ke/i386/kernel.c +++ b/reactos/ntoskrnl/ke/i386/kernel.c @@ -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(); } diff --git a/reactos/ntoskrnl/ke/i386/multiboot.S b/reactos/ntoskrnl/ke/i386/multiboot.S index 704e4e2d0e1..1f589943e4c 100644 --- a/reactos/ntoskrnl/ke/i386/multiboot.S +++ b/reactos/ntoskrnl/ke/i386/multiboot.S @@ -1,6 +1,7 @@ #include #include #include +#include #define KERNEL_BASE (0xc0000000) @@ -265,7 +266,7 @@ _multiboot_entry: */ movl $PCR_SELECTOR, %eax movl %eax, %fs - + /* * Load the initial kernel stack */ diff --git a/reactos/ntoskrnl/ke/i386/syscall.S b/reactos/ntoskrnl/ke/i386/syscall.S index 864298ea77b..6b3ff86a031 100644 --- a/reactos/ntoskrnl/ke/i386/syscall.S +++ b/reactos/ntoskrnl/ke/i386/syscall.S @@ -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 diff --git a/reactos/ntoskrnl/ke/i386/trap.s b/reactos/ntoskrnl/ke/i386/trap.s index e4cbb7d0821..79e67ed251a 100644 --- a/reactos/ntoskrnl/ke/i386/trap.s +++ b/reactos/ntoskrnl/ke/i386/trap.s @@ -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 diff --git a/reactos/ntoskrnl/ke/main.c b/reactos/ntoskrnl/ke/main.c index 438348a4495..664f0ffead1 100644 --- a/reactos/ntoskrnl/ke/main.c +++ b/reactos/ntoskrnl/ke/main.c @@ -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 */ diff --git a/reactos/ntoskrnl/ntoskrnl.def b/reactos/ntoskrnl/ntoskrnl.def index c7ba646f05e..4a8d886d423 100644 --- a/reactos/ntoskrnl/ntoskrnl.def +++ b/reactos/ntoskrnl/ntoskrnl.def @@ -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 diff --git a/reactos/ntoskrnl/ntoskrnl.edf b/reactos/ntoskrnl/ntoskrnl.edf index 529f60dd6f0..e7342982da5 100644 --- a/reactos/ntoskrnl/ntoskrnl.edf +++ b/reactos/ntoskrnl/ntoskrnl.edf @@ -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 diff --git a/reactos/ntoskrnl/rtl/seh.c b/reactos/ntoskrnl/rtl/seh.c new file mode 100644 index 00000000000..96e6bfc29f1 --- /dev/null +++ b/reactos/ntoskrnl/rtl/seh.c @@ -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 + +#define NDEBUG +#include + +/* 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 */