2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
5 * FILE: subsys/win32k/ntuser/message.c
6 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * 06-06-2001 CSH Created
11 /* INCLUDES ******************************************************************/
18 #define PM_BADMSGFLAGS ~((QS_RAWINPUT << 16)|PM_QS_SENDMESSAGE|PM_QS_PAINT|PM_QS_POSTMESSAGE|PM_QS_INPUT|PM_NOYIELD|PM_REMOVE)
26 DOSENDMESSAGE
, *PDOSENDMESSAGE
;
28 /* FUNCTIONS *****************************************************************/
31 IntInitMessageImpl(VOID
)
33 return STATUS_SUCCESS
;
37 IntCleanupMessageImpl(VOID
)
39 return STATUS_SUCCESS
;
42 #define MMS_SIZE_WPARAM -1
43 #define MMS_SIZE_WPARAMWCHAR -2
44 #define MMS_SIZE_LPARAMSZ -3
45 #define MMS_SIZE_SPECIAL -4
46 #define MMS_FLAG_READ 0x01
47 #define MMS_FLAG_WRITE 0x02
48 #define MMS_FLAG_READWRITE (MMS_FLAG_READ | MMS_FLAG_WRITE)
49 typedef struct tagMSGMEMORY
55 MSGMEMORY
, *PMSGMEMORY
;
57 static MSGMEMORY MsgMemory
[] =
59 { WM_CREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
60 { WM_DDE_ACK
, sizeof(KMDDELPARAM
), MMS_FLAG_READ
},
61 { WM_DDE_EXECUTE
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
62 { WM_GETMINMAXINFO
, sizeof(MINMAXINFO
), MMS_FLAG_READWRITE
},
63 { WM_GETTEXT
, MMS_SIZE_WPARAMWCHAR
, MMS_FLAG_WRITE
},
64 { WM_NCCALCSIZE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
65 { WM_NCCREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
66 { WM_SETTEXT
, MMS_SIZE_LPARAMSZ
, MMS_FLAG_READ
},
67 { WM_STYLECHANGED
, sizeof(STYLESTRUCT
), MMS_FLAG_READ
},
68 { WM_STYLECHANGING
, sizeof(STYLESTRUCT
), MMS_FLAG_READWRITE
},
69 { WM_COPYDATA
, MMS_SIZE_SPECIAL
, MMS_FLAG_READ
},
70 { WM_WINDOWPOSCHANGED
, sizeof(WINDOWPOS
), MMS_FLAG_READ
},
71 { WM_WINDOWPOSCHANGING
, sizeof(WINDOWPOS
), MMS_FLAG_READWRITE
},
74 static PMSGMEMORY FASTCALL
75 FindMsgMemory(UINT Msg
)
77 PMSGMEMORY MsgMemoryEntry
;
79 /* See if this message type is present in the table */
80 for (MsgMemoryEntry
= MsgMemory
;
81 MsgMemoryEntry
< MsgMemory
+ sizeof(MsgMemory
) / sizeof(MSGMEMORY
);
84 if (Msg
== MsgMemoryEntry
->Message
)
86 return MsgMemoryEntry
;
94 MsgMemorySize(PMSGMEMORY MsgMemoryEntry
, WPARAM wParam
, LPARAM lParam
)
97 PUNICODE_STRING WindowName
;
98 PUNICODE_STRING ClassName
;
103 if (MMS_SIZE_WPARAM
== MsgMemoryEntry
->Size
)
107 else if (MMS_SIZE_WPARAMWCHAR
== MsgMemoryEntry
->Size
)
109 Size
= (UINT
) (wParam
* sizeof(WCHAR
));
111 else if (MMS_SIZE_LPARAMSZ
== MsgMemoryEntry
->Size
)
113 Size
= (UINT
) ((wcslen((PWSTR
) lParam
) + 1) * sizeof(WCHAR
));
115 else if (MMS_SIZE_SPECIAL
== MsgMemoryEntry
->Size
)
117 switch(MsgMemoryEntry
->Message
)
121 Cs
= (CREATESTRUCTW
*) lParam
;
122 WindowName
= (PUNICODE_STRING
) Cs
->lpszName
;
123 ClassName
= (PUNICODE_STRING
) Cs
->lpszClass
;
124 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
125 if (IS_ATOM(ClassName
->Buffer
))
127 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
131 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
136 Size
= wParam
? sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
) : sizeof(RECT
);
140 Size
= sizeof(COPYDATASTRUCT
) + ((PCOPYDATASTRUCT
)lParam
)->cbData
;
143 case WM_COPYGLOBALDATA
:
155 Size
= MsgMemoryEntry
->Size
;
158 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
160 DPRINT1("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH2_GetExceptionCode());
168 PackParam(LPARAM
*lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
170 NCCALCSIZE_PARAMS
*UnpackedNcCalcsize
;
171 NCCALCSIZE_PARAMS
*PackedNcCalcsize
;
172 CREATESTRUCTW
*UnpackedCs
;
173 CREATESTRUCTW
*PackedCs
;
174 PUNICODE_STRING WindowName
;
175 PUNICODE_STRING ClassName
;
179 *lParamPacked
= lParam
;
180 if (WM_NCCALCSIZE
== Msg
&& wParam
)
182 UnpackedNcCalcsize
= (NCCALCSIZE_PARAMS
*) lParam
;
183 if (UnpackedNcCalcsize
->lppos
!= (PWINDOWPOS
) (UnpackedNcCalcsize
+ 1))
185 PackedNcCalcsize
= ExAllocatePoolWithTag(PagedPool
,
186 sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
),
188 if (NULL
== PackedNcCalcsize
)
190 DPRINT1("Not enough memory to pack lParam\n");
191 return STATUS_NO_MEMORY
;
193 RtlCopyMemory(PackedNcCalcsize
, UnpackedNcCalcsize
, sizeof(NCCALCSIZE_PARAMS
));
194 PackedNcCalcsize
->lppos
= (PWINDOWPOS
) (PackedNcCalcsize
+ 1);
195 RtlCopyMemory(PackedNcCalcsize
->lppos
, UnpackedNcCalcsize
->lppos
, sizeof(WINDOWPOS
));
196 *lParamPacked
= (LPARAM
) PackedNcCalcsize
;
199 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
201 UnpackedCs
= (CREATESTRUCTW
*) lParam
;
202 WindowName
= (PUNICODE_STRING
) UnpackedCs
->lpszName
;
203 ClassName
= (PUNICODE_STRING
) UnpackedCs
->lpszClass
;
204 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
205 if (IS_ATOM(ClassName
->Buffer
))
207 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
211 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
213 PackedCs
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
214 if (NULL
== PackedCs
)
216 DPRINT1("Not enough memory to pack lParam\n");
217 return STATUS_NO_MEMORY
;
219 RtlCopyMemory(PackedCs
, UnpackedCs
, sizeof(CREATESTRUCTW
));
220 CsData
= (PCHAR
) (PackedCs
+ 1);
221 PackedCs
->lpszName
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
222 RtlCopyMemory(CsData
, WindowName
->Buffer
, WindowName
->Length
);
223 CsData
+= WindowName
->Length
;
224 *((WCHAR
*) CsData
) = L
'\0';
225 CsData
+= sizeof(WCHAR
);
226 PackedCs
->lpszClass
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
227 if (IS_ATOM(ClassName
->Buffer
))
229 *((WCHAR
*) CsData
) = L
'A';
230 CsData
+= sizeof(WCHAR
);
231 *((ATOM
*) CsData
) = (ATOM
)(DWORD_PTR
) ClassName
->Buffer
;
232 CsData
+= sizeof(ATOM
);
236 *((WCHAR
*) CsData
) = L
'S';
237 CsData
+= sizeof(WCHAR
);
238 RtlCopyMemory(CsData
, ClassName
->Buffer
, ClassName
->Length
);
239 CsData
+= ClassName
->Length
;
240 *((WCHAR
*) CsData
) = L
'\0';
241 CsData
+= sizeof(WCHAR
);
243 ASSERT(CsData
== (PCHAR
) PackedCs
+ Size
);
244 *lParamPacked
= (LPARAM
) PackedCs
;
247 return STATUS_SUCCESS
;
251 UnpackParam(LPARAM lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
253 NCCALCSIZE_PARAMS
*UnpackedParams
;
254 NCCALCSIZE_PARAMS
*PackedParams
;
255 PWINDOWPOS UnpackedWindowPos
;
257 if (lParamPacked
== lParam
)
259 return STATUS_SUCCESS
;
262 if (WM_NCCALCSIZE
== Msg
&& wParam
)
264 PackedParams
= (NCCALCSIZE_PARAMS
*) lParamPacked
;
265 UnpackedParams
= (NCCALCSIZE_PARAMS
*) lParam
;
266 UnpackedWindowPos
= UnpackedParams
->lppos
;
267 RtlCopyMemory(UnpackedParams
, PackedParams
, sizeof(NCCALCSIZE_PARAMS
));
268 UnpackedParams
->lppos
= UnpackedWindowPos
;
269 RtlCopyMemory(UnpackedWindowPos
, PackedParams
+ 1, sizeof(WINDOWPOS
));
270 ExFreePool((PVOID
) lParamPacked
);
272 return STATUS_SUCCESS
;
274 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
276 ExFreePool((PVOID
) lParamPacked
);
278 return STATUS_SUCCESS
;
283 return STATUS_INVALID_PARAMETER
;
290 ( PWINDOW_OBJECT Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
292 BOOL SameThread
= FALSE
;
294 if (Window
->pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
297 if ((!SameThread
&& (Window
->pti
->fsHooks
& HOOKID_TO_FLAG(WH_CALLWNDPROC
))) ||
298 (SameThread
&& ISITHOOKED(WH_CALLWNDPROC
)) )
305 co_HOOK_CallHooks( WH_CALLWNDPROC
, HC_ACTION
, SameThread
, (LPARAM
)&CWP
);
313 ( PWINDOW_OBJECT Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*uResult
)
315 BOOL SameThread
= FALSE
;
317 if (Window
->pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
320 if ((!SameThread
&& (Window
->pti
->fsHooks
& HOOKID_TO_FLAG(WH_CALLWNDPROCRET
))) ||
321 (SameThread
&& ISITHOOKED(WH_CALLWNDPROCRET
)) )
326 CWPR
.wParam
= wParam
;
327 CWPR
.lParam
= lParam
;
328 CWPR
.lResult
= *uResult
;
329 co_HOOK_CallHooks( WH_CALLWNDPROCRET
, HC_ACTION
, SameThread
, (LPARAM
)&CWPR
);
335 IntDispatchMessage(PMSG pMsg
)
337 LARGE_INTEGER TickCount
;
340 PMSGMEMORY MsgMemoryEntry
;
341 INT lParamBufferSize
;
343 PWINDOW_OBJECT Window
= NULL
;
347 Window
= UserGetWindowObject(pMsg
->hwnd
);
348 if (!Window
|| !Window
->Wnd
) return 0;
351 if (((pMsg
->message
== WM_SYSTIMER
) ||
352 (pMsg
->message
== WM_TIMER
)) &&
355 if (pMsg
->message
== WM_TIMER
)
357 if (ValidateTimerCallback(PsGetCurrentThreadWin32Thread(),Window
,pMsg
->wParam
,pMsg
->lParam
))
359 KeQueryTickCount(&TickCount
);
360 Time
= MsqCalculateMessageTime(&TickCount
);
361 return co_IntCallWindowProc((WNDPROC
)pMsg
->lParam
,
373 PTIMER pTimer
= FindSystemTimer(pMsg
);
374 if (pTimer
&& pTimer
->pfn
)
376 KeQueryTickCount(&TickCount
);
377 Time
= MsqCalculateMessageTime(&TickCount
);
378 pTimer
->pfn(pMsg
->hwnd
, WM_SYSTIMER
, (UINT
)pMsg
->wParam
, Time
);
384 if ( !Window
|| !Window
->Wnd
) return 0;
386 /* See if this message type is present in the table */
387 MsgMemoryEntry
= FindMsgMemory(pMsg
->message
);
388 if ( !MsgMemoryEntry
)
390 lParamBufferSize
= -1;
394 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, pMsg
->wParam
, pMsg
->lParam
);
397 if (! NT_SUCCESS(PackParam(&lParamPacked
, pMsg
->message
, pMsg
->wParam
, pMsg
->lParam
)))
399 DPRINT1("Failed to pack message parameters\n");
403 retval
= co_IntCallWindowProc( Window
->Wnd
->lpfnWndProc
,
404 !Window
->Wnd
->Unicode
,
411 if (! NT_SUCCESS(UnpackParam(lParamPacked
, pMsg
->message
, pMsg
->wParam
, pMsg
->lParam
)))
413 DPRINT1("Failed to unpack message parameters\n");
416 if (pMsg
->message
== WM_PAINT
)
418 /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
419 HRGN hrgn
= IntSysCreateRectRgn( 0, 0, 0, 0 );
420 co_UserGetUpdateRgn( Window
, hrgn
, TRUE
);
421 REGION_FreeRgnByHandle( hrgn
);
427 co_IntSendHitTestMessages(PUSER_MESSAGE_QUEUE ThreadQueue
, LPMSG Msg
)
429 if(!Msg
->hwnd
|| ThreadQueue
->CaptureWindow
)
438 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(HTCLIENT
, Msg
->message
));
443 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(Msg
->wParam
, Msg
->message
));
450 case WM_LBUTTONDBLCLK
:
451 case WM_MBUTTONDBLCLK
:
452 case WM_RBUTTONDBLCLK
:
453 case WM_XBUTTONDBLCLK
:
456 PSYSTEM_CURSORINFO CurInfo
;
457 CurInfo
= IntGetSysCursorInfo();
459 wParam
= (WPARAM
)(CurInfo
->ButtonsDown
);
461 co_IntSendMessage(Msg
->hwnd
, WM_MOUSEMOVE
, wParam
, Msg
->lParam
);
462 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(HTCLIENT
, Msg
->message
));
465 case WM_NCLBUTTONDOWN
:
466 case WM_NCMBUTTONDOWN
:
467 case WM_NCRBUTTONDOWN
:
468 case WM_NCXBUTTONDOWN
:
469 case WM_NCLBUTTONDBLCLK
:
470 case WM_NCMBUTTONDBLCLK
:
471 case WM_NCRBUTTONDBLCLK
:
472 case WM_NCXBUTTONDBLCLK
:
474 co_IntSendMessage(Msg
->hwnd
, WM_NCMOUSEMOVE
, (WPARAM
)Msg
->wParam
, Msg
->lParam
);
475 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(Msg
->wParam
, Msg
->message
));
482 co_IntActivateWindowMouse(
483 PUSER_MESSAGE_QUEUE ThreadQueue
,
485 PWINDOW_OBJECT MsgWindow
,
489 PWINDOW_OBJECT Parent
;
491 ASSERT_REFS_CO(MsgWindow
);
493 if(*HitTest
== (USHORT
)HTTRANSPARENT
)
495 /* eat the message, search again! */
499 Parent
= IntGetParent(MsgWindow
);//fixme: deref retval?
501 /* If no parent window, pass MsgWindows HWND as wParam. Fixes bug #3111 */
502 Result
= co_IntSendMessage(MsgWindow
->hSelf
,
504 (WPARAM
) (Parent
? Parent
->hSelf
: MsgWindow
->hSelf
),
505 (LPARAM
)MAKELONG(*HitTest
, Msg
->message
)
510 case MA_NOACTIVATEANDEAT
:
514 case MA_ACTIVATEANDEAT
:
515 co_IntMouseActivateWindow(MsgWindow
);
519 co_IntMouseActivateWindow(MsgWindow
);
527 co_IntTranslateMouseMessage(
528 PUSER_MESSAGE_QUEUE ThreadQueue
,
533 PWINDOW_OBJECT Window
;
534 USER_REFERENCE_ENTRY Ref
, DesktopRef
;
536 if(!(Window
= UserGetWindowObject(Msg
->hwnd
)))
538 /* let's just eat the message?! */
542 UserRefObjectCo(Window
, &Ref
);
544 if ( ThreadQueue
== Window
->pti
->MessageQueue
&&
545 ThreadQueue
->CaptureWindow
!= Window
->hSelf
)
547 /* only send WM_NCHITTEST messages if we're not capturing the window! */
548 *HitTest
= co_IntSendMessage(Window
->hSelf
, WM_NCHITTEST
, 0,
549 MAKELONG(Msg
->pt
.x
, Msg
->pt
.y
));
551 if (*HitTest
== (USHORT
)HTTRANSPARENT
)
553 PWINDOW_OBJECT DesktopWindow
;
554 HWND hDesktop
= IntGetDesktopWindow();
556 if ((DesktopWindow
= UserGetWindowObject(hDesktop
)))
560 UserRefObjectCo(DesktopWindow
, &DesktopRef
);
562 co_WinPosWindowFromPoint(DesktopWindow
, Window
->pti
->MessageQueue
, &Msg
->pt
, &Wnd
);
567 /* post the message to the other window */
568 Msg
->hwnd
= Wnd
->hSelf
;
569 if(!(Wnd
->state
& WINDOWSTATUS_DESTROYING
))
571 MsqPostMessage(Wnd
->pti
->MessageQueue
, Msg
, FALSE
,
572 Msg
->message
== WM_MOUSEMOVE
? QS_MOUSEMOVE
:
576 /* eat the message */
577 UserDereferenceObject(Wnd
);
578 UserDerefObjectCo(DesktopWindow
);
579 UserDerefObjectCo(Window
);
582 UserDereferenceObject(Wnd
);
585 UserDerefObjectCo(DesktopWindow
);
594 if ( gspv
.bMouseClickLock
&&
595 ( (Msg
->message
== WM_LBUTTONUP
) ||
596 (Msg
->message
== WM_LBUTTONDOWN
) ) )
598 if (MsqIsClkLck(Msg
, Remove
))
600 // FIXME: drop the message, hack: use WM_NULL
601 Msg
->message
= WM_NULL
;
605 if (IS_BTN_MESSAGE(Msg
->message
, DOWN
))
607 /* generate double click messages, if necessary */
608 if ((((*HitTest
) != HTCLIENT
) ||
609 (Window
->Wnd
->pcls
->style
& CS_DBLCLKS
)) &&
610 MsqIsDblClk(Msg
, Remove
))
612 Msg
->message
+= WM_LBUTTONDBLCLK
- WM_LBUTTONDOWN
;
616 if(Msg
->message
!= WM_MOUSEWHEEL
)
619 if ((*HitTest
) != HTCLIENT
)
621 Msg
->message
+= WM_NCMOUSEMOVE
- WM_MOUSEMOVE
;
622 if ( (Msg
->message
== WM_NCRBUTTONUP
) &&
623 (((*HitTest
) == HTCAPTION
) || ((*HitTest
) == HTSYSMENU
)) )
625 Msg
->message
= WM_CONTEXTMENU
;
626 Msg
->wParam
= (WPARAM
)Window
->hSelf
;
630 Msg
->wParam
= *HitTest
;
632 Msg
->lParam
= MAKELONG(Msg
->pt
.x
, Msg
->pt
.y
);
634 else if ( ThreadQueue
->MoveSize
== NULL
&&
635 ThreadQueue
->MenuOwner
== NULL
)
637 /* NOTE: Msg->pt should remain in screen coordinates. -- FiN */
638 Msg
->lParam
= MAKELONG(
639 Msg
->pt
.x
- (WORD
)Window
->Wnd
->rcClient
.left
,
640 Msg
->pt
.y
- (WORD
)Window
->Wnd
->rcClient
.top
);
644 UserDerefObjectCo(Window
);
649 * Internal version of PeekMessage() doing all the work
652 co_IntPeekMessage( PUSER_MESSAGE Msg
,
653 PWINDOW_OBJECT Window
,
659 LARGE_INTEGER LargeTickCount
;
660 PUSER_MESSAGE_QUEUE ThreadQueue
;
661 PUSER_MESSAGE Message
;
662 BOOL Present
, RemoveMessages
;
663 USER_REFERENCE_ENTRY Ref
;
665 MOUSEHOOKSTRUCT MHook
;
667 /* The queues and order in which they are checked are documented in the MSDN
668 article on GetMessage() */
670 pti
= PsGetCurrentThreadWin32Thread();
671 ThreadQueue
= pti
->MessageQueue
;
673 /* Inspect RemoveMsg flags */
675 The only flag we process is PM_REMOVE.
676 Processing (High word) PM_QS_Xx Is needed. This and MsgFilterXxx can result
677 with QS_Xx flags to be used to isolate which message check to test for.
678 ATM, we look at all messages and the filters are sent to co_MsqFindMessage
679 and there, it is cross checked.
680 Example: Wine server/queue.c is_keyboard_msg, check_msg_filter and
681 filter_contains_hw_range.
683 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
686 If no filter is specified, messages are processed in the following order:
690 * Input (hardware) messages and system internal events
691 * Sent messages (again)
699 KeQueryTickCount(&LargeTickCount
);
700 ThreadQueue
->LastMsgRead
= LargeTickCount
.u
.LowPart
;
702 /* Dispatch sent messages here. */
703 while (co_MsqDispatchOneSentMessage(ThreadQueue
))
706 /* Now look for a quit message. */
708 if (ThreadQueue
->QuitPosted
)
710 /* According to the PSDK, WM_QUIT messages are always returned, regardless
711 of the filter specified */
712 Msg
->Msg
.hwnd
= NULL
;
713 Msg
->Msg
.message
= WM_QUIT
;
714 Msg
->Msg
.wParam
= ThreadQueue
->QuitExitCode
;
716 Msg
->FreeLParam
= FALSE
;
719 ThreadQueue
->QuitPosted
= FALSE
;
724 /* Now check for normal messages. */
725 Present
= co_MsqFindMessage( ThreadQueue
,
734 RtlCopyMemory(Msg
, Message
, sizeof(USER_MESSAGE
));
737 MsqDestroyMessage(Message
);
742 /* Check for hardware events. */
743 Present
= co_MsqFindMessage( ThreadQueue
,
752 RtlCopyMemory(Msg
, Message
, sizeof(USER_MESSAGE
));
755 MsqDestroyMessage(Message
);
760 /* Check for sent messages again. */
761 while (co_MsqDispatchOneSentMessage(ThreadQueue
))
764 /* Check for paint messages. */
765 if ( IntGetPaintMessage( Window
,
772 Msg
->FreeLParam
= FALSE
;
776 if (ThreadQueue
->WakeMask
& QS_TIMER
)
777 if (PostTimerMessages(Window
)) // If there are timers ready,
778 goto CheckMessages
; // go back and process them.
780 // LOL! Polling Timer Queue? How much time is spent doing this?
781 /* Check for WM_(SYS)TIMER messages */
782 Present
= MsqGetTimerMessage( ThreadQueue
,
790 Msg
->FreeLParam
= FALSE
;
800 PWINDOW_OBJECT MsgWindow
= NULL
;
802 /* Mouse message process */
805 ( MsgWindow
= UserGetWindowObject(Msg
->Msg
.hwnd
) ) &&
806 Msg
->Msg
.message
>= WM_MOUSEFIRST
&&
807 Msg
->Msg
.message
<= WM_MOUSELAST
)
811 UserRefObjectCo(MsgWindow
, &Ref
);
813 if ( co_IntTranslateMouseMessage( ThreadQueue
,
817 /* FIXME - check message filter again, if the message doesn't match anymore,
820 UserDerefObjectCo(MsgWindow
);
821 /* eat the message, search again */
825 if(ThreadQueue
->CaptureWindow
== NULL
)
827 co_IntSendHitTestMessages(ThreadQueue
, &Msg
->Msg
);
829 if ( ( Msg
->Msg
.message
!= WM_MOUSEMOVE
&&
830 Msg
->Msg
.message
!= WM_NCMOUSEMOVE
) &&
831 IS_BTN_MESSAGE(Msg
->Msg
.message
, DOWN
) &&
832 co_IntActivateWindowMouse(ThreadQueue
, &Msg
->Msg
, MsgWindow
, &HitTest
) )
834 UserDerefObjectCo(MsgWindow
);
835 /* eat the message, search again */
840 UserDerefObjectCo(MsgWindow
);
844 co_IntSendHitTestMessages(ThreadQueue
, &Msg
->Msg
);
849 // UserDereferenceObject(MsgWindow);
855 if ( ( Msg
->Msg
.hwnd
&&
856 Msg
->Msg
.message
>= WM_MOUSEFIRST
&&
857 Msg
->Msg
.message
<= WM_MOUSELAST
) &&
858 co_IntTranslateMouseMessage( ThreadQueue
,
862 /* FIXME - check message filter again, if the message doesn't match anymore,
865 /* eat the message, search again */
870 if ( ISITHOOKED(WH_MOUSE
) &&
871 Msg
->Msg
.message
>= WM_MOUSEFIRST
&&
872 Msg
->Msg
.message
<= WM_MOUSELAST
)
874 MHook
.pt
= Msg
->Msg
.pt
;
875 MHook
.hwnd
= Msg
->Msg
.hwnd
;
876 MHook
.wHitTestCode
= HitTest
;
877 MHook
.dwExtraInfo
= 0;
878 if (co_HOOK_CallHooks( WH_MOUSE
,
879 RemoveMsg
? HC_ACTION
: HC_NOREMOVE
,
883 if (ISITHOOKED(WH_CBT
))
885 MHook
.pt
= Msg
->Msg
.pt
;
886 MHook
.hwnd
= Msg
->Msg
.hwnd
;
887 MHook
.wHitTestCode
= HitTest
;
888 MHook
.dwExtraInfo
= 0;
889 co_HOOK_CallHooks( WH_CBT
,
898 if ( ISITHOOKED(WH_KEYBOARD
) &&
899 (Msg
->Msg
.message
== WM_KEYDOWN
|| Msg
->Msg
.message
== WM_KEYUP
) )
901 if (co_HOOK_CallHooks( WH_KEYBOARD
,
902 RemoveMsg
? HC_ACTION
: HC_NOREMOVE
,
903 LOWORD(Msg
->Msg
.wParam
),
906 if (ISITHOOKED(WH_CBT
))
908 /* skip this message */
909 co_HOOK_CallHooks( WH_CBT
,
911 LOWORD(Msg
->Msg
.wParam
),
917 // The WH_GETMESSAGE hook enables an application to monitor messages about to
918 // be returned by the GetMessage or PeekMessage function.
919 if (ISITHOOKED(WH_GETMESSAGE
))
921 //DPRINT1("Peek WH_GETMESSAGE -> %x\n",&Msg);
922 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)&Msg
->Msg
);
930 static NTSTATUS FASTCALL
931 CopyMsgToKernelMem(MSG
*KernelModeMsg
, MSG
*UserModeMsg
, PMSGMEMORY MsgMemoryEntry
)
938 *KernelModeMsg
= *UserModeMsg
;
940 /* See if this message type is present in the table */
941 if (NULL
== MsgMemoryEntry
)
943 /* Not present, no copying needed */
944 return STATUS_SUCCESS
;
947 /* Determine required size */
948 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
952 /* Allocate kernel mem */
953 KernelMem
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
954 if (NULL
== KernelMem
)
956 DPRINT1("Not enough memory to copy message to kernel mem\n");
957 return STATUS_NO_MEMORY
;
959 KernelModeMsg
->lParam
= (LPARAM
) KernelMem
;
961 /* Copy data if required */
962 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_READ
))
964 Status
= MmCopyFromCaller(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
965 if (! NT_SUCCESS(Status
))
967 DPRINT1("Failed to copy message to kernel: invalid usermode buffer\n");
968 ExFreePoolWithTag(KernelMem
, TAG_MSG
);
974 /* Make sure we don't pass any secrets to usermode */
975 RtlZeroMemory(KernelMem
, Size
);
980 KernelModeMsg
->lParam
= 0;
983 return STATUS_SUCCESS
;
986 static NTSTATUS FASTCALL
987 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
990 PMSGMEMORY MsgMemoryEntry
;
993 /* See if this message type is present in the table */
994 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
995 if (NULL
== MsgMemoryEntry
)
997 /* Not present, no copying needed */
998 return STATUS_SUCCESS
;
1001 /* Determine required size */
1002 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
1006 /* Copy data if required */
1007 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
1009 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
1010 if (! NT_SUCCESS(Status
))
1012 DPRINT1("Failed to copy message from kernel: invalid usermode buffer\n");
1013 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
1018 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
1021 return STATUS_SUCCESS
;
1024 static BOOL FASTCALL
1025 co_IntWaitMessage( PWINDOW_OBJECT Window
,
1030 PUSER_MESSAGE_QUEUE ThreadQueue
;
1031 NTSTATUS Status
= STATUS_SUCCESS
;
1034 pti
= PsGetCurrentThreadWin32Thread();
1035 ThreadQueue
= pti
->MessageQueue
;
1039 if ( co_IntPeekMessage( &Msg
,
1047 /* Nothing found. Wait for new messages. */
1048 Status
= co_MsqWaitForNewMessages( ThreadQueue
,
1053 while ( (STATUS_WAIT_0
<= Status
&& Status
<= STATUS_WAIT_63
) ||
1054 STATUS_TIMEOUT
== Status
);
1056 if (!NT_SUCCESS(Status
))
1058 SetLastNtError(Status
);
1059 DPRINT1("Exit co_IntWaitMessage on error!\n");
1066 co_IntGetPeekMessage( PMSG pMsg
,
1074 PWINDOW_OBJECT Window
;
1077 if ( hWnd
== HWND_TOPMOST
||
1078 hWnd
== HWND_BROADCAST
)
1081 /* Validate input */
1082 if (hWnd
&& hWnd
!= HWND_BOTTOM
)
1084 if (!(Window
= UserGetWindowObject(hWnd
)))
1094 Window
= (PWINDOW_OBJECT
)hWnd
;
1097 if (MsgFilterMax
< MsgFilterMin
)
1105 Present
= co_IntPeekMessage( &Msg
,
1112 RtlCopyMemory( pMsg
, &Msg
.Msg
, sizeof(MSG
));
1115 return (WM_QUIT
!= pMsg
->message
);
1120 if ( bGMSG
&& !co_IntWaitMessage(Window
, MsgFilterMin
, MsgFilterMax
) )
1126 if (!(RemoveMsg
& PM_NOYIELD
))
1128 // Yield this thread!
1131 UserEnterExclusive();
1132 // Fall through to fail.
1136 while( bGMSG
&& !Present
);
1142 UserPostThreadMessage( DWORD idThread
,
1149 PTHREADINFO pThread
;
1150 LARGE_INTEGER LargeTickCount
;
1153 DPRINT1("UserPostThreadMessage wParam 0x%x lParam 0x%x\n", wParam
,lParam
);
1155 if (FindMsgMemory(Msg
) != 0)
1157 SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY
);
1161 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
1163 if( Status
== STATUS_SUCCESS
)
1165 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
1167 !pThread
->MessageQueue
||
1168 (pThread
->TIF_flags
& TIF_INCLEANUP
))
1170 ObDereferenceObject( peThread
);
1174 Message
.hwnd
= NULL
;
1175 Message
.message
= Msg
;
1176 Message
.wParam
= wParam
;
1177 Message
.lParam
= lParam
;
1178 Message
.pt
= gpsi
->ptCursor
;
1180 KeQueryTickCount(&LargeTickCount
);
1181 pThread
->timeLast
= Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1182 MsqPostMessage(pThread
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
);
1183 ObDereferenceObject( peThread
);
1188 SetLastNtError( Status
);
1194 UserPostMessage( HWND Wnd
,
1201 LARGE_INTEGER LargeTickCount
;
1203 if (FindMsgMemory(Msg
) != 0)
1205 SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY
);
1210 return UserPostThreadMessage( PtrToInt(PsGetCurrentThreadId()),
1215 if (Wnd
== HWND_BROADCAST
)
1218 PWINDOW_OBJECT DesktopWindow
;
1221 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1222 List
= IntWinListChildren(DesktopWindow
);
1226 for (i
= 0; List
[i
]; i
++)
1227 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1233 PWINDOW_OBJECT Window
;
1235 Window
= UserGetWindowObject(Wnd
);
1236 if ( !Window
|| !Window
->Wnd
)
1241 pti
= Window
->Wnd
->head
.pti
;
1242 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1244 DPRINT1("Attempted to post message to window 0x%x when the thread is in cleanup!\n", Wnd
);
1248 if ( Window
->state
& WINDOWSTATUS_DESTROYING
)
1250 DPRINT1("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd
);
1251 /* FIXME - last error code? */
1257 MsqPostQuitMessage(Window
->pti
->MessageQueue
, wParam
);
1262 Message
.message
= Msg
;
1263 Message
.wParam
= wParam
;
1264 Message
.lParam
= lParam
;
1265 Message
.pt
= gpsi
->ptCursor
;
1266 KeQueryTickCount(&LargeTickCount
);
1267 pti
->timeLast
= Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1268 MsqPostMessage(Window
->pti
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
);
1276 co_IntSendMessage( HWND hWnd
,
1281 ULONG_PTR Result
= 0;
1282 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1284 return (LRESULT
)Result
;
1291 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1297 ULONG_PTR
*uResult
)
1301 PWINDOW_OBJECT Window
= NULL
;
1302 PMSGMEMORY MsgMemoryEntry
;
1303 INT lParamBufferSize
;
1304 LPARAM lParamPacked
;
1305 PTHREADINFO Win32Thread
;
1306 DECLARE_RETURN(LRESULT
);
1307 USER_REFERENCE_ENTRY Ref
;
1309 if (!(Window
= UserGetWindowObject(hWnd
)))
1314 UserRefObjectCo(Window
, &Ref
);
1316 Win32Thread
= PsGetCurrentThreadWin32Thread();
1318 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1320 if ( NULL
!= Win32Thread
&&
1321 Window
->pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1323 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1325 /* Never send messages to exiting threads */
1329 /* See if this message type is present in the table */
1330 MsgMemoryEntry
= FindMsgMemory(Msg
);
1331 if (NULL
== MsgMemoryEntry
)
1333 lParamBufferSize
= -1;
1337 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1340 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
)))
1342 DPRINT1("Failed to pack message parameters\n");
1346 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->Wnd
->lpfnWndProc
,
1347 !Window
->Wnd
->Unicode
,
1358 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1360 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
)))
1362 DPRINT1("Failed to unpack message parameters\n");
1369 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->pti
->MessageQueue
))
1371 /* FIXME - Set a LastError? */
1375 if (Window
->state
& WINDOWSTATUS_DESTROYING
)
1377 /* FIXME - last error? */
1378 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1384 Status
= co_MsqSendMessage( Window
->pti
->MessageQueue
,
1390 (uFlags
& SMTO_BLOCK
),
1394 while ((STATUS_TIMEOUT
== Status
) &&
1395 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1396 !MsqIsHung(Window
->pti
->MessageQueue
));
1398 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1400 if (STATUS_TIMEOUT
== Status
)
1404 Microsoft Windows 2000: If GetLastError returns zero, then the function
1406 XP+ : If the function fails or times out, the return value is zero.
1407 To get extended error information, call GetLastError. If GetLastError
1408 returns ERROR_TIMEOUT, then the function timed out.
1410 SetLastWin32Error(ERROR_TIMEOUT
);
1413 else if (! NT_SUCCESS(Status
))
1415 SetLastNtError(Status
);
1422 if (Window
) UserDerefObjectCo(Window
);
1427 co_IntSendMessageTimeout( HWND hWnd
,
1433 ULONG_PTR
*uResult
)
1435 PWINDOW_OBJECT DesktopWindow
;
1439 if (HWND_BROADCAST
!= hWnd
)
1441 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1444 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1445 if (NULL
== DesktopWindow
)
1447 SetLastWin32Error(ERROR_INTERNAL_ERROR
);
1451 Children
= IntWinListChildren(DesktopWindow
);
1452 if (NULL
== Children
)
1457 for (Child
= Children
; NULL
!= *Child
; Child
++)
1459 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1462 ExFreePool(Children
);
1464 return (LRESULT
) TRUE
;
1468 /* This function posts a message if the destination's message queue belongs to
1469 another thread, otherwise it sends the message. It does not support broadcast
1472 co_IntPostOrSendMessage( HWND hWnd
,
1479 PWINDOW_OBJECT Window
;
1481 if ( hWnd
== HWND_BROADCAST
)
1486 if(!(Window
= UserGetWindowObject(hWnd
)))
1491 pti
= PsGetCurrentThreadWin32Thread();
1493 if ( Window
->pti
->MessageQueue
!= pti
->MessageQueue
&&
1494 FindMsgMemory(Msg
) == 0 )
1496 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1500 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1506 return (LRESULT
)Result
;
1510 co_IntDoSendMessage( HWND hWnd
,
1515 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1518 LRESULT Result
= TRUE
;
1520 PWINDOW_OBJECT Window
= NULL
;
1521 NTUSERSENDMESSAGEINFO Info
;
1524 PMSGMEMORY MsgMemoryEntry
;
1526 RtlZeroMemory(&Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1528 /* FIXME: Call hooks. */
1529 if (HWND_BROADCAST
!= hWnd
)
1531 Window
= UserGetWindowObject(hWnd
);
1532 if ( !Window
|| !Window
->Wnd
)
1534 /* Tell usermode to not touch this one */
1535 Info
.HandledByKernel
= TRUE
;
1536 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1541 /* Check for an exiting window. */
1542 if (Window
&& Window
->state
& WINDOWSTATUS_DESTROYING
)
1544 DPRINT1("co_IntDoSendMessage Window Exiting!\n");
1547 /* See if the current thread can handle the message */
1548 pti
= PsGetCurrentThreadWin32Thread();
1550 // This is checked in user mode!!!!!!!
1551 if ( HWND_BROADCAST
!= hWnd
&&
1553 Window
->pti
->MessageQueue
== pti
->MessageQueue
&&
1554 !ISITHOOKED(WH_CALLWNDPROC
) &&
1555 !ISITHOOKED(WH_CALLWNDPROCRET
) &&
1556 ( Msg
< WM_DDE_FIRST
|| Msg
> WM_DDE_LAST
) )
1558 /* Gather the information usermode needs to call the window proc directly */
1559 Info
.HandledByKernel
= FALSE
;
1561 Status
= MmCopyFromCaller(&(Info
.Ansi
), &(UnsafeInfo
->Ansi
),
1563 if (! NT_SUCCESS(Status
))
1565 Info
.Ansi
= ! Window
->Wnd
->Unicode
;
1568 Info
.Ansi
= !Window
->Wnd
->Unicode
;
1569 Info
.Proc
= Window
->Wnd
->lpfnWndProc
;
1573 /* Must be handled by other thread */
1574 // if (HWND_BROADCAST != hWnd)
1576 // UserDereferenceObject(Window);
1578 Info
.HandledByKernel
= TRUE
;
1579 UserModeMsg
.hwnd
= hWnd
;
1580 UserModeMsg
.message
= Msg
;
1581 UserModeMsg
.wParam
= wParam
;
1582 UserModeMsg
.lParam
= lParam
;
1583 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1585 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1586 if (! NT_SUCCESS(Status
))
1588 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1589 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1590 return (dsm
? 0 : -1);
1595 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1596 KernelModeMsg
.message
,
1597 KernelModeMsg
.wParam
,
1598 KernelModeMsg
.lParam
);
1602 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1603 KernelModeMsg
.message
,
1604 KernelModeMsg
.wParam
,
1605 KernelModeMsg
.lParam
,
1611 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1612 if (! NT_SUCCESS(Status
))
1614 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1615 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1616 return(dsm
? 0 : -1);
1620 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1621 if (! NT_SUCCESS(Status
))
1623 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1626 return (LRESULT
)Result
;
1631 UserSendNotifyMessage( HWND hWnd
,
1638 if (FindMsgMemory(Msg
) != 0)
1640 SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY
);
1644 // Basicly the same as IntPostOrSendMessage
1645 if (hWnd
== HWND_BROADCAST
) //Handle Broadcast
1648 PWINDOW_OBJECT DesktopWindow
;
1651 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1652 List
= IntWinListChildren(DesktopWindow
);
1656 for (i
= 0; List
[i
]; i
++)
1658 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1667 PWINDOW_OBJECT Window
;
1670 if ( !(Window
= UserGetWindowObject(hWnd
)) ) return FALSE
;
1672 pti
= PsGetCurrentThreadWin32Thread();
1674 if (Window
->pti
->MessageQueue
!= pti
->MessageQueue
)
1675 { // Send message w/o waiting for it.
1676 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1679 { // Handle message and callback.
1680 Message
.hwnd
= hWnd
;
1681 Message
.message
= Msg
;
1682 Message
.wParam
= wParam
;
1683 Message
.lParam
= lParam
;
1685 Result
= co_IntSendMessageTimeoutSingle( hWnd
,
1699 IntGetQueueStatus(BOOL ClearChanges
)
1702 PUSER_MESSAGE_QUEUE Queue
;
1704 DECLARE_RETURN(DWORD
);
1706 DPRINT("Enter IntGetQueueStatus\n");
1708 pti
= PsGetCurrentThreadWin32Thread();
1709 Queue
= pti
->MessageQueue
;
1711 Result
= MAKELONG(Queue
->QueueBits
, Queue
->ChangedBits
);
1714 Queue
->ChangedBits
= 0;
1720 DPRINT("Leave IntGetQueueStatus, ret=%i\n",_ret_
);
1725 IntInitMessagePumpHook()
1727 if (((PTHREADINFO
)PsGetCurrentThread()->Tcb
.Win32Thread
)->pcti
)
1729 ((PTHREADINFO
)PsGetCurrentThread()->Tcb
.Win32Thread
)->pcti
->dwcPumpHook
++;
1736 IntUninitMessagePumpHook()
1738 if (((PTHREADINFO
)PsGetCurrentThread()->Tcb
.Win32Thread
)->pcti
)
1740 if (((PTHREADINFO
)PsGetCurrentThread()->Tcb
.Win32Thread
)->pcti
->dwcPumpHook
<= 0)
1744 ((PTHREADINFO
)PsGetCurrentThread()->Tcb
.Win32Thread
)->pcti
->dwcPumpHook
--;
1750 /** Functions ******************************************************************/
1753 NtUserPostMessage(HWND hWnd
,
1758 DECLARE_RETURN(BOOL
);
1760 DPRINT("Enter NtUserPostMessage\n");
1761 UserEnterExclusive();
1763 RETURN( UserPostMessage(hWnd
, Msg
, wParam
, lParam
));
1766 DPRINT("Leave NtUserPostMessage, ret=%i\n",_ret_
);
1772 NtUserPostThreadMessage(DWORD idThread
,
1777 DECLARE_RETURN(BOOL
);
1779 DPRINT("Enter NtUserPostThreadMessage\n");
1780 UserEnterExclusive();
1782 RETURN( UserPostThreadMessage( idThread
,
1788 DPRINT("Leave NtUserPostThreadMessage, ret=%i\n",_ret_
);
1794 NtUserQuerySendMessage(DWORD Unknown0
)
1802 ////////// API on the way out!
1804 NtUserSendMessageTimeout( HWND hWnd
,
1811 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1815 DECLARE_RETURN(BOOL
);
1817 DPRINT("Enter NtUserSendMessageTimeout\n");
1818 UserEnterExclusive();
1820 dsm
.uFlags
= uFlags
;
1821 dsm
.uTimeout
= uTimeout
;
1822 Result
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, &dsm
, UnsafeInfo
);
1823 if(uResult
!= NULL
&& Result
!= 0)
1827 Status
= MmCopyToCaller(uResult
, &dsm
.Result
, sizeof(ULONG_PTR
));
1828 if(!NT_SUCCESS(Status
))
1830 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1837 DPRINT("Leave NtUserSendMessageTimeout, ret=%i\n",_ret_
);
1843 NtUserSendMessage( HWND Wnd
,
1847 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1849 DECLARE_RETURN(BOOL
);
1851 DPRINT("Enter NtUserSendMessage\n");
1852 UserEnterExclusive();
1854 RETURN(co_IntDoSendMessage(Wnd
, Msg
, wParam
, lParam
, NULL
, UnsafeInfo
));
1857 DPRINT("Leave NtUserSendMessage, ret=%i\n",_ret_
);
1864 NtUserWaitMessage(VOID
)
1866 DECLARE_RETURN(BOOL
);
1868 DPRINT("EnterNtUserWaitMessage\n");
1869 UserEnterExclusive();
1871 RETURN(co_IntWaitMessage(NULL
, 0, 0));
1874 DPRINT("Leave NtUserWaitMessage, ret=%i\n",_ret_
);
1881 NtUserGetMessage( PNTUSERGETMESSAGEINFO UnsafeInfo
,
1886 * FUNCTION: Get a message from the calling thread's message queue.
1888 * UnsafeMsg - Pointer to the structure which receives the returned message.
1889 * Wnd - Window whose messages are to be retrieved.
1890 * MsgFilterMin - Integer value of the lowest message value to be
1892 * MsgFilterMax - Integer value of the highest message value to be
1897 NTUSERGETMESSAGEINFO Info
;
1899 /* FIXME: if initialization is removed, gcc complains that this may be used before initialization. Please review */
1900 PWINDOW_OBJECT Window
= NULL
;
1901 PMSGMEMORY MsgMemoryEntry
;
1905 DECLARE_RETURN(BOOL
);
1906 // USER_REFERENCE_ENTRY Ref;
1908 DPRINT("Enter NtUserGetMessage\n");
1909 UserEnterExclusive();
1911 /* Validate input */
1912 if (hWnd
&& !(Window
= UserGetWindowObject(hWnd
)))
1917 // if (Window) UserRefObjectCo(Window, &Ref);
1919 if (MsgFilterMax
< MsgFilterMin
)
1927 GotMessage
= co_IntPeekMessage(&Msg
, Window
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
);
1931 /* See if this message type is present in the table */
1932 MsgMemoryEntry
= FindMsgMemory(Info
.Msg
.message
);
1933 if (NULL
== MsgMemoryEntry
)
1935 /* Not present, no copying needed */
1936 Info
.LParamSize
= 0;
1940 /* Determine required size */
1941 Size
= MsgMemorySize(MsgMemoryEntry
, Info
.Msg
.wParam
,
1943 /* Allocate required amount of user-mode memory */
1944 Info
.LParamSize
= Size
;
1946 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem
, 0,
1947 &Info
.LParamSize
, MEM_COMMIT
, PAGE_READWRITE
);
1949 if (! NT_SUCCESS(Status
))
1951 SetLastNtError(Status
);
1954 /* Transfer lParam data to user-mode mem */
1955 Status
= MmCopyToCaller(UserMem
, (PVOID
) Info
.Msg
.lParam
, Size
);
1956 if (! NT_SUCCESS(Status
))
1958 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &UserMem
,
1959 &Info
.LParamSize
, MEM_DECOMMIT
);
1960 SetLastNtError(Status
);
1963 Info
.Msg
.lParam
= (LPARAM
) UserMem
;
1965 if (Msg
.FreeLParam
&& 0 != Msg
.Msg
.lParam
)
1967 ExFreePool((void *) Msg
.Msg
.lParam
);
1969 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERGETMESSAGEINFO
));
1970 if (! NT_SUCCESS(Status
))
1972 SetLastNtError(Status
);
1976 else if (! co_IntWaitMessage(Window
, MsgFilterMin
, MsgFilterMax
))
1981 while (! GotMessage
);
1983 RETURN( WM_QUIT
!= Info
.Msg
.message
);
1986 // if (Window) UserDerefObjectCo(Window);
1988 DPRINT("Leave NtUserGetMessage\n");
2004 DECLARE_RETURN(BOOL
);
2006 DPRINT("Enter NtUserGetMessage\n");
2007 UserEnterExclusive();
2009 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
2011 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2015 RtlZeroMemory(&Msg
, sizeof(MSG
));
2017 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
2023 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2024 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2026 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2028 SetLastNtError(_SEH2_GetExceptionCode());
2036 DPRINT("Leave NtUserGetMessage\n");
2042 NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo
,
2050 NTUSERGETMESSAGEINFO Info
;
2051 PWINDOW_OBJECT Window
;
2052 PMSGMEMORY MsgMemoryEntry
;
2056 DECLARE_RETURN(BOOL
);
2058 DPRINT("Enter NtUserPeekMessage\n");
2059 UserEnterExclusive();
2061 if (hWnd
== (HWND
)-1 || hWnd
== (HWND
)0x0000FFFF || hWnd
== (HWND
)0xFFFFFFFF)
2064 /* Validate input */
2065 if (hWnd
&& hWnd
!= (HWND
)1)
2067 if (!(Window
= UserGetWindowObject(hWnd
)))
2074 Window
= (PWINDOW_OBJECT
)hWnd
;
2077 if (MsgFilterMax
< MsgFilterMin
)
2083 Present
= co_IntPeekMessage(&Msg
, Window
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
);
2088 /* See if this message type is present in the table */
2089 MsgMemoryEntry
= FindMsgMemory(Info
.Msg
.message
);
2090 if (NULL
== MsgMemoryEntry
)
2092 /* Not present, no copying needed */
2093 Info
.LParamSize
= 0;
2097 /* Determine required size */
2098 Size
= MsgMemorySize(MsgMemoryEntry
, Info
.Msg
.wParam
,
2100 /* Allocate required amount of user-mode memory */
2101 Info
.LParamSize
= Size
;
2103 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem
, 0,
2104 &Info
.LParamSize
, MEM_COMMIT
, PAGE_READWRITE
);
2105 if (! NT_SUCCESS(Status
))
2107 SetLastNtError(Status
);
2110 /* Transfer lParam data to user-mode mem */
2111 Status
= MmCopyToCaller(UserMem
, (PVOID
) Info
.Msg
.lParam
, Size
);
2112 if (! NT_SUCCESS(Status
))
2114 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &UserMem
,
2115 &Info
.LParamSize
, MEM_RELEASE
);
2116 SetLastNtError(Status
);
2119 Info
.Msg
.lParam
= (LPARAM
) UserMem
;
2121 if (RemoveMsg
&& Msg
.FreeLParam
&& 0 != Msg
.Msg
.lParam
)
2123 ExFreePool((void *) Msg
.Msg
.lParam
);
2125 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERGETMESSAGEINFO
));
2126 if (! NT_SUCCESS(Status
))
2128 SetLastNtError(Status
);
2136 DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_
);
2152 DECLARE_RETURN(BOOL
);
2154 DPRINT("Enter NtUserPeekMessage\n");
2155 UserEnterExclusive();
2157 if ( RemoveMsg
& PM_BADMSGFLAGS
)
2159 SetLastWin32Error(ERROR_INVALID_FLAGS
);
2163 RtlZeroMemory(&Msg
, sizeof(MSG
));
2165 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
2171 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2172 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2174 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2176 SetLastNtError(_SEH2_GetExceptionCode());
2184 DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_
);
2191 NtUserCallMsgFilter(
2195 BOOL BadChk
= FALSE
, Ret
= FALSE
;
2197 DECLARE_RETURN(BOOL
);
2199 DPRINT("Enter NtUserCallMsgFilter\n");
2200 UserEnterExclusive();
2205 ProbeForRead((PVOID
)lpmsg
,
2208 RtlCopyMemory( &Msg
,
2212 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2221 if (BadChk
) RETURN( FALSE
);
2223 if ( ISITHOOKED(WH_SYSMSGFILTER
) &&
2224 co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
2230 if ( ISITHOOKED(WH_MSGFILTER
) )
2232 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
2238 ProbeForWrite((PVOID
)lpmsg
,
2241 RtlCopyMemory((PVOID
)lpmsg
,
2245 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2250 if (BadChk
) RETURN( FALSE
);
2254 DPRINT("Leave NtUserCallMsgFilter. ret=%i\n", _ret_
);
2260 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
2266 UserEnterExclusive();
2269 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
2270 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
2272 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2274 SetLastNtError(_SEH2_GetExceptionCode());
2279 if (!Hit
) Res
= IntDispatchMessage(&SafeMsg
);
2287 NtUserTranslateMessage(LPMSG lpMsg
,
2292 DECLARE_RETURN(BOOL
);
2294 DPRINT("Enter NtUserTranslateMessage\n");
2295 UserEnterExclusive();
2297 Status
= MmCopyFromCaller(&SafeMsg
, lpMsg
, sizeof(MSG
));
2298 if(!NT_SUCCESS(Status
))
2300 SetLastNtError(Status
);
2304 RETURN( IntTranslateKbdMessage(&SafeMsg
, flags
));
2307 DPRINT("Leave NtUserTranslateMessage: ret=%i\n",_ret_
);
2318 ULONG_PTR ResultInfo
,
2319 DWORD dwType
, // fnID?
2322 LRESULT lResult
= 0;
2324 BOOL BadChk
= FALSE
;
2325 PWINDOW_OBJECT Window
= NULL
;
2326 USER_REFERENCE_ENTRY Ref
;
2328 UserEnterExclusive();
2330 /* Validate input */
2331 if (hWnd
&& (hWnd
!= INVALID_HANDLE_VALUE
) && !(Window
= UserGetWindowObject(hWnd
)))
2338 case FNID_DEFWINDOWPROC
:
2339 UserRefObjectCo(Window
, &Ref
);
2340 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2342 UserDerefObjectCo(Window
);
2344 case FNID_SENDNOTIFYMESSAGE
:
2345 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2347 case FNID_BROADCASTSYSTEMMESSAGE
:
2350 DWORD_PTR RetVal
= 0;
2356 ProbeForWrite((PVOID
)ResultInfo
,
2357 sizeof(BROADCASTPARM
),
2359 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2361 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2371 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2372 parm
.recipients
== BSM_ALLCOMPONENTS
)
2375 else if (parm
.recipients
& BSM_APPLICATIONS
)
2377 if (parm
.flags
& BSF_QUERY
)
2379 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2381 co_IntSendMessageTimeout( HWND_BROADCAST
,
2389 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2391 co_IntSendMessageTimeout( HWND_BROADCAST
,
2395 SMTO_NOTIMEOUTIFNOTHUNG
,
2401 co_IntSendMessageTimeout( HWND_BROADCAST
,
2410 else if (parm
.flags
& BSF_POSTMESSAGE
)
2412 Ret
= UserPostMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2414 else if ( parm
.flags
& BSF_SENDNOTIFYMESSAGE
)
2416 Ret
= UserSendNotifyMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2421 case FNID_SENDMESSAGECALLBACK
:
2423 // CallNextHook bypass.
2424 case FNID_CALLWNDPROC
:
2425 case FNID_CALLWNDPROCRET
:
2427 PCLIENTINFO ClientInfo
= GetWin32ClientInfo();
2428 PHOOK NextObj
, Hook
= ClientInfo
->phkCurrent
;
2430 if (!ClientInfo
|| !Hook
) break;
2432 UserReferenceObject(Hook
);
2434 if (Hook
->Thread
&& (Hook
->Thread
!= PsGetCurrentThread()))
2436 UserDereferenceObject(Hook
);
2440 NextObj
= IntGetNextHook(Hook
);
2441 ClientInfo
->phkCurrent
= NextObj
;
2443 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2448 CWP
.wParam
= wParam
;
2449 CWP
.lParam
= lParam
;
2450 DPRINT("WH_CALLWNDPROC: Hook %x NextHook %x\n", Hook
, NextObj
);
2452 lResult
= co_IntCallHookProc( Hook
->HookId
,
2454 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2465 CWPR
.wParam
= wParam
;
2466 CWPR
.lParam
= lParam
;
2467 CWPR
.lResult
= ClientInfo
->dwHookData
;
2469 lResult
= co_IntCallHookProc( Hook
->HookId
,
2471 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2477 UserDereferenceObject(Hook
);
2478 lResult
= (LRESULT
) NextObj
;
2485 case FNID_DEFWINDOWPROC
:
2486 case FNID_CALLWNDPROC
:
2487 case FNID_CALLWNDPROCRET
:
2492 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2493 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2495 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2508 return BadChk
? FALSE
: Ret
;
2511 #define INFINITE 0xFFFFFFFF
2512 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2516 NtUserWaitForInputIdle(
2518 IN DWORD dwMilliseconds
,
2522 PPROCESSINFO W32Process
;
2525 LARGE_INTEGER Timeout
;
2526 ULONGLONG StartTime
, Run
, Elapsed
= 0;
2528 UserEnterExclusive();
2530 Status
= ObReferenceObjectByHandle(hProcess
,
2531 PROCESS_QUERY_INFORMATION
,
2537 if (!NT_SUCCESS(Status
))
2540 SetLastNtError(Status
);
2544 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2547 ObDereferenceObject(Process
);
2549 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2553 EngCreateEvent((PEVENT
*)&W32Process
->InputIdleEvent
);
2555 Handles
[0] = Process
;
2556 Handles
[1] = W32Process
->InputIdleEvent
;
2560 ObDereferenceObject(Process
);
2562 return STATUS_SUCCESS
; /* no event to wait on */
2565 StartTime
= EngGetTickCount();
2567 Run
= dwMilliseconds
;
2569 DPRINT("WFII: waiting for %p\n", Handles
[1] );
2572 Timeout
.QuadPart
= Run
- Elapsed
;
2574 Status
= KeWaitForMultipleObjects( 2,
2580 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2582 UserEnterExclusive();
2584 if (!NT_SUCCESS(Status
))
2586 SetLastNtError(Status
);
2587 Status
= WAIT_FAILED
;
2594 Status
= WAIT_FAILED
;
2600 co_IntPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
);
2604 case STATUS_USER_APC
:
2605 case STATUS_ALERTED
:
2606 case STATUS_TIMEOUT
:
2607 DPRINT1("WFII: timeout\n");
2608 Status
= STATUS_TIMEOUT
;
2612 DPRINT1("WFII: finished\n");
2613 Status
= STATUS_SUCCESS
;
2617 if (dwMilliseconds
!= INFINITE
)
2619 Elapsed
= EngGetTickCount() - StartTime
;
2622 Status
= STATUS_TIMEOUT
;
2629 if (W32Process
->InputIdleEvent
)
2631 EngFreeMem((PVOID
)W32Process
->InputIdleEvent
);
2632 W32Process
->InputIdleEvent
= NULL
;
2634 ObDereferenceObject(Process
);