diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in index db4002d9d7d..f8748f46295 100644 --- a/dlls/ntdll/Makefile.in +++ b/dlls/ntdll/Makefile.in @@ -6,6 +6,7 @@ VPATH = @srcdir@ 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 00000000000..62fbec9a7fc --- /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 d0c8c93beca..931bf979441 100644 --- a/dlls/ntdll/rtl.c +++ b/dlls/ntdll/rtl.c @@ -283,15 +283,7 @@ void __cdecl DbgPrint(LPCSTR fmt,LPVOID args) { 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 78c85996e91..652ba913f37 100644 --- a/include/debugdefs.h +++ b/include/debugdefs.h @@ -122,50 +122,51 @@ int dbch_resource = 110; 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 @@ char __debug_msg_enabled[DEBUG_CHANNEL_COUNT][DEBUG_CLASS_COUNT] = { {1, 1, 0, 0}, {1, 1, 0, 0}, {1, 1, 0, 0}, +{1, 1, 0, 0}, {1, 1, 0, 0} }; @@ -441,6 +443,7 @@ const char * const debug_ch_name[DEBUG_CHANNEL_COUNT] = { "scroll", "security", "segment", +"seh", "selector", "sem", "sendmsg", diff --git a/include/except.h b/include/except.h index c954177bd75..979fb0c92c0 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 #include "winnt.h" +#include "thread.h" /* * the function pointer to a exception handler @@ -18,7 +21,7 @@ struct __EXCEPTION_FRAME; 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 @@ typedef struct __EXCEPTION_FRAME } 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 898b1f40df0..4d19e40edde 100644 --- a/include/ntddk.h +++ b/include/ntddk.h @@ -573,8 +573,8 @@ BOOLEAN WINAPI RtlFreeHeap( * 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 c0595ff18a1..9cd30a88636 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 d9bfe5665de..419ed963661 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -992,42 +992,30 @@ typedef DWORD (WINAPI *LPPROGRESS_ROUTINE)(LARGE_INTEGER, LARGE_INTEGER, LARGE_I #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 @@ typedef DWORD (WINAPI *LPPROGRESS_ROUTINE)(LARGE_INTEGER, LARGE_INTEGER, LARGE_I #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 a99763fb8a9..a05415bdfd5 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -216,20 +216,32 @@ typedef HANDLE *PHANDLE; * 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 @@ typedef HANDLE *PHANDLE; #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 4375e1d2738..e736395fd7f 100644 --- a/relay32/kernel32.spec +++ b/relay32/kernel32.spec @@ -582,7 +582,7 @@ init MAIN_KernelInit 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 8dabefb4e8b..9207683d45c 100644 --- a/relay32/ntdll.spec +++ b/relay32/ntdll.spec @@ -180,7 +180,7 @@ type win32 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 @@ type win32 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 8750bd20b34..8290a08aca9 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 ); }