* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Win32k subsystem
* PURPOSE: Message queues
- * FILE: subsystems/win32/win32k/ntuser/msgqueue.c
+ * FILE: win32ss/user/ntuser/msgqueue.c
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
Alexandre Julliard
Maarten Lankhorst
/* GLOBALS *******************************************************************/
static PPAGED_LOOKASIDE_LIST pgMessageLookasideList;
+static PPAGED_LOOKASIDE_LIST pgSendMsgLookasideList;
+INT PostMsgCount = 0;
+INT SendMsgCount = 0;
PUSER_MESSAGE_QUEUE gpqCursor;
+ULONG_PTR gdwMouseMoveExtraInfo = 0;
+DWORD gdwMouseMoveTimeStamp = 0;
+LIST_ENTRY usmList;
/* FUNCTIONS *****************************************************************/
NTAPI
MsqInitializeImpl(VOID)
{
- pgMessageLookasideList = ExAllocatePoolWithTag(NonPagedPool, sizeof(PAGED_LOOKASIDE_LIST), TAG_USRMSG);
- if(!pgMessageLookasideList)
- return STATUS_NO_MEMORY;
+ // Setup Post Messages
+ pgMessageLookasideList = ExAllocatePoolWithTag(NonPagedPool, sizeof(PAGED_LOOKASIDE_LIST), TAG_USRMSG);
+ if (!pgMessageLookasideList)
+ return STATUS_NO_MEMORY;
ExInitializePagedLookasideList(pgMessageLookasideList,
NULL,
NULL,
sizeof(USER_MESSAGE),
TAG_USRMSG,
256);
+ // Setup Send Messages
+ pgSendMsgLookasideList = ExAllocatePoolWithTag(NonPagedPool, sizeof(PAGED_LOOKASIDE_LIST), TAG_USRMSG);
+ if (!pgSendMsgLookasideList)
+ return STATUS_NO_MEMORY;
+ ExInitializePagedLookasideList(pgSendMsgLookasideList,
+ NULL,
+ NULL,
+ 0,
+ sizeof(USER_SENT_MESSAGE),
+ TAG_USRMSG,
+ 16);
- return(STATUS_SUCCESS);
-}
-
-PWND FASTCALL
-IntChildrenWindowFromPoint(PWND pWndTop, INT x, INT y)
-{
- PWND pWnd, pWndChild;
-
- if ( !pWndTop )
- {
- pWndTop = UserGetDesktopWindow();
- if ( !pWndTop ) return NULL;
- }
-
- if (!(pWndTop->style & WS_VISIBLE)) return NULL;
- if ((pWndTop->style & WS_DISABLED)) return NULL;
- if (!IntPtInWindow(pWndTop, x, y)) return NULL;
-
- if (RECTL_bPointInRect(&pWndTop->rcClient, x, y))
- {
- for (pWnd = pWndTop->spwndChild;
- pWnd != NULL;
- pWnd = pWnd->spwndNext)
- {
- if (pWnd->state2 & WNDS2_INDESTROY || pWnd->state & WNDS_DESTROYED )
- {
- TRACE("The Window is in DESTROY!\n");
- continue;
- }
-
- pWndChild = IntChildrenWindowFromPoint(pWnd, x, y);
+ InitializeListHead(&usmList);
- if (pWndChild)
- {
- return pWndChild;
- }
- }
- }
- return pWndTop;
+ return(STATUS_SUCCESS);
}
PWND FASTCALL
continue;
}
- if ((pWnd->style & WS_VISIBLE) && IntPtInWindow(pWnd, x, y))
+ if ((pWnd->style & WS_VISIBLE) &&
+ (pWnd->ExStyle & (WS_EX_LAYERED|WS_EX_TRANSPARENT)) != (WS_EX_LAYERED|WS_EX_TRANSPARENT) &&
+ IntPtInWindow(pWnd, x, y))
return pWnd;
}
pti = PsGetCurrentThreadWin32Thread();
MessageQueue = pti->MessageQueue;
- /* Get the screen DC */
- if(!(hdcScreen = IntGetScreenDC()))
- {
- return NULL;
- }
-
OldCursor = MessageQueue->CursorObject;
/* Check if cursors are different */
if (MessageQueue->iCursorLevel < 0)
return OldCursor;
+ // Fixes the error message "Not the same cursor!".
+ if (gpqCursor == NULL)
+ {
+ gpqCursor = MessageQueue;
+ }
+
/* Update cursor if this message queue controls it */
pWnd = IntTopLevelWindowFromPoint(gpsi->ptCursor.x, gpsi->ptCursor.y);
if (pWnd && pWnd->head.pti->MessageQueue == MessageQueue)
{
+ /* Get the screen DC */
+ if (!(hdcScreen = IntGetScreenDC()))
+ {
+ return NULL;
+ }
+
if (NewCursor)
{
/* Call GDI to set the new screen cursor */
-#ifdef NEW_CURSORICON
PCURICON_OBJECT CursorFrame = NewCursor;
if(NewCursor->CURSORF_flags & CURSORF_ACON)
{
gpsi->ptCursor.x,
gpsi->ptCursor.y,
CursorFrame->hbmAlpha ? SPS_ALPHA : 0);
-#else
- GreSetPointerShape(hdcScreen,
- NewCursor->IconInfo.hbmMask,
- NewCursor->IconInfo.hbmColor,
- NewCursor->IconInfo.xHotspot,
- NewCursor->IconInfo.yHotspot,
- gpsi->ptCursor.x,
- gpsi->ptCursor.y,
- 0);
-#endif
}
else /* Note: OldCursor != NewCursor so we have to hide cursor */
{
}
}
+/*
+ Get down key states from the queue of prior processed input message key states.
+
+ This fixes the left button dragging on the desktop and release sticking outline issue.
+ USB Tablet pointer seems to stick the most and leaves the box outline displayed.
+ */
+WPARAM FASTCALL
+MsqGetDownKeyState(PUSER_MESSAGE_QUEUE MessageQueue)
+{
+ WPARAM ret = 0;
+
+ if (gspv.bMouseBtnSwap)
+ {
+ if (IS_KEY_DOWN(MessageQueue->afKeyState, VK_RBUTTON)) ret |= MK_LBUTTON;
+ if (IS_KEY_DOWN(MessageQueue->afKeyState, VK_LBUTTON)) ret |= MK_RBUTTON;
+ }
+ else
+ {
+ if (IS_KEY_DOWN(MessageQueue->afKeyState, VK_LBUTTON)) ret |= MK_LBUTTON;
+ if (IS_KEY_DOWN(MessageQueue->afKeyState, VK_RBUTTON)) ret |= MK_RBUTTON;
+ }
+
+ if (IS_KEY_DOWN(MessageQueue->afKeyState, VK_MBUTTON)) ret |= MK_MBUTTON;
+ if (IS_KEY_DOWN(MessageQueue->afKeyState, VK_SHIFT)) ret |= MK_SHIFT;
+ if (IS_KEY_DOWN(MessageQueue->afKeyState, VK_CONTROL)) ret |= MK_CONTROL;
+ if (IS_KEY_DOWN(MessageQueue->afKeyState, VK_XBUTTON1)) ret |= MK_XBUTTON1;
+ if (IS_KEY_DOWN(MessageQueue->afKeyState, VK_XBUTTON2)) ret |= MK_XBUTTON2;
+ return ret;
+}
+
HANDLE FASTCALL
IntMsqSetWakeMask(DWORD WakeMask)
{
VOID FASTCALL
ClearMsgBitsMask(PTHREADINFO pti, UINT MessageBits)
{
- PUSER_MESSAGE_QUEUE Queue;
UINT ClrMask = 0;
- Queue = pti->MessageQueue;
-
if (MessageBits & QS_KEY)
{
if (--pti->nCntsQBits[QSRosKey] == 0) ClrMask |= QS_KEY;
}
- if (MessageBits & QS_MOUSEMOVE) // ReactOS hard coded.
+ if (MessageBits & QS_MOUSEMOVE)
{ // Account for tracking mouse moves..
- if (--pti->nCntsQBits[QSRosMouseMove] == 0) ClrMask |= QS_MOUSEMOVE;
- // Handle mouse move bits here.
- if (Queue->MouseMoved) ClrMask |= QS_MOUSEMOVE;
+ if (pti->nCntsQBits[QSRosMouseMove])
+ {
+ pti->nCntsQBits[QSRosMouseMove] = 0; // Throttle down count. Up to > 3:1 entries are ignored.
+ ClrMask |= QS_MOUSEMOVE;
+ }
}
if (MessageBits & QS_MOUSEBUTTON)
{
ClearMsgBitsMask(pti, QS_PAINT);
}
+/*
+ Post the move or update the message still pending to be processed.
+ Do not overload the queue with mouse move messages.
+ */
+VOID FASTCALL
+MsqPostMouseMove(PTHREADINFO pti, MSG* Msg, LONG_PTR ExtraInfo)
+{
+ PUSER_MESSAGE Message;
+ PLIST_ENTRY ListHead;
+ PUSER_MESSAGE_QUEUE MessageQueue = pti->MessageQueue;
+
+ ListHead = &MessageQueue->HardwareMessagesListHead;
+
+ // Do nothing if empty.
+ if (!IsListEmpty(ListHead->Flink))
+ {
+ // Look at the end of the list,
+ Message = CONTAINING_RECORD(ListHead->Blink, USER_MESSAGE, ListEntry);
+
+ // If the mouse move message is existing on the list,
+ if (Message->Msg.message == WM_MOUSEMOVE)
+ {
+ // Overwrite the message with updated data!
+ Message->Msg = *Msg;
+
+ MsqWakeQueue(pti, QS_MOUSEMOVE, TRUE);
+ return;
+ }
+ }
+
+ MsqPostMessage(pti, Msg, TRUE, QS_MOUSEMOVE, 0, ExtraInfo);
+}
+
+/*
+ Bring together the mouse move message.
+ Named "Coalesce" from Amine email ;^) (jt).
+ */
VOID FASTCALL
-MsqPostMouseMove(PTHREADINFO pti, MSG* Msg)
+IntCoalesceMouseMove(PTHREADINFO pti)
{
- pti->MessageQueue->MouseMoveMsg = *Msg;
- pti->MessageQueue->MouseMoved = TRUE;
- MsqWakeQueue(pti, QS_MOUSEMOVE, TRUE);
+ MSG Msg;
+ LARGE_INTEGER LargeTickCount;
+
+ // Force time stamp to update, keeping message time in sync.
+ if (gdwMouseMoveTimeStamp == 0)
+ {
+ KeQueryTickCount(&LargeTickCount);
+ gdwMouseMoveTimeStamp = MsqCalculateMessageTime(&LargeTickCount);
+ }
+
+ // Build mouse move message.
+ Msg.hwnd = NULL;
+ Msg.message = WM_MOUSEMOVE;
+ Msg.wParam = 0;
+ Msg.lParam = MAKELONG(gpsi->ptCursor.x, gpsi->ptCursor.y);
+ Msg.time = gdwMouseMoveTimeStamp;
+ Msg.pt = gpsi->ptCursor;
+
+ // Post the move.
+ MsqPostMouseMove(pti, &Msg, gdwMouseMoveExtraInfo);
+
+ // Zero the time stamp.
+ gdwMouseMoveTimeStamp = 0;
+
+ // Clear flag since the move was posted.
+ pti->MessageQueue->QF_flags &= ~QF_MOUSEMOVED;
}
VOID FASTCALL
{
pti = pwnd->head.pti;
MessageQueue = pti->MessageQueue;
- // MessageQueue->ptiMouse = pti;
- if ( pti->TIF_flags & TIF_INCLEANUP || MessageQueue->QF_flags & QF_INDESTROY)
+ if (MessageQueue->QF_flags & QF_INDESTROY)
{
- ERR("Mouse is over the Window Thread is Dead!\n");
+ ERR("Mouse is over a Window with a Dead Message Queue!\n");
return;
}
+ // Check to see if this is attached.
+ if ( pti != MessageQueue->ptiMouse &&
+ MessageQueue->cThreads > 1 )
+ {
+ // Set the send pti to the message queue mouse pti.
+ pti = MessageQueue->ptiMouse;
+ }
+
if (Msg->message == WM_MOUSEMOVE)
{
/* Check if cursor should be visible */
if(CurInfo->CurrentCursorObject != MessageQueue->CursorObject)
{
/* Call GDI to set the new screen cursor */
-#ifdef NEW_CURSORICON
GreSetPointerShape(hdcScreen,
MessageQueue->CursorObject->hbmAlpha ?
NULL : MessageQueue->CursorObject->hbmMask,
gpsi->ptCursor.x,
gpsi->ptCursor.y,
MessageQueue->CursorObject->hbmAlpha ? SPS_ALPHA : 0);
-#else
- GreSetPointerShape(hdcScreen,
- MessageQueue->CursorObject->IconInfo.hbmMask,
- MessageQueue->CursorObject->IconInfo.hbmColor,
- MessageQueue->CursorObject->IconInfo.xHotspot,
- MessageQueue->CursorObject->IconInfo.yHotspot,
- gpsi->ptCursor.x,
- gpsi->ptCursor.y,
- 0);
-#endif
+
} else
GreMovePointer(hdcScreen, Msg->pt.x, Msg->pt.y);
}
- /* Check if w have to hide cursor */
+ /* Check if we have to hide cursor */
else if (CurInfo->ShowingCursor >= 0)
GreMovePointer(hdcScreen, -1, -1);
gpqCursor = MessageQueue;
/* Mouse move is a special case */
- MsqPostMouseMove(pti, Msg);
+ MessageQueue->QF_flags |= QF_MOUSEMOVED;
+ gdwMouseMoveExtraInfo = dwExtraInfo;
+ gdwMouseMoveTimeStamp = Msg->time;
+ MsqWakeQueue(pti, QS_MOUSEMOVE, TRUE);
}
else
{
{
// ERR("ptiLastInput is set\n");
// ptiLastInput = pti; // Once this is set during Reboot or Shutdown, this prevents the exit window having foreground.
+ // Find all the Move Mouse calls and fix mouse set active focus issues......
+ }
+
+ // Post mouse move before posting mouse buttons, keep it in sync.
+ if (pti->MessageQueue->QF_flags & QF_MOUSEMOVED)
+ {
+ IntCoalesceMouseMove(pti);
}
+
TRACE("Posting mouse message to hwnd=%p!\n", UserHMGetHandle(pwnd));
- MsqPostMessage(pti, Msg, TRUE, QS_MOUSEBUTTON, 0);
+ MsqPostMessage(pti, Msg, TRUE, QS_MOUSEBUTTON, 0, dwExtraInfo);
}
}
else if (hdcScreen)
return NULL;
}
+ RtlZeroMemory(Message, sizeof(*Message));
RtlMoveMemory(&Message->Msg, Msg, sizeof(MSG));
-
+ PostMsgCount++;
return Message;
}
VOID FASTCALL
MsqDestroyMessage(PUSER_MESSAGE Message)
{
+ TRACE("Post Destroy %d\n",PostMsgCount)
+ if (Message->pti == NULL)
+ {
+ ERR("Double Free Message\n");
+ return;
+ }
+ RemoveEntryList(&Message->ListEntry);
+ Message->pti = NULL;
ExFreeToPagedLookasideList(pgMessageLookasideList, Message);
+ PostMsgCount--;
+}
+
+PUSER_SENT_MESSAGE FASTCALL
+AllocateUserMessage(BOOL KEvent)
+{
+ PUSER_SENT_MESSAGE Message;
+
+ if(!(Message = ExAllocateFromPagedLookasideList(pgSendMsgLookasideList)))
+ {
+ ERR("AllocateUserMessage(): Not enough memory to allocate a message");
+ return NULL;
+ }
+ RtlZeroMemory(Message, sizeof(USER_SENT_MESSAGE));
+
+ if (KEvent)
+ {
+ Message->pkCompletionEvent = &Message->CompletionEvent;
+
+ KeInitializeEvent(Message->pkCompletionEvent, NotificationEvent, FALSE);
+ }
+ SendMsgCount++;
+ TRACE("AUM pti %p msg %p\n",PsGetCurrentThreadWin32Thread(),Message);
+ return Message;
+}
+
+VOID FASTCALL
+FreeUserMessage(PUSER_SENT_MESSAGE Message)
+{
+ Message->pkCompletionEvent = NULL;
+
+ /* Remove it from the list */
+ RemoveEntryList(&Message->ListEntry);
+
+ ExFreeToPagedLookasideList(pgSendMsgLookasideList, Message);
+ SendMsgCount--;
+}
+
+VOID APIENTRY
+MsqRemoveWindowMessagesFromQueue(PWND Window)
+{
+ PTHREADINFO pti;
+ PUSER_SENT_MESSAGE SentMessage;
+ PUSER_MESSAGE PostedMessage;
+ PLIST_ENTRY CurrentEntry, ListHead;
+
+ ASSERT(Window);
+
+ pti = Window->head.pti;
+
+ /* remove the posted messages for this window */
+ CurrentEntry = pti->PostedMessagesListHead.Flink;
+ ListHead = &pti->PostedMessagesListHead;
+ while (CurrentEntry != ListHead)
+ {
+ PostedMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, ListEntry);
+
+ if (PostedMessage->Msg.hwnd == Window->head.h)
+ {
+ if (PostedMessage->Msg.message == WM_QUIT && pti->QuitPosted == 0)
+ {
+ pti->QuitPosted = 1;
+ pti->exitCode = PostedMessage->Msg.wParam;
+ }
+ ClearMsgBitsMask(pti, PostedMessage->QS_Flags);
+ MsqDestroyMessage(PostedMessage);
+ CurrentEntry = pti->PostedMessagesListHead.Flink;
+ }
+ else
+ {
+ CurrentEntry = CurrentEntry->Flink;
+ }
+ }
+
+ /* remove the sent messages for this window */
+ CurrentEntry = pti->SentMessagesListHead.Flink;
+ ListHead = &pti->SentMessagesListHead;
+ while (CurrentEntry != ListHead)
+ {
+ SentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE, ListEntry);
+
+ if(SentMessage->Msg.hwnd == Window->head.h)
+ {
+ ERR("Remove Window Messages %p From Sent Queue\n",SentMessage);
+#if 0 // Should mark these as invalid and allow the rest clean up, so far no harm by just commenting out. See CORE-9210.
+ ClearMsgBitsMask(pti, SentMessage->QS_Flags);
+
+ /* wake the sender's thread */
+ if (SentMessage->pkCompletionEvent != NULL)
+ {
+ KeSetEvent(SentMessage->pkCompletionEvent, IO_NO_INCREMENT, FALSE);
+ }
+
+ if (SentMessage->HasPackedLParam)
+ {
+ if (SentMessage->Msg.lParam)
+ ExFreePool((PVOID)SentMessage->Msg.lParam);
+ }
+
+ /* free the message */
+ FreeUserMessage(SentMessage);
+
+ CurrentEntry = pti->SentMessagesListHead.Flink;
+#endif
+ CurrentEntry = CurrentEntry->Flink;
+ }
+ else
+ {
+ CurrentEntry = CurrentEntry->Flink;
+ }
+ }
}
BOOLEAN FASTCALL
-co_MsqDispatchOneSentMessage(PTHREADINFO pti)
+co_MsqDispatchOneSentMessage(
+ _In_ PTHREADINFO pti)
{
PUSER_SENT_MESSAGE SaveMsg, Message;
PLIST_ENTRY Entry;
BOOL Ret;
LRESULT Result = 0;
+ ASSERT(pti == PsGetCurrentThreadWin32Thread());
+
if (IsListEmpty(&pti->SentMessagesListHead))
{
return(FALSE);
Entry = RemoveHeadList(&pti->SentMessagesListHead);
Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
+ // Signal this message is being processed.
+ Message->flags |= SMF_RECEIVERBUSY|SMF_RECEIVEDMESSAGE;
+
SaveMsg = pti->pusmCurrent;
pti->pusmCurrent = Message;
pti->pcti->CTI_flags |= CTI_INSENDMESSAGE; // Let the user know...
}
- /* insert it to the list of messages that are currently dispatched by this
- message queue */
- InsertTailList(&pti->LocalDispatchingMessagesHead,
- &Message->ListEntry);
+ /* Now insert it to the global list of messages that can be removed Justin Case there's Trouble */
+ InsertTailList(&usmList, &Message->ListEntry);
ClearMsgBitsMask(pti, Message->QS_Flags);
if (Message->HookMessage == MSQ_ISHOOK)
{ // Direct Hook Call processor
- Result = co_CallHook( Message->Msg.message, // HookId
+ Result = co_CallHook( Message->Msg.message, // HookId
(INT)(INT_PTR)Message->Msg.hwnd, // Code
Message->Msg.wParam,
Message->Msg.lParam);
}
- else if (Message->HookMessage == MSQ_ISEVENT)
- { // Direct Event Call processor
- Result = co_EVENT_CallEvents( Message->Msg.message,
- Message->Msg.hwnd,
- Message->Msg.wParam,
- Message->Msg.lParam);
- }
else if(Message->HookMessage == MSQ_INJECTMODULE)
{
Result = IntLoadHookModule(Message->Msg.message,
/* The message has not been processed yet, reinsert it. */
RemoveEntryList(&Message->ListEntry);
InsertTailList(&Message->ptiCallBackSender->SentMessagesListHead, &Message->ListEntry);
- TRACE("Callback Message not processed yet. Requeuing the message\n");
+ // List is occupied need to set the bit.
+ MsqWakeQueue(Message->ptiCallBackSender, QS_SENDMESSAGE, TRUE);
+ ERR("Callback Message not processed yet. Requeuing the message\n"); //// <---- Need to see if this happens.
Ret = FALSE;
goto Exit;
}
Message->Msg.lParam);
}
- /* remove the message from the local dispatching list, because it doesn't need
- to be cleaned up on thread termination anymore */
- RemoveEntryList(&Message->ListEntry);
-
/* If the message is a callback, insert it in the callback senders MessageQueue */
if (Message->CompletionCallback)
{
Message->QS_Flags |= QS_SMRESULT;
/* insert it in the callers message queue */
+ RemoveEntryList(&Message->ListEntry);
InsertTailList(&Message->ptiCallBackSender->SentMessagesListHead, &Message->ListEntry);
MsqWakeQueue(Message->ptiCallBackSender, QS_SENDMESSAGE, TRUE);
}
goto Exit;
}
- /* remove the message from the dispatching list if needed, so lock the sender's message queue */
- if (Message->ptiSender)
- {
- if (Message->DispatchingListEntry.Flink != NULL)
- {
- /* only remove it from the dispatching list if not already removed by a timeout */
- RemoveEntryList(&Message->DispatchingListEntry);
- }
- }
- /* still keep the sender's message queue locked, so the sender can't exit the
- MsqSendMessage() function (if timed out) */
-
+ // Retrieve the result from callback.
if (Message->QS_Flags & QS_SMRESULT)
{
Result = Message->lResult;
}
/* Let the sender know the result. */
- if (Message->Result != NULL)
- {
- *Message->Result = Result;
- }
+ Message->lResult = Result;
- if (Message->HasPackedLParam == TRUE)
+ if (Message->HasPackedLParam)
{
if (Message->Msg.lParam)
ExFreePool((PVOID)Message->Msg.lParam);
}
+ // Clear busy signal.
+ Message->flags &= ~SMF_RECEIVERBUSY;
+
/* Notify the sender. */
- if (Message->CompletionEvent != NULL)
+ if (Message->pkCompletionEvent != NULL)
{
- KeSetEvent(Message->CompletionEvent, IO_NO_INCREMENT, FALSE);
+ KeSetEvent(Message->pkCompletionEvent, IO_NO_INCREMENT, FALSE);
}
/* free the message */
- ExFreePoolWithTag(Message, TAG_USRMSG);
+ if (Message->flags & SMF_RECEIVERFREE)
+ {
+ TRACE("Receiver Freeing Message %p\n",Message);
+ FreeUserMessage(Message);
+ }
+
Ret = TRUE;
Exit:
/* do not hangup on the user if this is reentering */
return Ret;
}
-VOID APIENTRY
-MsqRemoveWindowMessagesFromQueue(PWND Window)
-{
- PTHREADINFO pti;
- PUSER_SENT_MESSAGE SentMessage;
- PUSER_MESSAGE PostedMessage;
- PLIST_ENTRY CurrentEntry, ListHead;
-
- ASSERT(Window);
-
- pti = Window->head.pti;
-
- /* remove the posted messages for this window */
- CurrentEntry = pti->PostedMessagesListHead.Flink;
- ListHead = &pti->PostedMessagesListHead;
- while (CurrentEntry != ListHead)
- {
- PostedMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
- ListEntry);
- if (PostedMessage->Msg.hwnd == Window->head.h)
- {
- RemoveEntryList(&PostedMessage->ListEntry);
- ClearMsgBitsMask(pti, PostedMessage->QS_Flags);
- MsqDestroyMessage(PostedMessage);
- CurrentEntry = pti->PostedMessagesListHead.Flink;
- }
- else
- {
- CurrentEntry = CurrentEntry->Flink;
- }
- }
-
- /* remove the sent messages for this window */
- CurrentEntry = pti->SentMessagesListHead.Flink;
- ListHead = &pti->SentMessagesListHead;
- while (CurrentEntry != ListHead)
- {
- SentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE,
- ListEntry);
- if(SentMessage->Msg.hwnd == Window->head.h)
- {
- TRACE("Notify the sender and remove a message from the queue that had not been dispatched\n");
-
- RemoveEntryList(&SentMessage->ListEntry);
- ClearMsgBitsMask(pti, SentMessage->QS_Flags);
-
- /* Only if the message has a sender was the queue referenced */
- if ((SentMessage->ptiSender)
- && (SentMessage->DispatchingListEntry.Flink != NULL))
- {
- RemoveEntryList(&SentMessage->DispatchingListEntry);
- }
-
- /* wake the sender's thread */
- if (SentMessage->CompletionEvent != NULL)
- {
- KeSetEvent(SentMessage->CompletionEvent, IO_NO_INCREMENT, FALSE);
- }
-
- if (SentMessage->HasPackedLParam == TRUE)
- {
- if (SentMessage->Msg.lParam)
- ExFreePool((PVOID)SentMessage->Msg.lParam);
- }
-
- /* free the message */
- ExFreePoolWithTag(SentMessage, TAG_USRMSG);
-
- CurrentEntry = pti->SentMessagesListHead.Flink;
- }
- else
- {
- CurrentEntry = CurrentEntry->Flink;
- }
- }
-}
-
BOOL FASTCALL
co_MsqSendMessageAsync(PTHREADINFO ptiReceiver,
HWND hwnd,
PTHREADINFO ptiSender;
PUSER_SENT_MESSAGE Message;
- if(!(Message = ExAllocatePoolWithTag(NonPagedPool, sizeof(USER_SENT_MESSAGE), TAG_USRMSG)))
+ if(!(Message = AllocateUserMessage(FALSE)))
{
- ERR("MsqSendMessage(): Not enough memory to allocate a message");
+ ERR("MsqSendMessageAsync(): Not enough memory to allocate a message");
return FALSE;
}
Message->Msg.message = Msg;
Message->Msg.wParam = wParam;
Message->Msg.lParam = lParam;
- Message->CompletionEvent = NULL;
- Message->Result = 0;
- Message->lResult = 0;
+ Message->pkCompletionEvent = NULL; // No event needed.
Message->ptiReceiver = ptiReceiver;
- Message->ptiSender = NULL;
Message->ptiCallBackSender = ptiSender;
- Message->DispatchingListEntry.Flink = NULL;
Message->CompletionCallback = CompletionCallback;
Message->CompletionCallbackContext = CompletionCallbackContext;
Message->HookMessage = HookMessage;
Message->HasPackedLParam = HasPackedLParam;
Message->QS_Flags = QS_SENDMESSAGE;
+ Message->flags = SMF_RECEIVERFREE;
InsertTailList(&ptiReceiver->SentMessagesListHead, &Message->ListEntry);
MsqWakeQueue(ptiReceiver, QS_SENDMESSAGE, TRUE);
NTSTATUS FASTCALL
co_MsqSendMessage(PTHREADINFO ptirec,
- HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam,
- UINT uTimeout, BOOL Block, INT HookMessage,
+ HWND Wnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam,
+ UINT uTimeout,
+ BOOL Block,
+ INT HookMessage,
ULONG_PTR *uResult)
{
PTHREADINFO pti;
- PUSER_SENT_MESSAGE Message;
- KEVENT CompletionEvent;
+ PUSER_SENT_MESSAGE SaveMsg, Message;
NTSTATUS WaitStatus;
LARGE_INTEGER Timeout;
PLIST_ENTRY Entry;
PWND pWnd;
+ BOOLEAN SwapStateEnabled;
LRESULT Result = 0; //// Result could be trashed. ////
pti = PsGetCurrentThreadWin32Thread();
ASSERT(ptirec->pcti); // Send must have a client side to receive it!!!!
/* Don't send from or to a dying thread */
- if (pti->TIF_flags & TIF_INCLEANUP || ptirec->TIF_flags & TIF_INCLEANUP)
- {
- if (uResult) *uResult = -1;
- ERR("MsqSM: Current pti %lu or Rec pti %lu\n", pti->TIF_flags & TIF_INCLEANUP, ptirec->TIF_flags & TIF_INCLEANUP);
- return STATUS_UNSUCCESSFUL;
- }
+ if (pti->TIF_flags & TIF_INCLEANUP || ptirec->TIF_flags & TIF_INCLEANUP)
+ {
+ // Unless we are dying and need to tell our parents.
+ if (pti->TIF_flags & TIF_INCLEANUP && !(ptirec->TIF_flags & TIF_INCLEANUP))
+ {
+ // Parent notify is the big one. Fire and forget!
+ TRACE("Send message from dying thread %u\n", Msg);
+ co_MsqSendMessageAsync(ptirec, Wnd, Msg, wParam, lParam, NULL, 0, FALSE, HookMessage);
+ }
+ if (uResult) *uResult = -1;
+ TRACE("MsqSM: Msg %u Current pti %lu or Rec pti %lu\n", Msg, pti->TIF_flags & TIF_INCLEANUP, ptirec->TIF_flags & TIF_INCLEANUP);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if (IsThreadSuspended(ptirec))
+ {
+ ERR("Sending to Suspended Thread Msg %lx\n",Msg);
+ if (uResult) *uResult = -1;
+ return STATUS_UNSUCCESSFUL;
+ }
+ // Should we do the same for No Wait?
if ( HookMessage == MSQ_NORMAL )
{
pWnd = ValidateHwndNoErr(Wnd);
}
}
- if(!(Message = ExAllocatePoolWithTag(PagedPool, sizeof(USER_SENT_MESSAGE), TAG_USRMSG)))
+ if(!(Message = AllocateUserMessage(TRUE)))
{
- ERR("MsqSendMessage(): Not enough memory to allocate a message");
+ ERR("MsqSendMessage(): Not enough memory to allocate a message\n");
+ if (uResult) *uResult = -1;
return STATUS_INSUFFICIENT_RESOURCES;
}
- KeInitializeEvent(&CompletionEvent, NotificationEvent, FALSE);
-
- Timeout.QuadPart = (LONGLONG) uTimeout * (LONGLONG) -10000;
-
- /* FIXME: Increase reference counter of sender's message queue here */
+ Timeout.QuadPart = Int32x32To64(-10000,uTimeout); // Pass SMTO test with a TO of 0x80000000.
+ TRACE("Timeout val %lld\n",Timeout.QuadPart)
Message->Msg.hwnd = Wnd;
Message->Msg.message = Msg;
Message->Msg.wParam = wParam;
Message->Msg.lParam = lParam;
- Message->CompletionEvent = &CompletionEvent;
- Message->Result = &Result;
- Message->lResult = 0;
- Message->QS_Flags = 0;
Message->ptiReceiver = ptirec;
Message->ptiSender = pti;
- Message->ptiCallBackSender = NULL;
- Message->CompletionCallback = NULL;
- Message->CompletionCallbackContext = 0;
Message->HookMessage = HookMessage;
- Message->HasPackedLParam = FALSE;
+ Message->QS_Flags = QS_SENDMESSAGE;
- /* Add it to the list of pending messages */
- InsertTailList(&pti->DispatchingMessagesHead, &Message->DispatchingListEntry);
+ SaveMsg = pti->pusmSent;
+ pti->pusmSent = Message;
/* Queue it in the destination's message queue */
InsertTailList(&ptirec->SentMessagesListHead, &Message->ListEntry);
- Message->QS_Flags = QS_SENDMESSAGE;
MsqWakeQueue(ptirec, QS_SENDMESSAGE, TRUE);
- /* We can't access the Message anymore since it could have already been deleted! */
+ // First time in, turn off swapping of the stack.
+ if (pti->cEnterCount == 0)
+ {
+ SwapStateEnabled = KeSetKernelStackSwapEnable(FALSE);
+ }
+ pti->cEnterCount++;
- if(Block)
+ if (Block)
{
+ PVOID WaitObjects[2];
+
+ WaitObjects[0] = Message->pkCompletionEvent; // Wait 0
+ WaitObjects[1] = ptirec->pEThread; // Wait 1
+
UserLeaveCo();
- /* Don't process messages sent to the thread */
- WaitStatus = KeWaitForSingleObject(&CompletionEvent, UserRequest, UserMode,
- FALSE, (uTimeout ? &Timeout : NULL));
+ WaitStatus = KeWaitForMultipleObjects( 2,
+ WaitObjects,
+ WaitAny,
+ UserRequest,
+ UserMode,
+ FALSE,
+ (uTimeout ? &Timeout : NULL),
+ NULL );
UserEnterCo();
- if(WaitStatus == STATUS_TIMEOUT)
+ if (WaitStatus == STATUS_TIMEOUT)
{
/* Look up if the message has not yet dispatched, if so
make sure it can't pass a result and it must not set the completion event anymore */
Entry = ptirec->SentMessagesListHead.Flink;
while (Entry != &ptirec->SentMessagesListHead)
{
- if ((PUSER_SENT_MESSAGE) CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry)
- == Message)
+ if (CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry) == Message)
{
- /* We can access Message here, it's secure because the message queue is locked
- and the message is still hasn't been dispatched */
- Message->CompletionEvent = NULL;
- Message->Result = NULL;
+ Message->pkCompletionEvent = NULL;
+ RemoveEntryList(&Message->ListEntry);
+ ClearMsgBitsMask(ptirec, Message->QS_Flags);
+ InsertTailList(&usmList, &Message->ListEntry);
break;
}
Entry = Entry->Flink;
}
- /* Remove from the local dispatching list so the other thread knows,
- it can't pass a result and it must not set the completion event anymore */
- Entry = pti->DispatchingMessagesHead.Flink;
- while (Entry != &pti->DispatchingMessagesHead)
- {
- if ((PUSER_SENT_MESSAGE) CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, DispatchingListEntry)
- == Message)
- {
- /* We can access Message here, it's secure because the sender's message is locked
- and the message has definitely not yet been destroyed, otherwise it would
- have been removed from this list by the dispatching routine right after
- dispatching the message */
- Message->CompletionEvent = NULL;
- Message->Result = NULL;
- RemoveEntryList(&Message->DispatchingListEntry);
- Message->DispatchingListEntry.Flink = NULL;
- break;
- }
- Entry = Entry->Flink;
- }
-
- TRACE("MsqSendMessage (blocked) timed out 1\n");
+ ERR("MsqSendMessage (blocked) timed out 1 Status %lx\n", WaitStatus);
}
- while (co_MsqDispatchOneSentMessage(ptirec))
+ // Receiving thread passed on and left us hanging with issues still pending.
+ else if (WaitStatus == STATUS_WAIT_1)
+ {
+ ERR("Bk Receiving Thread woken up dead!\n");
+ Message->flags |= SMF_RECEIVERDIED;
+ }
+
+ while (co_MsqDispatchOneSentMessage(pti))
;
}
else
{
PVOID WaitObjects[3];
- WaitObjects[0] = &CompletionEvent; // Wait 0
- WaitObjects[1] = pti->pEventQueueServer; // Wait 1
- WaitObjects[2] = ptirec->pEThread; // Wait 2
+ WaitObjects[0] = Message->pkCompletionEvent; // Wait 0
+ WaitObjects[1] = pti->pEventQueueServer; // Wait 1
+ WaitObjects[2] = ptirec->pEThread; // Wait 2
do
{
UserLeaveCo();
- WaitStatus = KeWaitForMultipleObjects(3, WaitObjects, WaitAny, UserRequest,
- UserMode, FALSE, (uTimeout ? &Timeout : NULL), NULL);
+ WaitStatus = KeWaitForMultipleObjects( 3,
+ WaitObjects,
+ WaitAny,
+ UserRequest,
+ UserMode,
+ FALSE,
+ (uTimeout ? &Timeout : NULL),
+ NULL);
UserEnterCo();
- if(WaitStatus == STATUS_TIMEOUT)
+ if (WaitStatus == STATUS_TIMEOUT)
{
/* Look up if the message has not yet been dispatched, if so
make sure it can't pass a result and it must not set the completion event anymore */
Entry = ptirec->SentMessagesListHead.Flink;
while (Entry != &ptirec->SentMessagesListHead)
{
- if ((PUSER_SENT_MESSAGE) CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry)
- == Message)
+ if (CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry) == Message)
{
- /* We can access Message here, it's secure because the message queue is locked
- and the message is still hasn't been dispatched */
- Message->CompletionEvent = NULL;
- Message->Result = NULL;
+ Message->pkCompletionEvent = NULL;
+ RemoveEntryList(&Message->ListEntry);
+ ClearMsgBitsMask(ptirec, Message->QS_Flags);
+ InsertTailList(&usmList, &Message->ListEntry);
break;
}
Entry = Entry->Flink;
}
- /* Remove from the local dispatching list so the other thread knows,
- it can't pass a result and it must not set the completion event anymore */
- Entry = pti->DispatchingMessagesHead.Flink;
- while (Entry != &pti->DispatchingMessagesHead)
- {
- if ((PUSER_SENT_MESSAGE) CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, DispatchingListEntry)
- == Message)
- {
- /* We can access Message here, it's secure because the sender's message is locked
- and the message has definitely not yet been destroyed, otherwise it would
- have been removed from this list by the dispatching routine right after
- dispatching the message */
- Message->CompletionEvent = NULL;
- Message->Result = NULL;
- RemoveEntryList(&Message->DispatchingListEntry);
- Message->DispatchingListEntry.Flink = NULL;
- break;
- }
- Entry = Entry->Flink;
- }
-
- TRACE("MsqSendMessage timed out 2\n");
+ ERR("MsqSendMessage timed out 2 Status %lx\n", WaitStatus);
break;
}
// Receiving thread passed on and left us hanging with issues still pending.
- if ( WaitStatus == STATUS_WAIT_2 )
+ else 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;
- }
+ ERR("NB Receiving Thread woken up dead!\n");
+ Message->flags |= SMF_RECEIVERDIED;
+ break;
}
+
+ if (WaitStatus == STATUS_USER_APC) break;
+
while (co_MsqDispatchOneSentMessage(pti))
;
- }
- while (NT_SUCCESS(WaitStatus) && WaitStatus == STATUS_WAIT_1);
+ } while (WaitStatus == STATUS_WAIT_1);
+ }
+
+ // Count is nil, restore swapping of the stack.
+ if (--pti->cEnterCount == 0 )
+ {
+ KeSetKernelStackSwapEnable(SwapStateEnabled);
+ }
+
+ // Handle User APC
+ if (WaitStatus == STATUS_USER_APC)
+ {
+ // The current thread is dying!
+ TRACE("User APC\n");
+
+ // The Message will be on the Trouble list until Thread cleanup.
+ Message->flags |= SMF_SENDERDIED;
+
+ co_IntDeliverUserAPC();
+ ERR("User APC Returned\n"); // Should not see this message.
+ }
+
+ // Force this thread to wake up for the next go around.
+ KeSetEvent(pti->pEventQueueServer, IO_NO_INCREMENT, FALSE);
+
+ Result = Message->lResult;
+
+ // Determine whether this message is being processed or not.
+ if ((Message->flags & (SMF_RECEIVERBUSY|SMF_RECEIVEDMESSAGE)) != SMF_RECEIVEDMESSAGE)
+ {
+ Message->flags |= SMF_RECEIVERFREE;
+ }
+
+ if (!(Message->flags & SMF_RECEIVERFREE))
+ {
+ TRACE("Sender Freeing Message %p ptirec %p bit %d list empty %d\n",Message,ptirec,!!(ptirec->pcti->fsChangeBits & QS_SENDMESSAGE),IsListEmpty(&ptirec->SentMessagesListHead));
+ // Make it to this point, the message was received.
+ FreeUserMessage(Message);
}
- if(WaitStatus != STATUS_TIMEOUT)
- if (uResult) *uResult = (STATUS_WAIT_0 == WaitStatus ? Result : -1);
+ pti->pusmSent = SaveMsg;
+
+ TRACE("MSM Allocation Count %d Status %lx Result %d\n",SendMsgCount,WaitStatus,Result);
+
+ if (WaitStatus != STATUS_TIMEOUT)
+ {
+ if (uResult)
+ {
+ *uResult = (STATUS_WAIT_0 == WaitStatus ? Result : 0);
+ }
+ }
return WaitStatus;
}
MSG* Msg,
BOOLEAN HardwareMessage,
DWORD MessageBits,
- DWORD dwQEvent)
+ DWORD dwQEvent,
+ LONG_PTR ExtraInfo)
{
PUSER_MESSAGE Message;
PUSER_MESSAGE_QUEUE MessageQueue;
MessageQueue = pti->MessageQueue;
- if (dwQEvent)
- {
- ERR("Post Msg; System Qeued Event Message!\n");
- InsertHeadList(&pti->PostedMessagesListHead,
- &Message->ListEntry);
- }
- else if (!HardwareMessage)
+ if (!HardwareMessage)
{
- InsertTailList(&pti->PostedMessagesListHead,
- &Message->ListEntry);
+ InsertTailList(&pti->PostedMessagesListHead, &Message->ListEntry);
}
else
{
- InsertTailList(&MessageQueue->HardwareMessagesListHead,
- &Message->ListEntry);
+ InsertTailList(&MessageQueue->HardwareMessagesListHead, &Message->ListEntry);
}
if (Msg->message == WM_HOTKEY) MessageBits |= QS_HOTKEY; // Justin Case, just set it.
Message->dwQEvent = dwQEvent;
+ Message->ExtraInfo = ExtraInfo;
Message->QS_Flags = MessageBits;
Message->pti = pti;
MsqWakeQueue(pti, MessageBits, TRUE);
+ TRACE("Post Message %d\n",PostMsgCount);
}
VOID FASTCALL
}
}
-BOOL co_IntProcessMouseMessage(MSG* msg, BOOL* RemoveMessages, UINT first, UINT last)
+BOOL co_IntProcessMouseMessage(MSG* msg, BOOL* RemoveMessages, BOOL* NotForUs, LONG_PTR ExtraInfo, UINT first, UINT last)
{
MSG clk_msg;
POINT pt;
PTHREADINFO pti;
PSYSTEM_CURSORINFO CurInfo;
PDESKTOP pDesk;
- DECLARE_RETURN(BOOL);
pti = PsGetCurrentThreadWin32Thread();
pwndDesktop = UserGetDesktopWindow();
{
hittest = HTCLIENT;
pwndMsg = MessageQueue->spwndCapture;
- if (pwndMsg) UserReferenceObject(pwndMsg);
}
else
{
- pwndMsg = co_WinPosWindowFromPoint(NULL, &msg->pt, &hittest, FALSE);//TRUE);
+ /*
+ Start with null window. See wine win.c:test_mouse_input:WM_COMMAND tests.
+ */
+ pwndMsg = co_WinPosWindowFromPoint( NULL, &msg->pt, &hittest, FALSE);
}
TRACE("Got mouse message for %p, hittest: 0x%x\n", msg->hwnd, hittest);
- if (pwndMsg == NULL || pwndMsg->head.pti != pti)
+ // Null window or not the same "Hardware" message queue.
+ if (pwndMsg == NULL || pwndMsg->head.pti->MessageQueue != MessageQueue)
{
+ // Crossing a boundary, so set cursor. See default message queue cursor.
+ IntSystemSetCursor(SYSTEMCUR(ARROW));
/* Remove and ignore the message */
*RemoveMessages = TRUE;
- RETURN(FALSE);
+ return FALSE;
+ }
+
+ // Check to see if this is attached,
+ if ( pwndMsg->head.pti != pti && // window thread is not current,
+ MessageQueue->cThreads > 1 ) // and is attached...
+ {
+ // This is not for us and we should leave so the other thread can check for messages!!!
+ *NotForUs = TRUE;
+ *RemoveMessages = TRUE;
+ return FALSE;
}
if ( MessageQueue == gpqCursor ) // Cursor must use the same Queue!
pt = msg->pt;
message = msg->message;
+
/* Note: windows has no concept of a non-client wheel message */
if (message != WM_MOUSEWHEEL)
{
if (hittest != HTCLIENT)
{
message += WM_NCMOUSEMOVE - WM_MOUSEMOVE;
- msg->wParam = hittest;
+ msg->wParam = hittest; // Caution! This might break wParam check in DblClk.
}
else
{
{
if ((msg->message == clk_msg.message) &&
(msg->hwnd == clk_msg.hwnd) &&
- (msg->wParam == clk_msg.wParam) &&
+ // Only worry about XButton wParam.
+ (msg->message != WM_XBUTTONDOWN || GET_XBUTTON_WPARAM(msg->wParam) == GET_XBUTTON_WPARAM(clk_msg.wParam)) &&
((msg->time - clk_msg.time) < (ULONG)gspv.iDblClickTime) &&
(abs(msg->pt.x - clk_msg.pt.x) < UserGetSystemMetrics(SM_CXDOUBLECLK)/2) &&
(abs(msg->pt.y - clk_msg.pt.y) < UserGetSystemMetrics(SM_CYDOUBLECLK)/2))
if (!((first == 0 && last == 0) || (message >= first || message <= last)))
{
TRACE("Message out of range!!!\n");
- RETURN(FALSE);
+ return FALSE;
}
/* update static double click conditions */
if (!((first == 0 && last == 0) || (message >= first || message <= last)))
{
TRACE("Message out of range!!!\n");
- RETURN(FALSE);
+ return FALSE;
+ }
+
+ // Update mouse move down keys.
+ if (message == WM_MOUSEMOVE)
+ {
+ msg->wParam = MsqGetDownKeyState(MessageQueue);
}
}
- if(gspv.bMouseClickLock)
+ if (gspv.bMouseClickLock)
{
BOOL IsClkLck = FALSE;
{
/* Remove and ignore the message */
*RemoveMessages = TRUE;
- RETURN(FALSE);
+ TRACE("Remove and ignore the message\n");
+ return FALSE;
}
}
- /* message is accepted now (but may still get dropped) */
+ if (pti->TIF_flags & TIF_MSGPOSCHANGED)
+ {
+ pti->TIF_flags &= ~TIF_MSGPOSCHANGED;
+ IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, NULL, OBJID_CLIENT, CHILDID_SELF, 0);
+ }
+
+ /* message is accepted now (but still get dropped) */
event.message = msg->message;
event.time = msg->time;
hook.pt = msg->pt;
hook.hwnd = msg->hwnd;
hook.wHitTestCode = hittest;
- hook.dwExtraInfo = 0 /* extra_info */ ;
+ hook.dwExtraInfo = ExtraInfo;
if (co_HOOK_CallHooks( WH_MOUSE, *RemoveMessages ? HC_ACTION : HC_NOREMOVE,
message, (LPARAM)&hook ))
{
hook.pt = msg->pt;
hook.hwnd = msg->hwnd;
hook.wHitTestCode = hittest;
- hook.dwExtraInfo = 0 /* extra_info */ ;
+ hook.dwExtraInfo = ExtraInfo;
co_HOOK_CallHooks( WH_CBT, HCBT_CLICKSKIPPED, message, (LPARAM)&hook );
ERR("WH_MOUSE dropped mouse message!\n");
/* Remove and skip message */
*RemoveMessages = TRUE;
- RETURN(FALSE);
+ return FALSE;
}
- if ((hittest == HTERROR) || (hittest == HTNOWHERE))
+ if ((hittest == (USHORT)HTERROR) || (hittest == (USHORT)HTNOWHERE))
{
- co_IntSendMessage( msg->hwnd, WM_SETCURSOR, (WPARAM)msg->hwnd,
- MAKELONG( hittest, msg->message ));
+ co_IntSendMessage( msg->hwnd, WM_SETCURSOR, (WPARAM)msg->hwnd, MAKELONG( hittest, msg->message ));
/* Remove and skip message */
*RemoveMessages = TRUE;
- RETURN(FALSE);
+ return FALSE;
}
if ((*RemoveMessages == FALSE) || MessageQueue->spwndCapture)
{
/* Accept the message */
msg->message = message;
- RETURN(TRUE);
+ return TRUE;
}
if ((msg->message == WM_LBUTTONDOWN) ||
PWND pwndTop = pwndMsg;
pwndTop = IntGetNonChildAncestor(pwndTop);
+ TRACE("Mouse pti %p pwndMsg pti %p pwndTop pti %p\n",MessageQueue->ptiMouse,pwndMsg->head.pti,pwndTop->head.pti);
+
if (pwndTop && pwndTop != pwndDesktop)
{
LONG ret = co_IntSendMessage( msg->hwnd,
co_IntSendMessage( msg->hwnd, WM_SETCURSOR, (WPARAM)msg->hwnd, MAKELONG( hittest, msg->message ));
msg->message = message;
- RETURN(!eatMsg);
-
-CLEANUP:
- if(pwndMsg)
- UserDereferenceObject(pwndMsg);
-
- END_CLEANUP;
+ return !eatMsg;
}
BOOL co_IntProcessKeyboardMessage(MSG* Msg, BOOL* RemoveMessages)
{
EVENTMSG Event;
+ USER_REFERENCE_ENTRY Ref;
+ PWND pWnd;
+ UINT ImmRet;
+ BOOL Ret = TRUE;
+ WPARAM wParam = Msg->wParam;
+ PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+
+ if (Msg->message == VK_PACKET)
+ {
+ pti->wchInjected = HIWORD(Msg->wParam);
+ }
if (Msg->message == WM_KEYDOWN || Msg->message == WM_SYSKEYDOWN ||
Msg->message == WM_KEYUP || Msg->message == WM_SYSKEYUP)
}
}
+ pWnd = ValidateHwndNoErr(Msg->hwnd);
+ if (pWnd) UserRefObjectCo(pWnd, &Ref);
+
Event.message = Msg->message;
Event.hwnd = Msg->hwnd;
Event.time = Msg->time;
if (HIWORD(Msg->lParam) & 0x0100) Event.paramH |= 0x8000;
co_HOOK_CallHooks( WH_JOURNALRECORD, HC_ACTION, 0, (LPARAM)&Event);
+ if (*RemoveMessages)
+ {
+ if ((Msg->message == WM_KEYDOWN) &&
+ (Msg->hwnd != IntGetDesktopWindow()))
+ {
+ /* Handle F1 key by sending out WM_HELP message */
+ if (Msg->wParam == VK_F1)
+ {
+ UserPostMessage( Msg->hwnd, WM_KEYF1, 0, 0 );
+ }
+ else if (Msg->wParam >= VK_BROWSER_BACK &&
+ Msg->wParam <= VK_LAUNCH_APP2)
+ {
+ /* FIXME: Process keystate */
+ co_IntSendMessage(Msg->hwnd, WM_APPCOMMAND, (WPARAM)Msg->hwnd, MAKELPARAM(0, (FAPPCOMMAND_KEY | (Msg->wParam - VK_BROWSER_BACK + 1))));
+ }
+ }
+ else if (Msg->message == WM_KEYUP)
+ {
+ /* Handle VK_APPS key by posting a WM_CONTEXTMENU message */
+ if (Msg->wParam == VK_APPS && pti->MessageQueue->MenuOwner == NULL)
+ UserPostMessage( Msg->hwnd, WM_CONTEXTMENU, (WPARAM)Msg->hwnd, -1 );
+ }
+ }
+
+ //// Key Down!
+ if ( *RemoveMessages && Msg->message == WM_SYSKEYDOWN )
+ {
+ if ( HIWORD(Msg->lParam) & KF_ALTDOWN )
+ {
+ if ( Msg->wParam == VK_ESCAPE || Msg->wParam == VK_TAB ) // Alt-Tab/ESC Alt-Shift-Tab/ESC
+ {
+ WPARAM wParamTmp;
+
+ wParamTmp = UserGetKeyState(VK_SHIFT) & 0x8000 ? SC_PREVWINDOW : SC_NEXTWINDOW;
+ TRACE("Send WM_SYSCOMMAND Alt-Tab/ESC Alt-Shift-Tab/ESC\n");
+ co_IntSendMessage( Msg->hwnd, WM_SYSCOMMAND, wParamTmp, Msg->wParam );
+
+ //// Keep looping.
+ Ret = FALSE;
+ //// Skip the rest.
+ goto Exit;
+ }
+ }
+ }
+
+ if ( *RemoveMessages && (Msg->message == WM_SYSKEYDOWN || Msg->message == WM_KEYDOWN) )
+ {
+ if (gdwLanguageToggleKey < 3)
+ {
+ if (IS_KEY_DOWN(gafAsyncKeyState, gdwLanguageToggleKey == 1 ? VK_LMENU : VK_CONTROL)) // L Alt 1 or Ctrl 2 .
+ {
+ if ( wParam == VK_LSHIFT ) gLanguageToggleKeyState = INPUTLANGCHANGE_FORWARD; // Left Alt - Left Shift, Next
+ //// FIXME : It seems to always be VK_LSHIFT.
+ if ( wParam == VK_RSHIFT ) gLanguageToggleKeyState = INPUTLANGCHANGE_BACKWARD; // Left Alt - Right Shift, Previous
+ }
+ }
+ }
+
+ //// Key Up! Alt Key Ctrl Key
+ if ( *RemoveMessages && (Msg->message == WM_SYSKEYUP || Msg->message == WM_KEYUP) )
+ {
+ // When initializing win32k: Reading from the registry hotkey combination
+ // to switch the keyboard layout and store it to global variable.
+ // Using this combination of hotkeys in this function
+
+ if ( gdwLanguageToggleKey < 3 &&
+ IS_KEY_DOWN(gafAsyncKeyState, gdwLanguageToggleKey == 1 ? VK_LMENU : VK_CONTROL) )
+ {
+ if ( Msg->wParam == VK_SHIFT && !(IS_KEY_DOWN(gafAsyncKeyState, VK_SHIFT)))
+ {
+ WPARAM wParamILR;
+ PKL pkl = pti->KeyboardLayout;
+
+ if (pWnd) UserDerefObjectCo(pWnd);
+
+ //// Seems to override message window.
+ if (!(pWnd = pti->MessageQueue->spwndFocus))
+ {
+ pWnd = pti->MessageQueue->spwndActive;
+ }
+ if (pWnd) UserRefObjectCo(pWnd, &Ref);
+
+ if (pkl != NULL && gLanguageToggleKeyState)
+ {
+ TRACE("Posting WM_INPUTLANGCHANGEREQUEST KeyState %d\n", gLanguageToggleKeyState );
+
+ wParamILR = gLanguageToggleKeyState;
+ // If system character set and font signature send flag.
+ if ( gSystemFS & pkl->dwFontSigs )
+ {
+ wParamILR |= INPUTLANGCHANGE_SYSCHARSET;
+ }
+
+ UserPostMessage( UserHMGetHandle(pWnd),
+ WM_INPUTLANGCHANGEREQUEST,
+ wParamILR,
+ (LPARAM)pkl->hkl );
+
+ gLanguageToggleKeyState = 0;
+ //// Keep looping.
+ Ret = FALSE;
+ //// Skip the rest.
+ goto Exit;
+ }
+ }
+ }
+ }
+
if (co_HOOK_CallHooks( WH_KEYBOARD,
- *RemoveMessages ? HC_ACTION : HC_NOREMOVE,
+ *RemoveMessages ? HC_ACTION : HC_NOREMOVE,
LOWORD(Msg->wParam),
Msg->lParam))
{
HCBT_KEYSKIPPED,
LOWORD(Msg->wParam),
Msg->lParam );
- ERR("KeyboardMessage WH_CBT Call Hook return!\n");
- return FALSE;
+
+ ERR("KeyboardMessage WH_KEYBOARD Call Hook return!\n");
+
+ *RemoveMessages = TRUE;
+
+ Ret = FALSE;
}
- return TRUE;
+
+ if ( pWnd && Ret && *RemoveMessages && Msg->message == WM_KEYDOWN && !(pti->TIF_flags & TIF_DISABLEIME))
+ {
+ if ( (ImmRet = IntImmProcessKey(pti->MessageQueue, pWnd, Msg->message, Msg->wParam, Msg->lParam)) )
+ {
+ if ( ImmRet & (IPHK_HOTKEY|IPHK_SKIPTHISKEY) )
+ {
+ ImmRet = 0;
+ }
+ if ( ImmRet & IPHK_PROCESSBYIME )
+ {
+ Msg->wParam = VK_PROCESSKEY;
+ }
+ }
+ }
+Exit:
+ if (pWnd) UserDerefObjectCo(pWnd);
+ return Ret;
}
-BOOL co_IntProcessHardwareMessage(MSG* Msg, BOOL* RemoveMessages, UINT first, UINT last)
+BOOL co_IntProcessHardwareMessage(MSG* Msg, BOOL* RemoveMessages, BOOL* NotForUs, LONG_PTR ExtraInfo, UINT first, UINT last)
{
if ( IS_MOUSE_MESSAGE(Msg->message))
{
- return co_IntProcessMouseMessage(Msg, RemoveMessages, first, last);
+ return co_IntProcessMouseMessage(Msg, RemoveMessages, NotForUs, ExtraInfo, first, last);
}
else if ( IS_KBD_MESSAGE(Msg->message))
{
return TRUE;
}
-BOOL APIENTRY
-co_MsqPeekMouseMove(IN PTHREADINFO pti,
- IN BOOL Remove,
- IN PWND Window,
- IN UINT MsgFilterLow,
- IN UINT MsgFilterHigh,
- OUT MSG* pMsg)
-{
- BOOL AcceptMessage;
- MSG msg;
- PUSER_MESSAGE_QUEUE MessageQueue = pti->MessageQueue;
-
- if(!(MessageQueue->MouseMoved))
- return FALSE;
-
- if (!MessageQueue->ptiSysLock)
- {
- MessageQueue->ptiSysLock = pti;
- pti->pcti->CTI_flags |= CTI_THREADSYSLOCK;
- }
-
- if (MessageQueue->ptiSysLock != pti)
- {
- ERR("MsqPeekMouseMove: Thread Q is locked to another pti!\n");
- return FALSE;
- }
-
- msg = MessageQueue->MouseMoveMsg;
-
- AcceptMessage = co_IntProcessMouseMessage(&msg, &Remove, MsgFilterLow, MsgFilterHigh);
-
- if(AcceptMessage)
- *pMsg = msg;
-
- if(Remove)
- {
- ClearMsgBitsMask(pti, QS_MOUSEMOVE);
- MessageQueue->MouseMoved = FALSE;
- }
-
- MessageQueue->ptiSysLock = NULL;
- pti->pcti->CTI_flags &= ~CTI_THREADSYSLOCK;
- return AcceptMessage;
-}
-
/* check whether a message filter contains at least one potential hardware message */
static INT FASTCALL
filter_contains_hw_range( UINT first, UINT last )
return 1;
}
+/* check whether message is in the range of mouse messages */
+static inline BOOL is_mouse_message( UINT message )
+{
+ return ( //( message >= WM_NCMOUSEFIRST && message <= WM_NCMOUSELAST ) || This seems to break tests...
+ ( message >= WM_MOUSEFIRST && message <= WM_MOUSELAST ) ||
+ ( message >= WM_XBUTTONDOWN && message <= WM_XBUTTONDBLCLK ) ||
+ ( message >= WM_MBUTTONDOWN && message <= WM_MBUTTONDBLCLK ) ||
+ ( message >= WM_LBUTTONDOWN && message <= WM_RBUTTONDBLCLK ) );
+}
+
BOOL APIENTRY
co_MsqPeekHardwareMessage(IN PTHREADINFO pti,
IN BOOL Remove,
IN UINT QSflags,
OUT MSG* pMsg)
{
+ BOOL AcceptMessage, NotForUs;
+ PUSER_MESSAGE CurrentMessage;
+ PLIST_ENTRY ListHead;
+ MSG msg;
+ ULONG_PTR idSave;
+ DWORD QS_Flags;
+ LONG_PTR ExtraInfo;
+ BOOL Ret = FALSE;
+ PUSER_MESSAGE_QUEUE MessageQueue = pti->MessageQueue;
- BOOL AcceptMessage;
- PUSER_MESSAGE CurrentMessage;
- PLIST_ENTRY ListHead, CurrentEntry = NULL;
- MSG msg;
- BOOL Ret = FALSE;
- PUSER_MESSAGE_QUEUE MessageQueue = pti->MessageQueue;
+ if (!filter_contains_hw_range( MsgFilterLow, MsgFilterHigh )) return FALSE;
- if (!filter_contains_hw_range( MsgFilterLow, MsgFilterHigh )) return FALSE;
+ ListHead = MessageQueue->HardwareMessagesListHead.Flink;
- ListHead = &MessageQueue->HardwareMessagesListHead;
- CurrentEntry = ListHead->Flink;
+ if (IsListEmpty(ListHead)) return FALSE;
- if (IsListEmpty(CurrentEntry)) return FALSE;
+ if (!MessageQueue->ptiSysLock)
+ {
+ MessageQueue->ptiSysLock = pti;
+ pti->pcti->CTI_flags |= CTI_THREADSYSLOCK;
+ }
- if (!MessageQueue->ptiSysLock)
- {
- MessageQueue->ptiSysLock = pti;
- pti->pcti->CTI_flags |= CTI_THREADSYSLOCK;
- }
+ if (MessageQueue->ptiSysLock != pti)
+ {
+ ERR("Thread Q is locked to ptiSysLock 0x%p pti 0x%p\n",MessageQueue->ptiSysLock,pti);
+ return FALSE;
+ }
- if (MessageQueue->ptiSysLock != pti)
- {
- ERR("MsqPeekHardwareMessage: Thread Q is locked to another pti!\n");
- return FALSE;
- }
+ while (ListHead != &MessageQueue->HardwareMessagesListHead)
+ {
+ CurrentMessage = CONTAINING_RECORD(ListHead, USER_MESSAGE, ListEntry);
+ ListHead = ListHead->Flink;
- CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
- ListEntry);
- do
- {
- if (IsListEmpty(CurrentEntry)) break;
- if (!CurrentMessage) break;
- CurrentEntry = CurrentMessage->ListEntry.Flink;
- if (!CurrentEntry) break; //// Fix CORE-6734 reported crash.
+ if (MessageQueue->idSysPeek == (ULONG_PTR)CurrentMessage)
+ {
+ TRACE("Skip this message due to it is in play!\n");
+ continue;
+ }
/*
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.
*/
if ( ( !Window || // 1
( Window == PWND_BOTTOM && CurrentMessage->Msg.hwnd == NULL ) || // 2
- ( Window != PWND_BOTTOM && Window->head.h == CurrentMessage->Msg.hwnd ) ) && // 3
+ ( Window != PWND_BOTTOM && Window->head.h == CurrentMessage->Msg.hwnd ) || // 3
+ ( is_mouse_message(CurrentMessage->Msg.message) ) ) && // Null window for anything mouse.
( ( ( MsgFilterLow == 0 && MsgFilterHigh == 0 ) && CurrentMessage->QS_Flags & QSflags ) ||
( MsgFilterLow <= CurrentMessage->Msg.message && MsgFilterHigh >= CurrentMessage->Msg.message ) ) )
- {
- msg = CurrentMessage->Msg;
+ {
+ idSave = MessageQueue->idSysPeek;
+ MessageQueue->idSysPeek = (ULONG_PTR)CurrentMessage;
- UpdateKeyStateFromMsg(MessageQueue, &msg);
- AcceptMessage = co_IntProcessHardwareMessage(&msg, &Remove, MsgFilterLow, MsgFilterHigh);
+ msg = CurrentMessage->Msg;
+ ExtraInfo = CurrentMessage->ExtraInfo;
+ QS_Flags = CurrentMessage->QS_Flags;
- if (Remove)
- {
- RemoveEntryList(&CurrentMessage->ListEntry);
- ClearMsgBitsMask(pti, CurrentMessage->QS_Flags);
- MsqDestroyMessage(CurrentMessage);
- }
+ NotForUs = FALSE;
- if (AcceptMessage)
- {
- *pMsg = msg;
- Ret = TRUE;
- break;
- }
- }
- CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, ListEntry);
- }
- while(CurrentEntry != ListHead);
+ UpdateKeyStateFromMsg(MessageQueue, &msg);
+ AcceptMessage = co_IntProcessHardwareMessage(&msg, &Remove, &NotForUs, ExtraInfo, MsgFilterLow, MsgFilterHigh);
- MessageQueue->ptiSysLock = NULL;
- pti->pcti->CTI_flags &= ~CTI_THREADSYSLOCK;
- return Ret;
+ if (Remove)
+ {
+ if (CurrentMessage->pti != NULL && (MessageQueue->idSysPeek == (ULONG_PTR)CurrentMessage))
+ {
+ MsqDestroyMessage(CurrentMessage);
+ }
+ ClearMsgBitsMask(pti, QS_Flags);
+ }
+
+ MessageQueue->idSysPeek = idSave;
+
+ if (NotForUs)
+ {
+ Ret = FALSE;
+ break;
+ }
+
+ if (AcceptMessage)
+ {
+ *pMsg = msg;
+ // Fix all but one wine win:test_GetMessagePos WM_TIMER tests. See PostTimerMessages.
+ if (!RtlEqualMemory(&pti->ptLast, &msg.pt, sizeof(POINT)))
+ {
+ pti->TIF_flags |= TIF_MSGPOSCHANGED;
+ }
+ pti->ptLast = msg.pt;
+ pti->timeLast = msg.time;
+ MessageQueue->ExtraInfo = ExtraInfo;
+ Ret = TRUE;
+ break;
+ }
+ }
+ }
+
+ MessageQueue->ptiSysLock = NULL;
+ pti->pcti->CTI_flags &= ~CTI_THREADSYSLOCK;
+ return Ret;
}
BOOLEAN APIENTRY
IN UINT MsgFilterLow,
IN UINT MsgFilterHigh,
IN UINT QSflags,
+ OUT LONG_PTR *ExtraInfo,
+ OUT DWORD *dwQEvent,
OUT PMSG Message)
{
- PLIST_ENTRY CurrentEntry;
PUSER_MESSAGE CurrentMessage;
PLIST_ENTRY ListHead;
+ DWORD QS_Flags;
BOOL Ret = FALSE;
- CurrentEntry = pti->PostedMessagesListHead.Flink;
- ListHead = &pti->PostedMessagesListHead;
+ ListHead = pti->PostedMessagesListHead.Flink;
- if (IsListEmpty(CurrentEntry)) return FALSE;
+ if (IsListEmpty(ListHead)) return FALSE;
- CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
- ListEntry);
- do
+ while(ListHead != &pti->PostedMessagesListHead)
{
- if (IsListEmpty(CurrentEntry)) break;
- if (!CurrentMessage) break;
- CurrentEntry = CurrentEntry->Flink;
+ CurrentMessage = CONTAINING_RECORD(ListHead, USER_MESSAGE, ListEntry);
+ ListHead = ListHead->Flink;
/*
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.
( ( ( MsgFilterLow == 0 && MsgFilterHigh == 0 ) && CurrentMessage->QS_Flags & QSflags ) ||
( MsgFilterLow <= CurrentMessage->Msg.message && MsgFilterHigh >= CurrentMessage->Msg.message ) ) )
{
- *Message = CurrentMessage->Msg;
+ *Message = CurrentMessage->Msg;
+ *ExtraInfo = CurrentMessage->ExtraInfo;
+ QS_Flags = CurrentMessage->QS_Flags;
+ if (dwQEvent) *dwQEvent = CurrentMessage->dwQEvent;
if (Remove)
{
- RemoveEntryList(&CurrentMessage->ListEntry);
- ClearMsgBitsMask(pti, CurrentMessage->QS_Flags);
- MsqDestroyMessage(CurrentMessage);
+ if (CurrentMessage->pti != NULL)
+ {
+ MsqDestroyMessage(CurrentMessage);
+ }
+ ClearMsgBitsMask(pti, QS_Flags);
}
Ret = TRUE;
break;
}
- CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
- ListEntry);
}
- while (CurrentEntry != ListHead);
return Ret;
}
co_MsqWaitForNewMessages(PTHREADINFO pti, PWND WndFilter,
UINT MsgFilterMin, UINT MsgFilterMax)
{
- NTSTATUS ret;
+ NTSTATUS ret = STATUS_SUCCESS;
+
+ // Post mouse moves before waiting for messages.
+ if (pti->MessageQueue->QF_flags & QF_MOUSEMOVED)
+ {
+ IntCoalesceMouseMove(pti);
+ }
+
UserLeaveCo();
+
+ ZwYieldExecution(); // Let someone else run!
+
ret = KeWaitForSingleObject( pti->pEventQueueServer,
UserRequest,
UserMode,
FALSE,
NULL );
UserEnterCo();
+ if ( ret == STATUS_USER_APC )
+ {
+ TRACE("MWFNW User APC\n");
+ co_IntDeliverUserAPC();
+ }
return ret;
}
LARGE_INTEGER LargeTickCount;
KeQueryTickCount(&LargeTickCount);
- return ((LargeTickCount.u.LowPart - pti->timeLast) > MSQ_HUNG);
+
+ if ((LargeTickCount.u.LowPart - pti->timeLast) > MSQ_HUNG &&
+ !(pti->pcti->fsWakeMask & QS_INPUT) &&
+ !PsGetThreadFreezeCount(pti->pEThread) &&
+ !(pti->ppi->W32PF_flags & W32PF_APPSTARTING))
+ return TRUE;
+
+ return FALSE;
+}
+
+BOOL FASTCALL
+IsThreadSuspended(PTHREADINFO pti)
+{
+ if (pti->pEThread)
+ {
+ BOOL Ret = TRUE;
+ if (!(pti->pEThread->Tcb.SuspendCount) && !PsGetThreadFreezeCount(pti->pEThread)) Ret = FALSE;
+ return Ret;
+ }
+ return FALSE;
}
VOID
BOOLEAN FASTCALL
MsqInitializeMessageQueue(PTHREADINFO pti, PUSER_MESSAGE_QUEUE MessageQueue)
{
- MessageQueue->CaretInfo = (PTHRDCARETINFO)(MessageQueue + 1);
InitializeListHead(&MessageQueue->HardwareMessagesListHead); // Keep here!
MessageQueue->spwndFocus = NULL;
MessageQueue->iCursorLevel = 0;
- MessageQueue->CursorObject = NULL;
+ MessageQueue->CursorObject = SYSTEMCUR(WAIT); // See test_initial_cursor.
+ if (MessageQueue->CursorObject)
+ {
+ TRACE("Default cursor hcur %p\n",UserHMGetHandle(MessageQueue->CursorObject));
+ UserReferenceObject(MessageQueue->CursorObject);
+ }
RtlCopyMemory(MessageQueue->afKeyState, gafAsyncKeyState, sizeof(gafAsyncKeyState));
MessageQueue->ptiMouse = pti;
MessageQueue->ptiKeyboard = pti;
PUSER_MESSAGE CurrentMessage;
PUSER_SENT_MESSAGE CurrentSentMessage;
+ TRACE("MsqCleanupThreadMsgs %p\n",pti);
+
+ // Clear it all out.
+ if (pti->pcti)
+ {
+ pti->pcti->fsWakeBits = 0;
+ pti->pcti->fsChangeBits = 0;
+ }
+
+ pti->nCntsQBits[QSRosKey] = 0;
+ pti->nCntsQBits[QSRosMouseMove] = 0;
+ pti->nCntsQBits[QSRosMouseButton] = 0;
+ pti->nCntsQBits[QSRosPostMessage] = 0;
+ pti->nCntsQBits[QSRosSendMessage] = 0;
+ pti->nCntsQBits[QSRosHotKey] = 0;
+ pti->nCntsQBits[QSRosEvent] = 0;
+
/* cleanup posted messages */
while (!IsListEmpty(&pti->PostedMessagesListHead))
{
- CurrentEntry = RemoveHeadList(&pti->PostedMessagesListHead);
- CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
- ListEntry);
+ CurrentEntry = pti->PostedMessagesListHead.Flink;
+ CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, ListEntry);
+ ERR("Thread Cleanup Post Messages %p\n",CurrentMessage);
+ if (CurrentMessage->dwQEvent)
+ {
+ if (CurrentMessage->dwQEvent == POSTEVENT_NWE)
+ {
+ ExFreePoolWithTag( (PVOID)CurrentMessage->ExtraInfo, TAG_HOOK);
+ }
+ }
MsqDestroyMessage(CurrentMessage);
}
/* remove the messages that have not yet been dispatched */
while (!IsListEmpty(&pti->SentMessagesListHead))
{
- CurrentEntry = RemoveHeadList(&pti->SentMessagesListHead);
- CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE,
- ListEntry);
+ CurrentEntry = pti->SentMessagesListHead.Flink;
+ CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE, ListEntry);
- TRACE("Notify the sender and remove a message from the queue that had not been dispatched\n");
- /* Only if the message has a sender was the message in the DispatchingList */
- if ((CurrentSentMessage->ptiSender)
- && (CurrentSentMessage->DispatchingListEntry.Flink != NULL))
- {
- RemoveEntryList(&CurrentSentMessage->DispatchingListEntry);
- }
+ ERR("Thread Cleanup Sent Messages %p\n",CurrentSentMessage);
/* wake the sender's thread */
- if (CurrentSentMessage->CompletionEvent != NULL)
+ if (CurrentSentMessage->pkCompletionEvent != NULL)
{
- KeSetEvent(CurrentSentMessage->CompletionEvent, IO_NO_INCREMENT, FALSE);
+ KeSetEvent(CurrentSentMessage->pkCompletionEvent, IO_NO_INCREMENT, FALSE);
}
- if (CurrentSentMessage->HasPackedLParam == TRUE)
+ if (CurrentSentMessage->HasPackedLParam)
{
if (CurrentSentMessage->Msg.lParam)
ExFreePool((PVOID)CurrentSentMessage->Msg.lParam);
}
/* free the message */
- ExFreePool(CurrentSentMessage);
+ FreeUserMessage(CurrentSentMessage);
}
- /* notify senders of dispatching messages. This needs to be cleaned up if e.g.
- ExitThread() was called in a SendMessage() umode callback */
- while (!IsListEmpty(&pti->LocalDispatchingMessagesHead))
+ // Process Trouble Message List
+ if (!IsListEmpty(&usmList))
{
- CurrentEntry = RemoveHeadList(&pti->LocalDispatchingMessagesHead);
- CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE,
- ListEntry);
-
- /* remove the message from the dispatching list */
- if(CurrentSentMessage->DispatchingListEntry.Flink != NULL)
+ CurrentEntry = usmList.Flink;
+ while (CurrentEntry != &usmList)
{
- RemoveEntryList(&CurrentSentMessage->DispatchingListEntry);
- }
-
- TRACE("Notify the sender, the thread has been terminated while dispatching a message!\n");
+ CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE, ListEntry);
+ CurrentEntry = CurrentEntry->Flink;
- /* wake the sender's thread */
- if (CurrentSentMessage->CompletionEvent != NULL)
- {
- KeSetEvent(CurrentSentMessage->CompletionEvent, IO_NO_INCREMENT, FALSE);
- }
+ TRACE("Found troubled messages %p on the list\n",CurrentSentMessage);
- if (CurrentSentMessage->HasPackedLParam == TRUE)
- {
- if (CurrentSentMessage->Msg.lParam)
- ExFreePool((PVOID)CurrentSentMessage->Msg.lParam);
- }
+ if ( pti == CurrentSentMessage->ptiReceiver )
+ {
+ if (CurrentSentMessage->HasPackedLParam)
+ {
+ if (CurrentSentMessage->Msg.lParam)
+ ExFreePool((PVOID)CurrentSentMessage->Msg.lParam);
+ }
- /* free the message */
- ExFreePool(CurrentSentMessage);
- }
+ /* free the message */
+ FreeUserMessage(CurrentSentMessage);
+ }
+ else if ( pti == CurrentSentMessage->ptiSender ||
+ pti == CurrentSentMessage->ptiCallBackSender )
+ {
+ // Determine whether this message is being processed or not.
+ if ((CurrentSentMessage->flags & (SMF_RECEIVERBUSY|SMF_RECEIVEDMESSAGE)) != SMF_RECEIVEDMESSAGE)
+ {
+ CurrentSentMessage->flags |= SMF_RECEIVERFREE;
+ }
- /* tell other threads not to bother returning any info to us */
- while (! IsListEmpty(&pti->DispatchingMessagesHead))
- {
- CurrentEntry = RemoveHeadList(&pti->DispatchingMessagesHead);
- CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE,
- DispatchingListEntry);
- CurrentSentMessage->CompletionEvent = NULL;
- CurrentSentMessage->Result = NULL;
+ if (!(CurrentSentMessage->flags & SMF_RECEIVERFREE))
+ {
- /* do NOT dereference our message queue as it might get attempted to be
- locked later */
- }
+ if (CurrentSentMessage->HasPackedLParam)
+ {
+ if (CurrentSentMessage->Msg.lParam)
+ ExFreePool((PVOID)CurrentSentMessage->Msg.lParam);
+ }
- // Clear it all out.
- if (pti->pcti)
- {
- pti->pcti->fsWakeBits = 0;
- pti->pcti->fsChangeBits = 0;
+ /* free the message */
+ FreeUserMessage(CurrentSentMessage);
+ }
+ }
+ }
}
-
- pti->nCntsQBits[QSRosKey] = 0;
- pti->nCntsQBits[QSRosMouseMove] = 0;
- pti->nCntsQBits[QSRosMouseButton] = 0;
- 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;
+ PLIST_ENTRY CurrentEntry;
+ PUSER_MESSAGE CurrentMessage;
MessageQueue = pti->MessageQueue;
MessageQueue->cThreads--;
if (MessageQueue->ptiSysLock == pti) MessageQueue->ptiSysLock = NULL;
}
+ if (MessageQueue->cThreads == 0) //// Fix a crash related to CORE-10471 testing.
+ {
+ /* cleanup posted messages */
+ while (!IsListEmpty(&MessageQueue->HardwareMessagesListHead))
+ {
+ CurrentEntry = MessageQueue->HardwareMessagesListHead.Flink;
+ CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, ListEntry);
+ ERR("MQ Cleanup Post Messages %p\n",CurrentMessage);
+ MsqDestroyMessage(CurrentMessage);
+ }
+ } ////
+
if (MessageQueue->CursorObject)
{
PCURICON_OBJECT pCursor = MessageQueue->CursorObject;
IntGetSysCursorInfo()->CurrentCursorObject = NULL;
}
- ERR("DereferenceObject pCursor\n");
+ TRACE("DereferenceObject pCursor\n");
UserDereferenceObject(pCursor);
}
{
PUSER_MESSAGE_QUEUE MessageQueue;
- MessageQueue = (PUSER_MESSAGE_QUEUE)ExAllocatePoolWithTag(NonPagedPool,
- sizeof(USER_MESSAGE_QUEUE) + sizeof(THRDCARETINFO),
- USERTAG_Q);
+ MessageQueue = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(*MessageQueue),
+ USERTAG_Q);
if (!MessageQueue)
{
return NULL;
}
- RtlZeroMemory(MessageQueue, sizeof(USER_MESSAGE_QUEUE) + sizeof(THRDCARETINFO));
+ RtlZeroMemory(MessageQueue, sizeof(*MessageQueue));
/* hold at least one reference until it'll be destroyed */
IntReferenceMessageQueue(MessageQueue);
/* initialize the queue */
}
VOID FASTCALL
-MsqDestroyMessageQueue(PTHREADINFO pti)
+MsqDestroyMessageQueue(_In_ PTHREADINFO pti)
{
PDESKTOP desk;
PUSER_MESSAGE_QUEUE MessageQueue = pti->MessageQueue;
+ NT_ASSERT(MessageQueue != NULL);
MessageQueue->QF_flags |= QF_INDESTROY;
/* remove the message queue from any desktops */
MsqCleanupMessageQueue(pti);
/* decrease the reference counter, if it hits zero, the queue will be freed */
+ _PRAGMA_WARNING_SUPPRESS(__WARNING_USING_UNINIT_VAR);
IntDereferenceMessageQueue(MessageQueue);
}
if (Message->QS_Flags & QS_SMRESULT) return FALSE;
- // SendMessageXxx || Callback msg and not a notify msg
+ // SendMessageXxx || Callback msg and not a notify msg
if (Message->ptiSender || Message->CompletionCallback)
{
Message->lResult = lResult;
{
HWND Prev;
PUSER_MESSAGE_QUEUE MessageQueue;
-
+
MessageQueue = pti->MessageQueue;
switch(Type)
MessageQueue->MoveSize = hWnd;
return Prev;
case MSQ_STATE_CARET:
- ASSERT(MessageQueue->CaretInfo);
- Prev = MessageQueue->CaretInfo->hWnd;
- MessageQueue->CaretInfo->hWnd = hWnd;
+ Prev = MessageQueue->CaretInfo.hWnd;
+ MessageQueue->CaretInfo.hWnd = hWnd;
return Prev;
}