Before calling the timer window proc, make sure it is valid.

diff --git a/include/message.h b/include/message.h
index 29decbc..463921b 100644
--- a/include/message.h
+++ b/include/message.h
@@ -9,6 +9,7 @@
 
 #include "windef.h"
 #include "wine/windef16.h"
+#include "winproc.h"
 
 struct tagMSG;
 
@@ -22,6 +23,7 @@
 extern void TIMER_RemoveQueueTimers( HQUEUE16 hqueue );
 extern BOOL TIMER_GetTimerMsg( struct tagMSG *msg, HWND hwnd,
                                  HQUEUE16 hQueue, BOOL remove );
+extern BOOL TIMER_IsTimerValid( HWND hwnd, UINT id, HWINDOWPROC hProc );
 
 /* event.c */
 extern void EVENT_Synchronize( void );
diff --git a/windows/message.c b/windows/message.c
index 2e63551..880c860 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -2283,6 +2283,12 @@
     {
 	if (msg->lParam)
         {
+            /* before calling window proc, verify it the timer is still valid,
+               there's a slim chance the application kill the timer between
+               getMessage and DisaptachMessage API calls */
+            if (!TIMER_IsTimerValid(msg->hwnd, (UINT) msg->wParam, (HWINDOWPROC) msg->lParam))
+                return 0; /* invalid winproc */
+
 	    return CallWindowProc16( (WNDPROC16)msg->lParam, msg->hwnd,
                                    msg->message, msg->wParam, GetTickCount() );
         }
@@ -2359,6 +2365,13 @@
 	if (msg->lParam)
         {
 /*            HOOK_CallHooks32A( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
+
+            /* before calling window proc, verify it the timer is still valid,
+               there's a slim chance the application kill the timer between
+               getMessage and DisaptachMessage API calls */
+            if (!TIMER_IsTimerValid(msg->hwnd, (UINT) msg->wParam, (HWINDOWPROC) msg->lParam))
+                return 0; /* invalid winproc */
+
 	    return CallWindowProcA( (WNDPROC)msg->lParam, msg->hwnd,
                                    msg->message, msg->wParam, GetTickCount() );
         }
@@ -2434,6 +2447,13 @@
 	if (msg->lParam)
         {
 /*            HOOK_CallHooks32W( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
+
+            /* before calling window proc, verify it the timer is still valid,
+               there's a slim chance the application kill the timer between
+               getMessage and DisaptachMessage API calls */
+            if (!TIMER_IsTimerValid(msg->hwnd, (UINT) msg->wParam, (HWINDOWPROC) msg->lParam))
+                return 0; /* invalid winproc */
+
 	    return CallWindowProcW( (WNDPROC)msg->lParam, msg->hwnd,
                                    msg->message, msg->wParam, GetTickCount() );
         }
diff --git a/windows/timer.c b/windows/timer.c
index 4da21f1..126ef16 100644
--- a/windows/timer.c
+++ b/windows/timer.c
@@ -317,6 +317,30 @@
 
 
 /***********************************************************************
+ *           TIMER_IsTimerValid
+ */
+BOOL TIMER_IsTimerValid( HWND hwnd, UINT id, HWINDOWPROC hProc )
+{
+    int i;
+    TIMER *pTimer;
+    BOOL ret = FALSE;
+
+    EnterCriticalSection( &csTimer );
+    
+    for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
+        if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
+            (pTimer->proc == hProc))
+        {
+            ret = TRUE;
+            break;
+        }
+
+   LeaveCriticalSection( &csTimer );
+   return ret;
+}
+
+
+/***********************************************************************
  *           SetSystemTimer16   (USER.11)
  */
 UINT16 WINAPI SetSystemTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout,