Module: wine Branch: master Commit: 78c2b7dfe2f2d5d76400564be547fd8287d62d67 URL: https://gitlab.winehq.org/wine/wine/-/commit/78c2b7dfe2f2d5d76400564be547fd8...
Author: Alexandre Julliard julliard@winehq.org Date: Mon Jan 22 11:35:47 2024 +0100
ntdll: Use a .seh handler for KiUserCallbackDispatcher exceptions.
---
dlls/ntdll/exception.c | 21 +++++++++++++++++++++ dlls/ntdll/ntdll_misc.h | 2 ++ dlls/ntdll/signal_arm.c | 15 ++++++++++++--- dlls/ntdll/signal_arm64.c | 14 +++++++++----- dlls/ntdll/signal_arm64ec.c | 14 +++++++++----- dlls/ntdll/signal_x86_64.c | 10 ++++++++++ 6 files changed, 63 insertions(+), 13 deletions(-)
diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c index 98733045e17..69f061768bd 100644 --- a/dlls/ntdll/exception.c +++ b/dlls/ntdll/exception.c @@ -185,6 +185,26 @@ LONG call_vectored_handlers( EXCEPTION_RECORD *rec, CONTEXT *context ) }
+#if defined(__WINE_PE_BUILD) && !defined(__i386__) + +/******************************************************************* + * user_callback_handler + * + * Exception handler for KiUserCallbackDispatcher. + */ +EXCEPTION_DISPOSITION WINAPI user_callback_handler( EXCEPTION_RECORD *record, void *frame, + CONTEXT *context, void *dispatch ) +{ + if (!(record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))) + { + ERR( "ignoring exception %lx\n", record->ExceptionCode ); + RtlUnwind( frame, KiUserCallbackDispatcherReturn, record, ULongToPtr(record->ExceptionCode) ); + } + return ExceptionContinueSearch; +} + +#else + /******************************************************************* * dispatch_user_callback * @@ -208,6 +228,7 @@ NTSTATUS WINAPI dispatch_user_callback( void *args, ULONG len, ULONG id ) return status; }
+#endif
/******************************************************************* * raise_status diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 1512bc17132..da49c14e682 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -50,6 +50,8 @@ extern UINT_PTR page_size; /* exceptions */ extern LONG call_vectored_handlers( EXCEPTION_RECORD *rec, CONTEXT *context ); extern NTSTATUS WINAPI dispatch_user_callback( void *args, ULONG len, ULONG id ); +extern EXCEPTION_DISPOSITION WINAPI user_callback_handler( EXCEPTION_RECORD *record, void *frame, + CONTEXT *context, void *dispatch ); extern void DECLSPEC_NORETURN raise_status( NTSTATUS status, EXCEPTION_RECORD *rec ); extern LONG WINAPI call_unhandled_exception_filter( PEXCEPTION_POINTERS eptr );
diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c index ccb3f10b9f5..78db61fc764 100644 --- a/dlls/ntdll/signal_arm.c +++ b/dlls/ntdll/signal_arm.c @@ -585,10 +585,19 @@ __ASM_GLOBAL_FUNC( KiUserCallbackDispatcher, __ASM_EHABI(".save {sp, pc}\n\t") __ASM_EHABI(".save {lr}\n\t") __ASM_EHABI(".pad #0x0c\n\t") - "ldr r0, [sp]\n\t" /* args */ - "ldr r1, [sp, #0x04]\n\t" /* len */ - "ldr r2, [sp, #0x08]\n\t" /* id */ + "ldr r0, [sp]\n\t" /* args */ + "ldr r1, [sp, #0x04]\n\t" /* len */ + "ldr r2, [sp, #0x08]\n\t" /* id */ +#ifdef __WINE_PE_BUILD + "mrc p15, 0, r3, c13, c0, 2\n\t" /* NtCurrentTeb() */ + "ldr r3, [r3, 0x30]\n\t" /* peb */ + "ldr r3, [r3, 0x2c]\n\t" /* peb->KernelCallbackTable */ + "ldr ip, [r3, r2, lsl #3]\n\t" + "blx ip\n\t" + ".seh_handler " __ASM_NAME("user_callback_handler") ", %except\n\t" +#else "bl " __ASM_NAME("dispatch_user_callback") "\n\t" +#endif ".globl " __ASM_NAME("KiUserCallbackDispatcherReturn") "\n" __ASM_NAME("KiUserCallbackDispatcherReturn") ":\n\t" "mov r2, r0\n\t" /* status */ diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c index 8a59f9050b1..2d150528610 100644 --- a/dlls/ntdll/signal_arm64.c +++ b/dlls/ntdll/signal_arm64.c @@ -606,15 +606,19 @@ __ASM_GLOBAL_FUNC( KiUserApcDispatcher, * KiUserCallbackDispatcher (NTDLL.@) */ __ASM_GLOBAL_FUNC( KiUserCallbackDispatcher, - __ASM_SEH(".seh_pushframe\n\t") + ".seh_pushframe\n\t" "nop\n\t" - __ASM_SEH(".seh_stackalloc 0x20\n\t") + ".seh_stackalloc 0x20\n\t" "nop\n\t" - __ASM_SEH(".seh_save_reg lr, 0x18\n\t") - __ASM_SEH(".seh_endprologue\n\t") + ".seh_save_reg lr, 0x18\n\t" + ".seh_endprologue\n\t" + ".seh_handler " __ASM_NAME("user_callback_handler") ", @except\n\t" "ldr x0, [sp]\n\t" /* args */ "ldp w1, w2, [sp, #0x08]\n\t" /* len, id */ - "bl " __ASM_NAME("dispatch_user_callback") "\n\t" + "ldr x3, [x18, 0x60]\n\t" /* peb */ + "ldr x3, [x3, 0x58]\n\t" /* peb->KernelCallbackTable */ + "ldr x15, [x3, x2, lsl #3]\n\t" + "blr x15\n\t" ".globl " __ASM_NAME("KiUserCallbackDispatcherReturn") "\n" __ASM_NAME("KiUserCallbackDispatcherReturn") ":\n\t" "mov x2, x0\n\t" /* status */ diff --git a/dlls/ntdll/signal_arm64ec.c b/dlls/ntdll/signal_arm64ec.c index fb6654f4340..a54a5eeaceb 100644 --- a/dlls/ntdll/signal_arm64ec.c +++ b/dlls/ntdll/signal_arm64ec.c @@ -1717,15 +1717,19 @@ __ASM_GLOBAL_FUNC( "#KiUserApcDispatcher", * KiUserCallbackDispatcher (NTDLL.@) */ __ASM_GLOBAL_FUNC( "#KiUserCallbackDispatcher", - __ASM_SEH(".seh_pushframe\n\t") + ".seh_pushframe\n\t" "nop\n\t" - __ASM_SEH(".seh_stackalloc 0x20\n\t") + ".seh_stackalloc 0x20\n\t" "nop\n\t" - __ASM_SEH(".seh_save_reg lr, 0x18\n\t") - __ASM_SEH(".seh_endprologue\n\t") + ".seh_save_reg lr, 0x18\n\t" + ".seh_endprologue\n\t" + ".seh_handler " __ASM_NAME("user_callback_handler") ", @except\n\t" "ldr x0, [sp]\n\t" /* args */ "ldp w1, w2, [sp, #0x08]\n\t" /* len, id */ - "bl " __ASM_NAME("dispatch_user_callback") "\n\t" + "ldr x3, [x18, 0x60]\n\t" /* peb */ + "ldr x3, [x3, 0x58]\n\t" /* peb->KernelCallbackTable */ + "ldr x15, [x3, x2, lsl #3]\n\t" + "blr x15\n\t" ".globl "#KiUserCallbackDispatcherReturn"\n" ""#KiUserCallbackDispatcherReturn":\n\t" "mov x2, x0\n\t" /* status */ diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index c56552a74a7..b253c0b4f17 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -702,7 +702,17 @@ __ASM_GLOBAL_FUNC( KiUserCallbackDispatcher, "movq 0x20(%rsp),%rcx\n\t" /* args */ "movl 0x28(%rsp),%edx\n\t" /* len */ "movl 0x2c(%rsp),%r8d\n\t" /* id */ +#ifdef __WINE_PE_BUILD + "movq %gs:0x30,%rax\n\t" /* NtCurrentTeb() */ + "movq 0x60(%rax),%rax\n\t" /* peb */ + "movq 0x58(%rax),%rax\n\t" /* peb->KernelCallbackTable */ + "call *(%rax,%r8,8)\n\t" /* KernelCallbackTable[id] */ + ".seh_handler " __ASM_NAME("user_callback_handler") ", @except\n\t" + ".globl " __ASM_NAME("KiUserCallbackDispatcherReturn") "\n" + __ASM_NAME("KiUserCallbackDispatcherReturn") ":\n\t" +#else "call " __ASM_NAME("dispatch_user_callback") "\n\t" +#endif "xorq %rcx,%rcx\n\t" /* ret_ptr */ "xorl %edx,%edx\n\t" /* ret_len */ "movl %eax,%r8d\n\t" /* status */