[NtUser]
[reactos.git] / reactos / win32ss / user / ntuser / message.c
index 1f689c0..4662b4f 100644 (file)
@@ -7,6 +7,9 @@
  */
 
 #include <win32k.h>
+
+#include <dde.h>
+
 DBG_DEFAULT_CHANNEL(UserMsg);
 
 #define PM_BADMSGFLAGS ~((QS_RAWINPUT << 16)|PM_QS_SENDMESSAGE|PM_QS_PAINT|PM_QS_POSTMESSAGE|PM_QS_INPUT|PM_NOYIELD|PM_REMOVE)
@@ -128,10 +131,13 @@ static MSGMEMORY g_MsgMemory[] =
     { WM_SETTEXT, MMS_SIZE_LPARAMSZ, MMS_FLAG_READ },
     { WM_STYLECHANGED, sizeof(STYLESTRUCT), MMS_FLAG_READ },
     { WM_STYLECHANGING, sizeof(STYLESTRUCT), MMS_FLAG_READWRITE },
+    { WM_SETTINGCHANGE, MMS_SIZE_LPARAMSZ, MMS_FLAG_READ },
     { WM_COPYDATA, MMS_SIZE_SPECIAL, MMS_FLAG_READ },
     { WM_COPYGLOBALDATA, MMS_SIZE_WPARAM, MMS_FLAG_READ },
-    { WM_WINDOWPOSCHANGED, sizeof(WINDOWPOS), MMS_FLAG_READ },
+    { WM_WINDOWPOSCHANGED, sizeof(WINDOWPOS), MMS_FLAG_READWRITE },
     { WM_WINDOWPOSCHANGING, sizeof(WINDOWPOS), MMS_FLAG_READWRITE },
+    { WM_SIZING, sizeof(RECT), MMS_FLAG_READWRITE },
+    { WM_MOVING, sizeof(RECT), MMS_FLAG_READWRITE },
 };
 
 static PMSGMEMORY FASTCALL
@@ -173,7 +179,14 @@ MsgMemorySize(PMSGMEMORY MsgMemoryEntry, WPARAM wParam, LPARAM lParam)
         }
         else if (MMS_SIZE_LPARAMSZ == MsgMemoryEntry->Size)
         {
-            Size = (UINT) ((wcslen((PWSTR) lParam) + 1) * sizeof(WCHAR));
+            // WM_SETTEXT and WM_SETTINGCHANGE can be null!
+            if (!lParam)
+            {
+               TRACE("lParam is NULL!\n");
+               Size = 0;
+            }
+            else
+               Size = (UINT) ((wcslen((PWSTR) lParam) + 1) * sizeof(WCHAR));
         }
         else if (MMS_SIZE_SPECIAL == MsgMemoryEntry->Size)
         {
@@ -200,7 +213,10 @@ MsgMemorySize(PMSGMEMORY MsgMemoryEntry, WPARAM wParam, LPARAM lParam)
                 break;
 
             case WM_COPYDATA:
-                Size = sizeof(COPYDATASTRUCT) + ((PCOPYDATASTRUCT)lParam)->cbData;
+                {
+                COPYDATASTRUCT *cds = (COPYDATASTRUCT *)lParam;
+                Size = sizeof(COPYDATASTRUCT) + cds->cbData;
+                }
                 break;
 
             default:
@@ -323,7 +339,7 @@ PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL Non
 
         MsgMemoryEntry = FindMsgMemory(Msg);
 
-        if ((!MsgMemoryEntry) || (MsgMemoryEntry->Size < 0))
+        if (!MsgMemoryEntry)
         {
             /* Keep previous behavior */
             return STATUS_SUCCESS;
@@ -382,11 +398,6 @@ UnpackParam(LPARAM lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL No
         PMSGMEMORY MsgMemoryEntry;
         MsgMemoryEntry = FindMsgMemory(Msg);
         ASSERT(MsgMemoryEntry);
-        if (MsgMemoryEntry->Size < 0)
-        {
-            /* Keep previous behavior */
-            return STATUS_INVALID_PARAMETER;
-        }
 
         if (MsgMemoryEntry->Flags == MMS_FLAG_READWRITE)
         {
@@ -435,10 +446,11 @@ CopyMsgToKernelMem(MSG *KernelModeMsg, MSG *UserModeMsg, PMSGMEMORY MsgMemoryEnt
         /* Copy data if required */
         if (0 != (MsgMemoryEntry->Flags & MMS_FLAG_READ))
         {
+            TRACE("Copy Message %d from usermode buffer\n", KernelModeMsg->message);
             Status = MmCopyFromCaller(KernelMem, (PVOID) UserModeMsg->lParam, Size);
             if (! NT_SUCCESS(Status))
             {
-                ERR("Failed to copy message to kernel: invalid usermode buffer\n");
+                ERR("Failed to copy message to kernel: invalid usermode lParam buffer\n");
                 ExFreePoolWithTag(KernelMem, TAG_MSG);
                 return Status;
             }
@@ -483,12 +495,16 @@ CopyMsgToUserMem(MSG *UserModeMsg, MSG *KernelModeMsg)
             Status = MmCopyToCaller((PVOID) UserModeMsg->lParam, (PVOID) KernelModeMsg->lParam, Size);
             if (! NT_SUCCESS(Status))
             {
-                ERR("Failed to copy message from kernel: invalid usermode buffer\n");
+                ERR("Failed to copy message from kernel: invalid usermode lParam buffer\n");
                 ExFreePool((PVOID) KernelModeMsg->lParam);
                 return Status;
             }
         }
-
+        if (KernelModeMsg->message == WM_COPYDATA)
+        {
+           // Only the current process or thread can free the message lParam pointer.
+           return STATUS_SUCCESS;
+        }
         ExFreePool((PVOID) KernelModeMsg->lParam);
     }
 
@@ -502,13 +518,7 @@ VOID FASTCALL
 IdlePing(VOID)
 {
    PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
-   PUSER_MESSAGE_QUEUE ForegroundQueue;
-   PTHREADINFO pti, ptiForeground = NULL;
-
-   ForegroundQueue = IntGetFocusMessageQueue();
-
-   if (ForegroundQueue)
-      ptiForeground = ForegroundQueue->Thread->Tcb.Win32Thread;
+   PTHREADINFO pti;
 
    pti = PsGetCurrentThreadWin32Thread();
 
@@ -516,7 +526,7 @@ IdlePing(VOID)
    {
       pti->pClientInfo->cSpins = 0; // Reset spins.
 
-      if ( pti->pDeskInfo && pti == ptiForeground )
+      if ( pti->pDeskInfo && pti == gptiForeground )
       {
          if ( pti->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE) ||
               pti->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE) )
@@ -526,7 +536,7 @@ IdlePing(VOID)
       }
    }
 
-   TRACE("IdlePing ppi 0x%x\n",ppi);
+   TRACE("IdlePing ppi %p\n", ppi);
    if ( ppi && ppi->InputIdleEvent )
    {
       TRACE("InputIdleEvent\n");
@@ -539,7 +549,7 @@ IdlePong(VOID)
 {
    PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
 
-   TRACE("IdlePong ppi 0x%x\n",ppi);
+   TRACE("IdlePong ppi %p\n", ppi);
    if ( ppi && ppi->InputIdleEvent )
    {
       KeClearEvent(ppi->InputIdleEvent);
@@ -602,6 +612,7 @@ static LRESULT handle_internal_message( PWND pWnd, UINT msg, WPARAM wparam, LPAR
 {
     LRESULT lRes;
     USER_REFERENCE_ENTRY Ref;
+//    PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
 
     if (!pWnd ||
          pWnd == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
@@ -632,7 +643,7 @@ static LRESULT handle_internal_message( PWND pWnd, UINT msg, WPARAM wparam, LPAR
        {
           PWND Window = (PWND)wparam;
           if (wparam) UserRefObjectCo(Window, &Ref);
-          lRes = (LRESULT)co_IntSetActiveWindow(Window,NULL,(BOOL)lparam,TRUE,TRUE);
+          lRes = (LRESULT)co_IntSetActiveWindow(Window,(BOOL)lparam,TRUE,TRUE);
           if (wparam) UserDerefObjectCo(Window);
           return lRes;
        }
@@ -648,7 +659,6 @@ IntDispatchMessage(PMSG pMsg)
     LRESULT retval = 0;
     PTHREADINFO pti;
     PWND Window = NULL;
-    HRGN hrgn;
     BOOL DoCallBack = TRUE;
 
     if (pMsg->hwnd)
@@ -681,7 +691,7 @@ IntDispatchMessage(PMSG pMsg)
                                               WM_TIMER,
                                               pMsg->wParam,
                                               (LPARAM)Time,
-                                              0);
+                                              -1);
             }
             return retval;
         }
@@ -735,15 +745,16 @@ IntDispatchMessage(PMSG pMsg)
                                    pMsg->message,
                                    pMsg->wParam,
                                    pMsg->lParam,
-                                   0);
+                                   -1);
 
     if (pMsg->message == WM_PAINT)
     {
+        PREGION Rgn;
         Window->state2 &= ~WNDS2_WMPAINTSENT;
         /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
-        hrgn = IntSysCreateRectRgn( 0, 0, 0, 0 );
-        co_UserGetUpdateRgn( Window, hrgn, TRUE );
-        GreDeleteObject(hrgn);
+        Rgn = IntSysCreateRectpRgn( 0, 0, 0, 0 );
+        co_UserGetUpdateRgn( Window, Rgn, TRUE );
+        REGION_Delete(Rgn);
     }
 
     return retval;
@@ -751,6 +762,14 @@ IntDispatchMessage(PMSG pMsg)
 
 /*
  * Internal version of PeekMessage() doing all the work
+ *
+ * MSDN:
+ *   Sent messages
+ *   Posted messages
+ *   Input (hardware) messages and system internal events
+ *   Sent messages (again)
+ *   WM_PAINT messages
+ *   WM_TIMER messages
  */
 BOOL FASTCALL
 co_IntPeekMessage( PMSG Msg,
@@ -762,22 +781,15 @@ co_IntPeekMessage( PMSG Msg,
 {
     PTHREADINFO pti;
     LARGE_INTEGER LargeTickCount;
-    PUSER_MESSAGE_QUEUE ThreadQueue;
     BOOL RemoveMessages;
     UINT ProcessMask;
     BOOL Hit = FALSE;
 
     pti = PsGetCurrentThreadWin32Thread();
-    ThreadQueue = pti->MessageQueue;
 
     RemoveMessages = RemoveMsg & PM_REMOVE;
     ProcessMask = HIWORD(RemoveMsg);
 
-    if (ThreadQueue->ptiSysLock && ThreadQueue->ptiSysLock != pti)
-    {
-       ERR("PeekMessage: Thread Q 0x%p is locked 0x%p to another pti 0x%p!\n", ThreadQueue, ThreadQueue->ptiSysLock, pti );
-    }
-
  /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns
     all available messages (that is, no range filtering is performed)".        */
     if (!ProcessMask) ProcessMask = (QS_ALLPOSTMESSAGE|QS_ALLINPUT);
@@ -787,11 +799,17 @@ co_IntPeekMessage( PMSG Msg,
     do
     {
         KeQueryTickCount(&LargeTickCount);
-        ThreadQueue->LastMsgRead = LargeTickCount.u.LowPart;
+        pti->timeLast = LargeTickCount.u.LowPart;
         pti->pcti->tickLastMsgChecked = LargeTickCount.u.LowPart;
 
+        // Post mouse moves while looping through peek messages.
+        if (pti->MessageQueue->QF_flags & QF_MOUSEMOVED)
+        {
+           IntCoalesceMouseMove(pti);
+        }
+
         /* Dispatch sent messages here. */
-        while ( co_MsqDispatchOneSentMessage(ThreadQueue) )
+        while ( co_MsqDispatchOneSentMessage(pti) )
         {
            /* if some PM_QS* flags were specified, only handle sent messages from now on */
            if (HIWORD(RemoveMsg) && !bGMSG) Hit = TRUE; // wine does this; ProcessMask = QS_SENDMESSAGE;
@@ -816,7 +834,7 @@ co_IntPeekMessage( PMSG Msg,
         /* Now check for normal messages. */
         if (( (ProcessMask & QS_POSTMESSAGE) ||
               (ProcessMask & QS_HOTKEY) ) &&
-            MsqPeekMessage( ThreadQueue,
+            MsqPeekMessage( pti,
                             RemoveMessages,
                             Window,
                             MsgFilterMin,
@@ -828,18 +846,18 @@ co_IntPeekMessage( PMSG Msg,
         }
 
         /* Now look for a quit message. */
-        if (ThreadQueue->QuitPosted)
+        if (pti->QuitPosted)
         {
             /* According to the PSDK, WM_QUIT messages are always returned, regardless
                of the filter specified */
             Msg->hwnd = NULL;
             Msg->message = WM_QUIT;
-            Msg->wParam = ThreadQueue->QuitExitCode;
+            Msg->wParam = pti->exitCode;
             Msg->lParam = 0;
             if (RemoveMessages)
             {
-                ThreadQueue->QuitPosted = FALSE;
-                ClearMsgBitsMask(ThreadQueue, QS_POSTMESSAGE);
+                pti->QuitPosted = FALSE;
+                ClearMsgBitsMask(pti, QS_POSTMESSAGE);
                 pti->pcti->fsWakeBits &= ~QS_ALLPOSTMESSAGE;
                 pti->pcti->fsChangeBits &= ~QS_ALLPOSTMESSAGE;
             }
@@ -847,19 +865,8 @@ co_IntPeekMessage( PMSG Msg,
         }
 
         /* Check for hardware events. */
-        if ((ProcessMask & QS_MOUSE) &&
-            co_MsqPeekMouseMove( ThreadQueue,
-                                 RemoveMessages,
-                                 Window,
-                                 MsgFilterMin,
-                                 MsgFilterMax,
-                                 Msg ))
-        {
-            return TRUE;
-        }
-
         if ((ProcessMask & QS_INPUT) &&
-            co_MsqPeekHardwareMessage( ThreadQueue,
+            co_MsqPeekHardwareMessage( pti,
                                        RemoveMessages,
                                        Window,
                                        MsgFilterMin,
@@ -871,7 +878,7 @@ co_IntPeekMessage( PMSG Msg,
         }
 
         /* Check for sent messages again. */
-        while ( co_MsqDispatchOneSentMessage(ThreadQueue) )
+        while ( co_MsqDispatchOneSentMessage(pti) )
         {
            if (HIWORD(RemoveMsg) && !bGMSG) Hit = TRUE;
         }
@@ -912,12 +919,10 @@ co_IntWaitMessage( PWND Window,
                    UINT MsgFilterMax )
 {
     PTHREADINFO pti;
-    PUSER_MESSAGE_QUEUE ThreadQueue;
     NTSTATUS Status = STATUS_SUCCESS;
     MSG Msg;
 
     pti = PsGetCurrentThreadWin32Thread();
-    ThreadQueue = pti->MessageQueue;
 
     do
     {
@@ -932,7 +937,7 @@ co_IntWaitMessage( PWND Window,
         }
 
         /* Nothing found. Wait for new messages. */
-        Status = co_MsqWaitForNewMessages( ThreadQueue,
+        Status = co_MsqWaitForNewMessages( pti,
                                            Window,
                                            MsgFilterMin,
                                            MsgFilterMax);
@@ -1027,7 +1032,7 @@ co_IntGetPeekMessage( PMSG pMsg,
 
         if ( bGMSG )
         {
-            Status = co_MsqWaitForNewMessages( pti->MessageQueue,
+            Status = co_MsqWaitForNewMessages( pti,
                                                Window,
                                                MsgFilterMin,
                                                MsgFilterMax);
@@ -1067,53 +1072,43 @@ co_IntGetPeekMessage( PMSG pMsg,
 }
 
 BOOL FASTCALL
-UserPostThreadMessage( DWORD idThread,
+UserPostThreadMessage( PTHREADINFO pti,
                        UINT Msg,
                        WPARAM wParam,
                        LPARAM lParam )
 {
     MSG Message;
-    PETHREAD peThread;
-    PTHREADINFO pThread;
     LARGE_INTEGER LargeTickCount;
-    NTSTATUS Status;
 
     if (is_pointer_message(Msg))
     {
         EngSetLastError(ERROR_MESSAGE_SYNC_ONLY );
         return FALSE;
     }
+    Message.hwnd = NULL;
+    Message.message = Msg;
+    Message.wParam = wParam;
+    Message.lParam = lParam;
+    Message.pt = gpsi->ptCursor;
 
-    Status = PsLookupThreadByThreadId((HANDLE)idThread,&peThread);
-
-    if( Status == STATUS_SUCCESS )
-    {
-        pThread = (PTHREADINFO)peThread->Tcb.Win32Thread;
-        if( !pThread ||
-            !pThread->MessageQueue ||
-            (pThread->TIF_flags & TIF_INCLEANUP))
-        {
-            ObDereferenceObject( peThread );
-            return FALSE;
-        }
-
-        Message.hwnd = NULL;
-        Message.message = Msg;
-        Message.wParam = wParam;
-        Message.lParam = lParam;
-        Message.pt = gpsi->ptCursor;
+    KeQueryTickCount(&LargeTickCount);
+    Message.time = MsqCalculateMessageTime(&LargeTickCount);
+    MsqPostMessage(pti, &Message, FALSE, QS_POSTMESSAGE, 0, 0);
+    return TRUE;
+}
 
-        KeQueryTickCount(&LargeTickCount);
-        Message.time = MsqCalculateMessageTime(&LargeTickCount);
-        MsqPostMessage(pThread->MessageQueue, &Message, FALSE, QS_POSTMESSAGE, 0);
-        ObDereferenceObject( peThread );
-        return TRUE;
-    }
-    else
-    {
-        SetLastNtError( Status );
-    }
-    return FALSE;
+PTHREADINFO FASTCALL
+IntSendTo(PWND Window, PTHREADINFO ptiCur, UINT Msg)
+{
+   if ( ptiCur )
+   {
+      if (!Window ||
+           Window->head.pti->MessageQueue == ptiCur->MessageQueue )
+      {
+         return NULL;
+      }
+   }
+   return Window ? Window->head.pti : NULL;
 }
 
 BOOL FASTCALL
@@ -1166,7 +1161,8 @@ UserPostMessage( HWND Wnd,
 
     if (!Wnd)
     {
-        return UserPostThreadMessage( PtrToInt(PsGetCurrentThreadId()),
+        pti = PsGetCurrentThreadWin32Thread();
+        return UserPostThreadMessage( pti,
                                       Msg,
                                       wParam,
                                       lParam);
@@ -1204,31 +1200,31 @@ UserPostMessage( HWND Wnd,
         Window = UserGetWindowObject(Wnd);
         if ( !Window )
         {
-            ERR("UserPostMessage: Invalid handle 0x%p!\n",Wnd);
+            ERR("UserPostMessage: Invalid handle 0x%p Msg %d!\n",Wnd,Msg);
             return FALSE;
         }
 
         pti = Window->head.pti;
         if ( pti->TIF_flags & TIF_INCLEANUP )
         {
-            ERR("Attempted to post message to window 0x%x when the thread is in cleanup!\n", Wnd);
+            ERR("Attempted to post message to window %p when the thread is in cleanup!\n", Wnd);
             return FALSE;
         }
 
         if ( Window->state & WNDS_DESTROYED )
         {
-            ERR("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd);
+            ERR("Attempted to post message to window %p that is being destroyed!\n", Wnd);
             /* FIXME: Last error code? */
             return FALSE;
         }
 
         if (WM_QUIT == Msg)
         {
-            MsqPostQuitMessage(Window->head.pti->MessageQueue, wParam);
+            MsqPostQuitMessage(pti, wParam);
         }
         else
         {
-            MsqPostMessage(Window->head.pti->MessageQueue, &Message, FALSE, QS_POSTMESSAGE, 0);
+            MsqPostMessage(pti, &Message, FALSE, QS_POSTMESSAGE, 0, 0);
         }
     }
     return TRUE;
@@ -1262,7 +1258,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
     PMSGMEMORY MsgMemoryEntry;
     INT lParamBufferSize;
     LPARAM lParamPacked;
-    PTHREADINFO Win32Thread;
+    PTHREADINFO Win32Thread, ptiSendTo = NULL;
     ULONG_PTR Hi, Lo, Result = 0;
     DECLARE_RETURN(LRESULT);
     USER_REFERENCE_ENTRY Ref;
@@ -1278,8 +1274,9 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
 
     Win32Thread = PsGetCurrentThreadWin32Thread();
 
-    if ( Win32Thread &&
-         Window->head.pti->MessageQueue == Win32Thread->MessageQueue)
+    ptiSendTo = IntSendTo(Window, Win32Thread, Msg);
+
+    if ( !ptiSendTo )
     {
         if (Win32Thread->TIF_flags & TIF_INCLEANUP)
         {
@@ -1333,6 +1330,8 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
         else
         {
            lParamBufferSize = MsgMemorySize(MsgMemoryEntry, wParam, lParam);
+           // If zero, do not allow callback on client side to allocate a buffer!!!!! See CORE-7695.
+           if (!lParamBufferSize) lParamBufferSize = -1;
         }
 
         if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam, FALSE)))
@@ -1365,7 +1364,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
         RETURN( TRUE);
     }
 
-    if (uFlags & SMTO_ABORTIFHUNG && MsqIsHung(Window->head.pti->MessageQueue))
+    if (uFlags & SMTO_ABORTIFHUNG && MsqIsHung(ptiSendTo))
     {
         // FIXME: Set window hung and add to a list.
         /* FIXME: Set a LastError? */
@@ -1375,13 +1374,13 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
     if (Window->state & WNDS_DESTROYED)
     {
         /* FIXME: Last error? */
-        ERR("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd);
+        ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd);
         RETURN( FALSE);
     }
 
     do
     {
-        Status = co_MsqSendMessage( Window->head.pti->MessageQueue,
+        Status = co_MsqSendMessage( ptiSendTo,
                                     hWnd,
                                     Msg,
                                     wParam,
@@ -1393,7 +1392,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
     }
     while ((STATUS_TIMEOUT == Status) &&
            (uFlags & SMTO_NOTIMEOUTIFNOTHUNG) &&
-           !MsqIsHung(Window->head.pti->MessageQueue)); // FIXME: Set window hung and add to a list.
+           !MsqIsHung(ptiSendTo)); // FIXME: Set window hung and add to a list.
 
     if (STATUS_TIMEOUT == Status)
     {
@@ -1418,6 +1417,11 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
 
 CLEANUP:
     if (Window) UserDerefObjectCo(Window);
+    // Current Thread and it's a Copy Data message, then free kernel memory.
+    if ( !ptiSendTo && Msg == WM_COPYDATA )
+    {
+       ExFreePool((PVOID) lParam);
+    }
     END_CLEANUP;
 }
 
@@ -1523,7 +1527,7 @@ co_IntSendMessageWithCallBack( HWND hWnd,
     PMSGMEMORY MsgMemoryEntry;
     INT lParamBufferSize;
     LPARAM lParamPacked;
-    PTHREADINFO Win32Thread;
+    PTHREADINFO Win32Thread, ptiSendTo = NULL;
     DECLARE_RETURN(LRESULT);
     USER_REFERENCE_ENTRY Ref;
     PUSER_SENT_MESSAGE Message;
@@ -1540,7 +1544,7 @@ co_IntSendMessageWithCallBack( HWND hWnd,
     if (Window->state & WNDS_DESTROYED)
     {
         /* FIXME: last error? */
-        ERR("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd);
+        ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd);
         RETURN(FALSE);
     }
 
@@ -1552,8 +1556,10 @@ co_IntSendMessageWithCallBack( HWND hWnd,
         RETURN(FALSE);
     }
 
+    ptiSendTo = IntSendTo(Window, Win32Thread, Msg);
+
     if (Msg & 0x80000000 &&
-        Window->head.pti->MessageQueue == Win32Thread->MessageQueue)
+        !ptiSendTo)
     {
        if (Win32Thread->TIF_flags & TIF_INCLEANUP) RETURN( FALSE);
 
@@ -1572,16 +1578,17 @@ co_IntSendMessageWithCallBack( HWND hWnd,
     else
     {
         lParamBufferSize = MsgMemorySize(MsgMemoryEntry, wParam, lParam);
+        if (!lParamBufferSize) lParamBufferSize = -1;
     }
 
-    if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam, Window->head.pti->MessageQueue != Win32Thread->MessageQueue)))
+    if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam, !!ptiSendTo)))
     {
         ERR("Failed to pack message parameters\n");
         RETURN( FALSE);
     }
 
     /* If it can be sent now, then send it. */
-    if (Window->head.pti->MessageQueue == Win32Thread->MessageQueue)
+    if ( !ptiSendTo )
     {
         if (Win32Thread->TIF_flags & TIF_INCLEANUP)
         {
@@ -1631,7 +1638,7 @@ co_IntSendMessageWithCallBack( HWND hWnd,
         }
     }
 
-    if (Window->head.pti->MessageQueue == Win32Thread->MessageQueue)
+    if ( !ptiSendTo)
     {
         if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE)))
         {
@@ -1646,12 +1653,6 @@ co_IntSendMessageWithCallBack( HWND hWnd,
         RETURN( FALSE);
     }
 
-    IntReferenceMessageQueue(Window->head.pti->MessageQueue);
-    /* Take reference on this MessageQueue if its a callback. It will be released
-       when message is processed or removed from target hwnd MessageQueue */
-    if (CompletionCallback)
-       IntReferenceMessageQueue(Win32Thread->MessageQueue);
-
     Message->Msg.hwnd = hWnd;
     Message->Msg.message = Msg;
     Message->Msg.wParam = wParam;
@@ -1660,8 +1661,9 @@ co_IntSendMessageWithCallBack( HWND hWnd,
     Message->Result = 0;
     Message->lResult = 0;
     Message->QS_Flags = 0;
-    Message->SenderQueue = NULL; // mjmartin, you are right! This is null.
-    Message->CallBackSenderQueue = Win32Thread->MessageQueue;
+    Message->ptiReceiver = ptiSendTo;
+    Message->ptiSender = NULL; // mjmartin, you are right! This is null.
+    Message->ptiCallBackSender = Win32Thread;
     Message->DispatchingListEntry.Flink = NULL;
     Message->CompletionCallback = CompletionCallback;
     Message->CompletionCallbackContext = CompletionCallbackContext;
@@ -1669,9 +1671,11 @@ co_IntSendMessageWithCallBack( HWND hWnd,
     Message->HasPackedLParam = (lParamBufferSize > 0);
     Message->QS_Flags = QS_SENDMESSAGE;
 
-    InsertTailList(&Window->head.pti->MessageQueue->SentMessagesListHead, &Message->ListEntry);
-    MsqWakeQueue(Window->head.pti->MessageQueue, QS_SENDMESSAGE, TRUE);
-    IntDereferenceMessageQueue(Window->head.pti->MessageQueue);
+    if (Msg & 0x80000000) // Higher priority event message!
+       InsertHeadList(&ptiSendTo->SentMessagesListHead, &Message->ListEntry);
+    else
+       InsertTailList(&ptiSendTo->SentMessagesListHead, &Message->ListEntry);
+    MsqWakeQueue(ptiSendTo, QS_SENDMESSAGE, TRUE);
 
     RETURN(TRUE);
 
@@ -1680,7 +1684,7 @@ CLEANUP:
     END_CLEANUP;
 }
 
-
+#if 0
 /*
   This HACK function posts a message if the destination's message queue belongs to
   another thread, otherwise it sends the message. It does not support broadcast
@@ -1709,7 +1713,7 @@ co_IntPostOrSendMessage( HWND hWnd,
 
     pti = PsGetCurrentThreadWin32Thread();
 
-    if ( Window->head.pti->MessageQueue != pti->MessageQueue &&
+    if ( IntSendTo(Window, pti, Msg) &&
          FindMsgMemory(Msg) == 0 )
     {
         Result = UserPostMessage(hWnd, Msg, wParam, lParam);
@@ -1724,21 +1728,21 @@ co_IntPostOrSendMessage( HWND hWnd,
 
     return (LRESULT)Result;
 }
+#endif
 
-LRESULT FASTCALL
+static LRESULT FASTCALL
 co_IntDoSendMessage( HWND hWnd,
                      UINT Msg,
                      WPARAM wParam,
                      LPARAM lParam,
                      PDOSENDMESSAGE dsm)
 {
-    //PTHREADINFO pti;
     LRESULT Result = TRUE;
     NTSTATUS Status;
     PWND Window = NULL;
-    MSG UserModeMsg;
-    MSG KernelModeMsg;
+    MSG UserModeMsg, KernelModeMsg;
     PMSGMEMORY MsgMemoryEntry;
+    PTHREADINFO ptiSendTo;
 
     if (hWnd != HWND_BROADCAST && hWnd != HWND_TOPMOST)
     {
@@ -1755,20 +1759,30 @@ co_IntDoSendMessage( HWND hWnd,
         ERR("co_IntDoSendMessage Window Exiting!\n");
     }
 
-    /* See if the current thread can handle the message */
-    //pti = PsGetCurrentThreadWin32Thread();
+    /* See if the current thread can handle this message */
+    ptiSendTo = IntSendTo(Window, gptiCurrent, Msg);
 
-    UserModeMsg.hwnd = hWnd;
-    UserModeMsg.message = Msg;
-    UserModeMsg.wParam = wParam;
-    UserModeMsg.lParam = lParam;
-    MsgMemoryEntry = FindMsgMemory(UserModeMsg.message);
-
-    Status = CopyMsgToKernelMem(&KernelModeMsg, &UserModeMsg, MsgMemoryEntry);
-    if (! NT_SUCCESS(Status))
+    // If broadcasting or sending to another thread, save the users data.
+    if (!Window || ptiSendTo )
+    {
+       UserModeMsg.hwnd    = hWnd;
+       UserModeMsg.message = Msg;
+       UserModeMsg.wParam  = wParam;
+       UserModeMsg.lParam  = lParam;
+       MsgMemoryEntry = FindMsgMemory(UserModeMsg.message);
+       Status = CopyMsgToKernelMem(&KernelModeMsg, &UserModeMsg, MsgMemoryEntry);
+       if (!NT_SUCCESS(Status))
+       {
+          EngSetLastError(ERROR_INVALID_PARAMETER);
+          return (dsm ? 0 : -1);
+       }
+    }
+    else
     {
-       EngSetLastError(ERROR_INVALID_PARAMETER);
-       return (dsm ? 0 : -1);
+       KernelModeMsg.hwnd    = hWnd;
+       KernelModeMsg.message = Msg;
+       KernelModeMsg.wParam  = wParam;
+       KernelModeMsg.lParam  = lParam;
     }
 
     if (!dsm)
@@ -1789,11 +1803,14 @@ co_IntDoSendMessage( HWND hWnd,
                                          &dsm->Result );
     }
 
-    Status = CopyMsgToUserMem(&UserModeMsg, &KernelModeMsg);
-    if (! NT_SUCCESS(Status))
+    if (!Window || ptiSendTo )
     {
-       EngSetLastError(ERROR_INVALID_PARAMETER);
-       return(dsm ? 0 : -1);
+       Status = CopyMsgToUserMem(&UserModeMsg, &KernelModeMsg);
+       if (!NT_SUCCESS(Status))
+       {
+          EngSetLastError(ERROR_INVALID_PARAMETER);
+          return(dsm ? 0 : -1);
+       }
     }
 
     return (LRESULT)Result;
@@ -1899,6 +1916,22 @@ IntUninitMessagePumpHook()
     return FALSE;
 }
 
+BOOL FASTCALL
+IntCallMsgFilter( LPMSG lpmsg, INT code)
+{
+    BOOL Ret = FALSE;
+
+    if ( co_HOOK_CallHooks( WH_SYSMSGFILTER, code, 0, (LPARAM)lpmsg))
+    {
+        Ret = TRUE;
+    }
+    else
+    {
+        Ret = co_HOOK_CallHooks( WH_MSGFILTER, code, 0, (LPARAM)lpmsg);
+    }
+    return Ret;
+}
+
 /** Functions ******************************************************************/
 
 BOOL
@@ -1912,7 +1945,7 @@ NtUserDragDetect(
     ULONG wDragWidth, wDragHeight;
     DECLARE_RETURN(BOOL);
 
-    TRACE("Enter NtUserDragDetect(%x)\n", hWnd);
+    TRACE("Enter NtUserDragDetect(%p)\n", hWnd);
     UserEnterExclusive();
 
     wDragWidth = UserGetSystemMetrics(SM_CXDRAG);
@@ -1994,14 +2027,34 @@ NtUserPostThreadMessage(DWORD idThread,
                         WPARAM wParam,
                         LPARAM lParam)
 {
-    BOOL ret;
+    BOOL ret = FALSE;
+    PETHREAD peThread;
+    PTHREADINFO pThread;
+    NTSTATUS Status;
 
     UserEnterExclusive();
 
-    ret = UserPostThreadMessage( idThread, Msg, wParam, lParam);
+    Status = PsLookupThreadByThreadId((HANDLE)idThread,&peThread);
 
+    if ( Status == STATUS_SUCCESS )
+    {
+        pThread = (PTHREADINFO)peThread->Tcb.Win32Thread;
+        if( !pThread ||
+            !pThread->MessageQueue ||
+            (pThread->TIF_flags & TIF_INCLEANUP))
+        {
+            ObDereferenceObject( peThread );
+            goto exit;
+        }
+        ret = UserPostThreadMessage( pThread, Msg, wParam, lParam);
+        ObDereferenceObject( peThread );
+    }
+    else
+    {
+        SetLastNtError( Status );
+    }
+exit:
     UserLeave();
-
     return ret;
 }
 
@@ -2042,7 +2095,7 @@ NtUserGetMessage(PMSG pMsg,
 
     UserLeave();
 
-    if (Ret == TRUE)
+    if (Ret)
     {
         _SEH2_TRY
         {
@@ -2202,7 +2255,7 @@ NtUserTranslateMessage(LPMSG lpMsg, UINT flags)
     }
     else
     {
-        TRACE("No Window for Translate. hwnd 0x%p Msg %d\n",SafeMsg.hwnd,SafeMsg.message);
+        TRACE("No Window for Translate. hwnd 0x%p Msg %u\n", SafeMsg.hwnd, SafeMsg.message);
         Ret = FALSE;
     }
     UserLeave();
@@ -2351,7 +2404,7 @@ NtUserMessageCall( HWND hWnd,
 
                            if ( parm.flags & BSF_IGNORECURRENTTASK )
                            {
-                              if ( pwnd->head.pti->MessageQueue == gptiCurrent->MessageQueue )
+                              if ( pwnd->head.pti == gptiCurrent )
                                  continue;
                            }
                            co_IntSendMessageTimeout( List[i],
@@ -2406,7 +2459,7 @@ NtUserMessageCall( HWND hWnd,
 
                            if ( parm.flags & BSF_IGNORECURRENTTASK )
                            {
-                              if ( pwnd->head.pti->MessageQueue == gptiCurrent->MessageQueue )
+                              if ( pwnd->head.pti == gptiCurrent )
                                  continue;
                            }
                            UserPostMessage(List[i], Msg, wParam, lParam);
@@ -2432,7 +2485,7 @@ NtUserMessageCall( HWND hWnd,
 
                            if ( parm.flags & BSF_IGNORECURRENTTASK )
                            {
-                              if ( pwnd->head.pti->MessageQueue == gptiCurrent->MessageQueue )
+                              if ( pwnd->head.pti == gptiCurrent )
                                  continue;
                            }
                            UserSendNotifyMessage(List[i], Msg, wParam, lParam);
@@ -2489,7 +2542,7 @@ NtUserMessageCall( HWND hWnd,
 
                         if ( parm.flags & BSF_IGNORECURRENTTASK )
                         {
-                           if ( pwnd->head.pti->MessageQueue == gptiCurrent->MessageQueue )
+                           if ( pwnd->head.pti == gptiCurrent )
                               continue;
                         }
                         co_IntSendMessageTimeout( List[i],
@@ -2543,7 +2596,7 @@ NtUserMessageCall( HWND hWnd,
 
                         if ( parm.flags & BSF_IGNORECURRENTTASK )
                         {
-                           if ( pwnd->head.pti->MessageQueue == gptiCurrent->MessageQueue )
+                           if ( pwnd->head.pti == gptiCurrent )
                               continue;
                         }
                         UserPostMessage(List[i], Msg, wParam, lParam);
@@ -2569,7 +2622,7 @@ NtUserMessageCall( HWND hWnd,
 
                         if ( parm.flags & BSF_IGNORECURRENTTASK )
                         {
-                           if ( pwnd->head.pti->MessageQueue == gptiCurrent->MessageQueue )
+                           if ( pwnd->head.pti == gptiCurrent )
                               continue;
                         }
                         UserSendNotifyMessage(List[i], Msg, wParam, lParam);
@@ -2703,13 +2756,15 @@ NtUserMessageCall( HWND hWnd,
                 CWP.message = Msg;
                 CWP.wParam  = wParam;
                 CWP.lParam  = lParam;
-                TRACE("WH_CALLWNDPROC: Hook %x NextHook %x\n", Hook, NextObj );
+                TRACE("WH_CALLWNDPROC: Hook %p NextHook %p\n", Hook, NextObj);
 
                 lResult = co_IntCallHookProc( Hook->HookId,
                                               HC_ACTION,
                                               ((ClientInfo->CI_flags & CI_CURTHPRHOOK) ? 1 : 0),
                                               (LPARAM)&CWP,
                                               Hook->Proc,
+                                              Hook->ihmod,
+                                              Hook->offPfn,
                                               Hook->Ansi,
                                               &Hook->ModuleName);
             }
@@ -2727,6 +2782,8 @@ NtUserMessageCall( HWND hWnd,
                                               ((ClientInfo->CI_flags & CI_CURTHPRHOOK) ? 1 : 0),
                                               (LPARAM)&CWPR,
                                               Hook->Proc,
+                                              Hook->ihmod,
+                                              Hook->offPfn,
                                               Hook->Ansi,
                                               &Hook->ModuleName);
             }
@@ -2784,7 +2841,7 @@ NtUserWaitForInputIdle( IN HANDLE hProcess,
 
     Status = ObReferenceObjectByHandle(hProcess,
                                        PROCESS_QUERY_INFORMATION,
-                                       PsProcessType,
+                                       *PsProcessType,
                                        UserMode,
                                        (PVOID*)&Process,
                                        NULL);
@@ -2812,7 +2869,7 @@ NtUserWaitForInputIdle( IN HANDLE hProcess,
 
     Handles[0] = Process;
     Handles[1] = W32Process->InputIdleEvent;
-    Handles[2] = pti->MessageQueue->NewMessages; // pEventQueueServer; IntMsqSetWakeMask returns hEventQueueClient
+    Handles[2] = pti->pEventQueueServer; // IntMsqSetWakeMask returns hEventQueueClient
 
     if (!Handles[1])
     {
@@ -2831,8 +2888,15 @@ NtUserWaitForInputIdle( IN HANDLE hProcess,
        pti->pClientInfo->dwTIFlags = pti->TIF_flags;
     }
 
-    TRACE("WFII: ppi 0x%x\n",W32Process);
+    TRACE("WFII: ppi %p\n", W32Process);
     TRACE("WFII: waiting for %p\n", Handles[1] );
+
+    /*
+     * We must add a refcount to our current PROCESSINFO,
+     * because anything could happen (including process death) we're leaving win32k
+     */
+    IntReferenceProcessInfo(W32Process);
+
     do
     {
         UserLeave();
@@ -2886,6 +2950,7 @@ WaitExit:
        pti->pClientInfo->dwTIFlags = pti->TIF_flags;
     }
     W32Process->W32PF_flags &= ~W32PF_WAITFORINPUTIDLE;
+    IntDereferenceProcessInfo(W32Process);
     ObDereferenceObject(Process);
     UserLeave();
     return Status;