Peter Dons Tychsen : user32: Add exception handling for timer callbacks.
Alexandre Julliard
julliard at winehq.org
Wed Sep 30 10:56:09 CDT 2009
Module: wine
Branch: master
Commit: f20f411925e789a2aecf740776f441335837ac5f
URL: http://source.winehq.org/git/wine.git/?a=commit;h=f20f411925e789a2aecf740776f441335837ac5f
Author: Peter Dons Tychsen <donpedro at tdcadsl.dk>
Date: Wed Sep 30 01:39:25 2009 +0200
user32: Add exception handling for timer callbacks.
---
dlls/user32/message.c | 36 +++++++++++++++++++++++++++++++-----
dlls/user32/tests/msg.c | 13 +++++++++++++
2 files changed, 44 insertions(+), 5 deletions(-)
diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index 3f7a4cd..4e9a62c 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -43,6 +43,7 @@
#include "win.h"
#include "controls.h"
#include "wine/debug.h"
+#include "wine/exception.h"
WINE_DEFAULT_DEBUG_CHANNEL(msg);
WINE_DECLARE_DEBUG_CHANNEL(relay);
@@ -3065,8 +3066,20 @@ LRESULT WINAPI DispatchMessageA( const MSG* msg )
/* Process timer messages */
if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
{
- if (msg->lParam) return CallWindowProcA( (WNDPROC)msg->lParam, msg->hwnd,
- msg->message, msg->wParam, GetTickCount() );
+ if (msg->lParam)
+ {
+ __TRY
+ {
+ retval = CallWindowProcA( (WNDPROC)msg->lParam, msg->hwnd,
+ msg->message, msg->wParam, GetTickCount() );
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ retval = 0;
+ }
+ __ENDTRY
+ return retval;
+ }
}
if (!msg->hwnd) return 0;
@@ -3103,7 +3116,8 @@ LRESULT WINAPI DispatchMessageA( const MSG* msg )
* If the lpMsg parameter points to a WM_TIMER message and the
* parameter of the WM_TIMER message is not NULL, the lParam parameter
* points to the function that is called instead of the window
- * procedure.
+ * procedure. The function stored in lParam (timer callback) is protected
+ * from causing page-faults.
*
* The message must be valid.
*
@@ -3123,8 +3137,20 @@ LRESULT WINAPI DispatchMessageW( const MSG* msg )
/* Process timer messages */
if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
{
- if (msg->lParam) return CallWindowProcW( (WNDPROC)msg->lParam, msg->hwnd,
- msg->message, msg->wParam, GetTickCount() );
+ if (msg->lParam)
+ {
+ __TRY
+ {
+ retval = CallWindowProcW( (WNDPROC)msg->lParam, msg->hwnd,
+ msg->message, msg->wParam, GetTickCount() );
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ retval = 0;
+ }
+ __ENDTRY
+ return retval;
+ }
}
if (!msg->hwnd) return 0;
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c
index 9208c9d..aeb1b62 100644
--- a/dlls/user32/tests/msg.c
+++ b/dlls/user32/tests/msg.c
@@ -7813,6 +7813,12 @@ static VOID CALLBACK tfunc(HWND hwnd, UINT uMsg, UINT_PTR id, DWORD dwTime)
{
}
+static VOID CALLBACK tfunc_crash(HWND hwnd, UINT uMsg, UINT_PTR id, DWORD dwTime)
+{
+ /* Crash on purpose */
+ *(volatile int *)0 = 2;
+}
+
#define TIMER_ID 0x19
static DWORD WINAPI timer_thread_proc(LPVOID x)
@@ -7834,6 +7840,7 @@ static void test_timers(void)
{
struct timer_info info;
DWORD id;
+ MSG msg;
info.hWnd = CreateWindow ("TestWindowClass", NULL,
WS_OVERLAPPEDWINDOW ,
@@ -7855,6 +7862,12 @@ static void test_timers(void)
ok( KillTimer(info.hWnd, TIMER_ID), "KillTimer failed\n");
+ /* Test timer callback with crash */
+ info.id = SetTimer(info.hWnd, TIMER_ID, 0, tfunc_crash);
+ ok(info.id, "SetTimer failed\n");
+ Sleep(150);
+ while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
+
ok(DestroyWindow(info.hWnd), "failed to destroy window\n");
}
More information about the wine-cvs
mailing list