[WIN32K]
[reactos.git] / reactos / win32ss / user / ntuser / msgqueue.c
index dde85a9..3a7f3b3 100644 (file)
@@ -146,14 +146,20 @@ UserSetCursor(
         {
             /* Call GDI to set the new screen cursor */
 #ifdef NEW_CURSORICON
+            PCURICON_OBJECT CursorFrame = NewCursor;
+            if(NewCursor->CURSORF_flags & CURSORF_ACON)
+            {
+                FIXME("Should animate the cursor, using only the first frame now.\n");
+                CursorFrame = ((PACON)NewCursor)->aspcur[0];
+            }
             GreSetPointerShape(hdcScreen,
-                               NewCursor->hbmAlpha ? NULL : NewCursor->hbmMask,
-                               NewCursor->hbmAlpha ? NewCursor->hbmAlpha : NewCursor->hbmColor,
-                               NewCursor->xHotspot,
-                               NewCursor->yHotspot,
+                               CursorFrame->hbmAlpha ? NULL : NewCursor->hbmMask,
+                               CursorFrame->hbmAlpha ? NewCursor->hbmAlpha : NewCursor->hbmColor,
+                               CursorFrame->xHotspot,
+                               CursorFrame->yHotspot,
                                gpsi->ptCursor.x,
                                gpsi->ptCursor.y,
-                               NewCursor->hbmAlpha ? SPS_ALPHA : 0);
+                               CursorFrame->hbmAlpha ? SPS_ALPHA : 0);
 #else
             GreSetPointerShape(hdcScreen,
                                NewCursor->IconInfo.hbmMask,
@@ -260,7 +266,7 @@ UserGetKeyState(DWORD dwKey)
 static VOID
 UpdateKeyState(PUSER_MESSAGE_QUEUE MessageQueue, WORD wVk, BOOL bIsDown)
 {
-    TRACE("UpdateKeyState wVk: %d, bIsDown: %d\n", wVk, bIsDown);
+    TRACE("UpdateKeyState wVk: %u, bIsDown: %d\n", wVk, bIsDown);
 
     if (bIsDown)
     {
@@ -282,7 +288,7 @@ UpdateKeyStateFromMsg(PUSER_MESSAGE_QUEUE MessageQueue, MSG* msg)
     UCHAR key;
     BOOL down = FALSE;
 
-    TRACE("UpdateKeyStateFromMsg message:%d\n", msg->message);
+    TRACE("UpdateKeyStateFromMsg message:%u\n", msg->message);
 
     switch (msg->message)
     {
@@ -404,7 +410,6 @@ MsqWakeQueue(PTHREADINFO pti, DWORD MessageBits, BOOL KeyEvent)
    {
       ERR("This Message Queue is in Destroy!\n");
    }
-
    pti->pcti->fsWakeBits |= MessageBits;
    pti->pcti->fsChangeBits |= MessageBits;
 
@@ -475,6 +480,10 @@ ClearMsgBitsMask(PTHREADINFO pti, UINT MessageBits)
    {
       if (--pti->nCntsQBits[QSRosHotKey] == 0) ClrMask |= QS_HOTKEY;
    }
+   if (MessageBits & QS_EVENT)
+   {
+      if (--pti->nCntsQBits[QSRosEvent] == 0) ClrMask |= QS_EVENT;
+   }
 
    pti->pcti->fsWakeBits &= ~ClrMask;
    pti->pcti->fsChangeBits &= ~ClrMask;
@@ -506,7 +515,7 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook
 {
    LARGE_INTEGER LargeTickCount;
    MSLLHOOKSTRUCT MouseHookData;
-   PDESKTOP pDesk;
+//   PDESKTOP pDesk;
    PWND pwnd, pwndDesktop;
    HDC hdcScreen;
    PTHREADINFO pti;
@@ -550,7 +559,7 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook
    /* Get the desktop window */
    pwndDesktop = UserGetDesktopWindow();
    if (!pwndDesktop) return;
-   pDesk = pwndDesktop->head.rpdesk;
+//   pDesk = pwndDesktop->head.rpdesk;
 
    /* Check if the mouse is captured */
    Msg->hwnd = IntGetCaptureWindow();
@@ -572,6 +581,7 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook
    {
        pti = pwnd->head.pti;
        MessageQueue = pti->MessageQueue;
+       // MessageQueue->ptiMouse = pti;
 
        if ( pti->TIF_flags & TIF_INCLEANUP || MessageQueue->QF_flags & QF_INDESTROY)
        {
@@ -628,7 +638,12 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook
        }
        else
        {
-           TRACE("Posting mouse message to hwnd=0x%x!\n", UserHMGetHandle(pwnd));
+           if (!IntGetCaptureWindow())
+           {
+             // ERR("ptiLastInput is set\n");
+             // ptiLastInput = pti; // Once this is set during Reboot or Shutdown, this prevents the exit window having foreground.
+           }
+           TRACE("Posting mouse message to hwnd=%p!\n", UserHMGetHandle(pwnd));
            MsqPostMessage(pti, Msg, TRUE, QS_MOUSEBUTTON, 0);
        }
    }
@@ -640,54 +655,6 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook
    }
 }
 
-VOID FASTCALL
-MsqPostHotKeyMessage(PVOID Thread, HWND hWnd, WPARAM wParam, LPARAM lParam)
-{
-   PWND Window;
-   PTHREADINFO Win32Thread;
-   MSG Mesg;
-   LARGE_INTEGER LargeTickCount;
-   NTSTATUS Status;
-   INT id;
-   DWORD Type;
-
-   Status = ObReferenceObjectByPointer (Thread,
-                                        THREAD_ALL_ACCESS,
-                                        PsThreadType,
-                                        KernelMode);
-   if (!NT_SUCCESS(Status))
-      return;
-
-   Win32Thread = ((PETHREAD)Thread)->Tcb.Win32Thread;
-   if (Win32Thread == NULL || Win32Thread->MessageQueue == NULL)
-   {
-      ObDereferenceObject ((PETHREAD)Thread);
-      return;
-   }
-
-   Window = IntGetWindowObject(hWnd);
-   if (!Window)
-   {
-      ObDereferenceObject ((PETHREAD)Thread);
-      return;
-   }
-
-   id = wParam; // Check for hot keys unrelated to the hot keys set by RegisterHotKey.
-
-   Mesg.hwnd    = hWnd;
-   Mesg.message = id != IDHK_REACTOS ? WM_HOTKEY : WM_SYSCOMMAND;
-   Mesg.wParam  = id != IDHK_REACTOS ? wParam    : SC_HOTKEY;
-   Mesg.lParam  = id != IDHK_REACTOS ? lParam    : (LPARAM)hWnd;
-   Type         = id != IDHK_REACTOS ? QS_HOTKEY : QS_POSTMESSAGE;
-   KeQueryTickCount(&LargeTickCount);
-   Mesg.time    = MsqCalculateMessageTime(&LargeTickCount);
-   Mesg.pt      = gpsi->ptCursor;
-   MsqPostMessage(Window->head.pti, &Mesg, FALSE, Type, 0);
-   UserDereferenceObject(Window);
-   ObDereferenceObject (Thread);
-
-}
-
 PUSER_MESSAGE FASTCALL
 MsqCreateMessage(LPMSG Msg)
 {
@@ -711,7 +678,7 @@ MsqDestroyMessage(PUSER_MESSAGE Message)
 }
 
 BOOLEAN FASTCALL
-co_MsqDispatchOneSentMessage(_In_ PTHREADINFO pti)
+co_MsqDispatchOneSentMessage(PTHREADINFO pti)
 {
    PUSER_SENT_MESSAGE SaveMsg, Message;
    PLIST_ENTRY Entry;
@@ -961,12 +928,6 @@ co_MsqSendMessageAsync(PTHREADINFO ptiReceiver,
 
     ptiSender = PsGetCurrentThreadWin32Thread();
 
-    IntReferenceMessageQueue(ptiReceiver->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(ptiSender->MessageQueue);
-
     Message->Msg.hwnd = hwnd;
     Message->Msg.message = Msg;
     Message->Msg.wParam = wParam;
@@ -1013,7 +974,7 @@ co_MsqSendMessage(PTHREADINFO ptirec,
     if (pti->TIF_flags & TIF_INCLEANUP || ptirec->TIF_flags & TIF_INCLEANUP)
     {
         if (uResult) *uResult = -1;
-        ERR("MsqSM: Current pti %d or Rec pti %d\n",pti->TIF_flags & TIF_INCLEANUP, ptirec->TIF_flags & TIF_INCLEANUP);
+        ERR("MsqSM: Current pti %lu or Rec pti %lu\n", pti->TIF_flags & TIF_INCLEANUP, ptirec->TIF_flags & TIF_INCLEANUP);
         return STATUS_UNSUCCESSFUL;
     }
 
@@ -1152,15 +1113,17 @@ co_MsqSendMessage(PTHREADINFO ptirec,
    }
    else
    {
-      PVOID WaitObjects[2];
+      PVOID WaitObjects[3];
+
+      WaitObjects[0] = &CompletionEvent;       // Wait 0
+      WaitObjects[1] = pti->pEventQueueServer; // Wait 1
+      WaitObjects[2] = ptirec->pEThread;       // Wait 2
 
-      WaitObjects[0] = &CompletionEvent;
-      WaitObjects[1] = pti->pEventQueueServer;
       do
       {
          UserLeaveCo();
 
-         WaitStatus = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, UserRequest,
+         WaitStatus = KeWaitForMultipleObjects(3, WaitObjects, WaitAny, UserRequest,
                                                UserMode, FALSE, (uTimeout ? &Timeout : NULL), NULL);
 
          UserEnterCo();
@@ -1208,14 +1171,33 @@ co_MsqSendMessage(PTHREADINFO ptirec,
             TRACE("MsqSendMessage timed out 2\n");
             break;
          }
+         // Receiving thread passed on and left us hanging with issues still pending.
+         if ( WaitStatus == STATUS_WAIT_2 )
+         {
+            ERR("Receiving Thread woken up dead!\n");
+            Entry = pti->DispatchingMessagesHead.Flink;
+            while (Entry != &pti->DispatchingMessagesHead)
+            {
+               if ((PUSER_SENT_MESSAGE) CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, DispatchingListEntry)
+                     == Message)
+               {
+                  Message->CompletionEvent = NULL;
+                  Message->Result = NULL;
+                  RemoveEntryList(&Message->DispatchingListEntry);
+                  Message->DispatchingListEntry.Flink = NULL;
+                  break;
+               }
+               Entry = Entry->Flink;
+            }
+         }
          while (co_MsqDispatchOneSentMessage(pti))
             ;
       }
-      while (NT_SUCCESS(WaitStatus) && STATUS_WAIT_0 != WaitStatus);
+      while (NT_SUCCESS(WaitStatus) && WaitStatus == STATUS_WAIT_1);
    }
 
    if(WaitStatus != STATUS_TIMEOUT)
-      *uResult = (STATUS_WAIT_0 == WaitStatus ? Result : -1);
+      if (uResult) *uResult = (STATUS_WAIT_0 == WaitStatus ? Result : -1);
 
    return WaitStatus;
 }
@@ -1230,6 +1212,12 @@ MsqPostMessage(PTHREADINFO pti,
    PUSER_MESSAGE Message;
    PUSER_MESSAGE_QUEUE MessageQueue;
 
+   if ( pti->TIF_flags & TIF_INCLEANUP || pti->MessageQueue->QF_flags & QF_INDESTROY )
+   {
+      ERR("Post Msg; Thread or Q is Dead!\n");
+      return;
+   }
+
    if(!(Message = MsqCreateMessage(Msg)))
    {
       return;
@@ -1239,6 +1227,7 @@ MsqPostMessage(PTHREADINFO pti,
 
    if (dwQEvent)
    {
+       ERR("Post Msg; System Qeued Event Message!\n");
        InsertHeadList(&pti->PostedMessagesListHead,
                       &Message->ListEntry);
    }
@@ -1253,10 +1242,11 @@ MsqPostMessage(PTHREADINFO pti,
                       &Message->ListEntry);
    }
 
+   if (Msg->message == WM_HOTKEY) MessageBits |= QS_HOTKEY; // Justin Case, just set it.
    Message->dwQEvent = dwQEvent;
    Message->QS_Flags = MessageBits;
-   //Message->pti = pti; Fixed in ATI changes. See CORE-6551
-   MsqWakeQueue(pti, MessageBits, (MessageBits & QS_TIMER ? FALSE : TRUE));
+   Message->pti = pti;
+   MsqWakeQueue(pti, MessageBits, TRUE);
 }
 
 VOID FASTCALL
@@ -1303,7 +1293,7 @@ FASTCALL
 IntTrackMouseMove(PWND pwndTrack, PDESKTOP pDesk, PMSG msg, USHORT hittest)
 {
 //   PWND pwndTrack = IntChildrenWindowFromPoint(pwndMsg, msg->pt.x, msg->pt.y);
-   hittest = (USHORT)GetNCHitEx(pwndTrack, msg->pt); /// @todo WTF is this???
+//   hittest = (USHORT)GetNCHitEx(pwndTrack, msg->pt); /// @todo WTF is this???
 
    if ( pDesk->spwndTrack != pwndTrack || // Change with tracking window or
         msg->message != WM_MOUSEMOVE   || // Mouse click changes or
@@ -1359,7 +1349,7 @@ BOOL co_IntProcessMouseMessage(MSG* msg, BOOL* RemoveMessages, UINT first, UINT
     USHORT hittest;
     EVENTMSG event;
     MOUSEHOOKSTRUCT hook;
-    BOOL eatMsg;
+    BOOL eatMsg = FALSE;
 
     PWND pwndMsg, pwndDesktop;
     PUSER_MESSAGE_QUEUE MessageQueue;
@@ -1384,12 +1374,11 @@ BOOL co_IntProcessMouseMessage(MSG* msg, BOOL* RemoveMessages, UINT first, UINT
         if (pwndMsg) UserReferenceObject(pwndMsg);
     }
     else
-    {   // Fix wine Msg test_HTTRANSPARENT. Start with a NULL window.
-        // http://www.winehq.org/pipermail/wine-patches/2012-August/116776.html
-        pwndMsg = co_WinPosWindowFromPoint(NULL, &msg->pt, &hittest);
+    {
+        pwndMsg = co_WinPosWindowFromPoint(NULL, &msg->pt, &hittest, FALSE);//TRUE);
     }
 
-    TRACE("Got mouse message for 0x%x, hittest: 0x%x\n", msg->hwnd, hittest );
+    TRACE("Got mouse message for %p, hittest: 0x%x\n", msg->hwnd, hittest);
 
     if (pwndMsg == NULL || pwndMsg->head.pti != pti)
     {
@@ -1409,10 +1398,6 @@ BOOL co_IntProcessMouseMessage(MSG* msg, BOOL* RemoveMessages, UINT first, UINT
 
     msg->hwnd = UserHMGetHandle(pwndMsg);
 
-#if 0
-    if (!check_hwnd_filter( msg, hwnd_filter )) RETURN(FALSE);
-#endif
-
     pt = msg->pt;
     message = msg->message;
     /* Note: windows has no concept of a non-client wheel message */
@@ -1540,7 +1525,7 @@ BOOL co_IntProcessMouseMessage(MSG* msg, BOOL* RemoveMessages, UINT first, UINT
         hook.dwExtraInfo  = 0 /* extra_info */ ;
         co_HOOK_CallHooks( WH_CBT, HCBT_CLICKSKIPPED, message, (LPARAM)&hook );
 
-        ERR("WH_MOUSE dorpped mouse message!\n");
+        ERR("WH_MOUSE dropped mouse message!\n");
 
         /* Remove and skip message */
         *RemoveMessages = TRUE;
@@ -1564,8 +1549,6 @@ BOOL co_IntProcessMouseMessage(MSG* msg, BOOL* RemoveMessages, UINT first, UINT
         RETURN(TRUE);
     }
 
-    eatMsg = FALSE;
-
     if ((msg->message == WM_LBUTTONDOWN) ||
         (msg->message == WM_RBUTTONDOWN) ||
         (msg->message == WM_MBUTTONDOWN) ||
@@ -1582,10 +1565,7 @@ BOOL co_IntProcessMouseMessage(MSG* msg, BOOL* RemoveMessages, UINT first, UINT
         if (pwndMsg != MessageQueue->spwndActive)
         {
             PWND pwndTop = pwndMsg;
-            while (pwndTop && ((pwndTop->style & (WS_POPUP|WS_CHILD)) == WS_CHILD))
-            {
-                pwndTop = pwndTop->spwndParent;
-            }
+            pwndTop = IntGetNonChildAncestor(pwndTop);
 
             if (pwndTop && pwndTop != pwndDesktop)
             {
@@ -1795,6 +1775,7 @@ co_MsqPeekHardwareMessage(IN PTHREADINFO pti,
         if (IsListEmpty(CurrentEntry)) break;
         if (!CurrentMessage) break;
         CurrentEntry = CurrentMessage->ListEntry.Flink;
+        if (!CurrentEntry) break; //// Fix CORE-6734 reported crash.
 /*
  MSDN:
  1: any window that belongs to the current thread, and any messages on the current thread's message queue whose hwnd value is NULL.
@@ -1826,8 +1807,7 @@ co_MsqPeekHardwareMessage(IN PTHREADINFO pti,
               break;
            }
         }
-        CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
-                                          ListEntry);
+        CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, ListEntry);
     }
     while(CurrentEntry != ListHead);
 
@@ -1854,7 +1834,7 @@ MsqPeekMessage(IN PTHREADINFO pti,
    ListHead = &pti->PostedMessagesListHead;
 
    if (IsListEmpty(CurrentEntry)) return FALSE;
-   
+
    CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
                                          ListEntry);
    do
@@ -1929,9 +1909,8 @@ HungAppSysTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
 BOOLEAN FASTCALL
 MsqInitializeMessageQueue(PTHREADINFO pti, PUSER_MESSAGE_QUEUE MessageQueue)
 {
-   MessageQueue->ptiOwner = pti;
    MessageQueue->CaretInfo = (PTHRDCARETINFO)(MessageQueue + 1);
-   InitializeListHead(&MessageQueue->HardwareMessagesListHead);
+   InitializeListHead(&MessageQueue->HardwareMessagesListHead); // Keep here!
    MessageQueue->spwndFocus = NULL;
    MessageQueue->iCursorLevel = 0;
    MessageQueue->CursorObject = NULL;
@@ -1949,7 +1928,7 @@ MsqCleanupThreadMsgs(PTHREADINFO pti)
    PLIST_ENTRY CurrentEntry;
    PUSER_MESSAGE CurrentMessage;
    PUSER_SENT_MESSAGE CurrentSentMessage;
-   
+
    /* cleanup posted messages */
    while (!IsListEmpty(&pti->PostedMessagesListHead))
    {
@@ -1985,7 +1964,7 @@ MsqCleanupThreadMsgs(PTHREADINFO pti)
          if (CurrentSentMessage->Msg.lParam)
             ExFreePool((PVOID)CurrentSentMessage->Msg.lParam);
       }
-      
+
       /* free the message */
       ExFreePool(CurrentSentMessage);
    }
@@ -2048,16 +2027,16 @@ MsqCleanupThreadMsgs(PTHREADINFO pti)
    pti->nCntsQBits[QSRosPostMessage] = 0;
    pti->nCntsQBits[QSRosSendMessage] = 0;
    pti->nCntsQBits[QSRosHotKey] = 0;
-
+   pti->nCntsQBits[QSRosEvent] = 0;
 }
+
 VOID FASTCALL
 MsqCleanupMessageQueue(PTHREADINFO pti)
 {
    PUSER_MESSAGE_QUEUE MessageQueue;
 
    MessageQueue = pti->MessageQueue;
-  MessageQueue->cThreads--;
+   MessageQueue->cThreads--;
 
    if (MessageQueue->cThreads)
    {
@@ -2082,6 +2061,7 @@ MsqCleanupMessageQueue(PTHREADINFO pti)
            IntGetSysCursorInfo()->CurrentCursorObject = NULL;
        }
 
+       ERR("DereferenceObject pCursor\n");
        UserDereferenceObject(pCursor);
    }