Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com --- dlls/user32/tests/msg.c | 130 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+)
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index a2adf56565d..a2264361c24 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -34,6 +34,8 @@ #include "commctrl.h"
#include "wine/test.h" +#include "wine/asm.h" +#include "wine/exception.h"
#define MDI_FIRST_CHILD_ID 2004
@@ -10648,8 +10650,17 @@ static void CALLBACK callback_count(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWOR }
static DWORD exception; +static BOOL *tproc_exc_suppress = NULL; static void CALLBACK callback_exception(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) { + if (tproc_exc_suppress) + { + BOOL res = SetUserObjectInformationW(GetCurrentProcess(), UOI_TIMERPROC_EXCEPTION_SUPPRESSION, tproc_exc_suppress, sizeof(*tproc_exc_suppress)); + todo_wine + ok(res, "SetUserObjectInformationW error %lu\n", GetLastError()); + tproc_exc_suppress = NULL; + } + count++; RaiseException(exception, 0, 0, NULL); } @@ -10813,10 +10824,116 @@ static void test_timers_no_wnd(void) while (i > 0) KillTimer(NULL, ids[--i]); }
+static LONG WINAPI timer_exception_filter(EXCEPTION_POINTERS *eptr) +{ + if (eptr->ExceptionRecord->ExceptionCode == exception && + eptr->ExceptionRecord->ExceptionFlags == 0 && + eptr->ExceptionRecord->NumberParameters == 0) + { + exception = 0; + return EXCEPTION_CONTINUE_EXECUTION; + } + + return EXCEPTION_CONTINUE_SEARCH; +} + +#if defined(USE_COMPILER_EXCEPTIONS) || defined(__i386__) +static void dispatch_message_handle_exception(const MSG *msg) +{ + __TRY + { + DispatchMessageA( msg ); + } + __EXCEPT(timer_exception_filter) + { + } + __ENDTRY +} +#else +EXCEPTION_DISPOSITION WINAPI timer_exception_handler( EXCEPTION_RECORD *rec, + void *frame, + CONTEXT *context, + DISPATCHER_CONTEXT *dispatch ) +{ + EXCEPTION_POINTERS ptrs = { rec, context }; + + if (timer_exception_filter( &ptrs ) == EXCEPTION_CONTINUE_EXECUTION) + return ExceptionContinueExecution; + + return ExceptionContinueSearch; +} + +extern void dispatch_message_handle_exception(const MSG *msg); +#if defined(__x86_64__) +__ASM_GLOBAL_FUNC( dispatch_message_handle_exception, + __ASM_SEH(".seh_handler " __ASM_NAME("timer_exception_handler") ", @except\n\t") + "subq $0x28,%rsp\n\t" + __ASM_CFI(".cfi_adjust_cfa_offset 0x28\n\t") + __ASM_SEH(".seh_stackalloc 0x28\n\t") + __ASM_SEH(".seh_endprologue\n\t") + "callq *__imp_DispatchMessageA(%rip)\n\t" + "nop\n\t" + "addq $0x28,%rsp\n\t" + __ASM_CFI(".cfi_adjust_cfa_offset -0x28\n\t") + "ret" ); +#elif defined(__arm__) +__ASM_GLOBAL_FUNC( dispatch_message_handle_exception, + "1:\n\t" + "push {r4,lr}\n\t" + __ASM_CFI(".cfi_def_cfa_offset 8\n\t") + __ASM_CFI(".cfi_offset r4, -8\n\t") + __ASM_CFI(".cfi_offset lr, -4\n\t") + "ldr ip, =__imp_DispatchMessageA\n\t" + "ldr ip, [ip]\n\t" + "blx ip\n\t" + "pop {r4,pc}\n" + "2:\n\t" + ".section ".pdata", "dr"\n\t" + ".rva " __ASM_NAME("dispatch_message_handle_exception") "\n\t" + ".rva .Lunwind__dispatch_message_handle_exception\n\t" + ".section ".xdata", "dr"\n" + ".Lunwind__dispatch_message_handle_exception:\n\t" + ".long 0x10100000 + ((2b - 1b) / 2)\n\t" + ".long 0xfbfbffd4\n\t" + ".rva " __ASM_NAME("timer_exception_handler") "\n\t" + ".text" ); +#elif defined(__aarch64__) +__ASM_GLOBAL_FUNC( dispatch_message_handle_exception, + __ASM_SEH(".seh_handler " __ASM_NAME("timer_exception_handler") ", @except\n\t") + "stp x29, x30, [sp, #-16]!\n\t" + __ASM_CFI(".cfi_def_cfa_offset 16\n\t") + __ASM_CFI(".cfi_offset x29, -16\n\t") + __ASM_CFI(".cfi_offset x30, -8\n\t") + __ASM_SEH(".seh_save_fplr_x 16\n\t") + __ASM_SEH(".seh_endprologue\n\t") + "mov x29, sp\n\t" + "adrp x8, __imp_DispatchMessageA\n\t" + "ldr x8, [x8, :lo12:__imp_DispatchMessageA]\n\t" + "blr x8\n\t" + "nop\n\t" + __ASM_SEH(".seh_startepilogue\n\t") + "ldp x29, x30, [sp], #16\n\t" + __ASM_CFI(".cfi_restore x29\n\t") + __ASM_CFI(".cfi_restore x30\n\t") + __ASM_CFI(".cfi_def_cfa sp, 0\n\t") + __ASM_SEH(".seh_save_fplr_x 16\n\t") + __ASM_SEH(".seh_endepilogue\n\t") + "ret" ); +#else +void dispatch_message_handle_exception(const MSG *msg) +{ + skip("dispatch_message_handle_exception not implemented\n"); + count++; + exception = 0; +} +#endif +#endif + static void test_timers_exception(DWORD code) { UINT_PTR id; MSG msg; + BOOL ret, value;
exception = code; id = SetTimer(NULL, 0, 1000, callback_exception); @@ -10831,6 +10948,19 @@ static void test_timers_exception(DWORD code) DispatchMessageA(&msg); ok(count == 1, "did not get one count as expected (%i).\n", count);
+ value = FALSE; + tproc_exc_suppress = &value; + count = 0; + dispatch_message_handle_exception(&msg); + ok(count == 1, "expected count to be 1, got %d\n", count); + todo_wine + ok(exception == 0, "exception from timer procedure shall be propagated\n"); + + value = TRUE; + ret = SetUserObjectInformationW(GetCurrentProcess(), UOI_TIMERPROC_EXCEPTION_SUPPRESSION, &value, sizeof(value)); + todo_wine + ok(ret, "SetUserObjectInformation error %lu\n", GetLastError()); + KillTimer(NULL, id); }