Improved exception handling.
Based on the work of Sergey Turchanov <turchanov@usa.net>.
diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in
index db4002d..f8748f4 100644
--- a/dlls/ntdll/Makefile.in
+++ b/dlls/ntdll/Makefile.in
@@ -6,6 +6,7 @@
MODULE = ntdll
C_SRCS = \
+ exception.c \
file.c \
nt.c \
om.c \
diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c
new file mode 100644
index 0000000..62fbec9
--- /dev/null
+++ b/dlls/ntdll/exception.c
@@ -0,0 +1,317 @@
+/*
+ * NT exception handling routines
+ *
+ * Copyright 1999 Turchanov Sergey
+ * Copyright 1999 Alexandre Julliard
+ */
+
+#include "debugtools.h"
+#include "winnt.h"
+#include "ntddk.h"
+#include "except.h"
+#include "stackframe.h"
+
+DEFAULT_DEBUG_CHANNEL(seh)
+
+/* Exception record for handling exceptions happening inside exception handlers */
+typedef struct
+{
+ EXCEPTION_FRAME frame;
+ EXCEPTION_FRAME *prevFrame;
+} EXC_NESTED_FRAME;
+
+
+/*******************************************************************
+ * EXC_RaiseHandler
+ *
+ * Handler for exceptions happening inside a handler.
+ */
+static DWORD CALLBACK EXC_RaiseHandler( EXCEPTION_RECORD *rec, EXCEPTION_FRAME *frame,
+ CONTEXT *context, EXCEPTION_FRAME **dispatcher )
+{
+ if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
+ return ExceptionContinueSearch;
+ /* We shouldn't get here so we store faulty frame in dispatcher */
+ *dispatcher = ((EXC_NESTED_FRAME*)frame)->prevFrame;
+ return ExceptionNestedException;
+}
+
+
+/*******************************************************************
+ * EXC_UnwindHandler
+ *
+ * Handler for exceptions happening inside an unwind handler.
+ */
+static DWORD CALLBACK EXC_UnwindHandler( EXCEPTION_RECORD *rec, EXCEPTION_FRAME *frame,
+ CONTEXT *context, EXCEPTION_FRAME **dispatcher )
+{
+ if (!(rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)))
+ return ExceptionContinueSearch;
+ /* We shouldn't get here so we store faulty frame in dispatcher */
+ *dispatcher = ((EXC_NESTED_FRAME*)frame)->prevFrame;
+ return ExceptionCollidedUnwind;
+}
+
+
+/*******************************************************************
+ * EXC_CallHandler
+ *
+ * Call an exception handler, setting up an exception frame to catch exceptions
+ * happening during the handler execution.
+ */
+static DWORD EXC_CallHandler( PEXCEPTION_HANDLER handler, PEXCEPTION_HANDLER nested_handler,
+ EXCEPTION_RECORD *record, EXCEPTION_FRAME *frame,
+ CONTEXT *context, EXCEPTION_FRAME **dispatcher )
+{
+ EXC_NESTED_FRAME newframe;
+ DWORD ret;
+
+ newframe.frame.Handler = nested_handler;
+ newframe.prevFrame = frame;
+ EXC_push_frame( &newframe.frame );
+ TRACE( "calling handler at %p\n", handler );
+ ret = handler( record, frame, context, dispatcher );
+ TRACE( "handler returned %lx\n", ret );
+ EXC_pop_frame( &newframe.frame );
+ return ret;
+}
+
+
+/*******************************************************************
+ * EXC_DefaultHandling
+ *
+ * Default handling for exceptions. Called when we didn't find a suitable handler.
+ */
+static void EXC_DefaultHandling( EXCEPTION_RECORD *rec, CONTEXT *context )
+{
+ if (rec->ExceptionFlags & EH_STACK_INVALID)
+ ERR("Exception frame is not in stack limits => unable to dispatch exception.\n");
+ else if (rec->ExceptionCode == EXCEPTION_NONCONTINUABLE_EXCEPTION)
+ ERR("Process attempted to continue execution after noncontinuable exception.\n");
+ else
+ ERR("Unhandled exception code %lx flags %lx addr %p\n",
+ rec->ExceptionCode, rec->ExceptionFlags, rec->ExceptionAddress );
+ /* Should I add here a back trace ? */
+ TerminateProcess( GetCurrentProcess(), 1 );
+}
+
+
+/*******************************************************************
+ * EXC_RaiseException
+ *
+ * Implementation of NtRaiseException.
+ */
+static void EXC_RaiseException( EXCEPTION_RECORD *rec, CONTEXT *context )
+{
+ PEXCEPTION_FRAME frame, dispatch, nested_frame;
+ EXCEPTION_RECORD newrec;
+ DWORD res;
+
+ frame = NtCurrentTeb()->except;
+ nested_frame = NULL;
+ while (frame != (PEXCEPTION_FRAME)0xFFFFFFFF)
+ {
+ /* Check frame address */
+ if (((void*)frame < NtCurrentTeb()->stack_low) ||
+ ((void*)(frame+1) > NtCurrentTeb()->stack_top) ||
+ (int)frame & 3)
+ {
+ rec->ExceptionFlags |= EH_STACK_INVALID;
+ break;
+ }
+
+ /* Call handler */
+ res = EXC_CallHandler( frame->Handler, EXC_RaiseHandler, rec, frame, context, &dispatch );
+ if (frame == nested_frame)
+ {
+ /* no longer nested */
+ nested_frame = NULL;
+ rec->ExceptionFlags &= ~EH_NESTED_CALL;
+ }
+
+ switch(res)
+ {
+ case ExceptionContinueExecution:
+ if (!(rec->ExceptionFlags & EH_NONCONTINUABLE)) return;
+ newrec.ExceptionCode = STATUS_NONCONTINUABLE_EXCEPTION;
+ newrec.ExceptionFlags = EH_NONCONTINUABLE;
+ newrec.ExceptionRecord = rec;
+ newrec.NumberParameters = 0;
+ RtlRaiseException( &newrec ); /* never returns */
+ break;
+ case ExceptionContinueSearch:
+ break;
+ case ExceptionNestedException:
+ if (nested_frame < dispatch) nested_frame = dispatch;
+ rec->ExceptionFlags |= EH_NESTED_CALL;
+ break;
+ default:
+ newrec.ExceptionCode = STATUS_INVALID_DISPOSITION;
+ newrec.ExceptionFlags = EH_NONCONTINUABLE;
+ newrec.ExceptionRecord = rec;
+ newrec.NumberParameters = 0;
+ RtlRaiseException( &newrec ); /* never returns */
+ break;
+ }
+ frame = frame->Prev;
+ }
+ EXC_DefaultHandling( rec, context );
+}
+
+
+/*******************************************************************
+ * EXC_RtlUnwind
+ *
+ * Implementation of RtlUnwind.
+ */
+static void EXC_RtlUnwind( EXCEPTION_FRAME *pEndFrame, EXCEPTION_RECORD *pRecord,
+ CONTEXT *context )
+{
+ EXCEPTION_RECORD record, newrec;
+ PEXCEPTION_FRAME frame, dispatch;
+
+ /* build an exception record, if we do not have one */
+ if (!pRecord)
+ {
+ record.ExceptionCode = STATUS_UNWIND;
+ record.ExceptionFlags = 0;
+ record.ExceptionRecord = NULL;
+ record.ExceptionAddress = (LPVOID)EIP_reg(context);
+ record.NumberParameters = 0;
+ pRecord = &record;
+ }
+
+ pRecord->ExceptionFlags |= EH_UNWINDING | (pEndFrame ? 0 : EH_EXIT_UNWIND);
+
+ /* get chain of exception frames */
+ frame = NtCurrentTeb()->except;
+ while ((frame != (PEXCEPTION_FRAME)0xffffffff) && (frame != pEndFrame))
+ {
+ /* Check frame address */
+ if (pEndFrame && (frame > pEndFrame))
+ {
+ newrec.ExceptionCode = STATUS_INVALID_UNWIND_TARGET;
+ newrec.ExceptionFlags = EH_NONCONTINUABLE;
+ newrec.ExceptionRecord = pRecord;
+ newrec.NumberParameters = 0;
+ RtlRaiseException( &newrec ); /* never returns */
+ }
+ if (((void*)frame < NtCurrentTeb()->stack_low) ||
+ ((void*)(frame+1) > NtCurrentTeb()->stack_top) ||
+ (int)frame & 3)
+ {
+ newrec.ExceptionCode = STATUS_BAD_STACK;
+ newrec.ExceptionFlags = EH_NONCONTINUABLE;
+ newrec.ExceptionRecord = pRecord;
+ newrec.NumberParameters = 0;
+ RtlRaiseException( &newrec ); /* never returns */
+ }
+
+ /* Call handler */
+ switch(EXC_CallHandler( frame->Handler, EXC_UnwindHandler, pRecord,
+ frame, context, &dispatch ))
+ {
+ case ExceptionContinueSearch:
+ break;
+ case ExceptionCollidedUnwind:
+ frame = dispatch;
+ break;
+ default:
+ newrec.ExceptionCode = STATUS_INVALID_DISPOSITION;
+ newrec.ExceptionFlags = EH_NONCONTINUABLE;
+ newrec.ExceptionRecord = pRecord;
+ newrec.NumberParameters = 0;
+ RtlRaiseException( &newrec ); /* never returns */
+ break;
+ }
+ NtCurrentTeb()->except = frame = frame->Prev;
+ }
+}
+
+
+/*******************************************************************
+ * NtRaiseException (NTDLL.175)
+ *
+ * Real prototype:
+ * DWORD WINAPI NtRaiseException( EXCEPTION_RECORD *rec, CONTEXT *ctx, BOOL first );
+ */
+REGS_ENTRYPOINT(NtRaiseException)
+{
+ DWORD ret;
+ EXCEPTION_RECORD *rec;
+ CONTEXT *ctx;
+ BOOL first;
+
+ ret = STACK32_POP(context); /* return addr */
+ rec = (PEXCEPTION_RECORD)STACK32_POP(context);
+ ctx = (PCONTEXT)STACK32_POP(context);
+ first = (BOOL)STACK32_POP(context);
+ STACK32_PUSH(context,ret); /* restore return addr */
+
+ EXC_RaiseException( rec, context );
+ *context = *ctx;
+}
+
+
+/***********************************************************************
+ * RtlRaiseException (NTDLL.464)
+ *
+ * Real prototype:
+ * void WINAPI RtlRaiseException(PEXCEPTION_RECORD pRecord)
+ */
+REGS_ENTRYPOINT(RtlRaiseException)
+{
+ EXCEPTION_RECORD *rec;
+ DWORD ret;
+
+ ret = STACK32_POP(context); /* return addr */
+ rec = (PEXCEPTION_RECORD)STACK32_POP(context);
+ STACK32_PUSH(context,ret); /* restore return addr */
+
+ rec->ExceptionAddress = (LPVOID)EIP_reg(context);
+ EXC_RaiseException( rec, context );
+}
+
+
+/*******************************************************************
+ * RtlUnwind (KERNEL32.590) (NTDLL.518)
+ *
+ * This function is undocumented. This is the general idea of
+ * RtlUnwind, though. Note that error handling is not yet implemented.
+ *
+ * The real prototype is:
+ * void WINAPI RtlUnwind( PEXCEPTION_FRAME pEndFrame, LPVOID unusedEip,
+ * PEXCEPTION_RECORD pRecord, DWORD returnEax );
+ */
+REGS_ENTRYPOINT(RtlUnwind)
+{
+ PEXCEPTION_FRAME pEndFrame;
+ PEXCEPTION_RECORD pRecord;
+
+ /* get the arguments from the stack */
+ DWORD ret = STACK32_POP(context); /* return addr */
+ pEndFrame = (PEXCEPTION_FRAME)STACK32_POP(context);
+ (void)STACK32_POP(context); /* unused arg */
+ pRecord = (PEXCEPTION_RECORD)STACK32_POP(context);
+ EAX_reg(context) = STACK32_POP(context);
+ STACK32_PUSH(context,ret); /* restore return addr */
+
+ EXC_RtlUnwind( pEndFrame, pRecord, context );
+}
+
+
+/***********************************************************************
+ * RtlRaiseStatus (NTDLL.465)
+ *
+ * Raise an exception with ExceptionCode = status
+ */
+void WINAPI RtlRaiseStatus( NTSTATUS status )
+{
+ EXCEPTION_RECORD ExceptionRec;
+
+ ExceptionRec.ExceptionCode = status;
+ ExceptionRec.ExceptionFlags = EH_NONCONTINUABLE;
+ ExceptionRec.ExceptionRecord = NULL;
+ ExceptionRec.NumberParameters = 0;
+ RtlRaiseException( &ExceptionRec );
+}
diff --git a/dlls/ntdll/rtl.c b/dlls/ntdll/rtl.c
index d0c8c93..931bf97 100644
--- a/dlls/ntdll/rtl.c
+++ b/dlls/ntdll/rtl.c
@@ -283,15 +283,7 @@
MSG("DbgPrint says: %s",buf);
/* hmm, raise exception? */
}
-DWORD NtRaiseException ( DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments,CONST ULONG_PTR *lpArguments)
-{ FIXME(ntdll,"0x%08lx 0x%08lx 0x%08lx %p\n", dwExceptionCode, dwExceptionFlags, nNumberOfArguments, lpArguments);
- return 0;
-}
-DWORD RtlRaiseException ( DWORD x)
-{ FIXME(ntdll, "0x%08lx\n", x);
- return 0;
-}
/******************************************************************************
* RtlAcquirePebLock [NTDLL]
*/
diff --git a/include/debugdefs.h b/include/debugdefs.h
index 78c8599..652ba91 100644
--- a/include/debugdefs.h
+++ b/include/debugdefs.h
@@ -122,50 +122,51 @@
int dbch_scroll = 111;
int dbch_security = 112;
int dbch_segment = 113;
-int dbch_selector = 114;
-int dbch_sem = 115;
-int dbch_sendmsg = 116;
-int dbch_server = 117;
-int dbch_shell = 118;
-int dbch_shm = 119;
-int dbch_snoop = 120;
-int dbch_sound = 121;
-int dbch_static = 122;
-int dbch_statusbar = 123;
-int dbch_storage = 124;
-int dbch_stress = 125;
-int dbch_string = 126;
-int dbch_syscolor = 127;
-int dbch_system = 128;
-int dbch_tab = 129;
-int dbch_tapi = 130;
-int dbch_task = 131;
-int dbch_text = 132;
-int dbch_thread = 133;
-int dbch_thunk = 134;
-int dbch_timer = 135;
-int dbch_toolbar = 136;
-int dbch_toolhelp = 137;
-int dbch_tooltips = 138;
-int dbch_trackbar = 139;
-int dbch_treeview = 140;
-int dbch_ttydrv = 141;
-int dbch_tweak = 142;
-int dbch_updown = 143;
-int dbch_ver = 144;
-int dbch_virtual = 145;
-int dbch_vxd = 146;
-int dbch_wave = 147;
-int dbch_win = 148;
-int dbch_win16drv = 149;
-int dbch_win32 = 150;
-int dbch_wing = 151;
-int dbch_winsock = 152;
-int dbch_wnet = 153;
-int dbch_x11 = 154;
-int dbch_x11drv = 155;
+int dbch_seh = 114;
+int dbch_selector = 115;
+int dbch_sem = 116;
+int dbch_sendmsg = 117;
+int dbch_server = 118;
+int dbch_shell = 119;
+int dbch_shm = 120;
+int dbch_snoop = 121;
+int dbch_sound = 122;
+int dbch_static = 123;
+int dbch_statusbar = 124;
+int dbch_storage = 125;
+int dbch_stress = 126;
+int dbch_string = 127;
+int dbch_syscolor = 128;
+int dbch_system = 129;
+int dbch_tab = 130;
+int dbch_tapi = 131;
+int dbch_task = 132;
+int dbch_text = 133;
+int dbch_thread = 134;
+int dbch_thunk = 135;
+int dbch_timer = 136;
+int dbch_toolbar = 137;
+int dbch_toolhelp = 138;
+int dbch_tooltips = 139;
+int dbch_trackbar = 140;
+int dbch_treeview = 141;
+int dbch_ttydrv = 142;
+int dbch_tweak = 143;
+int dbch_updown = 144;
+int dbch_ver = 145;
+int dbch_virtual = 146;
+int dbch_vxd = 147;
+int dbch_wave = 148;
+int dbch_win = 149;
+int dbch_win16drv = 150;
+int dbch_win32 = 151;
+int dbch_wing = 152;
+int dbch_winsock = 153;
+int dbch_wnet = 154;
+int dbch_x11 = 155;
+int dbch_x11drv = 156;
-#define DEBUG_CHANNEL_COUNT 156
+#define DEBUG_CHANNEL_COUNT 157
char __debug_msg_enabled[DEBUG_CHANNEL_COUNT][DEBUG_CLASS_COUNT] = {
{1, 1, 0, 0},
@@ -323,6 +324,7 @@
{1, 1, 0, 0},
{1, 1, 0, 0},
{1, 1, 0, 0},
+{1, 1, 0, 0},
{1, 1, 0, 0}
};
@@ -441,6 +443,7 @@
"scroll",
"security",
"segment",
+"seh",
"selector",
"sem",
"sendmsg",
diff --git a/include/except.h b/include/except.h
index c954177..979fb0c 100644
--- a/include/except.h
+++ b/include/except.h
@@ -1,12 +1,15 @@
/*
* except.h
- * Copyright (c) 1996, Onno Hovers (onno@stack.urc.tue.nl)
+ * Copyright (c) 1996 Onno Hovers (onno@stack.urc.tue.nl)
+ * Copyright (c) 1999 Alexandre Julliard
*/
#ifndef __WINE_EXCEPT_H
#define __WINE_EXCEPT_H
+#include <setjmp.h>
#include "winnt.h"
+#include "thread.h"
/*
* the function pointer to a exception handler
@@ -18,7 +21,7 @@
typedef DWORD (CALLBACK *PEXCEPTION_HANDLER)( PEXCEPTION_RECORD pexcrec,
struct __EXCEPTION_FRAME *pestframe,
PCONTEXT pcontext,
- LPVOID pdispatcher);
+ struct __EXCEPTION_FRAME **pdispatcher);
/*
* The exception frame, used for registering exception handlers
@@ -33,22 +36,20 @@
} EXCEPTION_FRAME, *PEXCEPTION_FRAME;
-/*
- * this undocumented function is called when an exception
- * handler wants all the frames to be unwound. RtlUnwind
- * calls all exception handlers with the EH_UNWIND or
- * EH_EXIT_UNWIND flags set in the exception record
- *
- * This prototype assumes RtlUnwind takes the same
- * parameters as OS/2 2.0 DosUnwindException
- * Disassembling RtlUnwind shows this is true, except for
- * the TargetEIP parameter, which is unused. There is
- * a fourth parameter, that is used as the eax in the
- * context.
- */
-void WINAPI RtlUnwind( PEXCEPTION_FRAME pestframe,
- LPVOID unusedEIP,
- PEXCEPTION_RECORD pexcrec,
- DWORD contextEAX );
+void WINAPI RtlUnwind(PEXCEPTION_FRAME,LPVOID,PEXCEPTION_RECORD,DWORD);
+
+static inline EXCEPTION_FRAME *EXC_push_frame( EXCEPTION_FRAME *frame )
+{
+ TEB * teb = NtCurrentTeb();
+ frame->Prev = teb->except;
+ teb->except = frame;
+ return frame;
+}
+
+static inline EXCEPTION_FRAME *EXC_pop_frame( EXCEPTION_FRAME *frame )
+{
+ NtCurrentTeb()->except = frame->Prev;
+ return frame->Prev;
+}
#endif /* __WINE_EXCEPT_H */
diff --git a/include/ntddk.h b/include/ntddk.h
index 898b1f4..4d19e40 100644
--- a/include/ntddk.h
+++ b/include/ntddk.h
@@ -573,8 +573,8 @@
* misc
*/
void __cdecl DbgPrint(LPCSTR fmt,LPVOID args);
-DWORD NtRaiseException ( DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments,CONST ULONG_PTR *lpArguments);
-DWORD RtlRaiseException ( DWORD x);
+DWORD WINAPI NtRaiseException(PEXCEPTION_RECORD,PCONTEXT,BOOL);
+void WINAPI RtlRaiseException(PEXCEPTION_RECORD);
VOID WINAPI RtlAcquirePebLock(void);
VOID WINAPI RtlReleasePebLock(void);
DWORD WINAPI RtlAdjustPrivilege(DWORD x1,DWORD x2,DWORD x3,DWORD x4);
diff --git a/include/thread.h b/include/thread.h
index c0595ff..9cd30a8 100644
--- a/include/thread.h
+++ b/include/thread.h
@@ -12,11 +12,12 @@
#include "selectors.h" /* for SET_FS */
struct _PDB;
+struct __EXCEPTION_FRAME;
/* Thread exception block */
typedef struct _TEB
{
- void *except; /* 00 Head of exception handling chain */
+ struct __EXCEPTION_FRAME *except; /* 00 Head of exception handling chain */
void *stack_top; /* 04 Top of thread stack */
void *stack_low; /* 08 Stack low-water mark */
HTASK16 htask16; /* 0c Win16 task handle */
diff --git a/include/winbase.h b/include/winbase.h
index d9bfe56..419ed96 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -992,42 +992,30 @@
#define FS_CASE_IS_PRESERVED FILE_CASE_PRESERVED_NAMES
#define FS_UNICODE_STORED_ON_DISK FILE_UNICODE_ON_DISK
+#define EXCEPTION_ACCESS_VIOLATION STATUS_ACCESS_VIOLATION
+#define EXCEPTION_DATATYPE_MISALIGNMENT STATUS_DATATYPE_MISALIGNMENT
+#define EXCEPTION_BREAKPOINT STATUS_BREAKPOINT
+#define EXCEPTION_SINGLE_STEP STATUS_SINGLE_STEP
+#define EXCEPTION_ARRAY_BOUNDS_EXCEEDED STATUS_ARRAY_BOUNDS_EXCEEDED
+#define EXCEPTION_FLT_DENORMAL_OPERAND STATUS_FLOAT_DENORMAL_OPERAND
+#define EXCEPTION_FLT_DIVIDE_BY_ZERO STATUS_FLOAT_DIVIDE_BY_ZERO
+#define EXCEPTION_FLT_INEXACT_RESULT STATUS_FLOAT_INEXACT_RESULT
+#define EXCEPTION_FLT_INVALID_OPERATION STATUS_FLOAT_INVALID_OPERATION
+#define EXCEPTION_FLT_OVERFLOW STATUS_FLOAT_OVERFLOW
+#define EXCEPTION_FLT_STACK_CHECK STATUS_FLOAT_STACK_CHECK
+#define EXCEPTION_FLT_UNDERFLOW STATUS_FLOAT_UNDERFLOW
+#define EXCEPTION_INT_DIVIDE_BY_ZERO STATUS_INTEGER_DIVIDE_BY_ZERO
+#define EXCEPTION_INT_OVERFLOW STATUS_INTEGER_OVERFLOW
+#define EXCEPTION_PRIV_INSTRUCTION STATUS_PRIVILEGED_INSTRUCTION
+#define EXCEPTION_IN_PAGE_ERROR STATUS_IN_PAGE_ERROR
+#define EXCEPTION_ILLEGAL_INSTRUCTION STATUS_ILLEGAL_INSTRUCTION
+#define EXCEPTION_NONCONTINUABLE_EXCEPTION STATUS_NONCONTINUABLE_EXCEPTION
+#define EXCEPTION_STACK_OVERFLOW STATUS_STACK_OVERFLOW
+#define EXCEPTION_INVALID_DISPOSITION STATUS_INVALID_DISPOSITION
+#define EXCEPTION_GUARD_PAGE STATUS_GUARD_PAGE_VIOLATION
+#define EXCEPTION_INVALID_HANDLE STATUS_INVALID_HANDLE
+#define CONTROL_C_EXIT STATUS_CONTROL_C_EXIT
-#define STATUS_SUCCESS 0x00000000
-#define STATUS_WAIT_0 0x00000000
-#define STATUS_ABANDONED_WAIT_0 0x00000080
-#define STATUS_USER_APC 0x000000C0
-#define STATUS_TIMEOUT 0x00000102
-#define STATUS_PENDING 0x00000103
-#define STATUS_GUARD_PAGE_VIOLATION 0x80000001
-#define STATUS_DATATYPE_MISALIGNMENT 0x80000002
-#define STATUS_BREAKPOINT 0x80000003
-#define STATUS_SINGLE_STEP 0x80000004
-#define STATUS_BUFFER_OVERFLOW 0x80000005
-#define STATUS_ACCESS_VIOLATION 0xC0000005
-#define STATUS_IN_PAGE_ERROR 0xC0000006
-#define STATUS_INVALID_PARAMETER 0xC000000D
-#define STATUS_NO_MEMORY 0xC0000017
-#define STATUS_ILLEGAL_INSTRUCTION 0xC000001D
-#define STATUS_BUFFER_TOO_SMALL 0xC0000023
-#define STATUS_NONCONTINUABLE_EXCEPTION 0xC0000025
-#define STATUS_INVALID_DISPOSITION 0xC0000026
-#define STATUS_UNKNOWN_REVISION 0xC0000058
-#define STATUS_INVALID_SECURITY_DESCR 0xC0000079
-#define STATUS_ARRAY_BOUNDS_EXCEEDED 0xC000008C
-#define STATUS_FLOAT_DENORMAL_OPERAND 0xC000008D
-#define STATUS_FLOAT_DIVIDE_BY_ZERO 0xC000008E
-#define STATUS_FLOAT_INEXACT_RESULT 0xC000008F
-#define STATUS_FLOAT_INVALID_OPERATION 0xC0000090
-#define STATUS_FLOAT_OVERFLOW 0xC0000091
-#define STATUS_FLOAT_STACK_CHECK 0xC0000092
-#define STATUS_FLOAT_UNDERFLOW 0xC0000093
-#define STATUS_INTEGER_DIVIDE_BY_ZERO 0xC0000094
-#define STATUS_INTEGER_OVERFLOW 0xC0000095
-#define STATUS_PRIVILEGED_INSTRUCTION 0xC0000096
-#define STATUS_INVALID_PARAMETER_2 0xC00000F0
-#define STATUS_STACK_OVERFLOW 0xC00000FD
-#define STATUS_CONTROL_C_EXIT 0xC000013A
#define DUPLICATE_CLOSE_SOURCE 0x00000001
#define DUPLICATE_SAME_ACCESS 0x00000002
@@ -1046,29 +1034,6 @@
#define THREAD_PRIORITY_TIME_CRITICAL THREAD_BASE_PRIORITY_LOWRT
#define THREAD_PRIORITY_IDLE THREAD_BASE_PRIORITY_IDLE
-typedef struct
-{
- int type;
-} wine_exception;
-
-typedef struct
-{
- int pad[39];
- int edi;
- int esi;
- int ebx;
- int edx;
- int ecx;
- int eax;
-
- int ebp;
- int eip;
- int cs;
- int eflags;
- int esp;
- int ss;
-} exception_info;
-
/* Could this type be considered opaque? */
typedef struct {
LPVOID DebugInfo;
diff --git a/include/winnt.h b/include/winnt.h
index a99763f..a05415bd 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -216,20 +216,32 @@
* Exception codes
*/
+#define STATUS_SUCCESS 0x00000000
#define STATUS_WAIT_0 0x00000000
#define STATUS_ABANDONED_WAIT_0 0x00000080
#define STATUS_USER_APC 0x000000C0
#define STATUS_TIMEOUT 0x00000102
#define STATUS_PENDING 0x00000103
+#define STATUS_GUARD_PAGE_VIOLATION 0x80000001
#define STATUS_DATATYPE_MISALIGNMENT 0x80000002
#define STATUS_BREAKPOINT 0x80000003
#define STATUS_SINGLE_STEP 0x80000004
+#define STATUS_BUFFER_OVERFLOW 0x80000005
+#define STATUS_UNSUCCESSFUL 0xC0000001
#define STATUS_ACCESS_VIOLATION 0xC0000005
#define STATUS_IN_PAGE_ERROR 0xC0000006
+#define STATUS_INVALID_PARAMETER 0xC000000D
#define STATUS_NO_MEMORY 0xC0000017
+#define STATUS_CONFLICTING_ADDRESSES 0xC0000018
#define STATUS_ILLEGAL_INSTRUCTION 0xC000001D
+#define STATUS_BUFFER_TOO_SMALL 0xC0000023
#define STATUS_NONCONTINUABLE_EXCEPTION 0xC0000025
#define STATUS_INVALID_DISPOSITION 0xC0000026
+#define STATUS_UNWIND 0xC0000027
+#define STATUS_BAD_STACK 0xC0000028
+#define STATUS_INVALID_UNWIND_TARGET 0xC0000029
+#define STATUS_UNKNOWN_REVISION 0xC0000058
+#define STATUS_INVALID_SECURITY_DESCR 0xC0000079
#define STATUS_ARRAY_BOUNDS_EXCEEDED 0xC000008C
#define STATUS_FLOAT_DENORMAL_OPERAND 0xC000008D
#define STATUS_FLOAT_DIVIDE_BY_ZERO 0xC000008E
@@ -241,33 +253,10 @@
#define STATUS_INTEGER_DIVIDE_BY_ZERO 0xC0000094
#define STATUS_INTEGER_OVERFLOW 0xC0000095
#define STATUS_PRIVILEGED_INSTRUCTION 0xC0000096
+#define STATUS_INVALID_PARAMETER_2 0xC00000F0
#define STATUS_STACK_OVERFLOW 0xC00000FD
#define STATUS_CONTROL_C_EXIT 0xC000013A
-#define EXCEPTION_ACCESS_VIOLATION STATUS_ACCESS_VIOLATION
-#define EXCEPTION_DATATYPE_MISALIGNMENT STATUS_DATATYPE_MISALIGNMENT
-#define EXCEPTION_BREAKPOINT STATUS_BREAKPOINT
-#define EXCEPTION_SINGLE_STEP STATUS_SINGLE_STEP
-#define EXCEPTION_ARRAY_BOUNDS_EXCEEDED STATUS_ARRAY_BOUNDS_EXCEEDED
-#define EXCEPTION_FLT_DENORMAL_OPERAND STATUS_FLOAT_DENORMAL_OPERAND
-#define EXCEPTION_FLT_DIVIDE_BY_ZERO STATUS_FLOAT_DIVIDE_BY_ZERO
-#define EXCEPTION_FLT_INEXACT_RESULT STATUS_FLOAT_INEXACT_RESULT
-#define EXCEPTION_FLT_INVALID_OPERATION STATUS_FLOAT_INVALID_OPERATION
-#define EXCEPTION_FLT_OVERFLOW STATUS_FLOAT_OVERFLOW
-#define EXCEPTION_FLT_STACK_CHECK STATUS_FLOAT_STACK_CHECK
-#define EXCEPTION_FLT_UNDERFLOW STATUS_FLOAT_UNDERFLOW
-#define EXCEPTION_INT_DIVIDE_BY_ZERO STATUS_INTEGER_DIVIDE_BY_ZERO
-#define EXCEPTION_INT_OVERFLOW STATUS_INTEGER_OVERFLOW
-#define EXCEPTION_PRIV_INSTRUCTION STATUS_PRIVILEGED_INSTRUCTION
-#define EXCEPTION_IN_PAGE_ERROR STATUS_IN_PAGE_ERROR
-#define EXCEPTION_ILLEGAL_INSTRUCTION STATUS_ILLEGAL_INSTRUCTION
-#define EXCEPTION_NONCONTINUABLE_EXCEPTION STATUS_NONCONTINUABLE_EXCEPTION
-#define EXCEPTION_STACK_OVERFLOW STATUS_STACK_OVERFLOW
-#define EXCEPTION_INVALID_DISPOSITION STATUS_INVALID_DISPOSITION
-#define EXCEPTION_GUARD_PAGE STATUS_GUARD_PAGE_VIOLATION
-#define EXCEPTION_INVALID_HANDLE STATUS_INVALID_HANDLE
-#define CONTROL_C_EXIT STATUS_CONTROL_C_EXIT
-
#define MAXIMUM_WAIT_OBJECTS 64
#define MAXIMUM_SUSPEND_COUNT 127
diff --git a/relay32/kernel32.spec b/relay32/kernel32.spec
index 4375e1d..e736395 100644
--- a/relay32/kernel32.spec
+++ b/relay32/kernel32.spec
@@ -582,7 +582,7 @@
564 stdcall QueryPerformanceCounter(ptr) QueryPerformanceCounter
565 stdcall QueryPerformanceFrequency(ptr) QueryPerformanceFrequency
566 stdcall QueueUserAPC(ptr long long) QueueUserAPC
-567 register RaiseException() RaiseException
+567 stdcall RaiseException(long long long ptr) RaiseException
568 stdcall ReadConsoleA(long ptr long ptr ptr) ReadConsoleA
569 stdcall ReadConsoleInputA(long ptr long ptr) ReadConsoleInputA
570 stdcall ReadConsoleInputW(long ptr long ptr) ReadConsoleInputW
diff --git a/relay32/ntdll.spec b/relay32/ntdll.spec
index 8dabefb..9207683 100644
--- a/relay32/ntdll.spec
+++ b/relay32/ntdll.spec
@@ -180,7 +180,7 @@
172 stdcall NtQueryValueKey(long long long long long long) NtQueryValueKey
173 stub NtQueryVirtualMemory
174 stub NtQueryVolumeInformationFile
-175 stdcall NtRaiseException(long long long ptr) NtRaiseException
+175 register NtRaiseException() NtRaiseException
176 stub NtRaiseHardError
177 stdcall NtReadFile(long long long long long long long long long) NtReadFile
178 stub NtReadRequestData
@@ -469,8 +469,8 @@
461 stub RtlQuerySecurityObject
462 stub RtlQueryTagHeap
463 stub RtlQueryTimeZoneInformation
-464 stdcall RtlRaiseException (long) RtlRaiseException
-465 stub RtlRaiseStatus
+464 register RtlRaiseException() RtlRaiseException
+465 stdcall RtlRaiseStatus(long) RtlRaiseStatus
466 stub RtlRandom
467 stub RtlReAllocateHeap
468 stub RtlRealPredecessor
diff --git a/win32/except.c b/win32/except.c
index 8750bd2..8290a08 100644
--- a/win32/except.c
+++ b/win32/except.c
@@ -2,6 +2,7 @@
* Win32 exception functions
*
* Copyright (c) 1996 Onno Hovers, (onno@stack.urc.tue.nl)
+ * Copyright (c) 1999 Alexandre Julliard
*
* Notes:
* What really happens behind the scenes of those new
@@ -41,152 +42,31 @@
#include "except.h"
#include "stackframe.h"
-DECLARE_DEBUG_CHANNEL(relay)
-DECLARE_DEBUG_CHANNEL(win32)
-
-#define TEB_EXCEPTION_FRAME(pcontext) \
- ((PEXCEPTION_FRAME)((TEB *)GET_SEL_BASE((pcontext)->SegFs))->except)
-
-/*******************************************************************
- * RtlUnwind (KERNEL32.443)
- *
- * This function is undocumented. This is the general idea of
- * RtlUnwind, though. Note that error handling is not yet implemented.
- *
- * The real prototype is:
- * void WINAPI EXC_RtlUnwind( PEXCEPTION_FRAME pEndFrame, LPVOID unusedEip,
- * PEXCEPTION_RECORD pRecord, DWORD returnEax );
- */
-REGS_ENTRYPOINT(RtlUnwind)
-{
- EXCEPTION_RECORD record;
- DWORD dispatch;
- int retval;
- PEXCEPTION_FRAME pEndFrame;
- PEXCEPTION_RECORD pRecord;
-
- /* get the arguments from the stack */
-
- DWORD ret = STACK32_POP(context); /* return addr */
- pEndFrame = (PEXCEPTION_FRAME)STACK32_POP(context);
- (void)STACK32_POP(context); /* unused arg */
- pRecord = (PEXCEPTION_RECORD)STACK32_POP(context);
- EAX_reg(context) = STACK32_POP(context);
- STACK32_PUSH(context,ret); /* restore return addr */
-
- /* build an exception record, if we do not have one */
- if(!pRecord)
- {
- record.ExceptionCode = STATUS_INVALID_DISPOSITION;
- record.ExceptionFlags = 0;
- record.ExceptionRecord = NULL;
- record.ExceptionAddress = (LPVOID)EIP_reg(context);
- record.NumberParameters = 0;
- pRecord = &record;
- }
-
- if(pEndFrame)
- pRecord->ExceptionFlags|=EH_UNWINDING;
- else
- pRecord->ExceptionFlags|=EH_UNWINDING | EH_EXIT_UNWIND;
-
- /* get chain of exception frames */
- while ((TEB_EXCEPTION_FRAME(context) != NULL) &&
- (TEB_EXCEPTION_FRAME(context) != ((void *)0xffffffff)) &&
- (TEB_EXCEPTION_FRAME(context) != pEndFrame))
- {
- TRACE_(win32)("calling exception handler at 0x%x\n",
- (int)TEB_EXCEPTION_FRAME(context)->Handler );
-
- dispatch=0;
- retval = TEB_EXCEPTION_FRAME(context)->Handler( pRecord,
- TEB_EXCEPTION_FRAME(context),
- context, &dispatch);
-
- TRACE_(win32)("exception handler returns 0x%x, dispatch=0x%x\n",
- retval, (int) dispatch);
-
- if ( (retval == ExceptionCollidedUnwind) &&
- (TEB_EXCEPTION_FRAME(context) != (LPVOID)dispatch)
- )
- TEB_EXCEPTION_FRAME(context) = (LPVOID)dispatch;
- else if ( (TEB_EXCEPTION_FRAME(context) != pEndFrame) &&
- (TEB_EXCEPTION_FRAME(context) != TEB_EXCEPTION_FRAME(context)->Prev)
- )
- TEB_EXCEPTION_FRAME(context) = TEB_EXCEPTION_FRAME(context)->Prev;
- else
- break;
- }
-}
+DEFAULT_DEBUG_CHANNEL(seh)
/*******************************************************************
* RaiseException (KERNEL32.418)
- *
- * The real prototype is:
- * void WINAPI EXC_RaiseException(DWORD dwExceptionCode,
- * DWORD dwExceptionFlags,
- * DWORD cArguments,
- * const LPDWORD lpArguments );
*/
-REGS_ENTRYPOINT(RaiseException)
+void WINAPI RaiseException( DWORD code, DWORD flags, DWORD nbargs, const LPDWORD args )
{
- PEXCEPTION_FRAME pframe;
- EXCEPTION_RECORD record;
- DWORD dispatch; /* is this used in raising exceptions ?? */
- int retval;
- int i;
+ EXCEPTION_RECORD record;
- /* Get the arguments from the stack */
-
- DWORD ret = STACK32_POP(context); /* return addr */
- DWORD dwExceptionCode = STACK32_POP(context);
- DWORD dwExceptionFlags = STACK32_POP(context);
- DWORD cArguments = STACK32_POP(context);
- const LPDWORD lpArguments = (LPDWORD)STACK32_POP(context);
- STACK32_PUSH(context,ret); /* Restore the return address */
-
- /* compose an exception record */
+ /* Compose an exception record */
- record.ExceptionCode = dwExceptionCode;
- record.ExceptionFlags = dwExceptionFlags;
- record.ExceptionRecord = NULL;
- record.NumberParameters = cArguments;
- record.ExceptionAddress = (LPVOID)EIP_reg(context);
-
- if (lpArguments) for( i = 0; i < cArguments; i++)
- record.ExceptionInformation[i] = lpArguments[i];
-
- /* get chain of exception frames */
-
- retval = ExceptionContinueSearch;
- pframe = TEB_EXCEPTION_FRAME( context );
-
- while((pframe!=NULL)&&(pframe!=((void *)0xFFFFFFFF)))
+ record.ExceptionCode = code;
+ record.ExceptionFlags = flags & EH_NONCONTINUABLE;
+ record.ExceptionRecord = NULL;
+ record.ExceptionAddress = RaiseException;
+ if (nbargs && args)
{
- PEXCEPTION_FRAME prevframe;
- TRACE_(win32)("calling exception handler at 0x%x\n",
- (int) pframe->Handler);
- dispatch=0;
- TRACE_(relay)("(except=%p,record=%p,frame=%p,context=%p,dispatch=%p)\n",
- pframe->Handler, &record, pframe, context, &dispatch );
- prevframe = pframe->Prev;
- retval=pframe->Handler(&record,pframe,context,&dispatch);
-
- TRACE_(win32)("exception handler returns 0x%x, dispatch=0x%x\n",
- retval, (int) dispatch);
-
- if(retval==ExceptionContinueExecution)
- break;
- pframe=prevframe;
- }
+ if (nbargs > EXCEPTION_MAXIMUM_PARAMETERS) nbargs = EXCEPTION_MAXIMUM_PARAMETERS;
+ record.NumberParameters = nbargs;
+ memcpy( record.ExceptionInformation, args, nbargs * sizeof(*args) );
+ }
+ else record.NumberParameters = 0;
- if (retval!=ExceptionContinueExecution)
- {
- /* FIXME: what should we do here? */
- TRACE_(win32)("no handler wanted to handle the exception, exiting\n");
- ExitProcess(dwExceptionCode); /* what status should be used here ? */
- }
+ RtlRaiseException( &record );
}