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
;
381 if (0xFFFF0000 != ((DWORD
) Window
->WndProcW
& 0xFFFF0000))
383 if (0xFFFF0000 != ((DWORD
) Window
->WndProcA
& 0xFFFF0000))
385 /* Both Unicode and Ansi winprocs are real, use whatever
387 MsgInfo
.Proc
= (MsgInfo
.Ansi
? Window
->WndProcA
392 /* Real Unicode winproc */
393 MsgInfo
.Ansi
= FALSE
;
394 MsgInfo
.Proc
= Window
->WndProcW
;
399 /* Must have real Ansi winproc */
401 MsgInfo
.Proc
= Window
->WndProcA
;
406 Status
= MmCopyToCaller(UnsafeMsgInfo
, &MsgInfo
, sizeof(NTUSERDISPATCHMESSAGEINFO
));
407 if (! NT_SUCCESS(Status
))
409 SetLastNtError(Status
);
416 DPRINT("Leave NtUserDispatchMessage. ret=%i\n", _ret_
);
423 NtUserTranslateMessage(LPMSG lpMsg
,
428 DECLARE_RETURN(BOOL
);
430 DPRINT("Enter NtUserTranslateMessage\n");
431 UserEnterExclusive();
433 Status
= MmCopyFromCaller(&SafeMsg
, lpMsg
, sizeof(MSG
));
434 if(!NT_SUCCESS(Status
))
436 SetLastNtError(Status
);
440 RETURN( IntTranslateKbdMessage(&SafeMsg
, dwhkl
));
443 DPRINT("Leave NtUserTranslateMessage: ret=%i\n",_ret_
);
450 co_IntSendHitTestMessages(PUSER_MESSAGE_QUEUE ThreadQueue
, LPMSG Msg
)
452 if(!Msg
->hwnd
|| ThreadQueue
->CaptureWindow
)
461 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(HTCLIENT
, Msg
->message
));
466 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(Msg
->wParam
, Msg
->message
));
473 case WM_LBUTTONDBLCLK
:
474 case WM_MBUTTONDBLCLK
:
475 case WM_RBUTTONDBLCLK
:
476 case WM_XBUTTONDBLCLK
:
479 PSYSTEM_CURSORINFO CurInfo
;
481 if(!IntGetWindowStationObject(InputWindowStation
))
485 CurInfo
= IntGetSysCursorInfo(InputWindowStation
);
486 wParam
= (WPARAM
)(CurInfo
->ButtonsDown
);
487 ObDereferenceObject(InputWindowStation
);
489 co_IntSendMessage(Msg
->hwnd
, WM_MOUSEMOVE
, wParam
, Msg
->lParam
);
490 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(HTCLIENT
, Msg
->message
));
493 case WM_NCLBUTTONDOWN
:
494 case WM_NCMBUTTONDOWN
:
495 case WM_NCRBUTTONDOWN
:
496 case WM_NCXBUTTONDOWN
:
497 case WM_NCLBUTTONDBLCLK
:
498 case WM_NCMBUTTONDBLCLK
:
499 case WM_NCRBUTTONDBLCLK
:
500 case WM_NCXBUTTONDBLCLK
:
502 co_IntSendMessage(Msg
->hwnd
, WM_NCMOUSEMOVE
, (WPARAM
)Msg
->wParam
, Msg
->lParam
);
503 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(Msg
->wParam
, Msg
->message
));
510 co_IntActivateWindowMouse(PUSER_MESSAGE_QUEUE ThreadQueue
, LPMSG Msg
, PWINDOW_OBJECT MsgWindow
,
514 PWINDOW_OBJECT Parent
;
516 ASSERT_REFS_CO(MsgWindow
);
518 if(*HitTest
== (USHORT
)HTTRANSPARENT
)
520 /* eat the message, search again! */
524 Parent
= IntGetParent(MsgWindow
);//fixme: deref retval?
525 /* fixme: abort if no parent ? */
526 Result
= co_IntSendMessage(MsgWindow
->hSelf
,
528 (WPARAM
) (Parent
? Parent
->hSelf
: NULL
),
529 (LPARAM
)MAKELONG(*HitTest
, Msg
->message
)
534 case MA_NOACTIVATEANDEAT
:
538 case MA_ACTIVATEANDEAT
:
539 co_IntMouseActivateWindow(MsgWindow
);
543 co_IntMouseActivateWindow(MsgWindow
);
551 co_IntTranslateMouseMessage(PUSER_MESSAGE_QUEUE ThreadQueue
, LPMSG Msg
, USHORT
*HitTest
, BOOL Remove
)
553 PWINDOW_OBJECT Window
;
554 USER_REFERENCE_ENTRY Ref
, DesktopRef
;
556 if(!(Window
= UserGetWindowObject(Msg
->hwnd
)))
558 /* let's just eat the message?! */
562 UserRefObjectCo(Window
, &Ref
);
564 if(ThreadQueue
== Window
->MessageQueue
&&
565 ThreadQueue
->CaptureWindow
!= Window
->hSelf
)
567 /* only send WM_NCHITTEST messages if we're not capturing the window! */
568 *HitTest
= co_IntSendMessage(Window
->hSelf
, WM_NCHITTEST
, 0,
569 MAKELONG(Msg
->pt
.x
, Msg
->pt
.y
));
571 if(*HitTest
== (USHORT
)HTTRANSPARENT
)
573 PWINDOW_OBJECT DesktopWindow
;
574 HWND hDesktop
= IntGetDesktopWindow();
576 if((DesktopWindow
= UserGetWindowObject(hDesktop
)))
580 UserRefObjectCo(DesktopWindow
, &DesktopRef
);
582 co_WinPosWindowFromPoint(DesktopWindow
, Window
->MessageQueue
, &Msg
->pt
, &Wnd
);
587 /* post the message to the other window */
588 Msg
->hwnd
= Wnd
->hSelf
;
589 if(!(Wnd
->Status
& WINDOWSTATUS_DESTROYING
))
591 MsqPostMessage(Wnd
->MessageQueue
, Msg
, FALSE
,
592 Msg
->message
== WM_MOUSEMOVE
? QS_MOUSEMOVE
:
596 /* eat the message */
597 UserDerefObject(Wnd
);
598 UserDerefObjectCo(DesktopWindow
);
599 UserDerefObjectCo(Window
);
602 UserDerefObject(Wnd
);
605 UserDerefObjectCo(DesktopWindow
);
614 if(IS_BTN_MESSAGE(Msg
->message
, DOWN
))
616 /* generate double click messages, if necessary */
617 if ((((*HitTest
) != HTCLIENT
) ||
618 (IntGetClassLong(Window
, GCL_STYLE
, FALSE
) & CS_DBLCLKS
)) &&
619 MsqIsDblClk(Msg
, Remove
))
621 Msg
->message
+= WM_LBUTTONDBLCLK
- WM_LBUTTONDOWN
;
625 if(Msg
->message
!= WM_MOUSEWHEEL
)
628 if ((*HitTest
) != HTCLIENT
)
630 Msg
->message
+= WM_NCMOUSEMOVE
- WM_MOUSEMOVE
;
631 if((Msg
->message
== WM_NCRBUTTONUP
) &&
632 (((*HitTest
) == HTCAPTION
) || ((*HitTest
) == HTSYSMENU
)))
634 Msg
->message
= WM_CONTEXTMENU
;
635 Msg
->wParam
= (WPARAM
)Window
->hSelf
;
639 Msg
->wParam
= *HitTest
;
641 Msg
->lParam
= MAKELONG(Msg
->pt
.x
, Msg
->pt
.y
);
643 else if(ThreadQueue
->MoveSize
== NULL
&&
644 ThreadQueue
->MenuOwner
== NULL
)
646 /* NOTE: Msg->pt should remain in screen coordinates. -- FiN */
647 Msg
->lParam
= MAKELONG(
648 Msg
->pt
.x
- (WORD
)Window
->ClientRect
.left
,
649 Msg
->pt
.y
- (WORD
)Window
->ClientRect
.top
);
653 UserDerefObjectCo(Window
);
659 * Internal version of PeekMessage() doing all the work
662 co_IntPeekMessage(PUSER_MESSAGE Msg
,
668 LARGE_INTEGER LargeTickCount
;
669 PUSER_MESSAGE_QUEUE ThreadQueue
;
670 PUSER_MESSAGE Message
;
671 BOOL Present
, RemoveMessages
;
672 USER_REFERENCE_ENTRY Ref
;
675 /* The queues and order in which they are checked are documented in the MSDN
676 article on GetMessage() */
678 ThreadQueue
= (PUSER_MESSAGE_QUEUE
)PsGetWin32Thread()->MessageQueue
;
680 /* Inspect RemoveMsg flags */
681 /* FIXME: The only flag we process is PM_REMOVE - processing of others must still be implemented */
682 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
688 KeQueryTickCount(&LargeTickCount
);
689 ThreadQueue
->LastMsgRead
= LargeTickCount
.u
.LowPart
;
691 /* Dispatch sent messages here. */
692 while (co_MsqDispatchOneSentMessage(ThreadQueue
))
695 /* Now look for a quit message. */
697 if (ThreadQueue
->QuitPosted
)
699 /* According to the PSDK, WM_QUIT messages are always returned, regardless
700 of the filter specified */
701 Msg
->Msg
.hwnd
= NULL
;
702 Msg
->Msg
.message
= WM_QUIT
;
703 Msg
->Msg
.wParam
= ThreadQueue
->QuitExitCode
;
705 Msg
->FreeLParam
= FALSE
;
708 ThreadQueue
->QuitPosted
= FALSE
;
713 /* Now check for normal messages. */
714 Present
= co_MsqFindMessage(ThreadQueue
,
723 RtlCopyMemory(Msg
, Message
, sizeof(USER_MESSAGE
));
726 MsqDestroyMessage(Message
);
731 /* Check for hardware events. */
732 Present
= co_MsqFindMessage(ThreadQueue
,
741 RtlCopyMemory(Msg
, Message
, sizeof(USER_MESSAGE
));
744 MsqDestroyMessage(Message
);
749 /* Check for sent messages again. */
750 while (co_MsqDispatchOneSentMessage(ThreadQueue
))
753 /* Check for paint messages. */
754 if (IntGetPaintMessage(hWnd
, MsgFilterMin
, MsgFilterMax
, PsGetWin32Thread(), &Msg
->Msg
, RemoveMessages
))
756 Msg
->FreeLParam
= FALSE
;
760 /* Check for WM_(SYS)TIMER messages */
761 Present
= MsqGetTimerMessage(ThreadQueue
, hWnd
, MsgFilterMin
, MsgFilterMax
,
762 &Msg
->Msg
, RemoveMessages
);
765 Msg
->FreeLParam
= FALSE
;
775 PWINDOW_OBJECT MsgWindow
= NULL
;
777 if(Msg
->Msg
.hwnd
&& (MsgWindow
= UserGetWindowObject(Msg
->Msg
.hwnd
)) &&
778 Msg
->Msg
.message
>= WM_MOUSEFIRST
&& Msg
->Msg
.message
<= WM_MOUSELAST
)
782 UserRefObjectCo(MsgWindow
, &Ref
);
784 if(co_IntTranslateMouseMessage(ThreadQueue
, &Msg
->Msg
, &HitTest
, TRUE
))
785 /* FIXME - check message filter again, if the message doesn't match anymore,
788 UserDerefObjectCo(MsgWindow
);
789 /* eat the message, search again */
793 if(ThreadQueue
->CaptureWindow
== NULL
)
795 co_IntSendHitTestMessages(ThreadQueue
, &Msg
->Msg
);
796 if((Msg
->Msg
.message
!= WM_MOUSEMOVE
&& Msg
->Msg
.message
!= WM_NCMOUSEMOVE
) &&
797 IS_BTN_MESSAGE(Msg
->Msg
.message
, DOWN
) &&
798 co_IntActivateWindowMouse(ThreadQueue
, &Msg
->Msg
, MsgWindow
, &HitTest
))
800 UserDerefObjectCo(MsgWindow
);
801 /* eat the message, search again */
806 UserDerefObjectCo(MsgWindow
);
810 co_IntSendHitTestMessages(ThreadQueue
, &Msg
->Msg
);
815 // UserDerefObject(MsgWindow);
821 if((Msg
->Msg
.hwnd
&& Msg
->Msg
.message
>= WM_MOUSEFIRST
&& Msg
->Msg
.message
<= WM_MOUSELAST
) &&
822 co_IntTranslateMouseMessage(ThreadQueue
, &Msg
->Msg
, &HitTest
, FALSE
))
823 /* FIXME - check message filter again, if the message doesn't match anymore,
826 /* eat the message, search again */
837 NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo
,
845 NTUSERGETMESSAGEINFO Info
;
846 PWINDOW_OBJECT Window
;
847 PMSGMEMORY MsgMemoryEntry
;
851 DECLARE_RETURN(BOOL
);
853 DPRINT("Enter NtUserPeekMessage\n");
854 UserEnterExclusive();
857 if (hWnd
&& hWnd
!= INVALID_HANDLE_VALUE
)
859 if (!(Window
= UserGetWindowObject(hWnd
)))
865 if (MsgFilterMax
< MsgFilterMin
)
871 Present
= co_IntPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
);
875 /* See if this message type is present in the table */
876 MsgMemoryEntry
= FindMsgMemory(Info
.Msg
.message
);
877 if (NULL
== MsgMemoryEntry
)
879 /* Not present, no copying needed */
884 /* Determine required size */
885 Size
= MsgMemorySize(MsgMemoryEntry
, Info
.Msg
.wParam
,
887 /* Allocate required amount of user-mode memory */
888 Info
.LParamSize
= Size
;
890 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem
, 0,
891 &Info
.LParamSize
, MEM_COMMIT
, PAGE_READWRITE
);
892 if (! NT_SUCCESS(Status
))
894 SetLastNtError(Status
);
897 /* Transfer lParam data to user-mode mem */
898 Status
= MmCopyToCaller(UserMem
, (PVOID
) Info
.Msg
.lParam
, Size
);
899 if (! NT_SUCCESS(Status
))
901 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &UserMem
,
902 &Info
.LParamSize
, MEM_DECOMMIT
);
903 SetLastNtError(Status
);
906 Info
.Msg
.lParam
= (LPARAM
) UserMem
;
908 if (RemoveMsg
&& Msg
.FreeLParam
&& 0 != Msg
.Msg
.lParam
)
910 ExFreePool((void *) Msg
.Msg
.lParam
);
912 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERGETMESSAGEINFO
));
913 if (! NT_SUCCESS(Status
))
915 SetLastNtError(Status
);
923 DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_
);
929 co_IntWaitMessage(HWND Wnd
,
933 PUSER_MESSAGE_QUEUE ThreadQueue
;
937 ThreadQueue
= (PUSER_MESSAGE_QUEUE
)PsGetWin32Thread()->MessageQueue
;
941 if (co_IntPeekMessage(&Msg
, Wnd
, MsgFilterMin
, MsgFilterMax
, PM_NOREMOVE
))
946 /* Nothing found. Wait for new messages. */
947 Status
= co_MsqWaitForNewMessages(ThreadQueue
, Wnd
, MsgFilterMin
, MsgFilterMax
);
949 while ((STATUS_WAIT_0
<= Status
&& Status
<= STATUS_WAIT_63
) || STATUS_TIMEOUT
== Status
);
951 SetLastNtError(Status
);
957 NtUserGetMessage(PNTUSERGETMESSAGEINFO UnsafeInfo
,
962 * FUNCTION: Get a message from the calling thread's message queue.
964 * UnsafeMsg - Pointer to the structure which receives the returned message.
965 * Wnd - Window whose messages are to be retrieved.
966 * MsgFilterMin - Integer value of the lowest message value to be
968 * MsgFilterMax - Integer value of the highest message value to be
973 NTUSERGETMESSAGEINFO Info
;
975 PWINDOW_OBJECT Window
= NULL
;
976 PMSGMEMORY MsgMemoryEntry
;
980 DECLARE_RETURN(BOOL
);
981 // USER_REFERENCE_ENTRY Ref;
983 DPRINT("Enter NtUserGetMessage\n");
984 UserEnterExclusive();
987 if (hWnd
&& !(Window
= UserGetWindowObject(hWnd
)))
992 // if (Window) UserRefObjectCo(Window, &Ref);
994 if (MsgFilterMax
< MsgFilterMin
)
1002 GotMessage
= co_IntPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
);
1006 /* See if this message type is present in the table */
1007 MsgMemoryEntry
= FindMsgMemory(Info
.Msg
.message
);
1008 if (NULL
== MsgMemoryEntry
)
1010 /* Not present, no copying needed */
1011 Info
.LParamSize
= 0;
1015 /* Determine required size */
1016 Size
= MsgMemorySize(MsgMemoryEntry
, Info
.Msg
.wParam
,
1018 /* Allocate required amount of user-mode memory */
1019 Info
.LParamSize
= Size
;
1021 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem
, 0,
1022 &Info
.LParamSize
, MEM_COMMIT
, PAGE_READWRITE
);
1024 if (! NT_SUCCESS(Status
))
1026 SetLastNtError(Status
);
1029 /* Transfer lParam data to user-mode mem */
1030 Status
= MmCopyToCaller(UserMem
, (PVOID
) Info
.Msg
.lParam
, Size
);
1031 if (! NT_SUCCESS(Status
))
1033 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &UserMem
,
1034 &Info
.LParamSize
, MEM_DECOMMIT
);
1035 SetLastNtError(Status
);
1038 Info
.Msg
.lParam
= (LPARAM
) UserMem
;
1040 if (Msg
.FreeLParam
&& 0 != Msg
.Msg
.lParam
)
1042 ExFreePool((void *) Msg
.Msg
.lParam
);
1044 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERGETMESSAGEINFO
));
1045 if (! NT_SUCCESS(Status
))
1047 SetLastNtError(Status
);
1051 else if (! co_IntWaitMessage(hWnd
, MsgFilterMin
, MsgFilterMax
))
1056 while (! GotMessage
);
1058 RETURN( WM_QUIT
!= Info
.Msg
.message
);
1061 // if (Window) UserDerefObjectCo(Window);
1063 DPRINT("Leave NtUserGetMessage\n");
1084 static NTSTATUS FASTCALL
1085 CopyMsgToKernelMem(MSG
*KernelModeMsg
, MSG
*UserModeMsg
, PMSGMEMORY MsgMemoryEntry
)
1092 *KernelModeMsg
= *UserModeMsg
;
1094 /* See if this message type is present in the table */
1095 if (NULL
== MsgMemoryEntry
)
1097 /* Not present, no copying needed */
1098 return STATUS_SUCCESS
;
1101 /* Determine required size */
1102 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
1106 /* Allocate kernel mem */
1107 KernelMem
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
1108 if (NULL
== KernelMem
)
1110 DPRINT1("Not enough memory to copy message to kernel mem\n");
1111 return STATUS_NO_MEMORY
;
1113 KernelModeMsg
->lParam
= (LPARAM
) KernelMem
;
1115 /* Copy data if required */
1116 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_READ
))
1118 Status
= MmCopyFromCaller(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
1119 if (! NT_SUCCESS(Status
))
1121 DPRINT1("Failed to copy message to kernel: invalid usermode buffer\n");
1122 ExFreePool(KernelMem
);
1128 /* Make sure we don't pass any secrets to usermode */
1129 RtlZeroMemory(KernelMem
, Size
);
1134 KernelModeMsg
->lParam
= 0;
1137 return STATUS_SUCCESS
;
1140 static NTSTATUS FASTCALL
1141 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
1144 PMSGMEMORY MsgMemoryEntry
;
1147 /* See if this message type is present in the table */
1148 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
1149 if (NULL
== MsgMemoryEntry
)
1151 /* Not present, no copying needed */
1152 return STATUS_SUCCESS
;
1155 /* Determine required size */
1156 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
1160 /* Copy data if required */
1161 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
1163 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
1164 if (! NT_SUCCESS(Status
))
1166 DPRINT1("Failed to copy message from kernel: invalid usermode buffer\n");
1167 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
1172 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
1175 return STATUS_SUCCESS
;
1179 UserPostMessage(HWND Wnd
,
1184 MSG UserModeMsg
, KernelModeMsg
;
1185 LARGE_INTEGER LargeTickCount
;
1187 PMSGMEMORY MsgMemoryEntry
;
1191 MsqPostQuitMessage(PsGetWin32Thread()->MessageQueue
, wParam
);
1193 else if (Wnd
== HWND_BROADCAST
)
1196 PWINDOW_OBJECT DesktopWindow
;
1199 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1200 List
= IntWinListChildren(DesktopWindow
);
1204 for (i
= 0; List
[i
]; i
++)
1205 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1211 PWINDOW_OBJECT Window
;
1213 Window
= UserGetWindowObject(Wnd
);
1218 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
1220 DPRINT1("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd
);
1221 /* FIXME - last error code? */
1225 UserModeMsg
.hwnd
= Wnd
;
1226 UserModeMsg
.message
= Msg
;
1227 UserModeMsg
.wParam
= wParam
;
1228 UserModeMsg
.lParam
= lParam
;
1229 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1230 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1231 if (! NT_SUCCESS(Status
))
1233 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1236 IntGetCursorLocation(PsGetWin32Thread()->Desktop
->WindowStation
,
1238 KeQueryTickCount(&LargeTickCount
);
1239 KernelModeMsg
.time
= LargeTickCount
.u
.LowPart
;
1240 MsqPostMessage(Window
->MessageQueue
, &KernelModeMsg
,
1241 NULL
!= MsgMemoryEntry
&& 0 != KernelModeMsg
.lParam
,
1250 NtUserPostMessage(HWND hWnd
,
1255 DECLARE_RETURN(BOOL
);
1257 DPRINT("Enter NtUserPostMessage\n");
1258 UserEnterExclusive();
1260 RETURN(UserPostMessage(hWnd
, Msg
, wParam
, lParam
));
1263 DPRINT("Leave NtUserPostMessage, ret=%i\n",_ret_
);
1271 NtUserPostThreadMessage(DWORD idThread
,
1276 MSG UserModeMsg
, KernelModeMsg
;
1280 PMSGMEMORY MsgMemoryEntry
;
1281 DECLARE_RETURN(BOOL
);
1283 DPRINT("Enter NtUserPostThreadMessage\n");
1284 UserEnterExclusive();
1286 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
1288 if( Status
== STATUS_SUCCESS
)
1290 pThread
= (PW32THREAD
)peThread
->Tcb
.Win32Thread
;
1291 if( !pThread
|| !pThread
->MessageQueue
)
1293 ObDereferenceObject( peThread
);
1297 UserModeMsg
.hwnd
= NULL
;
1298 UserModeMsg
.message
= Msg
;
1299 UserModeMsg
.wParam
= wParam
;
1300 UserModeMsg
.lParam
= lParam
;
1301 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1302 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1303 if (! NT_SUCCESS(Status
))
1305 ObDereferenceObject( peThread
);
1306 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1309 MsqPostMessage(pThread
->MessageQueue
, &KernelModeMsg
,
1310 NULL
!= MsgMemoryEntry
&& 0 != KernelModeMsg
.lParam
,
1312 ObDereferenceObject( peThread
);
1317 SetLastNtError( Status
);
1322 DPRINT("Leave NtUserPostThreadMessage, ret=%i\n",_ret_
);
1328 NtUserQuerySendMessage(DWORD Unknown0
)
1336 co_IntSendMessage(HWND hWnd
,
1341 ULONG_PTR Result
= 0;
1342 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1344 return (LRESULT
)Result
;
1351 co_IntSendMessageTimeoutSingle(HWND hWnd
,
1361 PWINDOW_OBJECT Window
= NULL
;
1362 PMSGMEMORY MsgMemoryEntry
;
1363 INT lParamBufferSize
;
1364 LPARAM lParamPacked
;
1365 PW32THREAD Win32Thread
;
1366 DECLARE_RETURN(LRESULT
);
1367 USER_REFERENCE_ENTRY Ref
;
1369 /* FIXME: Call hooks. */
1370 if (!(Window
= UserGetWindowObject(hWnd
)))
1375 UserRefObjectCo(Window
, &Ref
);
1377 Win32Thread
= PsGetWin32Thread();
1379 if (NULL
!= Win32Thread
&&
1380 Window
->MessageQueue
== Win32Thread
->MessageQueue
)
1382 if (Win32Thread
->IsExiting
)
1384 /* Never send messages to exiting threads */
1388 /* See if this message type is present in the table */
1389 MsgMemoryEntry
= FindMsgMemory(Msg
);
1390 if (NULL
== MsgMemoryEntry
)
1392 lParamBufferSize
= -1;
1396 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1399 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
)))
1401 DPRINT1("Failed to pack message parameters\n");
1404 if (0xFFFF0000 != ((DWORD
) Window
->WndProcW
& 0xFFFF0000))
1406 Result
= (ULONG_PTR
)co_IntCallWindowProc(Window
->WndProcW
, FALSE
, hWnd
, Msg
, wParam
,
1407 lParamPacked
,lParamBufferSize
);
1411 Result
= (ULONG_PTR
)co_IntCallWindowProc(Window
->WndProcA
, TRUE
, hWnd
, Msg
, wParam
,
1412 lParamPacked
,lParamBufferSize
);
1420 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
)))
1422 DPRINT1("Failed to unpack message parameters\n");
1429 if(uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->MessageQueue
))
1431 /* FIXME - Set a LastError? */
1435 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
1437 /* FIXME - last error? */
1438 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1442 Status
= co_MsqSendMessage(Window
->MessageQueue
, hWnd
, Msg
, wParam
, lParam
,
1443 uTimeout
, (uFlags
& SMTO_BLOCK
), FALSE
, uResult
);
1446 if (STATUS_TIMEOUT
== Status
)
1448 /* MSDN says GetLastError() should return 0 after timeout */
1449 SetLastWin32Error(0);
1452 else if (! NT_SUCCESS(Status
))
1454 SetLastNtError(Status
);
1461 if (Window
) UserDerefObjectCo(Window
);
1466 co_IntSendMessageTimeout(HWND hWnd
,
1474 PWINDOW_OBJECT DesktopWindow
;
1478 if (HWND_BROADCAST
!= hWnd
)
1480 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1483 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1484 if (NULL
== DesktopWindow
)
1486 SetLastWin32Error(ERROR_INTERNAL_ERROR
);
1490 Children
= IntWinListChildren(DesktopWindow
);
1491 if (NULL
== Children
)
1496 for (Child
= Children
; NULL
!= *Child
; Child
++)
1498 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1501 ExFreePool(Children
);
1503 return (LRESULT
) TRUE
;
1507 /* This function posts a message if the destination's message queue belongs to
1508 another thread, otherwise it sends the message. It does not support broadcast
1511 co_IntPostOrSendMessage(HWND hWnd
,
1517 PWINDOW_OBJECT Window
;
1519 if(hWnd
== HWND_BROADCAST
)
1524 if(!(Window
= UserGetWindowObject(hWnd
)))
1529 if(Window
->MessageQueue
!= PsGetWin32Thread()->MessageQueue
)
1531 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1535 if(!co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1541 return (LRESULT
)Result
;
1545 co_IntDoSendMessage(HWND hWnd
,
1550 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1552 LRESULT Result
= TRUE
;
1554 PWINDOW_OBJECT Window
;
1555 NTUSERSENDMESSAGEINFO Info
;
1558 PMSGMEMORY MsgMemoryEntry
;
1560 RtlZeroMemory(&Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1562 /* FIXME: Call hooks. */
1563 if (HWND_BROADCAST
!= hWnd
)
1565 Window
= UserGetWindowObject(hWnd
);
1568 /* Tell usermode to not touch this one */
1569 Info
.HandledByKernel
= TRUE
;
1570 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1575 /* FIXME: Check for an exiting window. */
1577 /* See if the current thread can handle the message */
1578 if (HWND_BROADCAST
!= hWnd
&& NULL
!= PsGetWin32Thread() &&
1579 Window
->MessageQueue
== PsGetWin32Thread()->MessageQueue
)
1581 /* Gather the information usermode needs to call the window proc directly */
1582 Info
.HandledByKernel
= FALSE
;
1583 if (0xFFFF0000 != ((DWORD
) Window
->WndProcW
& 0xFFFF0000))
1585 if (0xFFFF0000 != ((DWORD
) Window
->WndProcA
& 0xFFFF0000))
1587 /* Both Unicode and Ansi winprocs are real, see what usermode prefers */
1588 Status
= MmCopyFromCaller(&(Info
.Ansi
), &(UnsafeInfo
->Ansi
),
1590 if (! NT_SUCCESS(Status
))
1592 Info
.Ansi
= ! Window
->Unicode
;
1594 Info
.Proc
= (Info
.Ansi
? Window
->WndProcA
: Window
->WndProcW
);
1598 /* Real Unicode winproc */
1600 Info
.Proc
= Window
->WndProcW
;
1605 /* Must have real Ansi winproc */
1607 Info
.Proc
= Window
->WndProcA
;
1612 /* Must be handled by other thread */
1613 // if (HWND_BROADCAST != hWnd)
1615 // UserDerefObject(Window);
1617 Info
.HandledByKernel
= TRUE
;
1618 UserModeMsg
.hwnd
= hWnd
;
1619 UserModeMsg
.message
= Msg
;
1620 UserModeMsg
.wParam
= wParam
;
1621 UserModeMsg
.lParam
= lParam
;
1622 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1623 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1624 if (! NT_SUCCESS(Status
))
1626 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1627 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1628 return (dsm
? 0 : -1);
1632 Result
= co_IntSendMessage(KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1633 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
);
1637 Result
= co_IntSendMessageTimeout(KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1638 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
,
1639 dsm
->uFlags
, dsm
->uTimeout
, &dsm
->Result
);
1641 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1642 if (! NT_SUCCESS(Status
))
1644 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1645 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1646 return(dsm
? 0 : -1);
1650 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1651 if (! NT_SUCCESS(Status
))
1653 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1656 return (LRESULT
)Result
;
1660 NtUserSendMessageTimeout(HWND hWnd
,
1667 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1671 DECLARE_RETURN(BOOL
);
1673 DPRINT("Enter NtUserSendMessageTimeout\n");
1674 UserEnterExclusive();
1676 dsm
.uFlags
= uFlags
;
1677 dsm
.uTimeout
= uTimeout
;
1678 Result
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, &dsm
, UnsafeInfo
);
1679 if(uResult
!= NULL
&& Result
!= 0)
1683 Status
= MmCopyToCaller(uResult
, &dsm
.Result
, sizeof(ULONG_PTR
));
1684 if(!NT_SUCCESS(Status
))
1686 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1693 DPRINT("Leave NtUserSendMessageTimeout, ret=%i\n",_ret_
);
1699 NtUserSendMessage(HWND Wnd
,
1703 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1705 DECLARE_RETURN(BOOL
);
1707 DPRINT("Enter NtUserSendMessage\n");
1708 UserEnterExclusive();
1710 RETURN(co_IntDoSendMessage(Wnd
, Msg
, wParam
, lParam
, NULL
, UnsafeInfo
));
1713 DPRINT("Leave NtUserSendMessage, ret=%i\n",_ret_
);
1719 NtUserSendMessageCallback(HWND hWnd
,
1723 SENDASYNCPROC lpCallBack
,
1732 NtUserSendNotifyMessage(HWND hWnd
,
1743 NtUserWaitMessage(VOID
)
1745 DECLARE_RETURN(BOOL
);
1747 DPRINT("EnterNtUserWaitMessage\n");
1748 UserEnterExclusive();
1750 RETURN(co_IntWaitMessage(NULL
, 0, 0));
1753 DPRINT("Leave NtUserWaitMessage, ret=%i\n",_ret_
);
1759 NtUserGetQueueStatus(BOOL ClearChanges
)
1761 PUSER_MESSAGE_QUEUE Queue
;
1763 DECLARE_RETURN(DWORD
);
1765 DPRINT("Enter NtUserGetQueueStatus\n");
1766 UserEnterExclusive();
1768 Queue
= PsGetWin32Thread()->MessageQueue
;
1770 Result
= MAKELONG(Queue
->QueueBits
, Queue
->ChangedBits
);
1773 Queue
->ChangedBits
= 0;
1779 DPRINT("Leave NtUserGetQueueStatus, ret=%i\n",_ret_
);
1785 IntInitMessagePumpHook()
1787 ((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->MessagePumpHookValue
++;
1792 IntUninitMessagePumpHook()
1794 if (((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->MessagePumpHookValue
<= 0)
1798 ((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->MessagePumpHookValue
--;