Follow up to https://gitlab.winehq.org/wine/wine/-/merge_requests/9209#note_120396
-- v7: ucrtbase: Add __C_specific_handler tests. msvcrt: Call the destructor for C++ exceptions in __C_specific_handler.
From: Vibhav Pant vibhavp@gmail.com
--- dlls/msvcr100/msvcr100.spec | 2 +- dlls/msvcr110/msvcr110.spec | 2 +- dlls/msvcr120/msvcr120.spec | 2 +- dlls/msvcr80/msvcr80.spec | 2 +- dlls/msvcr90/msvcr90.spec | 2 +- dlls/msvcrt/except.c | 254 +++++++++++++++++++++++++++++++++++ dlls/msvcrt/except_arm.c | 8 ++ dlls/msvcrt/except_arm64.c | 29 ++++ dlls/msvcrt/except_arm64ec.c | 30 +++++ dlls/msvcrt/msvcrt.spec | 2 +- dlls/ucrtbase/ucrtbase.spec | 2 +- 11 files changed, 328 insertions(+), 7 deletions(-)
diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec index d5949728840..95885b79162 100644 --- a/dlls/msvcr100/msvcr100.spec +++ b/dlls/msvcr100/msvcr100.spec @@ -712,7 +712,7 @@ @ cdecl __AdjustPointer(ptr ptr) @ stub __BuildCatchObject @ stub __BuildCatchObjectHelper -@ stdcall -arch=!i386 __C_specific_handler(ptr long ptr ptr) ntdll.__C_specific_handler +@ stdcall -arch=!i386 __C_specific_handler(ptr long ptr ptr) msvcrt.__C_specific_handler @ cdecl __CppXcptFilter(long ptr) @ stub __CxxCallUnwindDelDtor @ stub __CxxCallUnwindDtor diff --git a/dlls/msvcr110/msvcr110.spec b/dlls/msvcr110/msvcr110.spec index 9e45d08432f..b221cce714b 100644 --- a/dlls/msvcr110/msvcr110.spec +++ b/dlls/msvcr110/msvcr110.spec @@ -872,7 +872,7 @@ @ cdecl __AdjustPointer(ptr ptr) @ stub __BuildCatchObject @ stub __BuildCatchObjectHelper -@ stdcall -arch=!i386 __C_specific_handler(ptr long ptr ptr) ntdll.__C_specific_handler +@ stdcall -arch=!i386 __C_specific_handler(ptr long ptr ptr) msvcrt.__C_specific_handler @ cdecl __CppXcptFilter(long ptr) @ cdecl __CxxDetectRethrow(ptr) @ cdecl __CxxExceptionFilter(ptr ptr long ptr) diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec index 42494e4e39f..b7f89645888 100644 --- a/dlls/msvcr120/msvcr120.spec +++ b/dlls/msvcr120/msvcr120.spec @@ -857,7 +857,7 @@ @ cdecl __AdjustPointer(ptr ptr) @ stub __BuildCatchObject @ stub __BuildCatchObjectHelper -@ stdcall -arch=!i386 __C_specific_handler(ptr long ptr ptr) ntdll.__C_specific_handler +@ stdcall -arch=!i386 __C_specific_handler(ptr long ptr ptr) msvcrt.__C_specific_handler @ cdecl __CppXcptFilter(long ptr) @ cdecl __CxxDetectRethrow(ptr) @ cdecl __CxxExceptionFilter(ptr ptr long ptr) diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec index 0e5084c6c6e..a1a38586126 100644 --- a/dlls/msvcr80/msvcr80.spec +++ b/dlls/msvcr80/msvcr80.spec @@ -198,7 +198,7 @@ @ cdecl __AdjustPointer(ptr ptr) @ stub __BuildCatchObject @ stub __BuildCatchObjectHelper -@ stdcall -arch=!i386 __C_specific_handler(ptr long ptr ptr) ntdll.__C_specific_handler +@ stdcall -arch=!i386 __C_specific_handler(ptr long ptr ptr) msvcrt.__C_specific_handler @ cdecl __CppXcptFilter(long ptr) @ stub __CxxCallUnwindDelDtor @ stub __CxxCallUnwindDtor diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec index 97c6427bd80..cd09aaea497 100644 --- a/dlls/msvcr90/msvcr90.spec +++ b/dlls/msvcr90/msvcr90.spec @@ -189,7 +189,7 @@ @ cdecl __AdjustPointer(ptr ptr) @ stub __BuildCatchObject @ stub __BuildCatchObjectHelper -@ stdcall -arch=!i386 __C_specific_handler(ptr long ptr ptr) ntdll.__C_specific_handler +@ stdcall -arch=!i386 __C_specific_handler(ptr long ptr ptr) msvcrt.__C_specific_handler @ cdecl __CppXcptFilter(long ptr) @ stub __CxxCallUnwindDelDtor @ stub __CxxCallUnwindDtor diff --git a/dlls/msvcrt/except.c b/dlls/msvcrt/except.c index 383c67f7437..1b10387a810 100644 --- a/dlls/msvcrt/except.c +++ b/dlls/msvcrt/except.c @@ -43,6 +43,9 @@ #include "cppexcept.h"
WINE_DEFAULT_DEBUG_CHANNEL(seh); +#ifndef __i386__ +WINE_DECLARE_DEBUG_CHANNEL(unwind); +#endif
#if _MSVCR_VER>=70 && _MSVCR_VER<=71 static MSVCRT_security_error_handler security_error_handler; @@ -1077,3 +1080,254 @@ int* CDECL __processing_throw(void) }
#endif /* _MSVCR_VER>=140 */ + +#ifndef __i386__ +#define DUMP_SCOPE_TABLE(base,table) do { \ + for (unsigned int i = 0; i < table->Count; i++) \ + TRACE( " %u: %p-%p handler %p target %p\n", i, \ + (char *)base + table->ScopeRecord[i].BeginAddress, \ + (char *)base + table->ScopeRecord[i].EndAddress, \ + (char *)base + table->ScopeRecord[i].HandlerAddress, \ + (char *)base + table->ScopeRecord[i].JumpTarget ); \ +} while(0) + +LONG __C_ExecuteExceptionFilter( EXCEPTION_POINTERS *ptrs, void *frame, PEXCEPTION_FILTER filter, BYTE *nonvolatile ); +#endif + +/* msvcrt's __C_specific_handler will call the destructor on the exception object while handling C++ exceptions, unlike ntdll. */ + +#if defined(__aarch64__) || defined(__arm64ec__) + +#ifdef __arm64ec__ +#define __C_specific_handler __C_specific_handler_arm64 +#endif + +EXCEPTION_DISPOSITION WINAPI __C_specific_handler( EXCEPTION_RECORD *rec, void *frame, + ARM64_NT_CONTEXT *context, + DISPATCHER_CONTEXT_ARM64 *dispatch ) +{ + const SCOPE_TABLE *table = dispatch->HandlerData; + ULONG_PTR base = dispatch->ImageBase; + ULONG_PTR pc = dispatch->ControlPc; + unsigned int i; + void *handler; + + TRACE( "%p %p %p %p pc %Ix\n", rec, frame, context, dispatch, pc ); + if (TRACE_ON(unwind)) DUMP_SCOPE_TABLE( base, table ); + + if (dispatch->ControlPcIsUnwound) pc -= 4; + + if (rec->ExceptionFlags & (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND)) + { + for (i = dispatch->ScopeIndex; i < table->Count; i++) + { + if (pc < base + table->ScopeRecord[i].BeginAddress) continue; + if (pc >= base + table->ScopeRecord[i].EndAddress) continue; + if (table->ScopeRecord[i].JumpTarget) continue; + + if (rec->ExceptionFlags & EXCEPTION_TARGET_UNWIND && + dispatch->TargetPc >= base + table->ScopeRecord[i].BeginAddress && + dispatch->TargetPc < base + table->ScopeRecord[i].EndAddress) + { + break; + } + handler = (void *)(base + table->ScopeRecord[i].HandlerAddress); + dispatch->ScopeIndex = i + 1; + TRACE( "scope %u calling __finally %p frame %p\n", i, handler, frame ); + __C_ExecuteExceptionFilter( ULongToPtr(TRUE), frame, handler, dispatch->NonVolatileRegisters ); + } + } + else + { + for (i = dispatch->ScopeIndex; i < table->Count; i++) + { + if (pc < base + table->ScopeRecord[i].BeginAddress) continue; + if (pc >= base + table->ScopeRecord[i].EndAddress) continue; + if (!table->ScopeRecord[i].JumpTarget) continue; + + if (table->ScopeRecord[i].HandlerAddress != EXCEPTION_EXECUTE_HANDLER) + { + EXCEPTION_POINTERS ptrs = { rec, (CONTEXT *)context }; + + handler = (void *)(base + table->ScopeRecord[i].HandlerAddress); + TRACE( "scope %u calling filter %p ptrs %p frame %p\n", i, handler, &ptrs, frame ); + switch (__C_ExecuteExceptionFilter( &ptrs, frame, handler, dispatch->NonVolatileRegisters )) + { + case EXCEPTION_EXECUTE_HANDLER: + break; + case EXCEPTION_CONTINUE_SEARCH: + continue; + case EXCEPTION_CONTINUE_EXECUTION: + return ExceptionContinueExecution; + } + } + /* Call the destructor if we're handling a C++ exception. */ + if (is_cxx_exception(rec)) __DestructExceptionObject( rec ); + + TRACE( "unwinding to target %Ix\n", base + table->ScopeRecord[i].JumpTarget ); + RtlUnwindEx( frame, (char *)base + table->ScopeRecord[i].JumpTarget, + rec, ULongToPtr(rec->ExceptionCode), (CONTEXT *)dispatch->ContextRecord, + dispatch->HistoryTable ); + } + } + return ExceptionContinueSearch; +} + +#ifdef __arm64ec__ +#undef __C_specific_handler +#endif + +#endif /* __aarch64__ || __arm64ec__ */ + +#ifdef __arm__ + +EXCEPTION_DISPOSITION WINAPI __C_specific_handler( EXCEPTION_RECORD *rec, void *frame, + CONTEXT *context, DISPATCHER_CONTEXT *dispatch ) +{ + const SCOPE_TABLE *table = dispatch->HandlerData; + ULONG_PTR base = dispatch->ImageBase; + ULONG_PTR pc = dispatch->ControlPc; + unsigned int i; + void *handler; + + TRACE( "%p %p %p %p pc %Ix\n", rec, frame, context, dispatch, pc ); + if (TRACE_ON(unwind)) DUMP_SCOPE_TABLE( base, table ); + + if (dispatch->ControlPcIsUnwound) pc -= 2; + + if (rec->ExceptionFlags & (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND)) + { + for (i = dispatch->ScopeIndex; i < table->Count; i++) + { + if (pc < base + table->ScopeRecord[i].BeginAddress) continue; + if (pc >= base + table->ScopeRecord[i].EndAddress) continue; + if (table->ScopeRecord[i].JumpTarget) continue; + + if (rec->ExceptionFlags & EXCEPTION_TARGET_UNWIND && + dispatch->TargetPc >= base + table->ScopeRecord[i].BeginAddress && + dispatch->TargetPc < base + table->ScopeRecord[i].EndAddress) + { + break; + } + handler = (void *)(base + table->ScopeRecord[i].HandlerAddress); + dispatch->ScopeIndex = i + 1; + TRACE( "scope %u calling __finally %p frame %p\n", i, handler, frame ); + __C_ExecuteExceptionFilter( ULongToPtr(TRUE), frame, handler, dispatch->NonVolatileRegisters ); + } + } + else + { + for (i = dispatch->ScopeIndex; i < table->Count; i++) + { + if (pc < base + table->ScopeRecord[i].BeginAddress) continue; + if (pc >= base + table->ScopeRecord[i].EndAddress) continue; + if (!table->ScopeRecord[i].JumpTarget) continue; + + if (table->ScopeRecord[i].HandlerAddress != EXCEPTION_EXECUTE_HANDLER) + { + EXCEPTION_POINTERS ptrs = { rec, context }; + + handler = (void *)(base + table->ScopeRecord[i].HandlerAddress); + TRACE( "scope %u calling filter %p ptrs %p frame %p\n", i, handler, &ptrs, frame ); + switch (__C_ExecuteExceptionFilter( &ptrs, frame, handler, dispatch->NonVolatileRegisters )) + { + case EXCEPTION_EXECUTE_HANDLER: + break; + case EXCEPTION_CONTINUE_SEARCH: + continue; + case EXCEPTION_CONTINUE_EXECUTION: + return ExceptionContinueExecution; + } + } + /* Call the destructor if we're handling a C++ exception. */ + if (is_cxx_exception( rec )) __DestructExceptionObject( rec ); + + TRACE( "unwinding to target %lx\n", base + table->ScopeRecord[i].JumpTarget ); + RtlUnwindEx( frame, (char *)base + table->ScopeRecord[i].JumpTarget, + rec, ULongToPtr(rec->ExceptionCode), dispatch->ContextRecord, + dispatch->HistoryTable ); + } + } + return ExceptionContinueSearch; +} + +#endif /* __arm__ */ + +#ifdef __x86_64__ + +EXCEPTION_DISPOSITION WINAPI __C_specific_handler( EXCEPTION_RECORD *rec, void *frame, CONTEXT *context, + DISPATCHER_CONTEXT *dispatch ) +{ + const SCOPE_TABLE *table = dispatch->HandlerData; + ULONG_PTR base = dispatch->ImageBase; + ULONG_PTR pc = dispatch->ControlPc; + unsigned int i; + +#ifdef __arm64ec__ + if (RtlIsEcCode( pc )) + return __C_specific_handler_arm64( rec, frame, (ARM64_NT_CONTEXT *)context, + (DISPATCHER_CONTEXT_ARM64 *)dispatch ); +#endif + + TRACE( "%p %p %p %p pc %Ix\n", rec, frame, context, dispatch, pc ); + if (TRACE_ON(unwind)) DUMP_SCOPE_TABLE( base, table ); + + if (rec->ExceptionFlags & (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND)) + { + for (i = dispatch->ScopeIndex; i < table->Count; i++) + { + if (pc < base + table->ScopeRecord[i].BeginAddress) continue; + if (pc >= base + table->ScopeRecord[i].EndAddress) continue; + if (table->ScopeRecord[i].JumpTarget) continue; + + if (rec->ExceptionFlags & EXCEPTION_TARGET_UNWIND && + dispatch->TargetIp >= base + table->ScopeRecord[i].BeginAddress && + dispatch->TargetIp < base + table->ScopeRecord[i].EndAddress) + { + break; + } + else + { + PTERMINATION_HANDLER handler = (void *)(base + table->ScopeRecord[i].HandlerAddress); + dispatch->ScopeIndex = i + 1; + TRACE( "scope %u calling __finally %p frame %p\n", i, handler, frame ); + handler( TRUE, frame ); + } + } + } + else + { + for (i = dispatch->ScopeIndex; i < table->Count; i++) + { + if (pc < base + table->ScopeRecord[i].BeginAddress) continue; + if (pc >= base + table->ScopeRecord[i].EndAddress) continue; + if (!table->ScopeRecord[i].JumpTarget) continue; + + if (table->ScopeRecord[i].HandlerAddress != EXCEPTION_EXECUTE_HANDLER) + { + EXCEPTION_POINTERS ptrs = { rec, context }; + PEXCEPTION_FILTER filter = (void *)(base + table->ScopeRecord[i].HandlerAddress); + + TRACE( "scope %u calling filter %p ptrs %p frame %p\n", i, filter, &ptrs, frame ); + switch (filter( &ptrs, frame )) + { + case EXCEPTION_EXECUTE_HANDLER: + break; + case EXCEPTION_CONTINUE_SEARCH: + continue; + case EXCEPTION_CONTINUE_EXECUTION: + return ExceptionContinueExecution; + } + } + if (is_cxx_exception( rec )) __DestructExceptionObject( rec ); + + TRACE( "unwinding to target %Ix\n", base + table->ScopeRecord[i].JumpTarget ); + RtlUnwindEx( frame, (char *)base + table->ScopeRecord[i].JumpTarget, + rec, ULongToPtr(rec->ExceptionCode), dispatch->ContextRecord, + dispatch->HistoryTable ); + } + } + return ExceptionContinueSearch; +} + +#endif /* __x86_64__ */ \ No newline at end of file diff --git a/dlls/msvcrt/except_arm.c b/dlls/msvcrt/except_arm.c index b2bf94d5338..f54a93784ef 100644 --- a/dlls/msvcrt/except_arm.c +++ b/dlls/msvcrt/except_arm.c @@ -94,4 +94,12 @@ int handle_fpieee_flt( __msvcrt_ulong exception_code, EXCEPTION_POINTERS *ep, return EXCEPTION_CONTINUE_SEARCH; }
+__ASM_GLOBAL_FUNC( __C_ExecuteExceptionFilter, + "push {r3-r11,lr}\n\t" + ".seh_save_regs_w {r3-r11,lr}\n\t" + ".seh_endprologue\n\t" + "ldm r3, {r4-r11}\n\t" + "blx r2\n\t" + "pop {r3-r11,pc}\n\t" ); + #endif /* __arm__ */ diff --git a/dlls/msvcrt/except_arm64.c b/dlls/msvcrt/except_arm64.c index 6d515f8b150..81b0bf5b6ec 100644 --- a/dlls/msvcrt/except_arm64.c +++ b/dlls/msvcrt/except_arm64.c @@ -125,4 +125,33 @@ int handle_fpieee_flt( __msvcrt_ulong exception_code, EXCEPTION_POINTERS *ep, return EXCEPTION_CONTINUE_SEARCH; }
+__ASM_GLOBAL_FUNC( __C_ExecuteExceptionFilter, + "stp x29, x30, [sp, #-96]!\n\t" + ".seh_save_fplr_x 96\n\t" + "stp x19, x20, [sp, #16]\n\t" + ".seh_save_regp x19, 16\n\t" + "stp x21, x22, [sp, #32]\n\t" + ".seh_save_regp x21, 32\n\t" + "stp x23, x24, [sp, #48]\n\t" + ".seh_save_regp x23, 48\n\t" + "stp x25, x26, [sp, #64]\n\t" + ".seh_save_regp x25, 64\n\t" + "stp x27, x28, [sp, #80]\n\t" + ".seh_save_regp x27, 80\n\t" + ".seh_endprologue\n\t" + "ldp x19, x20, [x3, #0]\n\t" /* nonvolatile regs */ + "ldp x21, x22, [x3, #16]\n\t" + "ldp x23, x24, [x3, #32]\n\t" + "ldp x25, x26, [x3, #48]\n\t" + "ldp x27, x28, [x3, #64]\n\t" + "ldr x1, [x3, #80]\n\t" /* x29 = frame */ + "blr x2\n\t" /* filter */ + "ldp x19, x20, [sp, #16]\n\t" + "ldp x21, x22, [sp, #32]\n\t" + "ldp x23, x24, [sp, #48]\n\t" + "ldp x25, x26, [sp, #64]\n\t" + "ldp x27, x28, [sp, #80]\n\t" + "ldp x29, x30, [sp], #96\n\t" + "ret" ); + #endif /* __aarch64__ */ diff --git a/dlls/msvcrt/except_arm64ec.c b/dlls/msvcrt/except_arm64ec.c index b2e723f79b3..fe1d79610a2 100644 --- a/dlls/msvcrt/except_arm64ec.c +++ b/dlls/msvcrt/except_arm64ec.c @@ -166,4 +166,34 @@ void __cdecl __crtCapturePreviousContext( CONTEXT *ctx ) } #endif
+LONG __attribute__((naked)) __C_ExecuteExceptionFilter( EXCEPTION_POINTERS *ptrs, void *frame, + PEXCEPTION_FILTER filter, BYTE *nonvolatile ) +{ + asm( ".seh_proc _C_ExecuteExceptionFilter\n\t" + "stp x29, x30, [sp, #-80]!\n\t" + ".seh_save_fplr_x 80\n\t" + "stp x19, x20, [sp, #16]\n\t" + ".seh_save_regp x19, 16\n\t" + "stp x21, x22, [sp, #32]\n\t" + ".seh_save_regp x21, 32\n\t" + "stp x25, x26, [sp, #48]\n\t" + ".seh_save_regp x25, 48\n\t" + "str x27, [sp, #64]\n\t" + ".seh_save_reg x27, 64\n\t" + ".seh_endprologue\n\t" + "ldp x19, x20, [x3, #0]\n\t" /* nonvolatile regs */ + "ldp x21, x22, [x3, #16]\n\t" + "ldp x25, x26, [x3, #48]\n\t" + "ldr x27, [x3, #64]\n\t" + "ldr x1, [x3, #80]\n\t" /* x29 = frame */ + "blr x2\n\t" /* filter */ + "ldp x19, x20, [sp, #16]\n\t" + "ldp x21, x22, [sp, #32]\n\t" + "ldp x25, x26, [sp, #48]\n\t" + "ldr x27, [sp, #64]\n\t" + "ldp x29, x30, [sp], #80\n\t" + "ret\n\t" + ".seh_endproc" ); +} + #endif /* __arm64ec__ */ diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec index 27cd61376e4..c308c1711a7 100644 --- a/dlls/msvcrt/msvcrt.spec +++ b/dlls/msvcrt/msvcrt.spec @@ -174,7 +174,7 @@ @ extern _HUGE MSVCRT__HUGE @ cdecl _Strftime(ptr long str ptr ptr) @ cdecl _XcptFilter(long ptr) -@ stdcall -arch=!i386 __C_specific_handler(ptr long ptr ptr) ntdll.__C_specific_handler +@ stdcall -arch=!i386 __C_specific_handler(ptr long ptr ptr) @ cdecl __CppXcptFilter(long ptr) # stub __CxxCallUnwindDelDtor # stub __CxxCallUnwindDtor diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec index f2e5102b616..1f738637317 100644 --- a/dlls/ucrtbase/ucrtbase.spec +++ b/dlls/ucrtbase/ucrtbase.spec @@ -48,7 +48,7 @@ @ cdecl __AdjustPointer(ptr ptr) @ stub __BuildCatchObject @ stub __BuildCatchObjectHelper -@ stdcall -arch=!i386 __C_specific_handler(ptr long ptr ptr) ntdll.__C_specific_handler +@ stdcall -arch=!i386 __C_specific_handler(ptr long ptr ptr) msvcrt.__C_specific_handler @ cdecl __CxxDetectRethrow(ptr) @ cdecl __CxxExceptionFilter(ptr ptr long ptr) @ cdecl -norelay __CxxFrameHandler(ptr ptr ptr ptr)
From: Piotr Caban piotr@codeweavers.com
--- dlls/ucrtbase/tests/cpp.c | 83 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+)
diff --git a/dlls/ucrtbase/tests/cpp.c b/dlls/ucrtbase/tests/cpp.c index da06b2cbf2f..e5b52872cd6 100644 --- a/dlls/ucrtbase/tests/cpp.c +++ b/dlls/ucrtbase/tests/cpp.c @@ -24,6 +24,8 @@
#include <windef.h> #include <winbase.h> +#include <winternl.h> +#include <rtlsupportapi.h> #include <verrsrc.h> #include <dbghelp.h> #include <unknwn.h> @@ -323,6 +325,84 @@ static void test___DestructExceptionObject(void) CHECK_CALLED(iunknown_except_Release); }
+#ifdef __x86_64__ +EXCEPTION_DISPOSITION WINAPI __C_specific_handler(EXCEPTION_RECORD*,void*,CONTEXT*,DISPATCHER_CONTEXT*); +DEFINE_EXPECT(filter); +static CONTEXT ctx; + +static ULONG WINAPI iunknown_except2_Release(IUnknown *iface) +{ + CHECK_EXPECT(iunknown_except_Release); + NtContinue(&ctx, FALSE); + return 1; +} + +static IUnknownVtbl iunknown_except2_vtbl = { + iunknown_except_QueryInterface, + iunknown_except_AddRef, + iunknown_except2_Release +}; + +static IUnknown iunknown_except2 = { &iunknown_except2_vtbl }; + +static LONG WINAPI filter(struct _EXCEPTION_POINTERS *ep, void *frame) +{ + CHECK_EXPECT(filter); + + ok(frame == (void*)0x1234, "frame = %p\n", (void*)frame); + SET_EXPECT(iunknown_except_Release); + return EXCEPTION_EXECUTE_HANDLER; +} + +static void test___C_specific_handler(void) +{ + struct + { + UINT flags; + UINT arch_specific_data[8]; + } info = { 0x10 }; + IUnknown *piunk = &iunknown_except2; + DISPATCHER_CONTEXT dispatch; + SCOPE_TABLE scope_table; + EXCEPTION_RECORD rec; + CONTEXT context; + LONG pass = 0; + + InterlockedIncrement(&pass); + RtlCaptureContext(&ctx); + if (InterlockedIncrement(&pass) == 3) + { + CHECK_CALLED(filter); + CHECK_CALLED(iunknown_except_Release); + return; + } + + memset(&rec, 0, sizeof(rec)); + rec.ExceptionCode = 0xe06d7363; + rec.NumberParameters = 4; + rec.ExceptionInformation[0] = 0x19930520; + rec.ExceptionInformation[1] = (ULONG_PTR)&piunk; + rec.ExceptionInformation[2] = (ULONG_PTR)&info; + rec.ExceptionInformation[3] = (ULONG_PTR)GetModuleHandleA(NULL); + + memset(&dispatch, 0, sizeof(dispatch)); + dispatch.ImageBase = (ULONG_PTR)GetModuleHandleA(NULL); + dispatch.ControlPc = dispatch.ImageBase + 0x200; + dispatch.HandlerData = &scope_table; + dispatch.ContextRecord = &context; + scope_table.Count = 1; + scope_table.ScopeRecord[0].BeginAddress = 0x200; + scope_table.ScopeRecord[0].EndAddress = 0x400; + scope_table.ScopeRecord[0].HandlerAddress = (ULONG_PTR)filter - dispatch.ImageBase; + scope_table.ScopeRecord[0].JumpTarget = 1; + memset(&context, 0, sizeof(context)); + + SET_EXPECT(filter); + __C_specific_handler(&rec, (void*)0x1234, &context, &dispatch); + ok(0, "should not be reached\n"); +} +#endif + START_TEST(cpp) { if (!init()) return; @@ -330,4 +410,7 @@ START_TEST(cpp) test___std_type_info(); test___unDName(); test___DestructExceptionObject(); +#ifdef __x86_64__ + test___C_specific_handler(); +#endif }
On Mon Nov 3 17:29:35 2025 +0000, Piotr Caban wrote:
There's more spec files that should be updated.
All runtime libs should use msvcrt's __C_specific_handler now, I assume kernelbase and kernel32 still forward to ntdll?