2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Message queues
5 * FILE: subsystems/win32/win32k/ntuser/msgqueue.c
6 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
10 * 06-06-2001 CSH Created
13 /* INCLUDES ******************************************************************/
20 VOID FASTCALL
DoTheScreenSaver(VOID
);
22 /* GLOBALS *******************************************************************/
24 static PAGED_LOOKASIDE_LIST MessageLookasideList
;
25 MOUSEMOVEPOINT MouseHistoryOfMoves
[64];
28 /* FUNCTIONS *****************************************************************/
33 MsqInitializeImpl(VOID
)
35 ExInitializePagedLookasideList(&MessageLookasideList
,
43 return(STATUS_SUCCESS
);
47 IntChildrenWindowFromPoint(PWND pWndTop
, INT x
, INT y
)
51 if (!(pWndTop
->style
& WS_VISIBLE
)) return NULL
;
52 if ((pWndTop
->style
& WS_DISABLED
)) return NULL
;
53 if (!IntPtInWindow(pWndTop
, x
, y
)) return NULL
;
55 if (x
- pWndTop
->rcClient
.left
< pWndTop
->rcClient
.right
&&
56 y
- pWndTop
->rcClient
.top
< pWndTop
->rcClient
.bottom
)
58 for (pWnd
= pWndTop
->spwndChild
;
60 pWnd
= pWnd
->spwndNext
)
62 if (pWnd
->state2
& WNDS2_INDESTROY
|| pWnd
->state
& WNDS_DESTROYED
)
64 DPRINT("The Window is in DESTROY!\n");
68 pWndChild
= IntChildrenWindowFromPoint(pWnd
, x
, y
);
80 IntTopLevelWindowFromPoint(INT x
, INT y
)
82 PWND pWnd
, pwndDesktop
;
84 /* Get the desktop window */
85 pwndDesktop
= UserGetDesktopWindow();
89 /* Loop all top level windows */
90 for (pWnd
= pwndDesktop
->spwndChild
;
92 pWnd
= pWnd
->spwndNext
)
94 if (pWnd
->state2
& WNDS2_INDESTROY
|| pWnd
->state
& WNDS_DESTROYED
)
96 DPRINT("The Window is in DESTROY!\n");
100 if ((pWnd
->style
& WS_VISIBLE
) && IntPtInWindow(pWnd
, x
, y
))
104 /* Window has not been found */
111 PCURICON_OBJECT NewCursor
,
114 PCURICON_OBJECT OldCursor
;
117 PUSER_MESSAGE_QUEUE MessageQueue
;
120 pti
= PsGetCurrentThreadWin32Thread();
121 MessageQueue
= pti
->MessageQueue
;
123 /* Get the screen DC */
124 if(!(hdcScreen
= IntGetScreenDC()))
129 OldCursor
= MessageQueue
->CursorObject
;
131 /* Check if cursors are different */
132 if (OldCursor
== NewCursor
)
135 /* Update cursor for this message queue */
136 MessageQueue
->CursorObject
= NewCursor
;
138 /* If cursor is not visible we have nothing to do */
139 if (MessageQueue
->ShowingCursor
< 0)
142 /* Update cursor if this message queue controls it */
143 pWnd
= IntTopLevelWindowFromPoint(gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
144 if (pWnd
&& pWnd
->head
.pti
->MessageQueue
== MessageQueue
)
148 /* Call GDI to set the new screen cursor */
149 GreSetPointerShape(hdcScreen
,
150 NewCursor
->IconInfo
.hbmMask
,
151 NewCursor
->IconInfo
.hbmColor
,
152 NewCursor
->IconInfo
.xHotspot
,
153 NewCursor
->IconInfo
.yHotspot
,
157 else /* Note: OldCursor != NewCursor so we have to hide cursor */
159 /* Remove the cursor */
160 GreMovePointer(hdcScreen
, -1, -1);
161 DPRINT("Removing pointer!\n");
163 IntGetSysCursorInfo()->CurrentCursorObject
= NewCursor
;
166 /* Return the old cursor */
170 /* Called from NtUserCallOneParam with Routine ONEPARAM_ROUTINE_SHOWCURSOR
171 * User32 macro NtUserShowCursor */
172 int UserShowCursor(BOOL bShow
)
176 PUSER_MESSAGE_QUEUE MessageQueue
;
179 if (!(hdcScreen
= IntGetScreenDC()))
181 return -1; /* No mouse */
184 pti
= PsGetCurrentThreadWin32Thread();
185 MessageQueue
= pti
->MessageQueue
;
188 MessageQueue
->ShowingCursor
+= bShow
? 1 : -1;
190 /* Check for trivial cases */
191 if ((bShow
&& MessageQueue
->ShowingCursor
!= 0) ||
192 (!bShow
&& MessageQueue
->ShowingCursor
!= -1))
194 /* Note: w don't update global info here because it is used only
195 internally to check if cursor is visible */
196 return MessageQueue
->ShowingCursor
;
199 /* Check if cursor is above window owned by this MessageQueue */
200 pWnd
= IntTopLevelWindowFromPoint(gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
201 if (pWnd
&& pWnd
->head
.pti
->MessageQueue
== MessageQueue
)
205 /* Show the pointer */
206 GreMovePointer(hdcScreen
, gpsi
->ptCursor
.x
, gpsi
->ptCursor
.y
);
207 DPRINT("Showing pointer!\n");
211 /* Remove the pointer */
212 GreMovePointer(hdcScreen
, -1, -1);
213 DPRINT("Removing pointer!\n");
216 /* Update global info */
217 IntGetSysCursorInfo()->ShowingCursor
= MessageQueue
->ShowingCursor
;
220 return MessageQueue
->ShowingCursor
;
223 DWORD FASTCALL
UserGetKeyState(DWORD key
)
227 PUSER_MESSAGE_QUEUE MessageQueue
;
229 pti
= PsGetCurrentThreadWin32Thread();
230 MessageQueue
= pti
->MessageQueue
;
234 ret
= (DWORD
)MessageQueue
->KeyState
[key
];
235 if (MessageQueue
->KeyState
[key
] & KS_DOWN_BIT
)
236 ret
|= 0xFF00; // If down, windows returns 0xFF80.
240 EngSetLastError(ERROR_INVALID_PARAMETER
);
245 /* change the input key state for a given key */
246 static void set_input_key_state( PUSER_MESSAGE_QUEUE MessageQueue
, UCHAR key
, BOOL down
)
248 DPRINT("set_input_key_state key:%d, down:%d\n", key
, down
);
252 if (!(MessageQueue
->KeyState
[key
] & KS_DOWN_BIT
))
254 MessageQueue
->KeyState
[key
] ^= KS_LOCK_BIT
;
256 MessageQueue
->KeyState
[key
] |= KS_DOWN_BIT
;
260 MessageQueue
->KeyState
[key
] &= ~KS_DOWN_BIT
;
264 /* update the input key state for a keyboard message */
265 static void update_input_key_state( PUSER_MESSAGE_QUEUE MessageQueue
, MSG
* msg
)
270 DPRINT("update_input_key_state message:%d\n", msg
->message
);
272 switch (msg
->message
)
278 set_input_key_state( MessageQueue
, VK_LBUTTON
, down
);
284 set_input_key_state( MessageQueue
, VK_MBUTTON
, down
);
290 set_input_key_state( MessageQueue
, VK_RBUTTON
, down
);
296 if (msg
->wParam
== XBUTTON1
)
297 set_input_key_state( MessageQueue
, VK_XBUTTON1
, down
);
298 else if (msg
->wParam
== XBUTTON2
)
299 set_input_key_state( MessageQueue
, VK_XBUTTON2
, down
);
307 key
= (UCHAR
)msg
->wParam
;
308 set_input_key_state( MessageQueue
, key
, down
);
313 down
= (MessageQueue
->KeyState
[VK_LCONTROL
] | MessageQueue
->KeyState
[VK_RCONTROL
]) & KS_DOWN_BIT
;
314 set_input_key_state( MessageQueue
, VK_CONTROL
, down
);
318 down
= (MessageQueue
->KeyState
[VK_LMENU
] | MessageQueue
->KeyState
[VK_RMENU
]) & KS_DOWN_BIT
;
319 set_input_key_state( MessageQueue
, VK_MENU
, down
);
323 down
= (MessageQueue
->KeyState
[VK_LSHIFT
] | MessageQueue
->KeyState
[VK_RSHIFT
]) & KS_DOWN_BIT
;
324 set_input_key_state( MessageQueue
, VK_SHIFT
, down
);
332 IntMsqSetWakeMask(DWORD WakeMask
)
334 PTHREADINFO Win32Thread
;
335 PUSER_MESSAGE_QUEUE MessageQueue
;
336 HANDLE MessageEventHandle
;
337 DWORD dwFlags
= HIWORD(WakeMask
);
339 Win32Thread
= PsGetCurrentThreadWin32Thread();
340 if (Win32Thread
== NULL
|| Win32Thread
->MessageQueue
== NULL
)
343 MessageQueue
= Win32Thread
->MessageQueue
;
344 // Win32Thread->pEventQueueServer; IntMsqSetWakeMask returns Win32Thread->hEventQueueClient
345 MessageEventHandle
= MessageQueue
->NewMessagesHandle
;
347 if (Win32Thread
->pcti
)
349 if ( (Win32Thread
->pcti
->fsChangeBits
& LOWORD(WakeMask
)) ||
350 ( (dwFlags
& MWMO_INPUTAVAILABLE
) && (Win32Thread
->pcti
->fsWakeBits
& LOWORD(WakeMask
)) ) )
352 DPRINT1("Chg 0x%x Wake 0x%x Mask 0x%x\n",Win32Thread
->pcti
->fsChangeBits
, Win32Thread
->pcti
->fsWakeBits
, WakeMask
);
353 KeSetEvent(MessageQueue
->NewMessages
, IO_NO_INCREMENT
, FALSE
); // Wake it up!
354 return MessageEventHandle
;
360 return MessageEventHandle
;
364 IntMsqClearWakeMask(VOID
)
366 PTHREADINFO Win32Thread
;
368 Win32Thread
= PsGetCurrentThreadWin32Thread();
369 if (Win32Thread
== NULL
|| Win32Thread
->MessageQueue
== NULL
)
371 // Very hacky, but that is what they do.
372 Win32Thread
->pcti
->fsWakeBits
= 0;
380 Due to the uncertainty of knowing what was set in our multilevel message queue,
381 and even if the bits are all cleared. The same as cTimers/cPaintsReady.
382 I think this is the best solution... (jt) */
384 MsqWakeQueue(PUSER_MESSAGE_QUEUE Queue
, DWORD MessageBits
, BOOL KeyEvent
)
388 pti
= Queue
->Thread
->Tcb
.Win32Thread
;
389 pti
->pcti
->fsWakeBits
|= MessageBits
;
390 pti
->pcti
->fsChangeBits
|= MessageBits
;
392 // Start bit accounting to help clear the main set of bits.
393 if (MessageBits
& QS_KEY
) Queue
->nCntsQBits
[QSRosKey
]++;
394 if (MessageBits
& QS_MOUSEMOVE
) Queue
->nCntsQBits
[QSRosMouseMove
]++;
395 if (MessageBits
& QS_MOUSEBUTTON
) Queue
->nCntsQBits
[QSRosMouseButton
]++;
396 if (MessageBits
& QS_POSTMESSAGE
) Queue
->nCntsQBits
[QSRosPostMessage
]++;
397 if (MessageBits
& QS_SENDMESSAGE
) Queue
->nCntsQBits
[QSRosSendMessage
]++;
398 if (MessageBits
& QS_HOTKEY
) Queue
->nCntsQBits
[QSRosHotKey
]++;
401 KeSetEvent(Queue
->NewMessages
, IO_NO_INCREMENT
, FALSE
);
405 ClearMsgBitsMask(PUSER_MESSAGE_QUEUE Queue
, UINT MessageBits
)
410 pti
= Queue
->Thread
->Tcb
.Win32Thread
;
412 if (MessageBits
& QS_KEY
)
414 if (--Queue
->nCntsQBits
[QSRosKey
] == 0) ClrMask
|= QS_KEY
;
416 if (MessageBits
& QS_MOUSEMOVE
) // ReactOS hard coded.
417 { // Account for tracking mouse moves..
418 if (--Queue
->nCntsQBits
[QSRosMouseMove
] == 0) ClrMask
|= QS_MOUSEMOVE
;
419 // Handle mouse move bits here.
420 if (Queue
->MouseMoved
) ClrMask
|= QS_MOUSEMOVE
;
422 if (MessageBits
& QS_MOUSEBUTTON
)
424 if (--Queue
->nCntsQBits
[QSRosMouseButton
] == 0) ClrMask
|= QS_MOUSEBUTTON
;
426 if (MessageBits
& QS_POSTMESSAGE
)
428 if (--Queue
->nCntsQBits
[QSRosPostMessage
] == 0) ClrMask
|= QS_POSTMESSAGE
;
430 if (MessageBits
& QS_TIMER
) // ReactOS hard coded.
431 { // Handle timer bits here.
432 if ( pti
->cTimersReady
)
434 if (--pti
->cTimersReady
== 0) ClrMask
|= QS_TIMER
;
437 if (MessageBits
& QS_PAINT
) // ReactOS hard coded.
438 { // Handle paint bits here.
439 if ( pti
->cPaintsReady
)
441 if (--pti
->cPaintsReady
== 0) ClrMask
|= QS_PAINT
;
444 if (MessageBits
& QS_SENDMESSAGE
)
446 if (--Queue
->nCntsQBits
[QSRosSendMessage
] == 0) ClrMask
|= QS_SENDMESSAGE
;
448 if (MessageBits
& QS_HOTKEY
)
450 if (--Queue
->nCntsQBits
[QSRosHotKey
] == 0) ClrMask
|= QS_HOTKEY
;
453 pti
->pcti
->fsWakeBits
&= ~ClrMask
;
454 pti
->pcti
->fsChangeBits
&= ~ClrMask
;
458 MsqIncPaintCountQueue(PUSER_MESSAGE_QUEUE Queue
)
461 pti
= Queue
->Thread
->Tcb
.Win32Thread
;
463 MsqWakeQueue(Queue
, QS_PAINT
, TRUE
);
467 MsqDecPaintCountQueue(PUSER_MESSAGE_QUEUE Queue
)
469 ClearMsgBitsMask(Queue
, QS_PAINT
);
473 MsqPostMouseMove(PUSER_MESSAGE_QUEUE MessageQueue
, MSG
* Msg
)
475 MessageQueue
->MouseMoveMsg
= *Msg
;
476 MessageQueue
->MouseMoved
= TRUE
;
477 MsqWakeQueue(MessageQueue
, QS_MOUSEMOVE
, TRUE
);
481 co_MsqInsertMouseMessage(MSG
* Msg
, DWORD flags
, ULONG_PTR dwExtraInfo
, BOOL Hook
)
483 LARGE_INTEGER LargeTickCount
;
484 MSLLHOOKSTRUCT MouseHookData
;
486 PWND pwnd
, pwndDesktop
;
488 PSYSTEM_CURSORINFO CurInfo
;
490 KeQueryTickCount(&LargeTickCount
);
491 Msg
->time
= MsqCalculateMessageTime(&LargeTickCount
);
493 MouseHookData
.pt
.x
= LOWORD(Msg
->lParam
);
494 MouseHookData
.pt
.y
= HIWORD(Msg
->lParam
);
495 switch (Msg
->message
)
498 MouseHookData
.mouseData
= MAKELONG(0, GET_WHEEL_DELTA_WPARAM(Msg
->wParam
));
502 case WM_XBUTTONDBLCLK
:
503 case WM_NCXBUTTONDOWN
:
505 case WM_NCXBUTTONDBLCLK
:
506 MouseHookData
.mouseData
= MAKELONG(0, HIWORD(Msg
->wParam
));
509 MouseHookData
.mouseData
= 0;
513 MouseHookData
.flags
= flags
; // LLMHF_INJECTED
514 MouseHookData
.time
= Msg
->time
;
515 MouseHookData
.dwExtraInfo
= dwExtraInfo
;
517 /* If the hook procedure returned non zero, dont send the message */
520 if (co_HOOK_CallHooks(WH_MOUSE_LL
, HC_ACTION
, Msg
->message
, (LPARAM
) &MouseHookData
))
524 /* Get the desktop window */
525 pwndDesktop
= UserGetDesktopWindow();
526 if (!pwndDesktop
) return;
527 pDesk
= pwndDesktop
->head
.rpdesk
;
529 /* Check if the mouse is captured */
530 Msg
->hwnd
= IntGetCaptureWindow();
531 if (Msg
->hwnd
!= NULL
)
533 pwnd
= UserGetWindowObject(Msg
->hwnd
);
537 pwnd
= IntTopLevelWindowFromPoint(Msg
->pt
.x
, Msg
->pt
.y
);
538 if (pwnd
) Msg
->hwnd
= pwnd
->head
.h
;
543 PWND pwndTrack
= IntChildrenWindowFromPoint(pwnd
, Msg
->pt
.x
, Msg
->pt
.y
);
545 if ( pDesk
->spwndTrack
!= pwndTrack
&& pDesk
->dwDTFlags
& (DF_TME_LEAVE
|DF_TME_HOVER
) )
547 if ( pDesk
->dwDTFlags
& DF_TME_LEAVE
)
548 UserPostMessage( UserHMGetHandle(pDesk
->spwndTrack
),
549 (pDesk
->htEx
!= HTCLIENT
) ? WM_NCMOUSELEAVE
: WM_MOUSELEAVE
,
552 if ( pDesk
->dwDTFlags
& DF_TME_HOVER
)
553 IntKillTimer(UserHMGetHandle(pDesk
->spwndTrack
), ID_EVENT_SYSTIMER_MOUSEHOVER
, TRUE
);
555 pDesk
->dwDTFlags
&= ~(DF_TME_LEAVE
|DF_TME_HOVER
);
557 pDesk
->spwndTrack
= pwndTrack
;
558 pDesk
->htEx
= GetNCHitEx(pDesk
->spwndTrack
, Msg
->pt
);
561 hdcScreen
= IntGetScreenDC();
562 CurInfo
= IntGetSysCursorInfo();
564 /* Check if we found a window */
565 if (Msg
->hwnd
!= NULL
&& pwnd
!= NULL
)
567 if (Msg
->message
== WM_MOUSEMOVE
)
569 PUSER_MESSAGE_QUEUE MessageQueue
= pwnd
->head
.pti
->MessageQueue
;
571 /* Check if cursor should be visible */
573 MessageQueue
->CursorObject
&&
574 MessageQueue
->ShowingCursor
>= 0)
576 /* Check if shape has changed */
577 if(CurInfo
->CurrentCursorObject
!= MessageQueue
->CursorObject
)
579 /* Call GDI to set the new screen cursor */
580 GreSetPointerShape(hdcScreen
,
581 MessageQueue
->CursorObject
->IconInfo
.hbmMask
,
582 MessageQueue
->CursorObject
->IconInfo
.hbmColor
,
583 MessageQueue
->CursorObject
->IconInfo
.xHotspot
,
584 MessageQueue
->CursorObject
->IconInfo
.yHotspot
,
588 GreMovePointer(hdcScreen
, Msg
->pt
.x
, Msg
->pt
.y
);
590 /* Check if w have to hide cursor */
591 else if (CurInfo
->ShowingCursor
>= 0)
592 GreMovePointer(hdcScreen
, -1, -1);
594 /* Update global cursor info */
595 CurInfo
->ShowingCursor
= MessageQueue
->ShowingCursor
;
596 CurInfo
->CurrentCursorObject
= MessageQueue
->CursorObject
;
598 /* Mouse move is a special case */
599 MsqPostMouseMove(MessageQueue
, Msg
);
603 DPRINT("Posting mouse message to hwnd=0x%x!\n", UserHMGetHandle(pwnd
));
604 MsqPostMessage(pwnd
->head
.pti
->MessageQueue
, Msg
, TRUE
, QS_MOUSEBUTTON
);
609 /* always show cursor on background; FIXME: set default pointer */
610 GreMovePointer(hdcScreen
, Msg
->pt
.x
, Msg
->pt
.y
);
611 CurInfo
->ShowingCursor
= 0;
614 /* Do GetMouseMovePointsEx FIFO. */
615 MouseHistoryOfMoves
[gcur_count
].x
= Msg
->pt
.x
;
616 MouseHistoryOfMoves
[gcur_count
].y
= Msg
->pt
.y
;
617 MouseHistoryOfMoves
[gcur_count
].time
= Msg
->time
;
618 MouseHistoryOfMoves
[gcur_count
].dwExtraInfo
= dwExtraInfo
;
619 if (gcur_count
++ == 64) gcur_count
= 0; // 0 - 63 is 64, FIFO forwards.
623 // Note: Only called from input.c.
626 co_MsqPostKeyboardMessage(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
628 PUSER_MESSAGE_QUEUE FocusMessageQueue
;
630 LARGE_INTEGER LargeTickCount
;
631 KBDLLHOOKSTRUCT KbdHookData
;
633 DPRINT("MsqPostKeyboardMessage(uMsg 0x%x, wParam 0x%x, lParam 0x%x)\n",
634 uMsg
, wParam
, lParam
);
636 // Condition may arise when calling MsqPostMessage and waiting for an event.
637 ASSERT(UserIsEntered());
639 FocusMessageQueue
= IntGetFocusMessageQueue();
643 if (FocusMessageQueue
&& (FocusMessageQueue
->FocusWindow
!= (HWND
)0))
644 Msg
.hwnd
= FocusMessageQueue
->FocusWindow
;
650 KeQueryTickCount(&LargeTickCount
);
651 Msg
.time
= MsqCalculateMessageTime(&LargeTickCount
);
653 /* We can't get the Msg.pt point here since we don't know thread
654 (and thus the window station) the message will end up in yet. */
656 KbdHookData
.vkCode
= Msg
.wParam
;
657 KbdHookData
.scanCode
= (Msg
.lParam
>> 16) & 0xff;
658 KbdHookData
.flags
= (0 == (Msg
.lParam
& 0x01000000) ? 0 : LLKHF_EXTENDED
) |
659 (0 == (Msg
.lParam
& 0x20000000) ? 0 : LLKHF_ALTDOWN
) |
660 (0 == (Msg
.lParam
& 0x80000000) ? 0 : LLKHF_UP
);
661 KbdHookData
.time
= Msg
.time
;
662 KbdHookData
.dwExtraInfo
= 0;
663 if (co_HOOK_CallHooks(WH_KEYBOARD_LL
, HC_ACTION
, Msg
.message
, (LPARAM
) &KbdHookData
))
665 DPRINT1("Kbd msg %d wParam %d lParam 0x%08x dropped by WH_KEYBOARD_LL hook\n",
666 Msg
.message
, Msg
.wParam
, Msg
.lParam
);
670 if (FocusMessageQueue
== NULL
)
672 DPRINT("No focus message queue\n");
676 if (FocusMessageQueue
->FocusWindow
!= (HWND
)0)
678 Msg
.hwnd
= FocusMessageQueue
->FocusWindow
;
679 DPRINT("Msg.hwnd = %x\n", Msg
.hwnd
);
681 FocusMessageQueue
->Desktop
->pDeskInfo
->LastInputWasKbd
= TRUE
;
683 Msg
.pt
= gpsi
->ptCursor
;
684 MsqPostMessage(FocusMessageQueue
, &Msg
, TRUE
, QS_KEY
);
688 DPRINT("Invalid focus window handle\n");
695 MsqPostHotKeyMessage(PVOID Thread
, HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
698 PTHREADINFO Win32Thread
;
700 LARGE_INTEGER LargeTickCount
;
705 Status
= ObReferenceObjectByPointer (Thread
,
709 if (!NT_SUCCESS(Status
))
712 Win32Thread
= ((PETHREAD
)Thread
)->Tcb
.Win32Thread
;
713 if (Win32Thread
== NULL
|| Win32Thread
->MessageQueue
== NULL
)
715 ObDereferenceObject ((PETHREAD
)Thread
);
719 Window
= IntGetWindowObject(hWnd
);
722 ObDereferenceObject ((PETHREAD
)Thread
);
726 id
= wParam
; // Check for hot keys unrelated to the hot keys set by RegisterHotKey.
729 Mesg
.message
= id
!= IDHOT_REACTOS
? WM_HOTKEY
: WM_SYSCOMMAND
;
730 Mesg
.wParam
= id
!= IDHOT_REACTOS
? wParam
: SC_HOTKEY
;
731 Mesg
.lParam
= id
!= IDHOT_REACTOS
? lParam
: (LPARAM
)hWnd
;
732 Type
= id
!= IDHOT_REACTOS
? QS_HOTKEY
: QS_POSTMESSAGE
;
733 KeQueryTickCount(&LargeTickCount
);
734 Mesg
.time
= MsqCalculateMessageTime(&LargeTickCount
);
735 Mesg
.pt
= gpsi
->ptCursor
;
736 MsqPostMessage(Window
->head
.pti
->MessageQueue
, &Mesg
, FALSE
, Type
);
737 UserDereferenceObject(Window
);
738 ObDereferenceObject (Thread
);
742 PUSER_MESSAGE FASTCALL
743 MsqCreateMessage(LPMSG Msg
)
745 PUSER_MESSAGE Message
;
747 Message
= ExAllocateFromPagedLookasideList(&MessageLookasideList
);
753 RtlMoveMemory(&Message
->Msg
, Msg
, sizeof(MSG
));
759 MsqDestroyMessage(PUSER_MESSAGE Message
)
761 ExFreeToPagedLookasideList(&MessageLookasideList
, Message
);
765 co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue
)
767 PUSER_SENT_MESSAGE SaveMsg
, Message
;
772 if (IsListEmpty(&MessageQueue
->SentMessagesListHead
))
777 /* remove it from the list of pending messages */
778 Entry
= RemoveHeadList(&MessageQueue
->SentMessagesListHead
);
779 Message
= CONTAINING_RECORD(Entry
, USER_SENT_MESSAGE
, ListEntry
);
781 pti
= MessageQueue
->Thread
->Tcb
.Win32Thread
;
783 SaveMsg
= pti
->pusmCurrent
;
784 pti
->pusmCurrent
= Message
;
786 // Processing a message sent to it from another thread.
787 if ( ( Message
->SenderQueue
&& MessageQueue
!= Message
->SenderQueue
) ||
788 ( Message
->CallBackSenderQueue
&& MessageQueue
!= Message
->CallBackSenderQueue
))
789 { // most likely, but, to be sure.
790 pti
->pcti
->CTI_flags
|= CTI_INSENDMESSAGE
; // Let the user know...
793 /* insert it to the list of messages that are currently dispatched by this
795 InsertTailList(&MessageQueue
->LocalDispatchingMessagesHead
,
796 &Message
->ListEntry
);
798 ClearMsgBitsMask(MessageQueue
, Message
->QS_Flags
);
800 if (Message
->HookMessage
== MSQ_ISHOOK
)
801 { // Direct Hook Call processor
802 Result
= co_CallHook( Message
->Msg
.message
, // HookId
803 (INT
)(INT_PTR
)Message
->Msg
.hwnd
, // Code
805 Message
->Msg
.lParam
);
807 else if (Message
->HookMessage
== MSQ_ISEVENT
)
808 { // Direct Event Call processor
809 Result
= co_EVENT_CallEvents( Message
->Msg
.message
,
812 Message
->Msg
.lParam
);
814 else if ((Message
->CompletionCallback
)
815 && (Message
->CallBackSenderQueue
== MessageQueue
))
816 { /* Call the callback routine */
817 if (Message
->QS_Flags
& QS_SMRESULT
)
819 co_IntCallSentMessageCallback(Message
->CompletionCallback
,
821 Message
->Msg
.message
,
822 Message
->CompletionCallbackContext
,
824 /* Set callback to NULL to prevent reentry */
825 Message
->CompletionCallback
= NULL
;
829 /* The message has not been processed yet, reinsert it. */
830 RemoveEntryList(&Message
->ListEntry
);
831 InsertTailList(&Message
->CallBackSenderQueue
->SentMessagesListHead
, &Message
->ListEntry
);
832 DPRINT("Callback Message not processed yet. Requeuing the message\n");
837 { /* Call the window procedure. */
838 Result
= co_IntSendMessage( Message
->Msg
.hwnd
,
839 Message
->Msg
.message
,
841 Message
->Msg
.lParam
);
844 /* remove the message from the local dispatching list, because it doesn't need
845 to be cleaned up on thread termination anymore */
846 RemoveEntryList(&Message
->ListEntry
);
848 /* If the message is a callback, insert it in the callback senders MessageQueue */
849 if (Message
->CompletionCallback
)
851 if (Message
->CallBackSenderQueue
)
853 Message
->lResult
= Result
;
854 Message
->QS_Flags
|= QS_SMRESULT
;
856 /* insert it in the callers message queue */
857 InsertTailList(&Message
->CallBackSenderQueue
->SentMessagesListHead
, &Message
->ListEntry
);
858 MsqWakeQueue(Message
->CallBackSenderQueue
, QS_SENDMESSAGE
, TRUE
);
859 IntDereferenceMessageQueue(Message
->CallBackSenderQueue
);
864 /* remove the message from the dispatching list if needed, so lock the sender's message queue */
865 if (Message
->SenderQueue
)
867 if (Message
->DispatchingListEntry
.Flink
!= NULL
)
869 /* only remove it from the dispatching list if not already removed by a timeout */
870 RemoveEntryList(&Message
->DispatchingListEntry
);
873 /* still keep the sender's message queue locked, so the sender can't exit the
874 MsqSendMessage() function (if timed out) */
876 if (Message
->QS_Flags
& QS_SMRESULT
)
878 Result
= Message
->lResult
;
881 /* Let the sender know the result. */
882 if (Message
->Result
!= NULL
)
884 *Message
->Result
= Result
;
887 if (Message
->HasPackedLParam
== TRUE
)
889 if (Message
->Msg
.lParam
)
890 ExFreePool((PVOID
)Message
->Msg
.lParam
);
893 /* Notify the sender. */
894 if (Message
->CompletionEvent
!= NULL
)
896 KeSetEvent(Message
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
899 /* if the message has a sender */
900 if (Message
->SenderQueue
)
902 /* dereference our and the sender's message queue */
903 IntDereferenceMessageQueue(Message
->SenderQueue
);
904 IntDereferenceMessageQueue(MessageQueue
);
907 /* free the message */
908 ExFreePoolWithTag(Message
, TAG_USRMSG
);
910 /* do not hangup on the user if this is reentering */
911 if (!SaveMsg
) pti
->pcti
->CTI_flags
&= ~CTI_INSENDMESSAGE
;
912 pti
->pusmCurrent
= SaveMsg
;
918 MsqRemoveWindowMessagesFromQueue(PVOID pWindow
)
920 PUSER_SENT_MESSAGE SentMessage
;
921 PUSER_MESSAGE PostedMessage
;
922 PUSER_MESSAGE_QUEUE MessageQueue
;
923 PLIST_ENTRY CurrentEntry
, ListHead
;
924 PWND Window
= pWindow
;
928 MessageQueue
= Window
->head
.pti
->MessageQueue
;
929 ASSERT(MessageQueue
);
931 /* remove the posted messages for this window */
932 CurrentEntry
= MessageQueue
->PostedMessagesListHead
.Flink
;
933 ListHead
= &MessageQueue
->PostedMessagesListHead
;
934 while (CurrentEntry
!= ListHead
)
936 PostedMessage
= CONTAINING_RECORD(CurrentEntry
, USER_MESSAGE
,
938 if (PostedMessage
->Msg
.hwnd
== Window
->head
.h
)
940 RemoveEntryList(&PostedMessage
->ListEntry
);
941 ClearMsgBitsMask(MessageQueue
, PostedMessage
->QS_Flags
);
942 MsqDestroyMessage(PostedMessage
);
943 CurrentEntry
= MessageQueue
->PostedMessagesListHead
.Flink
;
947 CurrentEntry
= CurrentEntry
->Flink
;
951 /* remove the sent messages for this window */
952 CurrentEntry
= MessageQueue
->SentMessagesListHead
.Flink
;
953 ListHead
= &MessageQueue
->SentMessagesListHead
;
954 while (CurrentEntry
!= ListHead
)
956 SentMessage
= CONTAINING_RECORD(CurrentEntry
, USER_SENT_MESSAGE
,
958 if(SentMessage
->Msg
.hwnd
== Window
->head
.h
)
960 DPRINT("Notify the sender and remove a message from the queue that had not been dispatched\n");
962 RemoveEntryList(&SentMessage
->ListEntry
);
963 ClearMsgBitsMask(MessageQueue
, SentMessage
->QS_Flags
);
965 /* if it is a callback and this queue is not the sender queue, dereference queue */
966 if ((SentMessage
->CompletionCallback
) && (SentMessage
->CallBackSenderQueue
!= MessageQueue
))
968 IntDereferenceMessageQueue(SentMessage
->CallBackSenderQueue
);
970 /* Only if the message has a sender was the queue referenced */
971 if ((SentMessage
->SenderQueue
)
972 && (SentMessage
->DispatchingListEntry
.Flink
!= NULL
))
974 RemoveEntryList(&SentMessage
->DispatchingListEntry
);
977 /* wake the sender's thread */
978 if (SentMessage
->CompletionEvent
!= NULL
)
980 KeSetEvent(SentMessage
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
983 if (SentMessage
->HasPackedLParam
== TRUE
)
985 if (SentMessage
->Msg
.lParam
)
986 ExFreePool((PVOID
)SentMessage
->Msg
.lParam
);
989 /* if the message has a sender */
990 if (SentMessage
->SenderQueue
)
992 /* dereference our and the sender's message queue */
993 IntDereferenceMessageQueue(MessageQueue
);
994 IntDereferenceMessageQueue(SentMessage
->SenderQueue
);
997 /* free the message */
998 ExFreePoolWithTag(SentMessage
, TAG_USRMSG
);
1000 CurrentEntry
= MessageQueue
->SentMessagesListHead
.Flink
;
1004 CurrentEntry
= CurrentEntry
->Flink
;
1010 co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue
,
1011 HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
,
1012 UINT uTimeout
, BOOL Block
, INT HookMessage
,
1015 PTHREADINFO pti
, ptirec
;
1016 PUSER_SENT_MESSAGE Message
;
1017 KEVENT CompletionEvent
;
1018 NTSTATUS WaitStatus
;
1019 PUSER_MESSAGE_QUEUE ThreadQueue
;
1020 LARGE_INTEGER Timeout
;
1022 LRESULT Result
= 0; //// Result could be trashed. ////
1024 if(!(Message
= ExAllocatePoolWithTag(PagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
1026 DPRINT1("MsqSendMessage(): Not enough memory to allocate a message");
1027 return STATUS_INSUFFICIENT_RESOURCES
;
1030 KeInitializeEvent(&CompletionEvent
, NotificationEvent
, FALSE
);
1032 pti
= PsGetCurrentThreadWin32Thread();
1033 ThreadQueue
= pti
->MessageQueue
;
1034 ptirec
= MessageQueue
->Thread
->Tcb
.Win32Thread
;
1035 ASSERT(ThreadQueue
!= MessageQueue
);
1036 ASSERT(ptirec
->pcti
); // Send must have a client side to receive it!!!!
1038 /* Don't send from or to a dying thread */
1039 if (pti
->TIF_flags
& TIF_INCLEANUP
|| ptirec
->TIF_flags
& TIF_INCLEANUP
)
1042 return STATUS_TIMEOUT
;
1045 Timeout
.QuadPart
= (LONGLONG
) uTimeout
* (LONGLONG
) -10000;
1047 /* FIXME - increase reference counter of sender's message queue here */
1049 Message
->Msg
.hwnd
= Wnd
;
1050 Message
->Msg
.message
= Msg
;
1051 Message
->Msg
.wParam
= wParam
;
1052 Message
->Msg
.lParam
= lParam
;
1053 Message
->CompletionEvent
= &CompletionEvent
;
1054 Message
->Result
= &Result
;
1055 Message
->lResult
= 0;
1056 Message
->QS_Flags
= 0;
1057 Message
->SenderQueue
= ThreadQueue
;
1058 Message
->CallBackSenderQueue
= NULL
;
1059 IntReferenceMessageQueue(ThreadQueue
);
1060 Message
->CompletionCallback
= NULL
;
1061 Message
->CompletionCallbackContext
= 0;
1062 Message
->HookMessage
= HookMessage
;
1063 Message
->HasPackedLParam
= FALSE
;
1065 IntReferenceMessageQueue(MessageQueue
);
1067 /* add it to the list of pending messages */
1068 InsertTailList(&ThreadQueue
->DispatchingMessagesHead
, &Message
->DispatchingListEntry
);
1070 /* queue it in the destination's message queue */
1071 InsertTailList(&MessageQueue
->SentMessagesListHead
, &Message
->ListEntry
);
1073 Message
->QS_Flags
= QS_SENDMESSAGE
;
1074 MsqWakeQueue(MessageQueue
, QS_SENDMESSAGE
, TRUE
);
1076 /* we can't access the Message anymore since it could have already been deleted! */
1082 /* don't process messages sent to the thread */
1083 WaitStatus
= KeWaitForSingleObject(&CompletionEvent
, UserRequest
, UserMode
,
1084 FALSE
, (uTimeout
? &Timeout
: NULL
));
1088 if(WaitStatus
== STATUS_TIMEOUT
)
1090 /* look up if the message has not yet dispatched, if so
1091 make sure it can't pass a result and it must not set the completion event anymore */
1092 Entry
= MessageQueue
->SentMessagesListHead
.Flink
;
1093 while (Entry
!= &MessageQueue
->SentMessagesListHead
)
1095 if ((PUSER_SENT_MESSAGE
) CONTAINING_RECORD(Entry
, USER_SENT_MESSAGE
, ListEntry
)
1098 /* we can access Message here, it's secure because the message queue is locked
1099 and the message is still hasn't been dispatched */
1100 Message
->CompletionEvent
= NULL
;
1101 Message
->Result
= NULL
;
1104 Entry
= Entry
->Flink
;
1107 /* remove from the local dispatching list so the other thread knows,
1108 it can't pass a result and it must not set the completion event anymore */
1109 Entry
= ThreadQueue
->DispatchingMessagesHead
.Flink
;
1110 while (Entry
!= &ThreadQueue
->DispatchingMessagesHead
)
1112 if ((PUSER_SENT_MESSAGE
) CONTAINING_RECORD(Entry
, USER_SENT_MESSAGE
, DispatchingListEntry
)
1115 /* we can access Message here, it's secure because the sender's message is locked
1116 and the message has definitely not yet been destroyed, otherwise it would
1117 have been removed from this list by the dispatching routine right after
1118 dispatching the message */
1119 Message
->CompletionEvent
= NULL
;
1120 Message
->Result
= NULL
;
1121 RemoveEntryList(&Message
->DispatchingListEntry
);
1122 Message
->DispatchingListEntry
.Flink
= NULL
;
1125 Entry
= Entry
->Flink
;
1128 DPRINT("MsqSendMessage (blocked) timed out 1\n");
1130 while (co_MsqDispatchOneSentMessage(ThreadQueue
))
1135 PVOID WaitObjects
[2];
1137 WaitObjects
[0] = &CompletionEvent
;
1138 WaitObjects
[1] = ThreadQueue
->NewMessages
;
1143 WaitStatus
= KeWaitForMultipleObjects(2, WaitObjects
, WaitAny
, UserRequest
,
1144 UserMode
, FALSE
, (uTimeout
? &Timeout
: NULL
), NULL
);
1148 if(WaitStatus
== STATUS_TIMEOUT
)
1150 /* look up if the message has not yet been dispatched, if so
1151 make sure it can't pass a result and it must not set the completion event anymore */
1152 Entry
= MessageQueue
->SentMessagesListHead
.Flink
;
1153 while (Entry
!= &MessageQueue
->SentMessagesListHead
)
1155 if ((PUSER_SENT_MESSAGE
) CONTAINING_RECORD(Entry
, USER_SENT_MESSAGE
, ListEntry
)
1158 /* we can access Message here, it's secure because the message queue is locked
1159 and the message is still hasn't been dispatched */
1160 Message
->CompletionEvent
= NULL
;
1161 Message
->Result
= NULL
;
1164 Entry
= Entry
->Flink
;
1167 /* remove from the local dispatching list so the other thread knows,
1168 it can't pass a result and it must not set the completion event anymore */
1169 Entry
= ThreadQueue
->DispatchingMessagesHead
.Flink
;
1170 while (Entry
!= &ThreadQueue
->DispatchingMessagesHead
)
1172 if ((PUSER_SENT_MESSAGE
) CONTAINING_RECORD(Entry
, USER_SENT_MESSAGE
, DispatchingListEntry
)
1175 /* we can access Message here, it's secure because the sender's message is locked
1176 and the message has definitely not yet been destroyed, otherwise it would
1177 have been removed from this list by the dispatching routine right after
1178 dispatching the message */
1179 Message
->CompletionEvent
= NULL
;
1180 Message
->Result
= NULL
;
1181 RemoveEntryList(&Message
->DispatchingListEntry
);
1182 Message
->DispatchingListEntry
.Flink
= NULL
;
1185 Entry
= Entry
->Flink
;
1188 DPRINT("MsqSendMessage timed out 2\n");
1191 while (co_MsqDispatchOneSentMessage(ThreadQueue
))
1194 while (NT_SUCCESS(WaitStatus
) && STATUS_WAIT_0
!= WaitStatus
);
1197 if(WaitStatus
!= STATUS_TIMEOUT
)
1198 *uResult
= (STATUS_WAIT_0
== WaitStatus
? Result
: -1);
1204 MsqPostMessage(PUSER_MESSAGE_QUEUE MessageQueue
, MSG
* Msg
, BOOLEAN HardwareMessage
,
1207 PUSER_MESSAGE Message
;
1209 if(!(Message
= MsqCreateMessage(Msg
)))
1214 if(!HardwareMessage
)
1216 InsertTailList(&MessageQueue
->PostedMessagesListHead
,
1217 &Message
->ListEntry
);
1221 InsertTailList(&MessageQueue
->HardwareMessagesListHead
,
1222 &Message
->ListEntry
);
1224 update_input_key_state( MessageQueue
, Msg
);
1227 Message
->QS_Flags
= MessageBits
;
1228 MsqWakeQueue(MessageQueue
, MessageBits
, (MessageBits
& QS_TIMER
? FALSE
: TRUE
));
1232 MsqPostQuitMessage(PUSER_MESSAGE_QUEUE MessageQueue
, ULONG ExitCode
)
1234 MessageQueue
->QuitPosted
= TRUE
;
1235 MessageQueue
->QuitExitCode
= ExitCode
;
1236 MsqWakeQueue(MessageQueue
, QS_POSTMESSAGE
|QS_ALLPOSTMESSAGE
, TRUE
);
1239 /***********************************************************************
1240 * MsqSendParentNotify
1242 * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
1243 * the window has the WS_EX_NOPARENTNOTIFY style.
1245 static void MsqSendParentNotify( PWND pwnd
, WORD event
, WORD idChild
, POINT pt
)
1247 PWND pwndDesktop
= UserGetWindowObject(IntGetDesktopWindow());
1249 /* pt has to be in the client coordinates of the parent window */
1250 pt
.x
+= pwndDesktop
->rcClient
.left
- pwnd
->rcClient
.left
;
1251 pt
.y
+= pwndDesktop
->rcClient
.top
- pwnd
->rcClient
.top
;
1257 if (!(pwnd
->style
& WS_CHILD
)) break;
1258 if (pwnd
->ExStyle
& WS_EX_NOPARENTNOTIFY
) break;
1259 if (!(pwndParent
= IntGetParent(pwnd
))) break;
1260 if (pwndParent
== pwndDesktop
) break;
1261 pt
.x
+= pwnd
->rcClient
.left
- pwndParent
->rcClient
.left
;
1262 pt
.y
+= pwnd
->rcClient
.top
- pwndParent
->rcClient
.top
;
1265 co_IntSendMessage( UserHMGetHandle(pwnd
), WM_PARENTNOTIFY
,
1266 MAKEWPARAM( event
, idChild
), MAKELPARAM( pt
.x
, pt
.y
) );
1270 BOOL
co_IntProcessMouseMessage(MSG
* msg
, BOOL
* RemoveMessages
, UINT first
, UINT last
)
1277 MOUSEHOOKSTRUCT hook
;
1280 PWND pwndMsg
, pwndDesktop
;
1281 PUSER_MESSAGE_QUEUE MessageQueue
;
1283 PSYSTEM_CURSORINFO CurInfo
;
1284 DECLARE_RETURN(BOOL
);
1286 pti
= PsGetCurrentThreadWin32Thread();
1287 pwndDesktop
= UserGetDesktopWindow();
1288 MessageQueue
= pti
->MessageQueue
;
1289 CurInfo
= IntGetSysCursorInfo();
1290 pwndMsg
= UserGetWindowObject(msg
->hwnd
);
1291 clk_msg
= MessageQueue
->msgDblClk
;
1293 /* find the window to dispatch this mouse message to */
1294 if (MessageQueue
->CaptureWindow
)
1297 pwndMsg
= IntGetWindowObject(MessageQueue
->CaptureWindow
);
1301 pwndMsg
= co_WinPosWindowFromPoint(pwndMsg
, &msg
->pt
, &hittest
);
1304 DPRINT("Got mouse message for 0x%x, hittest: 0x%x\n", msg
->hwnd
, hittest
);
1306 if (pwndMsg
== NULL
|| pwndMsg
->head
.pti
!= pti
)
1308 /* Remove and ignore the message */
1309 *RemoveMessages
= TRUE
;
1313 msg
->hwnd
= UserHMGetHandle(pwndMsg
);
1316 if (!check_hwnd_filter( msg
, hwnd_filter
)) RETURN(FALSE
);
1320 message
= msg
->message
;
1321 /* Note: windows has no concept of a non-client wheel message */
1322 if (message
!= WM_MOUSEWHEEL
)
1324 if (hittest
!= HTCLIENT
)
1326 message
+= WM_NCMOUSEMOVE
- WM_MOUSEMOVE
;
1327 msg
->wParam
= hittest
;
1331 /* coordinates don't get translated while tracking a menu */
1332 /* FIXME: should differentiate popups and top-level menus */
1333 if (!(MessageQueue
->MenuOwner
))
1335 pt
.x
+= pwndDesktop
->rcClient
.left
- pwndMsg
->rcClient
.left
;
1336 pt
.y
+= pwndDesktop
->rcClient
.top
- pwndMsg
->rcClient
.top
;
1340 msg
->lParam
= MAKELONG( pt
.x
, pt
.y
);
1342 /* translate double clicks */
1344 if ((msg
->message
== WM_LBUTTONDOWN
) ||
1345 (msg
->message
== WM_RBUTTONDOWN
) ||
1346 (msg
->message
== WM_MBUTTONDOWN
) ||
1347 (msg
->message
== WM_XBUTTONDOWN
))
1349 BOOL update
= *RemoveMessages
;
1351 /* translate double clicks -
1352 * note that ...MOUSEMOVEs can slip in between
1353 * ...BUTTONDOWN and ...BUTTONDBLCLK messages */
1355 if ((MessageQueue
->MenuOwner
|| MessageQueue
->MoveSize
) ||
1356 hittest
!= HTCLIENT
||
1357 (pwndMsg
->pcls
->style
& CS_DBLCLKS
))
1359 if ((msg
->message
== clk_msg
.message
) &&
1360 (msg
->hwnd
== clk_msg
.hwnd
) &&
1361 (msg
->wParam
== clk_msg
.wParam
) &&
1362 (msg
->time
- clk_msg
.time
< gspv
.iDblClickTime
) &&
1363 (abs(msg
->pt
.x
- clk_msg
.pt
.x
) < UserGetSystemMetrics(SM_CXDOUBLECLK
)/2) &&
1364 (abs(msg
->pt
.y
- clk_msg
.pt
.y
) < UserGetSystemMetrics(SM_CYDOUBLECLK
)/2))
1366 message
+= (WM_LBUTTONDBLCLK
- WM_LBUTTONDOWN
);
1369 MessageQueue
->msgDblClk
.message
= 0; /* clear the double click conditions */
1375 if (!((first
== 0 && last
== 0) || (message
>= first
|| message
<= last
)))
1377 DPRINT("Message out of range!!!\n");
1381 /* update static double click conditions */
1382 if (update
) MessageQueue
->msgDblClk
= *msg
;
1386 if (!((first
== 0 && last
== 0) || (message
>= first
|| message
<= last
)))
1388 DPRINT("Message out of range!!!\n");
1393 if(gspv
.bMouseClickLock
)
1395 BOOL IsClkLck
= FALSE
;
1397 if(msg
->message
== WM_LBUTTONUP
)
1399 IsClkLck
= ((msg
->time
- CurInfo
->ClickLockTime
) >= gspv
.dwMouseClickLockTime
);
1400 if (IsClkLck
&& (!CurInfo
->ClickLockActive
))
1402 CurInfo
->ClickLockActive
= TRUE
;
1405 else if (msg
->message
== WM_LBUTTONDOWN
)
1407 if (CurInfo
->ClickLockActive
)
1410 CurInfo
->ClickLockActive
= FALSE
;
1413 CurInfo
->ClickLockTime
= msg
->time
;
1418 /* Remove and ignore the message */
1419 *RemoveMessages
= TRUE
;
1424 /* message is accepted now (but may still get dropped) */
1426 event
.message
= msg
->message
;
1427 event
.time
= msg
->time
;
1428 event
.hwnd
= msg
->hwnd
;
1429 event
.paramL
= msg
->pt
.x
;
1430 event
.paramH
= msg
->pt
.y
;
1431 co_HOOK_CallHooks( WH_JOURNALRECORD
, HC_ACTION
, 0, (LPARAM
)&event
);
1434 hook
.hwnd
= msg
->hwnd
;
1435 hook
.wHitTestCode
= hittest
;
1436 hook
.dwExtraInfo
= 0/*extra_info*/;
1437 if (co_HOOK_CallHooks( WH_MOUSE
, *RemoveMessages
? HC_ACTION
: HC_NOREMOVE
,
1438 message
, (LPARAM
)&hook
))
1441 hook
.hwnd
= msg
->hwnd
;
1442 hook
.wHitTestCode
= hittest
;
1443 hook
.dwExtraInfo
= 0/*extra_info*/;
1444 co_HOOK_CallHooks( WH_CBT
, HCBT_CLICKSKIPPED
, message
, (LPARAM
)&hook
);
1446 DPRINT1("WH_MOUSE dorpped mouse message!\n");
1448 /* Remove and skip message */
1449 *RemoveMessages
= TRUE
;
1453 if ((hittest
== HTERROR
) || (hittest
== HTNOWHERE
))
1455 co_IntSendMessage( msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)msg
->hwnd
,
1456 MAKELONG( hittest
, msg
->message
));
1458 /* Remove and skip message */
1459 *RemoveMessages
= TRUE
;
1463 if ((*RemoveMessages
== FALSE
) || MessageQueue
->CaptureWindow
)
1465 /* Accept the message */
1466 msg
->message
= message
;
1472 if ((msg
->message
== WM_LBUTTONDOWN
) ||
1473 (msg
->message
== WM_RBUTTONDOWN
) ||
1474 (msg
->message
== WM_MBUTTONDOWN
) ||
1475 (msg
->message
== WM_XBUTTONDOWN
))
1477 /* Send the WM_PARENTNOTIFY,
1478 * note that even for double/nonclient clicks
1479 * notification message is still WM_L/M/RBUTTONDOWN.
1481 MsqSendParentNotify(pwndMsg
, msg
->message
, 0, msg
->pt
);
1483 /* Activate the window if needed */
1485 if (msg
->hwnd
!= UserGetForegroundWindow())
1487 PWND pwndTop
= pwndMsg
;
1490 if ((pwndTop
->style
& (WS_POPUP
|WS_CHILD
)) != WS_CHILD
) break;
1491 pwndTop
= IntGetParent( pwndTop
);
1494 if (pwndTop
&& pwndTop
!= pwndDesktop
)
1496 LONG ret
= co_IntSendMessage( msg
->hwnd
,
1498 (WPARAM
)UserHMGetHandle(pwndTop
),
1499 MAKELONG( hittest
, msg
->message
));
1502 case MA_NOACTIVATEANDEAT
:
1507 case MA_ACTIVATEANDEAT
:
1512 if(!co_IntMouseActivateWindow(pwndMsg
)) eatMsg
= TRUE
;
1515 DPRINT1( "unknown WM_MOUSEACTIVATE code %d\n", ret
);
1522 /* send the WM_SETCURSOR message */
1524 /* Windows sends the normal mouse message as the message parameter
1525 in the WM_SETCURSOR message even if it's non-client mouse message */
1526 co_IntSendMessage( msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)msg
->hwnd
, MAKELONG( hittest
, msg
->message
));
1528 msg
->message
= message
;
1533 UserDereferenceObject(pwndMsg
);
1538 BOOL
co_IntProcessKeyboardMessage(MSG
* Msg
, BOOL
* RemoveMessages
)
1542 if (Msg
->message
== WM_KEYDOWN
|| Msg
->message
== WM_SYSKEYDOWN
||
1543 Msg
->message
== WM_KEYUP
|| Msg
->message
== WM_SYSKEYUP
)
1545 switch (Msg
->wParam
)
1547 case VK_LSHIFT
: case VK_RSHIFT
:
1548 Msg
->wParam
= VK_SHIFT
;
1550 case VK_LCONTROL
: case VK_RCONTROL
:
1551 Msg
->wParam
= VK_CONTROL
;
1553 case VK_LMENU
: case VK_RMENU
:
1554 Msg
->wParam
= VK_MENU
;
1559 Event
.message
= Msg
->message
;
1560 Event
.hwnd
= Msg
->hwnd
;
1561 Event
.time
= Msg
->time
;
1562 Event
.paramL
= (Msg
->wParam
& 0xFF) | (HIWORD(Msg
->lParam
) << 8);
1563 Event
.paramH
= Msg
->lParam
& 0x7FFF;
1564 if (HIWORD(Msg
->lParam
) & 0x0100) Event
.paramH
|= 0x8000;
1565 co_HOOK_CallHooks( WH_JOURNALRECORD
, HC_ACTION
, 0, (LPARAM
)&Event
);
1567 if (co_HOOK_CallHooks( WH_KEYBOARD
,
1568 *RemoveMessages
? HC_ACTION
: HC_NOREMOVE
,
1569 LOWORD(Msg
->wParam
),
1572 /* skip this message */
1573 co_HOOK_CallHooks( WH_CBT
,
1575 LOWORD(Msg
->wParam
),
1577 DPRINT1("KeyboardMessage WH_CBT Call Hook return!\n");
1583 BOOL
co_IntProcessHardwareMessage(MSG
* Msg
, BOOL
* RemoveMessages
, UINT first
, UINT last
)
1585 if ( IS_MOUSE_MESSAGE(Msg
->message
))
1587 return co_IntProcessMouseMessage(Msg
, RemoveMessages
, first
, last
);
1589 else if ( IS_KBD_MESSAGE(Msg
->message
))
1591 return co_IntProcessKeyboardMessage(Msg
, RemoveMessages
);
1598 co_MsqPeekMouseMove(IN PUSER_MESSAGE_QUEUE MessageQueue
,
1601 IN UINT MsgFilterLow
,
1602 IN UINT MsgFilterHigh
,
1608 if(!(MessageQueue
->MouseMoved
))
1611 msg
= MessageQueue
->MouseMoveMsg
;
1613 AcceptMessage
= co_IntProcessMouseMessage(&msg
, &Remove
, MsgFilterLow
, MsgFilterHigh
);
1620 ClearMsgBitsMask(MessageQueue
, QS_MOUSEMOVE
);
1621 MessageQueue
->MouseMoved
= FALSE
;
1624 return AcceptMessage
;
1627 /* check whether a message filter contains at least one potential hardware message */
1629 filter_contains_hw_range( UINT first
, UINT last
)
1631 /* hardware message ranges are (in numerical order):
1632 * WM_NCMOUSEFIRST .. WM_NCMOUSELAST
1633 * WM_KEYFIRST .. WM_KEYLAST
1634 * WM_MOUSEFIRST .. WM_MOUSELAST
1637 if (last
< WM_NCMOUSEFIRST
) return 0;
1638 if (first
> WM_NCMOUSELAST
&& last
< WM_KEYFIRST
) return 0;
1639 if (first
> WM_KEYLAST
&& last
< WM_MOUSEFIRST
) return 0;
1640 if (first
> WM_MOUSELAST
) return 0;
1645 co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue
,
1648 IN UINT MsgFilterLow
,
1649 IN UINT MsgFilterHigh
,
1655 PUSER_MESSAGE CurrentMessage
;
1656 PLIST_ENTRY ListHead
, CurrentEntry
= NULL
;
1659 if (!filter_contains_hw_range( MsgFilterLow
, MsgFilterHigh
)) return FALSE
;
1661 ListHead
= &MessageQueue
->HardwareMessagesListHead
;
1662 CurrentEntry
= ListHead
->Flink
;
1664 if (IsListEmpty(CurrentEntry
)) return FALSE
;
1666 CurrentMessage
= CONTAINING_RECORD(CurrentEntry
, USER_MESSAGE
,
1670 if (IsListEmpty(CurrentEntry
)) break;
1671 if (!CurrentMessage
) break;
1672 CurrentEntry
= CurrentMessage
->ListEntry
.Flink
;
1675 1: any window that belongs to the current thread, and any messages on the current thread's message queue whose hwnd value is NULL.
1676 2: retrieves only messages on the current thread's message queue whose hwnd value is NULL.
1677 3: handle to the window whose messages are to be retrieved.
1679 if ( ( !Window
|| // 1
1680 ( Window
== HWND_BOTTOM
&& CurrentMessage
->Msg
.hwnd
== NULL
) || // 2
1681 ( Window
!= HWND_BOTTOM
&& Window
->head
.h
== CurrentMessage
->Msg
.hwnd
) ) && // 3
1682 ( ( ( MsgFilterLow
== 0 && MsgFilterHigh
== 0 ) && CurrentMessage
->QS_Flags
& QSflags
) ||
1683 ( MsgFilterLow
<= CurrentMessage
->Msg
.message
&& MsgFilterHigh
>= CurrentMessage
->Msg
.message
) ) )
1685 msg
= CurrentMessage
->Msg
;
1687 AcceptMessage
= co_IntProcessHardwareMessage(&msg
, &Remove
, MsgFilterLow
, MsgFilterHigh
);
1691 update_input_key_state(MessageQueue
, &msg
);
1692 RemoveEntryList(&CurrentMessage
->ListEntry
);
1693 ClearMsgBitsMask(MessageQueue
, CurrentMessage
->QS_Flags
);
1694 MsqDestroyMessage(CurrentMessage
);
1703 CurrentMessage
= CONTAINING_RECORD(CurrentEntry
, USER_MESSAGE
,
1706 while(CurrentEntry
!= ListHead
);
1712 MsqPeekMessage(IN PUSER_MESSAGE_QUEUE MessageQueue
,
1715 IN UINT MsgFilterLow
,
1716 IN UINT MsgFilterHigh
,
1720 PLIST_ENTRY CurrentEntry
;
1721 PUSER_MESSAGE CurrentMessage
;
1722 PLIST_ENTRY ListHead
;
1724 CurrentEntry
= MessageQueue
->PostedMessagesListHead
.Flink
;
1725 ListHead
= &MessageQueue
->PostedMessagesListHead
;
1727 if (IsListEmpty(CurrentEntry
)) return FALSE
;
1729 CurrentMessage
= CONTAINING_RECORD(CurrentEntry
, USER_MESSAGE
,
1733 if (IsListEmpty(CurrentEntry
)) break;
1734 if (!CurrentMessage
) break;
1735 CurrentEntry
= CurrentEntry
->Flink
;
1738 1: any window that belongs to the current thread, and any messages on the current thread's message queue whose hwnd value is NULL.
1739 2: retrieves only messages on the current thread's message queue whose hwnd value is NULL.
1740 3: handle to the window whose messages are to be retrieved.
1742 if ( ( !Window
|| // 1
1743 ( Window
== HWND_BOTTOM
&& CurrentMessage
->Msg
.hwnd
== NULL
) || // 2
1744 ( Window
!= HWND_BOTTOM
&& Window
->head
.h
== CurrentMessage
->Msg
.hwnd
) ) && // 3
1745 ( ( ( MsgFilterLow
== 0 && MsgFilterHigh
== 0 ) && CurrentMessage
->QS_Flags
& QSflags
) ||
1746 ( MsgFilterLow
<= CurrentMessage
->Msg
.message
&& MsgFilterHigh
>= CurrentMessage
->Msg
.message
) ) )
1748 *Message
= CurrentMessage
->Msg
;
1752 RemoveEntryList(&CurrentMessage
->ListEntry
);
1753 ClearMsgBitsMask(MessageQueue
, CurrentMessage
->QS_Flags
);
1754 MsqDestroyMessage(CurrentMessage
);
1758 CurrentMessage
= CONTAINING_RECORD(CurrentEntry
, USER_MESSAGE
,
1761 while (CurrentEntry
!= ListHead
);
1767 co_MsqWaitForNewMessages(PUSER_MESSAGE_QUEUE MessageQueue
, PWND WndFilter
,
1768 UINT MsgFilterMin
, UINT MsgFilterMax
)
1772 ret
= KeWaitForSingleObject( MessageQueue
->NewMessages
,
1782 MsqIsHung(PUSER_MESSAGE_QUEUE MessageQueue
)
1784 LARGE_INTEGER LargeTickCount
;
1786 KeQueryTickCount(&LargeTickCount
);
1787 return ((LargeTickCount
.u
.LowPart
- MessageQueue
->LastMsgRead
) > MSQ_HUNG
);
1792 HungAppSysTimerProc(HWND hwnd
, UINT uMsg
, UINT_PTR idEvent
, DWORD dwTime
)
1795 DPRINT("HungAppSysTimerProc\n");
1796 // Process list of windows that are hung and waiting.
1800 MsqInitializeMessageQueue(struct _ETHREAD
*Thread
, PUSER_MESSAGE_QUEUE MessageQueue
)
1802 LARGE_INTEGER LargeTickCount
;
1805 MessageQueue
->Thread
= Thread
;
1806 MessageQueue
->CaretInfo
= (PTHRDCARETINFO
)(MessageQueue
+ 1);
1807 InitializeListHead(&MessageQueue
->PostedMessagesListHead
);
1808 InitializeListHead(&MessageQueue
->SentMessagesListHead
);
1809 InitializeListHead(&MessageQueue
->HardwareMessagesListHead
);
1810 InitializeListHead(&MessageQueue
->DispatchingMessagesHead
);
1811 InitializeListHead(&MessageQueue
->LocalDispatchingMessagesHead
);
1812 MessageQueue
->QuitPosted
= FALSE
;
1813 MessageQueue
->QuitExitCode
= 0;
1814 KeQueryTickCount(&LargeTickCount
);
1815 MessageQueue
->LastMsgRead
= LargeTickCount
.u
.LowPart
;
1816 MessageQueue
->FocusWindow
= NULL
;
1817 MessageQueue
->NewMessagesHandle
= NULL
;
1818 MessageQueue
->ShowingCursor
= 0;
1819 MessageQueue
->CursorObject
= NULL
;
1821 Status
= ZwCreateEvent(&MessageQueue
->NewMessagesHandle
, EVENT_ALL_ACCESS
,
1822 NULL
, SynchronizationEvent
, FALSE
);
1823 if (!NT_SUCCESS(Status
))
1828 Status
= ObReferenceObjectByHandle(MessageQueue
->NewMessagesHandle
, 0,
1829 ExEventObjectType
, KernelMode
,
1830 (PVOID
*)&MessageQueue
->NewMessages
, NULL
);
1831 if (!NT_SUCCESS(Status
))
1833 ZwClose(MessageQueue
->NewMessagesHandle
);
1834 MessageQueue
->NewMessagesHandle
= NULL
;
1842 MsqCleanupMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue
)
1844 PLIST_ENTRY CurrentEntry
;
1845 PUSER_MESSAGE CurrentMessage
;
1846 PUSER_SENT_MESSAGE CurrentSentMessage
;
1849 pti
= MessageQueue
->Thread
->Tcb
.Win32Thread
;
1852 /* cleanup posted messages */
1853 while (!IsListEmpty(&MessageQueue
->PostedMessagesListHead
))
1855 CurrentEntry
= RemoveHeadList(&MessageQueue
->PostedMessagesListHead
);
1856 CurrentMessage
= CONTAINING_RECORD(CurrentEntry
, USER_MESSAGE
,
1858 MsqDestroyMessage(CurrentMessage
);
1861 /* remove the messages that have not yet been dispatched */
1862 while (!IsListEmpty(&MessageQueue
->SentMessagesListHead
))
1864 CurrentEntry
= RemoveHeadList(&MessageQueue
->SentMessagesListHead
);
1865 CurrentSentMessage
= CONTAINING_RECORD(CurrentEntry
, USER_SENT_MESSAGE
,
1868 /* if it is a callback and this queue is not the sender queue, dereference queue */
1869 if ((CurrentSentMessage
->CompletionCallback
) && (CurrentSentMessage
->CallBackSenderQueue
!= MessageQueue
))
1871 IntDereferenceMessageQueue(CurrentSentMessage
->CallBackSenderQueue
);
1874 DPRINT("Notify the sender and remove a message from the queue that had not been dispatched\n");
1875 /* Only if the message has a sender was the message in the DispatchingList */
1876 if ((CurrentSentMessage
->SenderQueue
)
1877 && (CurrentSentMessage
->DispatchingListEntry
.Flink
!= NULL
))
1879 RemoveEntryList(&CurrentSentMessage
->DispatchingListEntry
);
1882 /* wake the sender's thread */
1883 if (CurrentSentMessage
->CompletionEvent
!= NULL
)
1885 KeSetEvent(CurrentSentMessage
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
1888 if (CurrentSentMessage
->HasPackedLParam
== TRUE
)
1890 if (CurrentSentMessage
->Msg
.lParam
)
1891 ExFreePool((PVOID
)CurrentSentMessage
->Msg
.lParam
);
1894 /* if the message has a sender */
1895 if (CurrentSentMessage
->SenderQueue
)
1897 /* dereference our and the sender's message queue */
1898 IntDereferenceMessageQueue(MessageQueue
);
1899 IntDereferenceMessageQueue(CurrentSentMessage
->SenderQueue
);
1902 /* free the message */
1903 ExFreePool(CurrentSentMessage
);
1906 /* notify senders of dispatching messages. This needs to be cleaned up if e.g.
1907 ExitThread() was called in a SendMessage() umode callback */
1908 while (!IsListEmpty(&MessageQueue
->LocalDispatchingMessagesHead
))
1910 CurrentEntry
= RemoveHeadList(&MessageQueue
->LocalDispatchingMessagesHead
);
1911 CurrentSentMessage
= CONTAINING_RECORD(CurrentEntry
, USER_SENT_MESSAGE
,
1914 /* if it is a callback and this queue is not the sender queue, dereference queue */
1915 if ((CurrentSentMessage
->CompletionCallback
) && (CurrentSentMessage
->CallBackSenderQueue
!= MessageQueue
))
1917 IntDereferenceMessageQueue(CurrentSentMessage
->CallBackSenderQueue
);
1920 /* remove the message from the dispatching list */
1921 if(CurrentSentMessage
->DispatchingListEntry
.Flink
!= NULL
)
1923 RemoveEntryList(&CurrentSentMessage
->DispatchingListEntry
);
1926 DPRINT("Notify the sender, the thread has been terminated while dispatching a message!\n");
1928 /* wake the sender's thread */
1929 if (CurrentSentMessage
->CompletionEvent
!= NULL
)
1931 KeSetEvent(CurrentSentMessage
->CompletionEvent
, IO_NO_INCREMENT
, FALSE
);
1934 if (CurrentSentMessage
->HasPackedLParam
== TRUE
)
1936 if (CurrentSentMessage
->Msg
.lParam
)
1937 ExFreePool((PVOID
)CurrentSentMessage
->Msg
.lParam
);
1940 /* if the message has a sender */
1941 if (CurrentSentMessage
->SenderQueue
)
1943 /* dereference our and the sender's message queue */
1944 IntDereferenceMessageQueue(MessageQueue
);
1945 IntDereferenceMessageQueue(CurrentSentMessage
->SenderQueue
);
1948 /* free the message */
1949 ExFreePool(CurrentSentMessage
);
1952 /* tell other threads not to bother returning any info to us */
1953 while (! IsListEmpty(&MessageQueue
->DispatchingMessagesHead
))
1955 CurrentEntry
= RemoveHeadList(&MessageQueue
->DispatchingMessagesHead
);
1956 CurrentSentMessage
= CONTAINING_RECORD(CurrentEntry
, USER_SENT_MESSAGE
,
1957 DispatchingListEntry
);
1958 CurrentSentMessage
->CompletionEvent
= NULL
;
1959 CurrentSentMessage
->Result
= NULL
;
1961 /* do NOT dereference our message queue as it might get attempted to be
1965 // Clear it all out.
1966 pti
->pcti
->fsWakeBits
= 0;
1967 pti
->pcti
->fsChangeBits
= 0;
1969 MessageQueue
->nCntsQBits
[QSRosKey
] = 0;
1970 MessageQueue
->nCntsQBits
[QSRosMouseMove
] = 0;
1971 MessageQueue
->nCntsQBits
[QSRosMouseButton
] = 0;
1972 MessageQueue
->nCntsQBits
[QSRosPostMessage
] = 0;
1973 MessageQueue
->nCntsQBits
[QSRosSendMessage
] = 0;
1974 MessageQueue
->nCntsQBits
[QSRosHotKey
] = 0;
1976 if (MessageQueue
->CursorObject
)
1978 PCURICON_OBJECT pCursor
= MessageQueue
->CursorObject
;
1980 /* Change to another cursor if we going to dereference current one */
1981 if (IntGetSysCursorInfo()->CurrentCursorObject
== pCursor
)
1982 UserSetCursor(NULL
, TRUE
);
1984 UserDereferenceObject(pCursor
);
1989 PUSER_MESSAGE_QUEUE FASTCALL
1990 MsqCreateMessageQueue(struct _ETHREAD
*Thread
)
1992 PUSER_MESSAGE_QUEUE MessageQueue
;
1994 MessageQueue
= (PUSER_MESSAGE_QUEUE
)ExAllocatePoolWithTag(NonPagedPool
,
1995 sizeof(USER_MESSAGE_QUEUE
) + sizeof(THRDCARETINFO
),
2003 RtlZeroMemory(MessageQueue
, sizeof(USER_MESSAGE_QUEUE
) + sizeof(THRDCARETINFO
));
2004 /* hold at least one reference until it'll be destroyed */
2005 IntReferenceMessageQueue(MessageQueue
);
2006 /* initialize the queue */
2007 if (!MsqInitializeMessageQueue(Thread
, MessageQueue
))
2009 IntDereferenceMessageQueue(MessageQueue
);
2013 return MessageQueue
;
2017 MsqDestroyMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue
)
2021 MessageQueue
->QF_flags
|= QF_INDESTROY
;
2023 /* remove the message queue from any desktops */
2024 if ((desk
= InterlockedExchangePointer((PVOID
*)&MessageQueue
->Desktop
, 0)))
2026 (void)InterlockedExchangePointer((PVOID
*)&desk
->ActiveMessageQueue
, 0);
2027 IntDereferenceMessageQueue(MessageQueue
);
2031 MsqCleanupMessageQueue(MessageQueue
);
2033 if (MessageQueue
->NewMessagesHandle
!= NULL
)
2034 ZwClose(MessageQueue
->NewMessagesHandle
);
2035 MessageQueue
->NewMessagesHandle
= NULL
;
2036 /* decrease the reference counter, if it hits zero, the queue will be freed */
2037 IntDereferenceMessageQueue(MessageQueue
);
2041 MsqSetMessageExtraInfo(LPARAM lParam
)
2045 PUSER_MESSAGE_QUEUE MessageQueue
;
2047 pti
= PsGetCurrentThreadWin32Thread();
2048 MessageQueue
= pti
->MessageQueue
;
2054 Ret
= MessageQueue
->ExtraInfo
;
2055 MessageQueue
->ExtraInfo
= lParam
;
2061 MsqGetMessageExtraInfo(VOID
)
2064 PUSER_MESSAGE_QUEUE MessageQueue
;
2066 pti
= PsGetCurrentThreadWin32Thread();
2067 MessageQueue
= pti
->MessageQueue
;
2073 return MessageQueue
->ExtraInfo
;
2076 // ReplyMessage is called by the thread receiving the window message.
2078 co_MsqReplyMessage( LRESULT lResult
)
2080 PUSER_SENT_MESSAGE Message
;
2083 pti
= PsGetCurrentThreadWin32Thread();
2084 Message
= pti
->pusmCurrent
;
2086 if (!Message
) return FALSE
;
2088 if (Message
->QS_Flags
& QS_SMRESULT
) return FALSE
;
2090 // SendMessageXxx || Callback msg and not a notify msg
2091 if (Message
->SenderQueue
|| Message
->CompletionCallback
)
2093 Message
->lResult
= lResult
;
2094 Message
->QS_Flags
|= QS_SMRESULT
;
2095 // See co_MsqDispatchOneSentMessage, change bits already accounted for and cleared and this msg is going away..
2101 MsqSetStateWindow(PUSER_MESSAGE_QUEUE MessageQueue
, ULONG Type
, HWND hWnd
)
2107 case MSQ_STATE_CAPTURE
:
2108 Prev
= MessageQueue
->CaptureWindow
;
2109 MessageQueue
->CaptureWindow
= hWnd
;
2111 case MSQ_STATE_ACTIVE
:
2112 Prev
= MessageQueue
->ActiveWindow
;
2113 MessageQueue
->ActiveWindow
= hWnd
;
2115 case MSQ_STATE_FOCUS
:
2116 Prev
= MessageQueue
->FocusWindow
;
2117 MessageQueue
->FocusWindow
= hWnd
;
2119 case MSQ_STATE_MENUOWNER
:
2120 Prev
= MessageQueue
->MenuOwner
;
2121 MessageQueue
->MenuOwner
= hWnd
;
2123 case MSQ_STATE_MOVESIZE
:
2124 Prev
= MessageQueue
->MoveSize
;
2125 MessageQueue
->MoveSize
= hWnd
;
2127 case MSQ_STATE_CARET
:
2128 ASSERT(MessageQueue
->CaretInfo
);
2129 Prev
= MessageQueue
->CaretInfo
->hWnd
;
2130 MessageQueue
->CaretInfo
->hWnd
= hWnd
;
2139 NtUserGetKeyState(INT key
)
2143 UserEnterExclusive();
2145 Ret
= UserGetKeyState(key
);
2155 NtUserGetKeyboardState(LPBYTE lpKeyState
)
2159 PUSER_MESSAGE_QUEUE MessageQueue
;
2163 pti
= PsGetCurrentThreadWin32Thread();
2164 MessageQueue
= pti
->MessageQueue
;
2168 ProbeForWrite(lpKeyState
,sizeof(MessageQueue
->KeyState
) ,1);
2169 RtlCopyMemory(lpKeyState
,MessageQueue
->KeyState
,sizeof(MessageQueue
->KeyState
));
2171 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2173 SetLastNtError(_SEH2_GetExceptionCode());
2185 NtUserSetKeyboardState(LPBYTE lpKeyState
)
2189 PUSER_MESSAGE_QUEUE MessageQueue
;
2191 UserEnterExclusive();
2193 pti
= PsGetCurrentThreadWin32Thread();
2194 MessageQueue
= pti
->MessageQueue
;
2198 ProbeForRead(lpKeyState
,sizeof(MessageQueue
->KeyState
) ,1);
2199 RtlCopyMemory(MessageQueue
->KeyState
,lpKeyState
,sizeof(MessageQueue
->KeyState
));
2201 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2203 SetLastNtError(_SEH2_GetExceptionCode());