2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
22 * PURPOSE: Message queues
23 * FILE: subsystems/win32/win32k/ntuser/msgqueue.c
24 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
28 * 06-06-2001 CSH Created
31 /* INCLUDES ******************************************************************/
38 /* GLOBALS *******************************************************************/
40 static PAGED_LOOKASIDE_LIST MessageLookasideList
;
42 /* FUNCTIONS *****************************************************************/
45 IntMsqSetWakeMask(DWORD WakeMask
)
47 PTHREADINFO Win32Thread
;
48 PUSER_MESSAGE_QUEUE MessageQueue
;
49 HANDLE MessageEventHandle
;
51 Win32Thread
= PsGetCurrentThreadWin32Thread();
52 if (Win32Thread
== NULL
|| Win32Thread
->MessageQueue
== NULL
)
55 MessageQueue
= Win32Thread
->MessageQueue
;
56 MessageQueue
->WakeMask
= WakeMask
;
57 MessageEventHandle
= MessageQueue
->NewMessagesHandle
;
59 if (Win32Thread
->pcti
)
60 Win32Thread
->pcti
->fsWakeMask
= WakeMask
;
64 return MessageEventHandle
;
68 IntMsqClearWakeMask(VOID
)
70 PTHREADINFO Win32Thread
;
71 PUSER_MESSAGE_QUEUE MessageQueue
;
73 Win32Thread
= PsGetCurrentThreadWin32Thread();
74 if (Win32Thread
== NULL
|| Win32Thread
->MessageQueue
== NULL
)
77 MessageQueue
= Win32Thread
->MessageQueue
;
78 // HACK!!!!!!! Newbies that wrote this should hold your head down in shame! (jt)
79 MessageQueue
->WakeMask
= ~0;
81 if (Win32Thread
->pcti
)
82 Win32Thread
->pcti
->fsWakeMask
= 0;
90 MsqWakeQueue(PUSER_MESSAGE_QUEUE Queue
, DWORD MessageBits
)
92 Queue
->QueueBits
|= MessageBits
;
93 Queue
->ChangedBits
|= MessageBits
;
94 if (Queue
->WakeMask
& MessageBits
)
95 KeSetEvent(Queue
->NewMessages
, IO_NO_INCREMENT
, FALSE
);
99 MsqIncPaintCountQueue(PUSER_MESSAGE_QUEUE Queue
)
102 MsqWakeQueue(Queue
, QS_PAINT
);
106 MsqDecPaintCountQueue(PUSER_MESSAGE_QUEUE Queue
)
115 MsqInitializeImpl(VOID
)
117 ExInitializePagedLookasideList(&MessageLookasideList
,
121 sizeof(USER_MESSAGE
),
125 return(STATUS_SUCCESS
);
129 MsqPostMouseMove(PUSER_MESSAGE_QUEUE MessageQueue
, MSG
* Msg
)
131 MessageQueue
->MouseMoveMsg
= *Msg
;
132 MessageQueue
->MouseMoved
= TRUE
;
133 MsqWakeQueue(MessageQueue
, QS_MOUSEMOVE
);
137 co_MsqInsertMouseMessage(MSG
* Msg
)
139 LARGE_INTEGER LargeTickCount
;
140 MSLLHOOKSTRUCT MouseHookData
;
141 PWND pwnd
, pwndDesktop
;
143 KeQueryTickCount(&LargeTickCount
);
144 Msg
->time
= MsqCalculateMessageTime(&LargeTickCount
);
146 MouseHookData
.pt
.x
= LOWORD(Msg
->lParam
);
147 MouseHookData
.pt
.y
= HIWORD(Msg
->lParam
);
151 MouseHookData
.mouseData
= MAKELONG(0, GET_WHEEL_DELTA_WPARAM(Msg
->wParam
));
155 case WM_XBUTTONDBLCLK
:
156 case WM_NCXBUTTONDOWN
:
158 case WM_NCXBUTTONDBLCLK
:
159 MouseHookData
.mouseData
= MAKELONG(0, HIWORD(Msg
->wParam
));
162 MouseHookData
.mouseData
= 0;
166 MouseHookData
.flags
= 0;
167 MouseHookData
.time
= Msg
->time
;
168 MouseHookData
.dwExtraInfo
= 0;
170 /* If the hook procedure returned non zero, dont send the message */
171 if (co_HOOK_CallHooks(WH_MOUSE_LL
, HC_ACTION
, Msg
->message
, (LPARAM
) &MouseHookData
))
174 /* Get the desktop window */
175 pwndDesktop
= UserGetDesktopWindow();
179 /* Check if the mouse is captured */
180 Msg
->hwnd
= IntGetCaptureWindow();
181 if(Msg
->hwnd
!= NULL
)
183 pwnd
= UserGetWindowObject(Msg
->hwnd
);
187 /* Loop all top level windows to find which one should receive input */
188 for( pwnd
= pwndDesktop
->spwndChild
;
190 pwnd
= pwnd
->spwndNext
)
192 if((pwnd
->style
& WS_VISIBLE
) &&
193 IntPtInWindow(pwnd
, Msg
->pt
.x
, Msg
->pt
.y
))
195 Msg
->hwnd
= pwnd
->head
.h
;
201 /* Check if we found a window */
202 if(Msg
->hwnd
!= NULL
&& pwnd
!= NULL
)
204 if(Msg
->message
== WM_MOUSEMOVE
)
206 /* Mouse move is a special case*/
207 MsqPostMouseMove(pwnd
->head
.pti
->MessageQueue
, Msg
);
211 DPRINT("Posting mouse message to hwnd=0x%x!\n", UserHMGetHandle(pwnd
));
212 MsqPostMessage(pwnd
->head
.pti
->MessageQueue
, Msg
, TRUE
, QS_MOUSEBUTTON
);
218 // Note: Only called from input.c.
221 co_MsqPostKeyboardMessage(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
223 PUSER_MESSAGE_QUEUE FocusMessageQueue
;
225 LARGE_INTEGER LargeTickCount
;
226 KBDLLHOOKSTRUCT KbdHookData
;
227 BOOLEAN Entered
= FALSE
;
229 DPRINT("MsqPostKeyboardMessage(uMsg 0x%x, wParam 0x%x, lParam 0x%x)\n",
230 uMsg
, wParam
, lParam
);
232 // Condition may arise when calling MsqPostMessage and waiting for an event.
233 if (!UserIsEntered())
235 // Fixme: Not sure ATM if this thread is locked.
236 UserEnterExclusive();
240 FocusMessageQueue
= IntGetFocusMessageQueue();
244 if (FocusMessageQueue
&& (FocusMessageQueue
->FocusWindow
!= (HWND
)0))
245 Msg
.hwnd
= FocusMessageQueue
->FocusWindow
;
251 KeQueryTickCount(&LargeTickCount
);
252 Msg
.time
= MsqCalculateMessageTime(&LargeTickCount
);
254 /* We can't get the Msg.pt point here since we don't know thread
255 (and thus the window station) the message will end up in yet. */
257 KbdHookData
.vkCode
= Msg
.wParam
;
258 KbdHookData
.scanCode
= (Msg
.lParam
>> 16) & 0xff;
259 KbdHookData
.flags
= (0 == (Msg
.lParam
& 0x01000000) ? 0 : LLKHF_EXTENDED
) |
260 (0 == (Msg
.lParam
& 0x20000000) ? 0 : LLKHF_ALTDOWN
) |
261 (0 == (Msg
.lParam
& 0x80000000) ? 0 : LLKHF_UP
);
262 KbdHookData
.time
= Msg
.time
;
263 KbdHookData
.dwExtraInfo
= 0;
264 if (co_HOOK_CallHooks(WH_KEYBOARD_LL
, HC_ACTION
, Msg
.message
, (LPARAM
) &KbdHookData
))
266 DPRINT1("Kbd msg %d wParam %d lParam 0x%08x dropped by WH_KEYBOARD_LL hook\n",
267 Msg
.message
, Msg
.wParam
, Msg
.lParam
);
268 if (Entered
) UserLeave();
272 if (FocusMessageQueue
== NULL
)
274 DPRINT("No focus message queue\n");
275 if (Entered
) UserLeave();
279 if (FocusMessageQueue
->FocusWindow
!= (HWND
)0)
281 Msg
.hwnd
= FocusMessageQueue
->FocusWindow
;
282 DPRINT("Msg.hwnd = %x\n", Msg
.hwnd
);
284 FocusMessageQueue
->Desktop
->pDeskInfo
->LastInputWasKbd
= TRUE
;
286 Msg
.pt
= gpsi
->ptCursor
;
287 MsqPostMessage(FocusMessageQueue
, &Msg
, TRUE
, QS_KEY
);
291 DPRINT("Invalid focus window handle\n");
294 if (Entered
) UserLeave();
299 MsqPostHotKeyMessage(PVOID Thread
, HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
302 PTHREADINFO Win32Thread
;
304 LARGE_INTEGER LargeTickCount
;
307 Status
= ObReferenceObjectByPointer (Thread
,
311 if (!NT_SUCCESS(Status
))
314 Win32Thread
= ((PETHREAD
)Thread
)->Tcb
.Win32Thread
;
315 if (Win32Thread
== NULL
|| Win32Thread
->MessageQueue
== NULL
)
317 ObDereferenceObject ((PETHREAD
)Thread
);
321 Window
= IntGetWindowObject(hWnd
);
324 ObDereferenceObject ((PETHREAD
)Thread
);
329 Mesg
.message
= WM_HOTKEY
;
330 Mesg
.wParam
= wParam
;
331 Mesg
.lParam
= lParam
;
332 KeQueryTickCount(&LargeTickCount
);
333 Mesg
.time
= MsqCalculateMessageTime(&LargeTickCount
);
334 Mesg
.pt
= gpsi
->ptCursor
;
335 MsqPostMessage(Window
->head
.pti
->MessageQueue
, &Mesg
, FALSE
, QS_HOTKEY
);
336 UserDereferenceObject(Window
);
337 ObDereferenceObject (Thread
);
341 PUSER_MESSAGE FASTCALL
342 MsqCreateMessage(LPMSG Msg
)
344 PUSER_MESSAGE Message
;
346 Message
= ExAllocateFromPagedLookasideList(&MessageLookasideList
);
352 RtlMoveMemory(&Message
->Msg
, Msg
, sizeof(MSG
));
358 MsqDestroyMessage(PUSER_MESSAGE Message
)
360 ExFreeToPagedLookasideList(&MessageLookasideList
, Message
);
364 co_MsqDispatchSentNotifyMessages(PUSER_MESSAGE_QUEUE MessageQueue
)
366 PLIST_ENTRY ListEntry
;
367 PUSER_SENT_MESSAGE_NOTIFY Message
;
369 while (!IsListEmpty(&MessageQueue
->SentMessagesListHead
))
371 ListEntry
= RemoveHeadList(&MessageQueue
->SentMessagesListHead
);
372 Message
= CONTAINING_RECORD(ListEntry
, USER_SENT_MESSAGE_NOTIFY
,
375 co_IntCallSentMessageCallback(Message
->CompletionCallback
,
378 Message
->CompletionCallbackContext
,
386 MsqPeekSentMessages(PUSER_MESSAGE_QUEUE MessageQueue
)
388 return(!IsListEmpty(&MessageQueue
->SentMessagesListHead
));
392 co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue
)
394 PUSER_SENT_MESSAGE Message
;
398 if (IsListEmpty(&MessageQueue
->SentMessagesListHead
))
403 /* remove it from the list of pending messages */
404 Entry
= RemoveHeadList(&MessageQueue
->SentMessagesListHead
);
405 Message
= CONTAINING_RECORD(Entry
, USER_SENT_MESSAGE
, ListEntry
);
407 /* insert it to the list of messages that are currently dispatched by this
409 InsertTailList(&MessageQueue
->LocalDispatchingMessagesHead
,
410 &Message
->ListEntry
);
412 if (Message
->HookMessage
== MSQ_ISHOOK
)
413 { // Direct Hook Call processor
414 Result
= co_CallHook( Message
->Msg
.message
, // HookId
415 (INT
)(INT_PTR
)Message
->Msg
.hwnd
, // Code
417 Message
->Msg
.lParam
);
419 else if (Message
->HookMessage
== MSQ_ISEVENT
)
420 { // Direct Event Call processor
421 Result
= co_EVENT_CallEvents( Message
->Msg
.message
,
424 Message
->Msg
.lParam
);
427 { /* Call the window procedure. */
428 Result
= co_IntSendMessage( Message
->Msg
.hwnd
,
429 Message
->Msg
.message
,
431 Message
->Msg
.lParam
);
434 /* remove the message from the local dispatching list, because it doesn't need
435 to be cleaned up on thread termination anymore */
436 RemoveEntryList(&Message
->ListEntry
);
438 /* remove the message from the dispatching list if needed, so lock the sender's message queue */
439 if (!(Message
->HookMessage
& MSQ_SENTNOWAIT
))
441 if (Message
->DispatchingListEntry
.Flink
!= NULL
)
443 /* only remove it from the dispatching list if not already removed by a timeout */
444 RemoveEntryList(&Message
->DispatchingListEntry
);
447 /* still keep the sender's message queue locked, so the sender can't exit the
448 MsqSendMessage() function (if timed out) */
450 /* Let the sender know the result. */
451 if (Message
->Result
!= NULL
)
453 *Message
->Result
= Result
;
456 if (Message
->HasPackedLParam
== TRUE
)
458 if (Message
->Msg
.lParam
)
459 ExFreePool((PVOID
)Message
->Msg
.lParam
);
462 /* Notify the sender. */
463 if (Message
->CompletionEvent
!= NULL
)
465 KeSetEvent(Message
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
468 /* Call the callback if the message was sent with SendMessageCallback */
469 if (Message
->CompletionCallback
!= NULL
)
471 co_IntCallSentMessageCallback(Message
->CompletionCallback
,
473 Message
->Msg
.message
,
474 Message
->CompletionCallbackContext
,
478 /* Only if it is not a no wait message */
479 if (!(Message
->HookMessage
& MSQ_SENTNOWAIT
))
481 IntDereferenceMessageQueue(Message
->SenderQueue
);
482 IntDereferenceMessageQueue(MessageQueue
);
485 /* free the message */
486 ExFreePoolWithTag(Message
, TAG_USRMSG
);
491 MsqRemoveWindowMessagesFromQueue(PVOID pWindow
)
493 PUSER_SENT_MESSAGE SentMessage
;
494 PUSER_MESSAGE PostedMessage
;
495 PUSER_MESSAGE_QUEUE MessageQueue
;
496 PLIST_ENTRY CurrentEntry
, ListHead
;
497 PWND Window
= pWindow
;
501 MessageQueue
= Window
->head
.pti
->MessageQueue
;
502 ASSERT(MessageQueue
);
504 /* remove the posted messages for this window */
505 CurrentEntry
= MessageQueue
->PostedMessagesListHead
.Flink
;
506 ListHead
= &MessageQueue
->PostedMessagesListHead
;
507 while (CurrentEntry
!= ListHead
)
509 PostedMessage
= CONTAINING_RECORD(CurrentEntry
, USER_MESSAGE
,
511 if (PostedMessage
->Msg
.hwnd
== Window
->head
.h
)
513 RemoveEntryList(&PostedMessage
->ListEntry
);
514 MsqDestroyMessage(PostedMessage
);
515 CurrentEntry
= MessageQueue
->PostedMessagesListHead
.Flink
;
519 CurrentEntry
= CurrentEntry
->Flink
;
523 /* remove the sent messages for this window */
524 CurrentEntry
= MessageQueue
->SentMessagesListHead
.Flink
;
525 ListHead
= &MessageQueue
->SentMessagesListHead
;
526 while (CurrentEntry
!= ListHead
)
528 SentMessage
= CONTAINING_RECORD(CurrentEntry
, USER_SENT_MESSAGE
,
530 if(SentMessage
->Msg
.hwnd
== Window
->head
.h
)
532 DPRINT("Notify the sender and remove a message from the queue that had not been dispatched\n");
534 RemoveEntryList(&SentMessage
->ListEntry
);
536 /* remove the message from the dispatching list if neede */
537 if ((!(SentMessage
->HookMessage
& MSQ_SENTNOWAIT
))
538 && (SentMessage
->DispatchingListEntry
.Flink
!= NULL
))
540 RemoveEntryList(&SentMessage
->DispatchingListEntry
);
543 /* wake the sender's thread */
544 if (SentMessage
->CompletionEvent
!= NULL
)
546 KeSetEvent(SentMessage
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
549 if (SentMessage
->HasPackedLParam
== TRUE
)
551 if (SentMessage
->Msg
.lParam
)
552 ExFreePool((PVOID
)SentMessage
->Msg
.lParam
);
555 /* Only if it is not a no wait message */
556 if (!(SentMessage
->HookMessage
& MSQ_SENTNOWAIT
))
558 /* dereference our and the sender's message queue */
559 IntDereferenceMessageQueue(MessageQueue
);
560 IntDereferenceMessageQueue(SentMessage
->SenderQueue
);
563 /* free the message */
564 ExFreePoolWithTag(SentMessage
, TAG_USRMSG
);
566 CurrentEntry
= MessageQueue
->SentMessagesListHead
.Flink
;
570 CurrentEntry
= CurrentEntry
->Flink
;
576 MsqSendNotifyMessage(PUSER_MESSAGE_QUEUE MessageQueue
,
577 PUSER_SENT_MESSAGE_NOTIFY NotifyMessage
)
579 InsertTailList(&MessageQueue
->NotifyMessagesListHead
,
580 &NotifyMessage
->ListEntry
);
581 MsqWakeQueue(MessageQueue
, QS_SENDMESSAGE
);
585 co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue
,
586 HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
,
587 UINT uTimeout
, BOOL Block
, INT HookMessage
,
591 PUSER_SENT_MESSAGE Message
;
592 KEVENT CompletionEvent
;
594 PUSER_MESSAGE_QUEUE ThreadQueue
;
595 LARGE_INTEGER Timeout
;
597 LRESULT Result
= 0; //// Result could be trashed. ////
599 if(!(Message
= ExAllocatePoolWithTag(PagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
601 DPRINT1("MsqSendMessage(): Not enough memory to allocate a message");
602 return STATUS_INSUFFICIENT_RESOURCES
;
605 KeInitializeEvent(&CompletionEvent
, NotificationEvent
, FALSE
);
607 pti
= PsGetCurrentThreadWin32Thread();
608 ThreadQueue
= pti
->MessageQueue
;
609 ASSERT(ThreadQueue
!= MessageQueue
);
611 Timeout
.QuadPart
= (LONGLONG
) uTimeout
* (LONGLONG
) -10000;
613 /* FIXME - increase reference counter of sender's message queue here */
615 Message
->Msg
.hwnd
= Wnd
;
616 Message
->Msg
.message
= Msg
;
617 Message
->Msg
.wParam
= wParam
;
618 Message
->Msg
.lParam
= lParam
;
619 Message
->CompletionEvent
= &CompletionEvent
;
620 Message
->Result
= &Result
;
621 Message
->SenderQueue
= ThreadQueue
;
622 IntReferenceMessageQueue(ThreadQueue
);
623 Message
->CompletionCallback
= NULL
;
624 Message
->CompletionCallbackContext
= 0;
625 Message
->HookMessage
= HookMessage
;
626 Message
->HasPackedLParam
= FALSE
;
628 IntReferenceMessageQueue(MessageQueue
);
630 /* add it to the list of pending messages */
631 InsertTailList(&ThreadQueue
->DispatchingMessagesHead
, &Message
->DispatchingListEntry
);
633 /* queue it in the destination's message queue */
634 InsertTailList(&MessageQueue
->SentMessagesListHead
, &Message
->ListEntry
);
636 MsqWakeQueue(MessageQueue
, QS_SENDMESSAGE
);
638 /* we can't access the Message anymore since it could have already been deleted! */
644 /* don't process messages sent to the thread */
645 WaitStatus
= KeWaitForSingleObject(&CompletionEvent
, UserRequest
, UserMode
,
646 FALSE
, (uTimeout
? &Timeout
: NULL
));
650 if(WaitStatus
== STATUS_TIMEOUT
)
652 /* look up if the message has not yet dispatched, if so
653 make sure it can't pass a result and it must not set the completion event anymore */
654 Entry
= MessageQueue
->SentMessagesListHead
.Flink
;
655 while (Entry
!= &MessageQueue
->SentMessagesListHead
)
657 if ((PUSER_SENT_MESSAGE
) CONTAINING_RECORD(Entry
, USER_SENT_MESSAGE
, ListEntry
)
660 /* we can access Message here, it's secure because the message queue is locked
661 and the message is still hasn't been dispatched */
662 Message
->CompletionEvent
= NULL
;
663 Message
->Result
= NULL
;
666 Entry
= Entry
->Flink
;
669 /* remove from the local dispatching list so the other thread knows,
670 it can't pass a result and it must not set the completion event anymore */
671 Entry
= ThreadQueue
->DispatchingMessagesHead
.Flink
;
672 while (Entry
!= &ThreadQueue
->DispatchingMessagesHead
)
674 if ((PUSER_SENT_MESSAGE
) CONTAINING_RECORD(Entry
, USER_SENT_MESSAGE
, DispatchingListEntry
)
677 /* we can access Message here, it's secure because the sender's message is locked
678 and the message has definitely not yet been destroyed, otherwise it would
679 have been removed from this list by the dispatching routine right after
680 dispatching the message */
681 Message
->CompletionEvent
= NULL
;
682 Message
->Result
= NULL
;
683 RemoveEntryList(&Message
->DispatchingListEntry
);
684 Message
->DispatchingListEntry
.Flink
= NULL
;
687 Entry
= Entry
->Flink
;
690 DPRINT("MsqSendMessage (blocked) timed out\n");
692 while (co_MsqDispatchOneSentMessage(ThreadQueue
))
697 PVOID WaitObjects
[2];
699 WaitObjects
[0] = &CompletionEvent
;
700 WaitObjects
[1] = ThreadQueue
->NewMessages
;
705 WaitStatus
= KeWaitForMultipleObjects(2, WaitObjects
, WaitAny
, UserRequest
,
706 UserMode
, FALSE
, (uTimeout
? &Timeout
: NULL
), NULL
);
710 if(WaitStatus
== STATUS_TIMEOUT
)
712 /* look up if the message has not yet been dispatched, if so
713 make sure it can't pass a result and it must not set the completion event anymore */
714 Entry
= MessageQueue
->SentMessagesListHead
.Flink
;
715 while (Entry
!= &MessageQueue
->SentMessagesListHead
)
717 if ((PUSER_SENT_MESSAGE
) CONTAINING_RECORD(Entry
, USER_SENT_MESSAGE
, ListEntry
)
720 /* we can access Message here, it's secure because the message queue is locked
721 and the message is still hasn't been dispatched */
722 Message
->CompletionEvent
= NULL
;
723 Message
->Result
= NULL
;
726 Entry
= Entry
->Flink
;
729 /* remove from the local dispatching list so the other thread knows,
730 it can't pass a result and it must not set the completion event anymore */
731 Entry
= ThreadQueue
->DispatchingMessagesHead
.Flink
;
732 while (Entry
!= &ThreadQueue
->DispatchingMessagesHead
)
734 if ((PUSER_SENT_MESSAGE
) CONTAINING_RECORD(Entry
, USER_SENT_MESSAGE
, DispatchingListEntry
)
737 /* we can access Message here, it's secure because the sender's message is locked
738 and the message has definitely not yet been destroyed, otherwise it would
739 have been removed from this list by the dispatching routine right after
740 dispatching the message */
741 Message
->CompletionEvent
= NULL
;
742 Message
->Result
= NULL
;
743 RemoveEntryList(&Message
->DispatchingListEntry
);
744 Message
->DispatchingListEntry
.Flink
= NULL
;
747 Entry
= Entry
->Flink
;
750 DPRINT("MsqSendMessage timed out\n");
753 while (co_MsqDispatchOneSentMessage(ThreadQueue
))
756 while (NT_SUCCESS(WaitStatus
) && STATUS_WAIT_0
!= WaitStatus
);
759 if(WaitStatus
!= STATUS_TIMEOUT
)
760 *uResult
= (STATUS_WAIT_0
== WaitStatus
? Result
: -1);
766 MsqPostMessage(PUSER_MESSAGE_QUEUE MessageQueue
, MSG
* Msg
, BOOLEAN HardwareMessage
,
769 PUSER_MESSAGE Message
;
771 if(!(Message
= MsqCreateMessage(Msg
)))
778 InsertTailList(&MessageQueue
->PostedMessagesListHead
,
779 &Message
->ListEntry
);
783 InsertTailList(&MessageQueue
->HardwareMessagesListHead
,
784 &Message
->ListEntry
);
786 MsqWakeQueue(MessageQueue
, MessageBits
);
790 MsqPostQuitMessage(PUSER_MESSAGE_QUEUE MessageQueue
, ULONG ExitCode
)
792 MessageQueue
->QuitPosted
= TRUE
;
793 MessageQueue
->QuitExitCode
= ExitCode
;
794 MsqWakeQueue(MessageQueue
, QS_POSTMESSAGE
);
797 /***********************************************************************
798 * MsqSendParentNotify
800 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
801 * the window has the WS_EX_NOPARENTNOTIFY style.
803 static void MsqSendParentNotify( PWND pwnd
, WORD event
, WORD idChild
, POINT pt
)
805 PWND pwndDesktop
= UserGetWindowObject(IntGetDesktopWindow());
807 /* pt has to be in the client coordinates of the parent window */
808 pt
.x
+= pwndDesktop
->rcClient
.left
- pwnd
->rcClient
.left
;
809 pt
.y
+= pwndDesktop
->rcClient
.top
- pwnd
->rcClient
.top
;
815 if (!(pwnd
->style
& WS_CHILD
)) break;
816 if (pwnd
->ExStyle
& WS_EX_NOPARENTNOTIFY
) break;
817 if (!(pwndParent
= IntGetParent(pwnd
))) break;
818 if (pwndParent
== pwndDesktop
) break;
819 pt
.x
+= pwnd
->rcClient
.left
- pwndParent
->rcClient
.left
;
820 pt
.y
+= pwnd
->rcClient
.top
- pwndParent
->rcClient
.top
;
823 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_PARENTNOTIFY
,
824 MAKEWPARAM( event
, idChild
), MAKELPARAM( pt
.x
, pt
.y
) );
828 BOOL
co_IntProcessMouseMessage(MSG
* msg
, BOOL
* RemoveMessages
, UINT first
, UINT last
)
835 MOUSEHOOKSTRUCT hook
;
838 PWND pwndMsg
, pwndDesktop
;
839 PUSER_MESSAGE_QUEUE MessageQueue
;
841 PSYSTEM_CURSORINFO CurInfo
;
842 DECLARE_RETURN(BOOL
);
844 pti
= PsGetCurrentThreadWin32Thread();
845 pwndDesktop
= UserGetDesktopWindow();
846 MessageQueue
= pti
->MessageQueue
;
847 CurInfo
= IntGetSysCursorInfo();
848 pwndMsg
= UserGetWindowObject(msg
->hwnd
);
849 clk_msg
= MessageQueue
->msgDblClk
;
851 /* find the window to dispatch this mouse message to */
852 if (MessageQueue
->CaptureWindow
)
855 pwndMsg
= IntGetWindowObject(MessageQueue
->CaptureWindow
);
859 pwndMsg
= co_WinPosWindowFromPoint(pwndMsg
, &msg
->pt
, &hittest
);
862 DPRINT("Got mouse message for 0x%x, hittest: 0x%x\n", msg
->hwnd
, hittest
);
864 if (pwndMsg
== NULL
|| pwndMsg
->head
.pti
!= pti
)
866 /* Remove and ignore the message */
867 *RemoveMessages
= TRUE
;
871 msg
->hwnd
= UserHMGetHandle(pwndMsg
);
874 if (!check_hwnd_filter( msg
, hwnd_filter
)) RETURN(FALSE
);
878 message
= msg
->message
;
879 /* Note: windows has no concept of a non-client wheel message */
880 if (message
!= WM_MOUSEWHEEL
)
882 if (hittest
!= HTCLIENT
)
884 message
+= WM_NCMOUSEMOVE
- WM_MOUSEMOVE
;
885 msg
->wParam
= hittest
;
889 /* coordinates don't get translated while tracking a menu */
890 /* FIXME: should differentiate popups and top-level menus */
891 if (!(MessageQueue
->MenuOwner
))
893 pt
.x
+= pwndDesktop
->rcClient
.left
- pwndMsg
->rcClient
.left
;
894 pt
.y
+= pwndDesktop
->rcClient
.top
- pwndMsg
->rcClient
.top
;
898 msg
->lParam
= MAKELONG( pt
.x
, pt
.y
);
900 /* translate double clicks */
902 if ((msg
->message
== WM_LBUTTONDOWN
) ||
903 (msg
->message
== WM_RBUTTONDOWN
) ||
904 (msg
->message
== WM_MBUTTONDOWN
) ||
905 (msg
->message
== WM_XBUTTONDOWN
))
907 BOOL update
= *RemoveMessages
;
909 /* translate double clicks -
910 * note that ...MOUSEMOVEs can slip in between
911 * ...BUTTONDOWN and ...BUTTONDBLCLK messages */
913 if ((MessageQueue
->MenuOwner
|| MessageQueue
->MoveSize
) ||
914 hittest
!= HTCLIENT
||
915 (pwndMsg
->pcls
->style
& CS_DBLCLKS
))
917 if ((msg
->message
== clk_msg
.message
) &&
918 (msg
->hwnd
== clk_msg
.hwnd
) &&
919 (msg
->wParam
== clk_msg
.wParam
) &&
920 (msg
->time
- clk_msg
.time
< gspv
.iDblClickTime
) &&
921 (abs(msg
->pt
.x
- clk_msg
.pt
.x
) < UserGetSystemMetrics(SM_CXDOUBLECLK
)/2) &&
922 (abs(msg
->pt
.y
- clk_msg
.pt
.y
) < UserGetSystemMetrics(SM_CYDOUBLECLK
)/2))
924 message
+= (WM_LBUTTONDBLCLK
- WM_LBUTTONDOWN
);
927 MessageQueue
->msgDblClk
.message
= 0; /* clear the double click conditions */
933 if (!((first
== 0 && last
== 0) || (message
>= first
|| message
<= last
)))
935 DPRINT("Message out of range!!!\n");
939 /* update static double click conditions */
940 if (update
) MessageQueue
->msgDblClk
= *msg
;
944 if (!((first
== 0 && last
== 0) || (message
>= first
|| message
<= last
)))
946 DPRINT("Message out of range!!!\n");
951 if(gspv
.bMouseClickLock
)
953 BOOL IsClkLck
= FALSE
;
955 if(msg
->message
== WM_LBUTTONUP
)
957 IsClkLck
= ((msg
->time
- CurInfo
->ClickLockTime
) >= gspv
.dwMouseClickLockTime
);
958 if (IsClkLck
&& (!CurInfo
->ClickLockActive
))
960 CurInfo
->ClickLockActive
= TRUE
;
963 else if (msg
->message
== WM_LBUTTONDOWN
)
965 if (CurInfo
->ClickLockActive
)
968 CurInfo
->ClickLockActive
= FALSE
;
971 CurInfo
->ClickLockTime
= msg
->time
;
976 /* Remove and ignore the message */
977 *RemoveMessages
= TRUE
;
982 /* message is accepted now (but may still get dropped) */
984 pti
->rpdesk
->htEx
= hittest
; /* Now set the capture hit. */
986 event
.message
= msg
->message
;
987 event
.time
= msg
->time
;
988 event
.hwnd
= msg
->hwnd
;
989 event
.paramL
= msg
->pt
.x
;
990 event
.paramH
= msg
->pt
.y
;
991 co_HOOK_CallHooks( WH_JOURNALRECORD
, HC_ACTION
, 0, (LPARAM
)&event
);
994 hook
.hwnd
= msg
->hwnd
;
995 hook
.wHitTestCode
= hittest
;
996 hook
.dwExtraInfo
= 0/*extra_info*/;
997 if (co_HOOK_CallHooks( WH_MOUSE
, *RemoveMessages
? HC_ACTION
: HC_NOREMOVE
,
998 message
, (LPARAM
)&hook
))
1001 hook
.hwnd
= msg
->hwnd
;
1002 hook
.wHitTestCode
= hittest
;
1003 hook
.dwExtraInfo
= 0/*extra_info*/;
1004 co_HOOK_CallHooks( WH_CBT
, HCBT_CLICKSKIPPED
, message
, (LPARAM
)&hook
);
1006 DPRINT1("WH_MOUSE dorpped mouse message!\n");
1008 /* Remove and skip message */
1009 *RemoveMessages
= TRUE
;
1013 if ((hittest
== HTERROR
) || (hittest
== HTNOWHERE
))
1015 co_IntSendMessage( msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)msg
->hwnd
,
1016 MAKELONG( hittest
, msg
->message
));
1018 /* Remove and skip message */
1019 *RemoveMessages
= TRUE
;
1023 if ((*RemoveMessages
== FALSE
) || MessageQueue
->CaptureWindow
)
1025 /* Accept the message */
1026 msg
->message
= message
;
1032 if ((msg
->message
== WM_LBUTTONDOWN
) ||
1033 (msg
->message
== WM_RBUTTONDOWN
) ||
1034 (msg
->message
== WM_MBUTTONDOWN
) ||
1035 (msg
->message
== WM_XBUTTONDOWN
))
1037 /* Send the WM_PARENTNOTIFY,
1038 * note that even for double/nonclient clicks
1039 * notification message is still WM_L/M/RBUTTONDOWN.
1041 MsqSendParentNotify(pwndMsg
, msg
->message
, 0, msg
->pt
);
1043 /* Activate the window if needed */
1045 if (msg
->hwnd
!= MessageQueue
->ActiveWindow
)
1047 PWND pwndTop
= pwndMsg
;
1050 if ((pwndTop
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
) break;
1051 pwndTop
= IntGetParent( pwndTop
);
1054 if (pwndTop
&& pwndTop
!= pwndDesktop
)
1056 LONG ret
= co_IntSendMessage( msg
->hwnd
,
1058 (WPARAM
)UserHMGetHandle(pwndTop
),
1059 MAKELONG( hittest
, msg
->message
));
1062 case MA_NOACTIVATEANDEAT
:
1067 case MA_ACTIVATEANDEAT
:
1072 if(!co_IntMouseActivateWindow(pwndMsg
)) eatMsg
= TRUE
;
1075 DPRINT1( "unknown WM_MOUSEACTIVATE code %d\n", ret
);
1082 /* send the WM_SETCURSOR message */
1084 /* Windows sends the normal mouse message as the message parameter
1085 in the WM_SETCURSOR message even if it's non-client mouse message */
1086 co_IntSendMessage( msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)msg
->hwnd
, MAKELONG( hittest
, msg
->message
));
1088 msg
->message
= message
;
1093 UserDereferenceObject(pwndMsg
);
1098 BOOL
co_IntProcessKeyboardMessage(MSG
* Msg
, BOOL
* RemoveMessages
)
1102 Event
.message
= Msg
->message
;
1103 Event
.hwnd
= Msg
->hwnd
;
1104 Event
.time
= Msg
->time
;
1105 Event
.paramL
= (Msg
->wParam
& 0xFF) | (HIWORD(Msg
->lParam
) << 8);
1106 Event
.paramH
= Msg
->lParam
& 0x7FFF;
1107 if (HIWORD(Msg
->lParam
) & 0x0100) Event
.paramH
|= 0x8000;
1108 co_HOOK_CallHooks( WH_JOURNALRECORD
, HC_ACTION
, 0, (LPARAM
)&Event
);
1110 if (co_HOOK_CallHooks( WH_KEYBOARD
,
1111 *RemoveMessages
? HC_ACTION
: HC_NOREMOVE
,
1112 LOWORD(Msg
->wParam
),
1115 /* skip this message */
1116 co_HOOK_CallHooks( WH_CBT
,
1118 LOWORD(Msg
->wParam
),
1120 DPRINT1("KeyboardMessage WH_CBT Call Hook return!\n");
1126 BOOL
co_IntProcessHardwareMessage(MSG
* Msg
, BOOL
* RemoveMessages
, UINT first
, UINT last
)
1128 if ( IS_MOUSE_MESSAGE(Msg
->message
))
1130 return co_IntProcessMouseMessage(Msg
, RemoveMessages
, first
, last
);
1132 else if ( IS_KBD_MESSAGE(Msg
->message
))
1134 return co_IntProcessKeyboardMessage(Msg
, RemoveMessages
);
1141 co_MsqPeekMouseMove(IN PUSER_MESSAGE_QUEUE MessageQueue
,
1144 IN UINT MsgFilterLow
,
1145 IN UINT MsgFilterHigh
,
1151 if(!(MessageQueue
->MouseMoved
))
1154 msg
= MessageQueue
->MouseMoveMsg
;
1156 AcceptMessage
= co_IntProcessMouseMessage(&msg
, &Remove
, MsgFilterLow
, MsgFilterHigh
);
1162 MessageQueue
->MouseMoved
= FALSE
;
1164 return AcceptMessage
;
1168 co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue
,
1171 IN UINT MsgFilterLow
,
1172 IN UINT MsgFilterHigh
,
1177 PUSER_MESSAGE CurrentMessage
;
1178 PLIST_ENTRY ListHead
, CurrentEntry
= NULL
;
1181 ListHead
= &MessageQueue
->HardwareMessagesListHead
;
1182 CurrentEntry
= ListHead
->Flink
;
1184 while(CurrentEntry
!= ListHead
)
1186 CurrentMessage
= CONTAINING_RECORD(CurrentEntry
, USER_MESSAGE
,
1189 msg
= CurrentMessage
->Msg
;
1191 AcceptMessage
= co_IntProcessHardwareMessage(&msg
, &Remove
, MsgFilterLow
, MsgFilterHigh
);
1193 CurrentEntry
= CurrentMessage
->ListEntry
.Flink
;
1197 RemoveEntryList(&CurrentMessage
->ListEntry
);
1198 MsqDestroyMessage(CurrentMessage
);
1213 MsqPeekMessage(IN PUSER_MESSAGE_QUEUE MessageQueue
,
1216 IN UINT MsgFilterLow
,
1217 IN UINT MsgFilterHigh
,
1220 PLIST_ENTRY CurrentEntry
;
1221 PUSER_MESSAGE CurrentMessage
;
1222 PLIST_ENTRY ListHead
;
1224 CurrentEntry
= MessageQueue
->PostedMessagesListHead
.Flink
;
1225 ListHead
= &MessageQueue
->PostedMessagesListHead
;
1226 while (CurrentEntry
!= ListHead
)
1228 CurrentMessage
= CONTAINING_RECORD(CurrentEntry
, USER_MESSAGE
,
1231 PtrToInt(Window
) == 1 ||
1232 Window
->head
.h
== CurrentMessage
->Msg
.hwnd
) &&
1233 ( (MsgFilterLow
== 0 && MsgFilterHigh
== 0) ||
1234 ( MsgFilterLow
<= CurrentMessage
->Msg
.message
&&
1235 MsgFilterHigh
>= CurrentMessage
->Msg
.message
) ) )
1237 *Message
= CurrentMessage
->Msg
;
1241 RemoveEntryList(&CurrentMessage
->ListEntry
);
1242 MsqDestroyMessage(CurrentMessage
);
1247 CurrentEntry
= CurrentEntry
->Flink
;
1254 co_MsqWaitForNewMessages(PUSER_MESSAGE_QUEUE MessageQueue
, PWND WndFilter
,
1255 UINT MsgFilterMin
, UINT MsgFilterMax
)
1260 ret
= KeWaitForSingleObject(MessageQueue
->NewMessages
,
1270 MsqIsHung(PUSER_MESSAGE_QUEUE MessageQueue
)
1272 LARGE_INTEGER LargeTickCount
;
1274 KeQueryTickCount(&LargeTickCount
);
1275 return ((LargeTickCount
.u
.LowPart
- MessageQueue
->LastMsgRead
) > MSQ_HUNG
);
1279 MsqInitializeMessageQueue(struct _ETHREAD
*Thread
, PUSER_MESSAGE_QUEUE MessageQueue
)
1281 LARGE_INTEGER LargeTickCount
;
1284 MessageQueue
->Thread
= Thread
;
1285 MessageQueue
->CaretInfo
= (PTHRDCARETINFO
)(MessageQueue
+ 1);
1286 InitializeListHead(&MessageQueue
->PostedMessagesListHead
);
1287 InitializeListHead(&MessageQueue
->SentMessagesListHead
);
1288 InitializeListHead(&MessageQueue
->HardwareMessagesListHead
);
1289 InitializeListHead(&MessageQueue
->DispatchingMessagesHead
);
1290 InitializeListHead(&MessageQueue
->LocalDispatchingMessagesHead
);
1291 KeInitializeMutex(&MessageQueue
->HardwareLock
, 0);
1292 MessageQueue
->QuitPosted
= FALSE
;
1293 MessageQueue
->QuitExitCode
= 0;
1294 KeQueryTickCount(&LargeTickCount
);
1295 MessageQueue
->LastMsgRead
= LargeTickCount
.u
.LowPart
;
1296 MessageQueue
->FocusWindow
= NULL
;
1297 MessageQueue
->PaintCount
= 0;
1298 // HACK!!!!!!! Newbies that wrote this should hold your head down in shame! (jt)
1299 MessageQueue
->WakeMask
= ~0;
1300 MessageQueue
->NewMessagesHandle
= NULL
;
1302 Status
= ZwCreateEvent(&MessageQueue
->NewMessagesHandle
, EVENT_ALL_ACCESS
,
1303 NULL
, SynchronizationEvent
, FALSE
);
1304 if (!NT_SUCCESS(Status
))
1309 Status
= ObReferenceObjectByHandle(MessageQueue
->NewMessagesHandle
, 0,
1310 ExEventObjectType
, KernelMode
,
1311 (PVOID
*)&MessageQueue
->NewMessages
, NULL
);
1312 if (!NT_SUCCESS(Status
))
1314 ZwClose(MessageQueue
->NewMessagesHandle
);
1315 MessageQueue
->NewMessagesHandle
= NULL
;
1323 MsqCleanupMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue
)
1325 PLIST_ENTRY CurrentEntry
;
1326 PUSER_MESSAGE CurrentMessage
;
1327 PUSER_SENT_MESSAGE CurrentSentMessage
;
1329 /* cleanup posted messages */
1330 while (!IsListEmpty(&MessageQueue
->PostedMessagesListHead
))
1332 CurrentEntry
= RemoveHeadList(&MessageQueue
->PostedMessagesListHead
);
1333 CurrentMessage
= CONTAINING_RECORD(CurrentEntry
, USER_MESSAGE
,
1335 MsqDestroyMessage(CurrentMessage
);
1338 /* remove the messages that have not yet been dispatched */
1339 while (!IsListEmpty(&MessageQueue
->SentMessagesListHead
))
1341 CurrentEntry
= RemoveHeadList(&MessageQueue
->SentMessagesListHead
);
1342 CurrentSentMessage
= CONTAINING_RECORD(CurrentEntry
, USER_SENT_MESSAGE
,
1345 DPRINT("Notify the sender and remove a message from the queue that had not been dispatched\n");
1347 /* remove the message from the dispatching list if needed */
1348 if ((!(CurrentSentMessage
->HookMessage
& MSQ_SENTNOWAIT
))
1349 && (CurrentSentMessage
->DispatchingListEntry
.Flink
!= NULL
))
1351 RemoveEntryList(&CurrentSentMessage
->DispatchingListEntry
);
1354 /* wake the sender's thread */
1355 if (CurrentSentMessage
->CompletionEvent
!= NULL
)
1357 KeSetEvent(CurrentSentMessage
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
1360 if (CurrentSentMessage
->HasPackedLParam
== TRUE
)
1362 if (CurrentSentMessage
->Msg
.lParam
)
1363 ExFreePool((PVOID
)CurrentSentMessage
->Msg
.lParam
);
1366 /* Only if it is not a no wait message */
1367 if (!(CurrentSentMessage
->HookMessage
& MSQ_SENTNOWAIT
))
1369 /* dereference our and the sender's message queue */
1370 IntDereferenceMessageQueue(MessageQueue
);
1371 IntDereferenceMessageQueue(CurrentSentMessage
->SenderQueue
);
1374 /* free the message */
1375 ExFreePool(CurrentSentMessage
);
1378 /* notify senders of dispatching messages. This needs to be cleaned up if e.g.
1379 ExitThread() was called in a SendMessage() umode callback */
1380 while (!IsListEmpty(&MessageQueue
->LocalDispatchingMessagesHead
))
1382 CurrentEntry
= RemoveHeadList(&MessageQueue
->LocalDispatchingMessagesHead
);
1383 CurrentSentMessage
= CONTAINING_RECORD(CurrentEntry
, USER_SENT_MESSAGE
,
1386 /* remove the message from the dispatching list */
1387 if(CurrentSentMessage
->DispatchingListEntry
.Flink
!= NULL
)
1389 RemoveEntryList(&CurrentSentMessage
->DispatchingListEntry
);
1392 DPRINT("Notify the sender, the thread has been terminated while dispatching a message!\n");
1394 /* wake the sender's thread */
1395 if (CurrentSentMessage
->CompletionEvent
!= NULL
)
1397 KeSetEvent(CurrentSentMessage
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
1400 if (CurrentSentMessage
->HasPackedLParam
== TRUE
)
1402 if (CurrentSentMessage
->Msg
.lParam
)
1403 ExFreePool((PVOID
)CurrentSentMessage
->Msg
.lParam
);
1406 /* Only if it is not a no wait message */
1407 if (!(CurrentSentMessage
->HookMessage
& MSQ_SENTNOWAIT
))
1409 /* dereference our and the sender's message queue */
1410 IntDereferenceMessageQueue(MessageQueue
);
1411 IntDereferenceMessageQueue(CurrentSentMessage
->SenderQueue
);
1414 /* free the message */
1415 ExFreePool(CurrentSentMessage
);
1418 /* tell other threads not to bother returning any info to us */
1419 while (! IsListEmpty(&MessageQueue
->DispatchingMessagesHead
))
1421 CurrentEntry
= RemoveHeadList(&MessageQueue
->DispatchingMessagesHead
);
1422 CurrentSentMessage
= CONTAINING_RECORD(CurrentEntry
, USER_SENT_MESSAGE
,
1423 DispatchingListEntry
);
1424 CurrentSentMessage
->CompletionEvent
= NULL
;
1425 CurrentSentMessage
->Result
= NULL
;
1427 /* do NOT dereference our message queue as it might get attempted to be
1433 PUSER_MESSAGE_QUEUE FASTCALL
1434 MsqCreateMessageQueue(struct _ETHREAD
*Thread
)
1436 PUSER_MESSAGE_QUEUE MessageQueue
;
1438 MessageQueue
= (PUSER_MESSAGE_QUEUE
)ExAllocatePoolWithTag(NonPagedPool
,
1439 sizeof(USER_MESSAGE_QUEUE
) + sizeof(THRDCARETINFO
),
1447 RtlZeroMemory(MessageQueue
, sizeof(USER_MESSAGE_QUEUE
) + sizeof(THRDCARETINFO
));
1448 /* hold at least one reference until it'll be destroyed */
1449 IntReferenceMessageQueue(MessageQueue
);
1450 /* initialize the queue */
1451 if (!MsqInitializeMessageQueue(Thread
, MessageQueue
))
1453 IntDereferenceMessageQueue(MessageQueue
);
1457 return MessageQueue
;
1461 MsqDestroyMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue
)
1465 /* remove the message queue from any desktops */
1466 if ((desk
= InterlockedExchangePointer((PVOID
*)&MessageQueue
->Desktop
, 0)))
1468 (void)InterlockedExchangePointer((PVOID
*)&desk
->ActiveMessageQueue
, 0);
1469 IntDereferenceMessageQueue(MessageQueue
);
1473 MsqCleanupMessageQueue(MessageQueue
);
1475 /* decrease the reference counter, if it hits zero, the queue will be freed */
1476 IntDereferenceMessageQueue(MessageQueue
);
1480 MsqSetMessageExtraInfo(LPARAM lParam
)
1484 PUSER_MESSAGE_QUEUE MessageQueue
;
1486 pti
= PsGetCurrentThreadWin32Thread();
1487 MessageQueue
= pti
->MessageQueue
;
1493 Ret
= MessageQueue
->ExtraInfo
;
1494 MessageQueue
->ExtraInfo
= lParam
;
1500 MsqGetMessageExtraInfo(VOID
)
1503 PUSER_MESSAGE_QUEUE MessageQueue
;
1505 pti
= PsGetCurrentThreadWin32Thread();
1506 MessageQueue
= pti
->MessageQueue
;
1512 return MessageQueue
->ExtraInfo
;
1516 MsqSetStateWindow(PUSER_MESSAGE_QUEUE MessageQueue
, ULONG Type
, HWND hWnd
)
1522 case MSQ_STATE_CAPTURE
:
1523 Prev
= MessageQueue
->CaptureWindow
;
1524 MessageQueue
->CaptureWindow
= hWnd
;
1526 case MSQ_STATE_ACTIVE
:
1527 Prev
= MessageQueue
->ActiveWindow
;
1528 MessageQueue
->ActiveWindow
= hWnd
;
1530 case MSQ_STATE_FOCUS
:
1531 Prev
= MessageQueue
->FocusWindow
;
1532 MessageQueue
->FocusWindow
= hWnd
;
1534 case MSQ_STATE_MENUOWNER
:
1535 Prev
= MessageQueue
->MenuOwner
;
1536 MessageQueue
->MenuOwner
= hWnd
;
1538 case MSQ_STATE_MOVESIZE
:
1539 Prev
= MessageQueue
->MoveSize
;
1540 MessageQueue
->MoveSize
= hWnd
;
1542 case MSQ_STATE_CARET
:
1543 ASSERT(MessageQueue
->CaretInfo
);
1544 Prev
= MessageQueue
->CaretInfo
->hWnd
;
1545 MessageQueue
->CaretInfo
->hWnd
= hWnd
;