diff --git a/dlls/winecrt0/exception.c b/dlls/winecrt0/exception.c index c81c8216a24..0e00f73a6fd 100644 --- a/dlls/winecrt0/exception.c +++ b/dlls/winecrt0/exception.c @@ -99,6 +99,31 @@ DWORD __wine_exception_handler( EXCEPTION_RECORD *record, unwind_frame( record, frame ); } +DWORD __wine_exception_ctx_handler( EXCEPTION_RECORD *record, + EXCEPTION_REGISTRATION_RECORD *frame, + CONTEXT *context, + EXCEPTION_REGISTRATION_RECORD **pdispatcher ) +{ + __WINE_FRAME *wine_frame = (__WINE_FRAME *)frame; + EXCEPTION_POINTERS ptrs; + + if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND | EH_NESTED_CALL)) + return ExceptionContinueSearch; + + ptrs.ExceptionRecord = record; + ptrs.ContextRecord = context; + switch(wine_frame->u.filter_ctx( &ptrs, wine_frame->ctx )) + { + case EXCEPTION_CONTINUE_SEARCH: + return ExceptionContinueSearch; + case EXCEPTION_CONTINUE_EXECUTION: + return ExceptionContinueExecution; + case EXCEPTION_EXECUTE_HANDLER: + break; + } + unwind_frame( record, frame ); +} + DWORD __wine_exception_handler_page_fault( EXCEPTION_RECORD *record, EXCEPTION_REGISTRATION_RECORD *frame, CONTEXT *context, @@ -133,3 +158,16 @@ DWORD __wine_finally_handler( EXCEPTION_RECORD *record, } return ExceptionContinueSearch; } + +DWORD __wine_finally_ctx_handler( EXCEPTION_RECORD *record, + EXCEPTION_REGISTRATION_RECORD *frame, + CONTEXT *context, + EXCEPTION_REGISTRATION_RECORD **pdispatcher ) +{ + if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)) + { + __WINE_FRAME *wine_frame = (__WINE_FRAME *)frame; + wine_frame->u.finally_func_ctx( FALSE, wine_frame->ctx ); + } + return ExceptionContinueSearch; +} diff --git a/include/wine/exception.h b/include/wine/exception.h index f275568f4d1..5bc4d1c6922 100644 --- a/include/wine/exception.h +++ b/include/wine/exception.h @@ -81,7 +81,9 @@ extern "C" { #define __TRY __try #define __EXCEPT(func) __except((func)(GetExceptionInformation())) +#define __EXCEPT_CTX(func, ctx) __except((func)(GetExceptionInformation(), ctx)) #define __FINALLY(func) __finally { (func)(!AbnormalTermination()); } +#define __FINALLY_CTX(func, ctx) __finally { (func)(!AbnormalTermination(), ctx); } #define __ENDTRY /*nothing*/ #define __EXCEPT_PAGE_FAULT __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) #define __EXCEPT_ALL __except(EXCEPTION_EXECUTE_HANDLER) @@ -100,6 +102,10 @@ extern DWORD __wine_exception_handler( EXCEPTION_RECORD *record, EXCEPTION_REGISTRATION_RECORD *frame, CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **pdispatcher ) DECLSPEC_HIDDEN; +extern DWORD __wine_exception_ctx_handler( EXCEPTION_RECORD *record, + EXCEPTION_REGISTRATION_RECORD *frame, + CONTEXT *context, + EXCEPTION_REGISTRATION_RECORD **pdispatcher ) DECLSPEC_HIDDEN; extern DWORD __wine_exception_handler_page_fault( EXCEPTION_RECORD *record, EXCEPTION_REGISTRATION_RECORD *frame, CONTEXT *context, @@ -112,6 +118,10 @@ extern DWORD __wine_finally_handler( EXCEPTION_RECORD *record, EXCEPTION_REGISTRATION_RECORD *frame, CONTEXT *context, EXCEPTION_REGISTRATION_RECORD **pdispatcher ) DECLSPEC_HIDDEN; +extern DWORD __wine_finally_ctx_handler( EXCEPTION_RECORD *record, + EXCEPTION_REGISTRATION_RECORD *frame, + CONTEXT *context, + EXCEPTION_REGISTRATION_RECORD **pdispatcher ) DECLSPEC_HIDDEN; #define __TRY \ do { __WINE_FRAME __f; \ @@ -131,6 +141,18 @@ extern DWORD __wine_finally_handler( EXCEPTION_RECORD *record, const __WINE_FRAME * const __eptr __attribute__((unused)) = &__f; \ do { +#define __EXCEPT_CTX(func, context) \ + } while(0); \ + __wine_pop_frame( &__f.frame ); \ + break; \ + } else { \ + __f.frame.Handler = __wine_exception_ctx_handler; \ + __f.u.filter_ctx = (func); \ + __f.ctx = context; \ + if (sigsetjmp( __f.jmp, 0 )) { \ + const __WINE_FRAME * const __eptr __attribute__((unused)) = &__f; \ + do { + /* convenience handler for page fault exceptions */ #define __EXCEPT_PAGE_FAULT \ } while(0); \ @@ -175,9 +197,25 @@ extern DWORD __wine_finally_handler( EXCEPTION_RECORD *record, } \ } while (0); +#define __FINALLY_CTX(func, context) \ + } while(0); \ + __wine_pop_frame( &__f.frame ); \ + (func)(1, context); \ + break; \ + } else { \ + __f.frame.Handler = __wine_finally_ctx_handler; \ + __f.u.finally_func_ctx = (func); \ + __f.ctx = context; \ + __wine_push_frame( &__f.frame ); \ + __first = 0; \ + } \ + } while (0); + typedef LONG (CALLBACK *__WINE_FILTER)(PEXCEPTION_POINTERS); +typedef LONG (CALLBACK *__WINE_FILTER_CTX)(PEXCEPTION_POINTERS, void*); typedef void (CALLBACK *__WINE_FINALLY)(BOOL); +typedef void (CALLBACK *__WINE_FINALLY_CTX)(BOOL, void*); #define GetExceptionInformation() (__eptr) #define GetExceptionCode() (__eptr->ExceptionRecord->ExceptionCode) @@ -190,9 +228,12 @@ typedef struct __tagWINE_FRAME { /* exception data */ __WINE_FILTER filter; + __WINE_FILTER_CTX filter_ctx; /* finally data */ __WINE_FINALLY finally_func; + __WINE_FINALLY_CTX finally_func_ctx; } u; + void *ctx; sigjmp_buf jmp; /* hack to make GetExceptionCode() work in handler */ DWORD ExceptionCode;