From 98b7852051a18200372108dede112e0f6ff9d407 Mon Sep 17 00:00:00 2001 From: Piotr Caban Date: Wed, 31 May 2017 12:39:29 +0200 Subject: [PATCH 1/2] include: Add __EXCEPT_CTX/__FINALLY_CTX macros. Piotr's draft from https://www.winehq.org/pipermail/wine-devel/2017-May/117946.html but with 2 changes: - subject line to match convention - small tweaks to fix compile errors: define __FINALLY_CTX(func, context) \ } while(0); \ __wine_pop_frame( &__f.frame ); \ - (func)(1); \ + (func)(1, context); \ break; \ } else { \ __f.frame.Handler = __wine_finally_ctx_handler; \ - __f.u.finally_ctx_func = (func); \ + __f.u.finally_func_ctx = (func); \ __f.ctx = context; \ __wine_push_frame( &__f.frame ); \ __first = 0; \ Signed-off-by: Daniel Lehman --- dlls/winecrt0/exception.c | 38 ++++++++++++++++++++++++++++++++++++++ include/wine/exception.h | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/dlls/winecrt0/exception.c b/dlls/winecrt0/exception.c index c81c821..0e00f73 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 f275568..5bc4d1c 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; -- 1.9.5