[WIN32K]
[reactos.git] / reactos / win32ss / user / ntuser / message.c
index 6d01944..8d6a76c 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,11 +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_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
@@ -174,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)
         {
@@ -324,7 +336,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;
@@ -383,11 +395,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)
         {
@@ -436,10 +443,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;
             }
@@ -484,7 +492,7 @@ 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;
             }
@@ -644,7 +652,6 @@ IntDispatchMessage(PMSG pMsg)
     LRESULT retval = 0;
     PTHREADINFO pti;
     PWND Window = NULL;
-    HRGN hrgn;
     BOOL DoCallBack = TRUE;
 
     if (pMsg->hwnd)
@@ -677,7 +684,7 @@ IntDispatchMessage(PMSG pMsg)
                                               WM_TIMER,
                                               pMsg->wParam,
                                               (LPARAM)Time,
-                                              0);
+                                              -1);
             }
             return retval;
         }
@@ -731,15 +738,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;
@@ -844,17 +852,6 @@ co_IntPeekMessage( PMSG Msg,
         }
 
         /* Check for hardware events. */
-        if ((ProcessMask & QS_MOUSE) &&
-            co_MsqPeekMouseMove( pti,
-                                 RemoveMessages,
-                                 Window,
-                                 MsgFilterMin,
-                                 MsgFilterMax,
-                                 Msg ))
-        {
-            return TRUE;
-        }
-
         if ((ProcessMask & QS_INPUT) &&
             co_MsqPeekHardwareMessage( pti,
                                        RemoveMessages,
@@ -867,6 +864,17 @@ co_IntPeekMessage( PMSG Msg,
             return TRUE;
         }
 
+        if ((ProcessMask & QS_MOUSE) &&
+            co_MsqPeekMouseMove( pti,
+                                 RemoveMessages,
+                                 Window,
+                                 MsgFilterMin,
+                                 MsgFilterMax,
+                                 Msg ))
+        {
+            return TRUE;
+        }
+
         /* Check for sent messages again. */
         while ( co_MsqDispatchOneSentMessage(pti) )
         {
@@ -1092,12 +1100,13 @@ IntSendTo(PWND Window, PTHREADINFO ptiCur, UINT Msg)
 {
    if ( ptiCur )
    {
-      if ( Window->head.pti->MessageQueue == ptiCur->MessageQueue )
+      if (!Window ||
+           Window->head.pti->MessageQueue == ptiCur->MessageQueue )
       {
          return NULL;
       }
    }
-   return Window->head.pti;
+   return Window ? Window->head.pti : NULL;
 }
 
 BOOL FASTCALL
@@ -1189,7 +1198,7 @@ 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;
         }
 
@@ -1319,6 +1328,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)))
@@ -1351,7 +1362,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
         RETURN( TRUE);
     }
 
-    if (uFlags & SMTO_ABORTIFHUNG && MsqIsHung(ptiSendTo/*Window->head.pti*/))
+    if (uFlags & SMTO_ABORTIFHUNG && MsqIsHung(ptiSendTo))
     {
         // FIXME: Set window hung and add to a list.
         /* FIXME: Set a LastError? */
@@ -1367,7 +1378,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
 
     do
     {
-        Status = co_MsqSendMessage( ptiSendTo, //Window->head.pti,
+        Status = co_MsqSendMessage( ptiSendTo,
                                     hWnd,
                                     Msg,
                                     wParam,
@@ -1379,7 +1390,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
     }
     while ((STATUS_TIMEOUT == Status) &&
            (uFlags & SMTO_NOTIMEOUTIFNOTHUNG) &&
-           !MsqIsHung(ptiSendTo/*Window->head.pti*/)); // FIXME: Set window hung and add to a list.
+           !MsqIsHung(ptiSendTo)); // FIXME: Set window hung and add to a list.
 
     if (STATUS_TIMEOUT == Status)
     {
@@ -1537,7 +1548,7 @@ co_IntSendMessageWithCallBack( HWND hWnd,
     {
         RETURN(FALSE);
     }
-    
+
     ptiSendTo = IntSendTo(Window, Win32Thread, Msg);
 
     if (Msg & 0x80000000 &&
@@ -1560,6 +1571,7 @@ co_IntSendMessageWithCallBack( HWND hWnd,
     else
     {
         lParamBufferSize = MsgMemorySize(MsgMemoryEntry, wParam, lParam);
+        if (!lParamBufferSize) lParamBufferSize = -1;
     }
 
     if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam, !!ptiSendTo)))
@@ -1642,7 +1654,7 @@ co_IntSendMessageWithCallBack( HWND hWnd,
     Message->Result = 0;
     Message->lResult = 0;
     Message->QS_Flags = 0;
-    Message->ptiReceiver = ptiSendTo; //Window->head.pti;
+    Message->ptiReceiver = ptiSendTo;
     Message->ptiSender = NULL; // mjmartin, you are right! This is null.
     Message->ptiCallBackSender = Win32Thread;
     Message->DispatchingListEntry.Flink = NULL;
@@ -1653,10 +1665,10 @@ co_IntSendMessageWithCallBack( HWND hWnd,
     Message->QS_Flags = QS_SENDMESSAGE;
 
     if (Msg & 0x80000000) // Higher priority event message!
-       InsertHeadList(&ptiSendTo->SentMessagesListHead/*&Window->head.pti->SentMessagesListHead*/, &Message->ListEntry);
+       InsertHeadList(&ptiSendTo->SentMessagesListHead, &Message->ListEntry);
     else
-       InsertTailList(&ptiSendTo->SentMessagesListHead/*&Window->head.pti->SentMessagesListHead*/, &Message->ListEntry);
-    MsqWakeQueue(ptiSendTo/*Window->head.pti*/, QS_SENDMESSAGE, TRUE);
+       InsertTailList(&ptiSendTo->SentMessagesListHead, &Message->ListEntry);
+    MsqWakeQueue(ptiSendTo, QS_SENDMESSAGE, TRUE);
 
     RETURN(TRUE);
 
@@ -1710,20 +1722,19 @@ co_IntPostOrSendMessage( HWND hWnd,
     return (LRESULT)Result;
 }
 
-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)
     {
@@ -1740,20 +1751,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 )
     {
-       EngSetLastError(ERROR_INVALID_PARAMETER);
-       return (dsm ? 0 : -1);
+       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
+    {
+       KernelModeMsg.hwnd    = hWnd;
+       KernelModeMsg.message = Msg;
+       KernelModeMsg.wParam  = wParam;
+       KernelModeMsg.lParam  = lParam;
     }
 
     if (!dsm)
@@ -1774,11 +1795,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;
@@ -1884,6 +1908,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
@@ -1979,7 +2019,7 @@ NtUserPostThreadMessage(DWORD idThread,
                         WPARAM wParam,
                         LPARAM lParam)
 {
-    BOOL ret;
+    BOOL ret = FALSE;
     PETHREAD peThread;
     PTHREADINFO pThread;
     NTSTATUS Status;
@@ -2715,7 +2755,7 @@ NtUserMessageCall( HWND hWnd,
                                               ((ClientInfo->CI_flags & CI_CURTHPRHOOK) ? 1 : 0),
                                               (LPARAM)&CWP,
                                               Hook->Proc,
-                                              Hook->ihmod, 
+                                              Hook->ihmod,
                                               Hook->offPfn,
                                               Hook->Ansi,
                                               &Hook->ModuleName);
@@ -2734,7 +2774,7 @@ NtUserMessageCall( HWND hWnd,
                                               ((ClientInfo->CI_flags & CI_CURTHPRHOOK) ? 1 : 0),
                                               (LPARAM)&CWPR,
                                               Hook->Proc,
-                                              Hook->ihmod, 
+                                              Hook->ihmod,
                                               Hook->offPfn,
                                               Hook->Ansi,
                                               &Hook->ModuleName);
@@ -2793,7 +2833,7 @@ NtUserWaitForInputIdle( IN HANDLE hProcess,
 
     Status = ObReferenceObjectByHandle(hProcess,
                                        PROCESS_QUERY_INFORMATION,
-                                       PsProcessType,
+                                       *PsProcessType,
                                        UserMode,
                                        (PVOID*)&Process,
                                        NULL);
@@ -2842,6 +2882,13 @@ NtUserWaitForInputIdle( IN HANDLE hProcess,
 
     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();
@@ -2895,6 +2942,7 @@ WaitExit:
        pti->pClientInfo->dwTIFlags = pti->TIF_flags;
     }
     W32Process->W32PF_flags &= ~W32PF_WAITFORINPUTIDLE;
+    IntDereferenceProcessInfo(W32Process);
     ObDereferenceObject(Process);
     UserLeave();
     return Status;