2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
24 * FILE: subsys/win32k/ntuser/message.c
25 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
27 * 06-06-2001 CSH Created
30 /* INCLUDES ******************************************************************/
43 DOSENDMESSAGE
, *PDOSENDMESSAGE
;
45 /* FUNCTIONS *****************************************************************/
48 IntInitMessageImpl(VOID
)
50 return STATUS_SUCCESS
;
54 IntCleanupMessageImpl(VOID
)
56 return STATUS_SUCCESS
;
59 #define MMS_SIZE_WPARAM -1
60 #define MMS_SIZE_WPARAMWCHAR -2
61 #define MMS_SIZE_LPARAMSZ -3
62 #define MMS_SIZE_SPECIAL -4
63 #define MMS_FLAG_READ 0x01
64 #define MMS_FLAG_WRITE 0x02
65 #define MMS_FLAG_READWRITE (MMS_FLAG_READ | MMS_FLAG_WRITE)
66 typedef struct tagMSGMEMORY
72 MSGMEMORY
, *PMSGMEMORY
;
74 static MSGMEMORY MsgMemory
[] =
76 { WM_CREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
77 { WM_DDE_ACK
, sizeof(KMDDELPARAM
), MMS_FLAG_READ
},
78 { WM_DDE_EXECUTE
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
79 { WM_GETMINMAXINFO
, sizeof(MINMAXINFO
), MMS_FLAG_READWRITE
},
80 { WM_GETTEXT
, MMS_SIZE_WPARAMWCHAR
, MMS_FLAG_WRITE
},
81 { WM_NCCALCSIZE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
82 { WM_NCCREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
83 { WM_SETTEXT
, MMS_SIZE_LPARAMSZ
, MMS_FLAG_READ
},
84 { WM_STYLECHANGED
, sizeof(STYLESTRUCT
), MMS_FLAG_READ
},
85 { WM_STYLECHANGING
, sizeof(STYLESTRUCT
), MMS_FLAG_READWRITE
},
86 { WM_COPYDATA
, MMS_SIZE_SPECIAL
, MMS_FLAG_READ
},
87 { WM_WINDOWPOSCHANGED
, sizeof(WINDOWPOS
), MMS_FLAG_READ
},
88 { WM_WINDOWPOSCHANGING
, sizeof(WINDOWPOS
), MMS_FLAG_READWRITE
},
91 static PMSGMEMORY FASTCALL
92 FindMsgMemory(UINT Msg
)
94 PMSGMEMORY MsgMemoryEntry
;
96 /* See if this message type is present in the table */
97 for (MsgMemoryEntry
= MsgMemory
;
98 MsgMemoryEntry
< MsgMemory
+ sizeof(MsgMemory
) / sizeof(MSGMEMORY
);
101 if (Msg
== MsgMemoryEntry
->Message
)
103 return MsgMemoryEntry
;
111 MsgMemorySize(PMSGMEMORY MsgMemoryEntry
, WPARAM wParam
, LPARAM lParam
)
114 PUNICODE_STRING WindowName
;
115 PUNICODE_STRING ClassName
;
120 if (MMS_SIZE_WPARAM
== MsgMemoryEntry
->Size
)
124 else if (MMS_SIZE_WPARAMWCHAR
== MsgMemoryEntry
->Size
)
126 Size
= (UINT
) (wParam
* sizeof(WCHAR
));
128 else if (MMS_SIZE_LPARAMSZ
== MsgMemoryEntry
->Size
)
130 Size
= (UINT
) ((wcslen((PWSTR
) lParam
) + 1) * sizeof(WCHAR
));
132 else if (MMS_SIZE_SPECIAL
== MsgMemoryEntry
->Size
)
134 switch(MsgMemoryEntry
->Message
)
138 Cs
= (CREATESTRUCTW
*) lParam
;
139 WindowName
= (PUNICODE_STRING
) Cs
->lpszName
;
140 ClassName
= (PUNICODE_STRING
) Cs
->lpszClass
;
141 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
142 if (IS_ATOM(ClassName
->Buffer
))
144 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
148 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
153 Size
= wParam
? sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
) : sizeof(RECT
);
157 Size
= sizeof(COPYDATASTRUCT
) + ((PCOPYDATASTRUCT
)lParam
)->cbData
;
168 Size
= MsgMemoryEntry
->Size
;
173 DPRINT1("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH_GetExceptionCode());
181 PackParam(LPARAM
*lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
183 NCCALCSIZE_PARAMS
*UnpackedNcCalcsize
;
184 NCCALCSIZE_PARAMS
*PackedNcCalcsize
;
185 CREATESTRUCTW
*UnpackedCs
;
186 CREATESTRUCTW
*PackedCs
;
187 PUNICODE_STRING WindowName
;
188 PUNICODE_STRING ClassName
;
192 *lParamPacked
= lParam
;
193 if (WM_NCCALCSIZE
== Msg
&& wParam
)
195 UnpackedNcCalcsize
= (NCCALCSIZE_PARAMS
*) lParam
;
196 if (UnpackedNcCalcsize
->lppos
!= (PWINDOWPOS
) (UnpackedNcCalcsize
+ 1))
198 PackedNcCalcsize
= ExAllocatePoolWithTag(PagedPool
,
199 sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
),
201 if (NULL
== PackedNcCalcsize
)
203 DPRINT1("Not enough memory to pack lParam\n");
204 return STATUS_NO_MEMORY
;
206 RtlCopyMemory(PackedNcCalcsize
, UnpackedNcCalcsize
, sizeof(NCCALCSIZE_PARAMS
));
207 PackedNcCalcsize
->lppos
= (PWINDOWPOS
) (PackedNcCalcsize
+ 1);
208 RtlCopyMemory(PackedNcCalcsize
->lppos
, UnpackedNcCalcsize
->lppos
, sizeof(WINDOWPOS
));
209 *lParamPacked
= (LPARAM
) PackedNcCalcsize
;
212 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
214 UnpackedCs
= (CREATESTRUCTW
*) lParam
;
215 WindowName
= (PUNICODE_STRING
) UnpackedCs
->lpszName
;
216 ClassName
= (PUNICODE_STRING
) UnpackedCs
->lpszClass
;
217 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
218 if (IS_ATOM(ClassName
->Buffer
))
220 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
224 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
226 PackedCs
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
227 if (NULL
== PackedCs
)
229 DPRINT1("Not enough memory to pack lParam\n");
230 return STATUS_NO_MEMORY
;
232 RtlCopyMemory(PackedCs
, UnpackedCs
, sizeof(CREATESTRUCTW
));
233 CsData
= (PCHAR
) (PackedCs
+ 1);
234 PackedCs
->lpszName
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
235 RtlCopyMemory(CsData
, WindowName
->Buffer
, WindowName
->Length
);
236 CsData
+= WindowName
->Length
;
237 *((WCHAR
*) CsData
) = L
'\0';
238 CsData
+= sizeof(WCHAR
);
239 PackedCs
->lpszClass
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
240 if (IS_ATOM(ClassName
->Buffer
))
242 *((WCHAR
*) CsData
) = L
'A';
243 CsData
+= sizeof(WCHAR
);
244 *((ATOM
*) CsData
) = (ATOM
)(DWORD_PTR
) ClassName
->Buffer
;
245 CsData
+= sizeof(ATOM
);
249 *((WCHAR
*) CsData
) = L
'S';
250 CsData
+= sizeof(WCHAR
);
251 RtlCopyMemory(CsData
, ClassName
->Buffer
, ClassName
->Length
);
252 CsData
+= ClassName
->Length
;
253 *((WCHAR
*) CsData
) = L
'\0';
254 CsData
+= sizeof(WCHAR
);
256 ASSERT(CsData
== (PCHAR
) PackedCs
+ Size
);
257 *lParamPacked
= (LPARAM
) PackedCs
;
260 return STATUS_SUCCESS
;
264 UnpackParam(LPARAM lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
266 NCCALCSIZE_PARAMS
*UnpackedParams
;
267 NCCALCSIZE_PARAMS
*PackedParams
;
268 PWINDOWPOS UnpackedWindowPos
;
270 if (lParamPacked
== lParam
)
272 return STATUS_SUCCESS
;
275 if (WM_NCCALCSIZE
== Msg
&& wParam
)
277 PackedParams
= (NCCALCSIZE_PARAMS
*) lParamPacked
;
278 UnpackedParams
= (NCCALCSIZE_PARAMS
*) lParam
;
279 UnpackedWindowPos
= UnpackedParams
->lppos
;
280 RtlCopyMemory(UnpackedParams
, PackedParams
, sizeof(NCCALCSIZE_PARAMS
));
281 UnpackedParams
->lppos
= UnpackedWindowPos
;
282 RtlCopyMemory(UnpackedWindowPos
, PackedParams
+ 1, sizeof(WINDOWPOS
));
283 ExFreePool((PVOID
) lParamPacked
);
285 return STATUS_SUCCESS
;
287 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
289 ExFreePool((PVOID
) lParamPacked
);
291 return STATUS_SUCCESS
;
296 return STATUS_INVALID_PARAMETER
;
305 DECLARE_RETURN(BOOL
);
307 DPRINT("Enter NtUserCallMsgFilter\n");
308 UserEnterExclusive();
310 if (co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)msg
))
312 RETURN( co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)msg
));
315 DPRINT("Leave NtUserCallMsgFilter. ret=%i\n", _ret_
);
321 NtUserDispatchMessage(PNTUSERDISPATCHMESSAGEINFO UnsafeMsgInfo
)
324 NTUSERDISPATCHMESSAGEINFO MsgInfo
;
325 LRESULT Result
= TRUE
;
326 DECLARE_RETURN(LRESULT
);
328 DPRINT("Enter NtUserDispatchMessage\n");
329 UserEnterExclusive();
331 Status
= MmCopyFromCaller(&MsgInfo
, UnsafeMsgInfo
, sizeof(NTUSERDISPATCHMESSAGEINFO
));
332 if (! NT_SUCCESS(Status
))
334 SetLastNtError(Status
);
338 /* Process timer messages. */
339 if (WM_TIMER
== MsgInfo
.Msg
.message
&& 0 != MsgInfo
.Msg
.lParam
)
341 LARGE_INTEGER LargeTickCount
;
342 /* FIXME: Call hooks. */
344 /* FIXME: Check for continuing validity of timer. */
346 MsgInfo
.HandledByKernel
= FALSE
;
347 KeQueryTickCount(&LargeTickCount
);
348 MsgInfo
.Proc
= (WNDPROC
) MsgInfo
.Msg
.lParam
;
349 MsgInfo
.Msg
.lParam
= (LPARAM
)LargeTickCount
.u
.LowPart
;
351 else if (NULL
== MsgInfo
.Msg
.hwnd
)
353 MsgInfo
.HandledByKernel
= TRUE
;
358 PWINDOW_OBJECT Window
;
360 /* Get the window object. */
361 Window
= UserGetWindowObject(MsgInfo
.Msg
.hwnd
);
364 MsgInfo
.HandledByKernel
= TRUE
;
369 if (Window
->OwnerThread
!= PsGetCurrentThread())
371 DPRINT1("Window doesn't belong to the calling thread!\n");
372 MsgInfo
.HandledByKernel
= TRUE
;
377 /* FIXME: Call hook procedures. */
379 MsgInfo
.HandledByKernel
= FALSE
;
382 MsgInfo
.Ansi
= !Window
->Unicode
;
383 if (Window
->IsSystem
)
384 MsgInfo
.Proc
= (Window
->Unicode
? Window
->WndProc
: Window
->WndProcExtra
);
386 MsgInfo
.Proc
= Window
->WndProc
;
390 Status
= MmCopyToCaller(UnsafeMsgInfo
, &MsgInfo
, sizeof(NTUSERDISPATCHMESSAGEINFO
));
391 if (! NT_SUCCESS(Status
))
393 SetLastNtError(Status
);
400 DPRINT("Leave NtUserDispatchMessage. ret=%i\n", _ret_
);
407 NtUserTranslateMessage(LPMSG lpMsg
,
412 DECLARE_RETURN(BOOL
);
414 DPRINT("Enter NtUserTranslateMessage\n");
415 UserEnterExclusive();
417 Status
= MmCopyFromCaller(&SafeMsg
, lpMsg
, sizeof(MSG
));
418 if(!NT_SUCCESS(Status
))
420 SetLastNtError(Status
);
424 RETURN( IntTranslateKbdMessage(&SafeMsg
, dwhkl
));
427 DPRINT("Leave NtUserTranslateMessage: ret=%i\n",_ret_
);
434 co_IntSendHitTestMessages(PUSER_MESSAGE_QUEUE ThreadQueue
, LPMSG Msg
)
436 if(!Msg
->hwnd
|| ThreadQueue
->CaptureWindow
)
445 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(HTCLIENT
, Msg
->message
));
450 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(Msg
->wParam
, Msg
->message
));
457 case WM_LBUTTONDBLCLK
:
458 case WM_MBUTTONDBLCLK
:
459 case WM_RBUTTONDBLCLK
:
460 case WM_XBUTTONDBLCLK
:
463 PSYSTEM_CURSORINFO CurInfo
;
465 if(!IntGetWindowStationObject(InputWindowStation
))
469 CurInfo
= IntGetSysCursorInfo(InputWindowStation
);
470 wParam
= (WPARAM
)(CurInfo
->ButtonsDown
);
471 ObDereferenceObject(InputWindowStation
);
473 co_IntSendMessage(Msg
->hwnd
, WM_MOUSEMOVE
, wParam
, Msg
->lParam
);
474 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(HTCLIENT
, Msg
->message
));
477 case WM_NCLBUTTONDOWN
:
478 case WM_NCMBUTTONDOWN
:
479 case WM_NCRBUTTONDOWN
:
480 case WM_NCXBUTTONDOWN
:
481 case WM_NCLBUTTONDBLCLK
:
482 case WM_NCMBUTTONDBLCLK
:
483 case WM_NCRBUTTONDBLCLK
:
484 case WM_NCXBUTTONDBLCLK
:
486 co_IntSendMessage(Msg
->hwnd
, WM_NCMOUSEMOVE
, (WPARAM
)Msg
->wParam
, Msg
->lParam
);
487 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(Msg
->wParam
, Msg
->message
));
494 co_IntActivateWindowMouse(PUSER_MESSAGE_QUEUE ThreadQueue
, LPMSG Msg
, PWINDOW_OBJECT MsgWindow
,
498 PWINDOW_OBJECT Parent
;
500 ASSERT_REFS_CO(MsgWindow
);
502 if(*HitTest
== (USHORT
)HTTRANSPARENT
)
504 /* eat the message, search again! */
508 Parent
= IntGetParent(MsgWindow
);//fixme: deref retval?
509 /* fixme: abort if no parent ? */
510 Result
= co_IntSendMessage(MsgWindow
->hSelf
,
512 (WPARAM
) (Parent
? Parent
->hSelf
: NULL
),
513 (LPARAM
)MAKELONG(*HitTest
, Msg
->message
)
518 case MA_NOACTIVATEANDEAT
:
522 case MA_ACTIVATEANDEAT
:
523 co_IntMouseActivateWindow(MsgWindow
);
527 co_IntMouseActivateWindow(MsgWindow
);
535 co_IntTranslateMouseMessage(PUSER_MESSAGE_QUEUE ThreadQueue
, LPMSG Msg
, USHORT
*HitTest
, BOOL Remove
)
537 PWINDOW_OBJECT Window
;
538 USER_REFERENCE_ENTRY Ref
, DesktopRef
;
540 if(!(Window
= UserGetWindowObject(Msg
->hwnd
)))
542 /* let's just eat the message?! */
546 UserRefObjectCo(Window
, &Ref
);
548 if(ThreadQueue
== Window
->MessageQueue
&&
549 ThreadQueue
->CaptureWindow
!= Window
->hSelf
)
551 /* only send WM_NCHITTEST messages if we're not capturing the window! */
552 *HitTest
= co_IntSendMessage(Window
->hSelf
, WM_NCHITTEST
, 0,
553 MAKELONG(Msg
->pt
.x
, Msg
->pt
.y
));
555 if(*HitTest
== (USHORT
)HTTRANSPARENT
)
557 PWINDOW_OBJECT DesktopWindow
;
558 HWND hDesktop
= IntGetDesktopWindow();
560 if((DesktopWindow
= UserGetWindowObject(hDesktop
)))
564 UserRefObjectCo(DesktopWindow
, &DesktopRef
);
566 co_WinPosWindowFromPoint(DesktopWindow
, Window
->MessageQueue
, &Msg
->pt
, &Wnd
);
571 /* post the message to the other window */
572 Msg
->hwnd
= Wnd
->hSelf
;
573 if(!(Wnd
->Status
& WINDOWSTATUS_DESTROYING
))
575 MsqPostMessage(Wnd
->MessageQueue
, Msg
, FALSE
,
576 Msg
->message
== WM_MOUSEMOVE
? QS_MOUSEMOVE
:
580 /* eat the message */
581 UserDerefObject(Wnd
);
582 UserDerefObjectCo(DesktopWindow
);
583 UserDerefObjectCo(Window
);
586 UserDerefObject(Wnd
);
589 UserDerefObjectCo(DesktopWindow
);
598 if(IS_BTN_MESSAGE(Msg
->message
, DOWN
))
600 /* generate double click messages, if necessary */
601 if ((((*HitTest
) != HTCLIENT
) ||
602 (Window
->Class
->Style
& CS_DBLCLKS
)) &&
603 MsqIsDblClk(Msg
, Remove
))
605 Msg
->message
+= WM_LBUTTONDBLCLK
- WM_LBUTTONDOWN
;
609 if(Msg
->message
!= WM_MOUSEWHEEL
)
612 if ((*HitTest
) != HTCLIENT
)
614 Msg
->message
+= WM_NCMOUSEMOVE
- WM_MOUSEMOVE
;
615 if((Msg
->message
== WM_NCRBUTTONUP
) &&
616 (((*HitTest
) == HTCAPTION
) || ((*HitTest
) == HTSYSMENU
)))
618 Msg
->message
= WM_CONTEXTMENU
;
619 Msg
->wParam
= (WPARAM
)Window
->hSelf
;
623 Msg
->wParam
= *HitTest
;
625 Msg
->lParam
= MAKELONG(Msg
->pt
.x
, Msg
->pt
.y
);
627 else if(ThreadQueue
->MoveSize
== NULL
&&
628 ThreadQueue
->MenuOwner
== NULL
)
630 /* NOTE: Msg->pt should remain in screen coordinates. -- FiN */
631 Msg
->lParam
= MAKELONG(
632 Msg
->pt
.x
- (WORD
)Window
->ClientRect
.left
,
633 Msg
->pt
.y
- (WORD
)Window
->ClientRect
.top
);
637 UserDerefObjectCo(Window
);
643 * Internal version of PeekMessage() doing all the work
646 co_IntPeekMessage(PUSER_MESSAGE Msg
,
652 LARGE_INTEGER LargeTickCount
;
653 PUSER_MESSAGE_QUEUE ThreadQueue
;
654 PUSER_MESSAGE Message
;
655 BOOL Present
, RemoveMessages
;
656 USER_REFERENCE_ENTRY Ref
;
659 /* The queues and order in which they are checked are documented in the MSDN
660 article on GetMessage() */
662 ThreadQueue
= (PUSER_MESSAGE_QUEUE
)PsGetWin32Thread()->MessageQueue
;
664 /* Inspect RemoveMsg flags */
665 /* FIXME: The only flag we process is PM_REMOVE - processing of others must still be implemented */
666 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
672 KeQueryTickCount(&LargeTickCount
);
673 ThreadQueue
->LastMsgRead
= LargeTickCount
.u
.LowPart
;
675 /* Dispatch sent messages here. */
676 while (co_MsqDispatchOneSentMessage(ThreadQueue
))
679 /* Now look for a quit message. */
681 if (ThreadQueue
->QuitPosted
)
683 /* According to the PSDK, WM_QUIT messages are always returned, regardless
684 of the filter specified */
685 Msg
->Msg
.hwnd
= NULL
;
686 Msg
->Msg
.message
= WM_QUIT
;
687 Msg
->Msg
.wParam
= ThreadQueue
->QuitExitCode
;
689 Msg
->FreeLParam
= FALSE
;
692 ThreadQueue
->QuitPosted
= FALSE
;
697 /* Now check for normal messages. */
698 Present
= co_MsqFindMessage(ThreadQueue
,
707 RtlCopyMemory(Msg
, Message
, sizeof(USER_MESSAGE
));
710 MsqDestroyMessage(Message
);
715 /* Check for hardware events. */
716 Present
= co_MsqFindMessage(ThreadQueue
,
725 RtlCopyMemory(Msg
, Message
, sizeof(USER_MESSAGE
));
728 MsqDestroyMessage(Message
);
733 /* Check for sent messages again. */
734 while (co_MsqDispatchOneSentMessage(ThreadQueue
))
737 /* Check for paint messages. */
738 if (IntGetPaintMessage(hWnd
, MsgFilterMin
, MsgFilterMax
, PsGetWin32Thread(), &Msg
->Msg
, RemoveMessages
))
740 Msg
->FreeLParam
= FALSE
;
744 /* Check for WM_(SYS)TIMER messages */
745 Present
= MsqGetTimerMessage(ThreadQueue
, hWnd
, MsgFilterMin
, MsgFilterMax
,
746 &Msg
->Msg
, RemoveMessages
);
749 Msg
->FreeLParam
= FALSE
;
759 PWINDOW_OBJECT MsgWindow
= NULL
;
761 if(Msg
->Msg
.hwnd
&& (MsgWindow
= UserGetWindowObject(Msg
->Msg
.hwnd
)) &&
762 Msg
->Msg
.message
>= WM_MOUSEFIRST
&& Msg
->Msg
.message
<= WM_MOUSELAST
)
766 UserRefObjectCo(MsgWindow
, &Ref
);
768 if(co_IntTranslateMouseMessage(ThreadQueue
, &Msg
->Msg
, &HitTest
, TRUE
))
769 /* FIXME - check message filter again, if the message doesn't match anymore,
772 UserDerefObjectCo(MsgWindow
);
773 /* eat the message, search again */
777 if(ThreadQueue
->CaptureWindow
== NULL
)
779 co_IntSendHitTestMessages(ThreadQueue
, &Msg
->Msg
);
780 if((Msg
->Msg
.message
!= WM_MOUSEMOVE
&& Msg
->Msg
.message
!= WM_NCMOUSEMOVE
) &&
781 IS_BTN_MESSAGE(Msg
->Msg
.message
, DOWN
) &&
782 co_IntActivateWindowMouse(ThreadQueue
, &Msg
->Msg
, MsgWindow
, &HitTest
))
784 UserDerefObjectCo(MsgWindow
);
785 /* eat the message, search again */
790 UserDerefObjectCo(MsgWindow
);
794 co_IntSendHitTestMessages(ThreadQueue
, &Msg
->Msg
);
799 // UserDerefObject(MsgWindow);
805 if((Msg
->Msg
.hwnd
&& Msg
->Msg
.message
>= WM_MOUSEFIRST
&& Msg
->Msg
.message
<= WM_MOUSELAST
) &&
806 co_IntTranslateMouseMessage(ThreadQueue
, &Msg
->Msg
, &HitTest
, FALSE
))
807 /* FIXME - check message filter again, if the message doesn't match anymore,
810 /* eat the message, search again */
821 NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo
,
829 NTUSERGETMESSAGEINFO Info
;
830 PWINDOW_OBJECT Window
;
831 PMSGMEMORY MsgMemoryEntry
;
835 DECLARE_RETURN(BOOL
);
837 DPRINT("Enter NtUserPeekMessage\n");
838 UserEnterExclusive();
841 if (hWnd
&& hWnd
!= INVALID_HANDLE_VALUE
)
843 if (!(Window
= UserGetWindowObject(hWnd
)))
849 if (MsgFilterMax
< MsgFilterMin
)
855 Present
= co_IntPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
);
859 /* See if this message type is present in the table */
860 MsgMemoryEntry
= FindMsgMemory(Info
.Msg
.message
);
861 if (NULL
== MsgMemoryEntry
)
863 /* Not present, no copying needed */
868 /* Determine required size */
869 Size
= MsgMemorySize(MsgMemoryEntry
, Info
.Msg
.wParam
,
871 /* Allocate required amount of user-mode memory */
872 Info
.LParamSize
= Size
;
874 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem
, 0,
875 &Info
.LParamSize
, MEM_COMMIT
, PAGE_READWRITE
);
876 if (! NT_SUCCESS(Status
))
878 SetLastNtError(Status
);
881 /* Transfer lParam data to user-mode mem */
882 Status
= MmCopyToCaller(UserMem
, (PVOID
) Info
.Msg
.lParam
, Size
);
883 if (! NT_SUCCESS(Status
))
885 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &UserMem
,
886 &Info
.LParamSize
, MEM_DECOMMIT
);
887 SetLastNtError(Status
);
890 Info
.Msg
.lParam
= (LPARAM
) UserMem
;
892 if (RemoveMsg
&& Msg
.FreeLParam
&& 0 != Msg
.Msg
.lParam
)
894 ExFreePool((void *) Msg
.Msg
.lParam
);
896 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERGETMESSAGEINFO
));
897 if (! NT_SUCCESS(Status
))
899 SetLastNtError(Status
);
907 DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_
);
913 co_IntWaitMessage(HWND Wnd
,
917 PUSER_MESSAGE_QUEUE ThreadQueue
;
921 ThreadQueue
= (PUSER_MESSAGE_QUEUE
)PsGetWin32Thread()->MessageQueue
;
925 if (co_IntPeekMessage(&Msg
, Wnd
, MsgFilterMin
, MsgFilterMax
, PM_NOREMOVE
))
930 /* Nothing found. Wait for new messages. */
931 Status
= co_MsqWaitForNewMessages(ThreadQueue
, Wnd
, MsgFilterMin
, MsgFilterMax
);
933 while ((STATUS_WAIT_0
<= Status
&& Status
<= STATUS_WAIT_63
) || STATUS_TIMEOUT
== Status
);
935 SetLastNtError(Status
);
941 NtUserGetMessage(PNTUSERGETMESSAGEINFO UnsafeInfo
,
946 * FUNCTION: Get a message from the calling thread's message queue.
948 * UnsafeMsg - Pointer to the structure which receives the returned message.
949 * Wnd - Window whose messages are to be retrieved.
950 * MsgFilterMin - Integer value of the lowest message value to be
952 * MsgFilterMax - Integer value of the highest message value to be
957 NTUSERGETMESSAGEINFO Info
;
959 PWINDOW_OBJECT Window
= NULL
;
960 PMSGMEMORY MsgMemoryEntry
;
964 DECLARE_RETURN(BOOL
);
965 // USER_REFERENCE_ENTRY Ref;
967 DPRINT("Enter NtUserGetMessage\n");
968 UserEnterExclusive();
971 if (hWnd
&& !(Window
= UserGetWindowObject(hWnd
)))
976 // if (Window) UserRefObjectCo(Window, &Ref);
978 if (MsgFilterMax
< MsgFilterMin
)
986 GotMessage
= co_IntPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
);
990 /* See if this message type is present in the table */
991 MsgMemoryEntry
= FindMsgMemory(Info
.Msg
.message
);
992 if (NULL
== MsgMemoryEntry
)
994 /* Not present, no copying needed */
999 /* Determine required size */
1000 Size
= MsgMemorySize(MsgMemoryEntry
, Info
.Msg
.wParam
,
1002 /* Allocate required amount of user-mode memory */
1003 Info
.LParamSize
= Size
;
1005 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem
, 0,
1006 &Info
.LParamSize
, MEM_COMMIT
, PAGE_READWRITE
);
1008 if (! NT_SUCCESS(Status
))
1010 SetLastNtError(Status
);
1013 /* Transfer lParam data to user-mode mem */
1014 Status
= MmCopyToCaller(UserMem
, (PVOID
) Info
.Msg
.lParam
, Size
);
1015 if (! NT_SUCCESS(Status
))
1017 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &UserMem
,
1018 &Info
.LParamSize
, MEM_DECOMMIT
);
1019 SetLastNtError(Status
);
1022 Info
.Msg
.lParam
= (LPARAM
) UserMem
;
1024 if (Msg
.FreeLParam
&& 0 != Msg
.Msg
.lParam
)
1026 ExFreePool((void *) Msg
.Msg
.lParam
);
1028 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERGETMESSAGEINFO
));
1029 if (! NT_SUCCESS(Status
))
1031 SetLastNtError(Status
);
1035 else if (! co_IntWaitMessage(hWnd
, MsgFilterMin
, MsgFilterMax
))
1040 while (! GotMessage
);
1042 RETURN( WM_QUIT
!= Info
.Msg
.message
);
1045 // if (Window) UserDerefObjectCo(Window);
1047 DPRINT("Leave NtUserGetMessage\n");
1068 static NTSTATUS FASTCALL
1069 CopyMsgToKernelMem(MSG
*KernelModeMsg
, MSG
*UserModeMsg
, PMSGMEMORY MsgMemoryEntry
)
1076 *KernelModeMsg
= *UserModeMsg
;
1078 /* See if this message type is present in the table */
1079 if (NULL
== MsgMemoryEntry
)
1081 /* Not present, no copying needed */
1082 return STATUS_SUCCESS
;
1085 /* Determine required size */
1086 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
1090 /* Allocate kernel mem */
1091 KernelMem
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
1092 if (NULL
== KernelMem
)
1094 DPRINT1("Not enough memory to copy message to kernel mem\n");
1095 return STATUS_NO_MEMORY
;
1097 KernelModeMsg
->lParam
= (LPARAM
) KernelMem
;
1099 /* Copy data if required */
1100 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_READ
))
1102 Status
= MmCopyFromCaller(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
1103 if (! NT_SUCCESS(Status
))
1105 DPRINT1("Failed to copy message to kernel: invalid usermode buffer\n");
1106 ExFreePool(KernelMem
);
1112 /* Make sure we don't pass any secrets to usermode */
1113 RtlZeroMemory(KernelMem
, Size
);
1118 KernelModeMsg
->lParam
= 0;
1121 return STATUS_SUCCESS
;
1124 static NTSTATUS FASTCALL
1125 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
1128 PMSGMEMORY MsgMemoryEntry
;
1131 /* See if this message type is present in the table */
1132 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
1133 if (NULL
== MsgMemoryEntry
)
1135 /* Not present, no copying needed */
1136 return STATUS_SUCCESS
;
1139 /* Determine required size */
1140 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
1144 /* Copy data if required */
1145 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
1147 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
1148 if (! NT_SUCCESS(Status
))
1150 DPRINT1("Failed to copy message from kernel: invalid usermode buffer\n");
1151 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
1156 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
1159 return STATUS_SUCCESS
;
1163 UserPostMessage(HWND Wnd
,
1168 MSG UserModeMsg
, KernelModeMsg
;
1169 LARGE_INTEGER LargeTickCount
;
1171 PMSGMEMORY MsgMemoryEntry
;
1175 MsqPostQuitMessage(PsGetWin32Thread()->MessageQueue
, wParam
);
1177 else if (Wnd
== HWND_BROADCAST
)
1180 PWINDOW_OBJECT DesktopWindow
;
1183 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1184 List
= IntWinListChildren(DesktopWindow
);
1188 for (i
= 0; List
[i
]; i
++)
1189 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1195 PWINDOW_OBJECT Window
;
1197 Window
= UserGetWindowObject(Wnd
);
1202 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
1204 DPRINT1("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd
);
1205 /* FIXME - last error code? */
1209 UserModeMsg
.hwnd
= Wnd
;
1210 UserModeMsg
.message
= Msg
;
1211 UserModeMsg
.wParam
= wParam
;
1212 UserModeMsg
.lParam
= lParam
;
1213 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1214 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1215 if (! NT_SUCCESS(Status
))
1217 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1220 IntGetCursorLocation(PsGetWin32Thread()->Desktop
->WindowStation
,
1222 KeQueryTickCount(&LargeTickCount
);
1223 KernelModeMsg
.time
= LargeTickCount
.u
.LowPart
;
1224 MsqPostMessage(Window
->MessageQueue
, &KernelModeMsg
,
1225 NULL
!= MsgMemoryEntry
&& 0 != KernelModeMsg
.lParam
,
1234 NtUserPostMessage(HWND hWnd
,
1239 DECLARE_RETURN(BOOL
);
1241 DPRINT("Enter NtUserPostMessage\n");
1242 UserEnterExclusive();
1244 RETURN(UserPostMessage(hWnd
, Msg
, wParam
, lParam
));
1247 DPRINT("Leave NtUserPostMessage, ret=%i\n",_ret_
);
1255 NtUserPostThreadMessage(DWORD idThread
,
1260 MSG UserModeMsg
, KernelModeMsg
;
1264 PMSGMEMORY MsgMemoryEntry
;
1265 DECLARE_RETURN(BOOL
);
1267 DPRINT("Enter NtUserPostThreadMessage\n");
1268 UserEnterExclusive();
1270 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
1272 if( Status
== STATUS_SUCCESS
)
1274 pThread
= (PW32THREAD
)peThread
->Tcb
.Win32Thread
;
1275 if( !pThread
|| !pThread
->MessageQueue
)
1277 ObDereferenceObject( peThread
);
1281 UserModeMsg
.hwnd
= NULL
;
1282 UserModeMsg
.message
= Msg
;
1283 UserModeMsg
.wParam
= wParam
;
1284 UserModeMsg
.lParam
= lParam
;
1285 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1286 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1287 if (! NT_SUCCESS(Status
))
1289 ObDereferenceObject( peThread
);
1290 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1293 MsqPostMessage(pThread
->MessageQueue
, &KernelModeMsg
,
1294 NULL
!= MsgMemoryEntry
&& 0 != KernelModeMsg
.lParam
,
1296 ObDereferenceObject( peThread
);
1301 SetLastNtError( Status
);
1306 DPRINT("Leave NtUserPostThreadMessage, ret=%i\n",_ret_
);
1312 NtUserQuerySendMessage(DWORD Unknown0
)
1320 co_IntSendMessage(HWND hWnd
,
1325 ULONG_PTR Result
= 0;
1326 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1328 return (LRESULT
)Result
;
1335 co_IntSendMessageTimeoutSingle(HWND hWnd
,
1345 PWINDOW_OBJECT Window
= NULL
;
1346 PMSGMEMORY MsgMemoryEntry
;
1347 INT lParamBufferSize
;
1348 LPARAM lParamPacked
;
1349 PW32THREAD Win32Thread
;
1350 DECLARE_RETURN(LRESULT
);
1351 USER_REFERENCE_ENTRY Ref
;
1353 /* FIXME: Call hooks. */
1354 if (!(Window
= UserGetWindowObject(hWnd
)))
1359 UserRefObjectCo(Window
, &Ref
);
1361 Win32Thread
= PsGetWin32Thread();
1363 if (NULL
!= Win32Thread
&&
1364 Window
->MessageQueue
== Win32Thread
->MessageQueue
)
1366 if (Win32Thread
->IsExiting
)
1368 /* Never send messages to exiting threads */
1372 /* See if this message type is present in the table */
1373 MsgMemoryEntry
= FindMsgMemory(Msg
);
1374 if (NULL
== MsgMemoryEntry
)
1376 lParamBufferSize
= -1;
1380 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1383 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
)))
1385 DPRINT1("Failed to pack message parameters\n");
1389 Result
= (ULONG_PTR
)co_IntCallWindowProc(Window
->WndProc
, !Window
->Unicode
, hWnd
, Msg
, wParam
,
1390 lParamPacked
,lParamBufferSize
);
1397 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
)))
1399 DPRINT1("Failed to unpack message parameters\n");
1406 if(uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->MessageQueue
))
1408 /* FIXME - Set a LastError? */
1412 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
1414 /* FIXME - last error? */
1415 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1419 Status
= co_MsqSendMessage(Window
->MessageQueue
, hWnd
, Msg
, wParam
, lParam
,
1420 uTimeout
, (uFlags
& SMTO_BLOCK
), FALSE
, uResult
);
1423 if (STATUS_TIMEOUT
== Status
)
1425 /* MSDN says GetLastError() should return 0 after timeout */
1426 SetLastWin32Error(0);
1429 else if (! NT_SUCCESS(Status
))
1431 SetLastNtError(Status
);
1438 if (Window
) UserDerefObjectCo(Window
);
1443 co_IntSendMessageTimeout(HWND hWnd
,
1451 PWINDOW_OBJECT DesktopWindow
;
1455 if (HWND_BROADCAST
!= hWnd
)
1457 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1460 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1461 if (NULL
== DesktopWindow
)
1463 SetLastWin32Error(ERROR_INTERNAL_ERROR
);
1467 Children
= IntWinListChildren(DesktopWindow
);
1468 if (NULL
== Children
)
1473 for (Child
= Children
; NULL
!= *Child
; Child
++)
1475 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1478 ExFreePool(Children
);
1480 return (LRESULT
) TRUE
;
1484 /* This function posts a message if the destination's message queue belongs to
1485 another thread, otherwise it sends the message. It does not support broadcast
1488 co_IntPostOrSendMessage(HWND hWnd
,
1494 PWINDOW_OBJECT Window
;
1496 if(hWnd
== HWND_BROADCAST
)
1501 if(!(Window
= UserGetWindowObject(hWnd
)))
1506 if(Window
->MessageQueue
!= PsGetWin32Thread()->MessageQueue
)
1508 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1512 if(!co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1518 return (LRESULT
)Result
;
1522 co_IntDoSendMessage(HWND hWnd
,
1527 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1529 LRESULT Result
= TRUE
;
1531 PWINDOW_OBJECT Window
;
1532 NTUSERSENDMESSAGEINFO Info
;
1535 PMSGMEMORY MsgMemoryEntry
;
1537 RtlZeroMemory(&Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1539 /* FIXME: Call hooks. */
1540 if (HWND_BROADCAST
!= hWnd
)
1542 Window
= UserGetWindowObject(hWnd
);
1545 /* Tell usermode to not touch this one */
1546 Info
.HandledByKernel
= TRUE
;
1547 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1552 /* FIXME: Check for an exiting window. */
1554 /* See if the current thread can handle the message */
1555 if (HWND_BROADCAST
!= hWnd
&& NULL
!= PsGetWin32Thread() &&
1556 Window
->MessageQueue
== PsGetWin32Thread()->MessageQueue
)
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
->Unicode
;
1568 Info
.Ansi
= !Window
->Unicode
;
1569 if (Window
->IsSystem
)
1570 Info
.Proc
= (Window
->Unicode
? Window
->WndProc
: Window
->WndProcExtra
);
1572 Info
.Proc
= Window
->WndProc
;
1576 /* Must be handled by other thread */
1577 // if (HWND_BROADCAST != hWnd)
1579 // UserDerefObject(Window);
1581 Info
.HandledByKernel
= TRUE
;
1582 UserModeMsg
.hwnd
= hWnd
;
1583 UserModeMsg
.message
= Msg
;
1584 UserModeMsg
.wParam
= wParam
;
1585 UserModeMsg
.lParam
= lParam
;
1586 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1587 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1588 if (! NT_SUCCESS(Status
))
1590 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1591 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1592 return (dsm
? 0 : -1);
1596 Result
= co_IntSendMessage(KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1597 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
);
1601 Result
= co_IntSendMessageTimeout(KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1602 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
,
1603 dsm
->uFlags
, dsm
->uTimeout
, &dsm
->Result
);
1605 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1606 if (! NT_SUCCESS(Status
))
1608 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1609 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1610 return(dsm
? 0 : -1);
1614 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1615 if (! NT_SUCCESS(Status
))
1617 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1620 return (LRESULT
)Result
;
1624 NtUserSendMessageTimeout(HWND hWnd
,
1631 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1635 DECLARE_RETURN(BOOL
);
1637 DPRINT("Enter NtUserSendMessageTimeout\n");
1638 UserEnterExclusive();
1640 dsm
.uFlags
= uFlags
;
1641 dsm
.uTimeout
= uTimeout
;
1642 Result
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, &dsm
, UnsafeInfo
);
1643 if(uResult
!= NULL
&& Result
!= 0)
1647 Status
= MmCopyToCaller(uResult
, &dsm
.Result
, sizeof(ULONG_PTR
));
1648 if(!NT_SUCCESS(Status
))
1650 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1657 DPRINT("Leave NtUserSendMessageTimeout, ret=%i\n",_ret_
);
1663 NtUserSendMessage(HWND Wnd
,
1667 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1669 DECLARE_RETURN(BOOL
);
1671 DPRINT("Enter NtUserSendMessage\n");
1672 UserEnterExclusive();
1674 RETURN(co_IntDoSendMessage(Wnd
, Msg
, wParam
, lParam
, NULL
, UnsafeInfo
));
1677 DPRINT("Leave NtUserSendMessage, ret=%i\n",_ret_
);
1683 NtUserSendMessageCallback(HWND hWnd
,
1687 SENDASYNCPROC lpCallBack
,
1696 NtUserSendNotifyMessage(HWND hWnd
,
1707 NtUserWaitMessage(VOID
)
1709 DECLARE_RETURN(BOOL
);
1711 DPRINT("EnterNtUserWaitMessage\n");
1712 UserEnterExclusive();
1714 RETURN(co_IntWaitMessage(NULL
, 0, 0));
1717 DPRINT("Leave NtUserWaitMessage, ret=%i\n",_ret_
);
1723 NtUserGetQueueStatus(BOOL ClearChanges
)
1725 PUSER_MESSAGE_QUEUE Queue
;
1727 DECLARE_RETURN(DWORD
);
1729 DPRINT("Enter NtUserGetQueueStatus\n");
1730 UserEnterExclusive();
1732 Queue
= PsGetWin32Thread()->MessageQueue
;
1734 Result
= MAKELONG(Queue
->QueueBits
, Queue
->ChangedBits
);
1737 Queue
->ChangedBits
= 0;
1743 DPRINT("Leave NtUserGetQueueStatus, ret=%i\n",_ret_
);
1749 IntInitMessagePumpHook()
1751 ((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->MessagePumpHookValue
++;
1756 IntUninitMessagePumpHook()
1758 if (((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->MessagePumpHookValue
<= 0)
1762 ((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->MessagePumpHookValue
--;