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 ******************************************************************/
42 } DOSENDMESSAGE
, *PDOSENDMESSAGE
;
44 /* FUNCTIONS *****************************************************************/
47 IntInitMessageImpl(VOID
)
49 return STATUS_SUCCESS
;
53 IntCleanupMessageImpl(VOID
)
55 return STATUS_SUCCESS
;
58 #define MMS_SIZE_WPARAM -1
59 #define MMS_SIZE_WPARAMWCHAR -2
60 #define MMS_SIZE_LPARAMSZ -3
61 #define MMS_SIZE_SPECIAL -4
62 #define MMS_FLAG_READ 0x01
63 #define MMS_FLAG_WRITE 0x02
64 #define MMS_FLAG_READWRITE (MMS_FLAG_READ | MMS_FLAG_WRITE)
65 typedef struct tagMSGMEMORY
70 } MSGMEMORY
, *PMSGMEMORY
;
72 static MSGMEMORY MsgMemory
[] =
74 { WM_CREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
75 { WM_DDE_ACK
, sizeof(KMDDELPARAM
), MMS_FLAG_READ
},
76 { WM_DDE_EXECUTE
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
77 { WM_GETMINMAXINFO
, sizeof(MINMAXINFO
), MMS_FLAG_READWRITE
},
78 { WM_GETTEXT
, MMS_SIZE_WPARAMWCHAR
, MMS_FLAG_WRITE
},
79 { WM_NCCALCSIZE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
80 { WM_NCCREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
81 { WM_SETTEXT
, MMS_SIZE_LPARAMSZ
, MMS_FLAG_READ
},
82 { WM_STYLECHANGED
, sizeof(STYLESTRUCT
), MMS_FLAG_READ
},
83 { WM_STYLECHANGING
, sizeof(STYLESTRUCT
), MMS_FLAG_READWRITE
},
84 { WM_COPYDATA
, MMS_SIZE_SPECIAL
, MMS_FLAG_READ
},
85 { WM_WINDOWPOSCHANGED
, sizeof(WINDOWPOS
), MMS_FLAG_READ
},
86 { WM_WINDOWPOSCHANGING
, sizeof(WINDOWPOS
), MMS_FLAG_READWRITE
},
89 static PMSGMEMORY FASTCALL
90 FindMsgMemory(UINT Msg
)
92 PMSGMEMORY MsgMemoryEntry
;
94 /* See if this message type is present in the table */
95 for (MsgMemoryEntry
= MsgMemory
;
96 MsgMemoryEntry
< MsgMemory
+ sizeof(MsgMemory
) / sizeof(MSGMEMORY
);
99 if (Msg
== MsgMemoryEntry
->Message
)
101 return MsgMemoryEntry
;
109 MsgMemorySize(PMSGMEMORY MsgMemoryEntry
, WPARAM wParam
, LPARAM lParam
)
112 PUNICODE_STRING WindowName
;
113 PUNICODE_STRING ClassName
;
117 if (MMS_SIZE_WPARAM
== MsgMemoryEntry
->Size
)
119 return (UINT
) wParam
;
121 else if (MMS_SIZE_WPARAMWCHAR
== MsgMemoryEntry
->Size
)
123 return (UINT
) (wParam
* sizeof(WCHAR
));
125 else if (MMS_SIZE_LPARAMSZ
== MsgMemoryEntry
->Size
)
127 return (UINT
) ((wcslen((PWSTR
) lParam
) + 1) * sizeof(WCHAR
));
129 else if (MMS_SIZE_SPECIAL
== MsgMemoryEntry
->Size
)
131 switch(MsgMemoryEntry
->Message
)
135 Cs
= (CREATESTRUCTW
*) lParam
;
136 WindowName
= (PUNICODE_STRING
) Cs
->lpszName
;
137 ClassName
= (PUNICODE_STRING
) Cs
->lpszClass
;
138 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
139 if (IS_ATOM(ClassName
->Buffer
))
141 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
145 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
151 return wParam
? sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
) : sizeof(RECT
);
155 return sizeof(COPYDATASTRUCT
) + ((PCOPYDATASTRUCT
)lParam
)->cbData
;
165 return MsgMemoryEntry
->Size
;
169 DPRINT1("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH_GetExceptionCode());
174 static FASTCALL NTSTATUS
175 PackParam(LPARAM
*lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
177 NCCALCSIZE_PARAMS
*UnpackedNcCalcsize
;
178 NCCALCSIZE_PARAMS
*PackedNcCalcsize
;
179 CREATESTRUCTW
*UnpackedCs
;
180 CREATESTRUCTW
*PackedCs
;
181 PUNICODE_STRING WindowName
;
182 PUNICODE_STRING ClassName
;
186 *lParamPacked
= lParam
;
187 if (WM_NCCALCSIZE
== Msg
&& wParam
)
189 UnpackedNcCalcsize
= (NCCALCSIZE_PARAMS
*) lParam
;
190 if (UnpackedNcCalcsize
->lppos
!= (PWINDOWPOS
) (UnpackedNcCalcsize
+ 1))
192 PackedNcCalcsize
= ExAllocatePoolWithTag(PagedPool
,
193 sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
),
195 if (NULL
== PackedNcCalcsize
)
197 DPRINT1("Not enough memory to pack lParam\n");
198 return STATUS_NO_MEMORY
;
200 RtlCopyMemory(PackedNcCalcsize
, UnpackedNcCalcsize
, sizeof(NCCALCSIZE_PARAMS
));
201 PackedNcCalcsize
->lppos
= (PWINDOWPOS
) (PackedNcCalcsize
+ 1);
202 RtlCopyMemory(PackedNcCalcsize
->lppos
, UnpackedNcCalcsize
->lppos
, sizeof(WINDOWPOS
));
203 *lParamPacked
= (LPARAM
) PackedNcCalcsize
;
206 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
208 UnpackedCs
= (CREATESTRUCTW
*) lParam
;
209 WindowName
= (PUNICODE_STRING
) UnpackedCs
->lpszName
;
210 ClassName
= (PUNICODE_STRING
) UnpackedCs
->lpszClass
;
211 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
212 if (IS_ATOM(ClassName
->Buffer
))
214 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
218 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
220 PackedCs
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
221 if (NULL
== PackedCs
)
223 DPRINT1("Not enough memory to pack lParam\n");
224 return STATUS_NO_MEMORY
;
226 RtlCopyMemory(PackedCs
, UnpackedCs
, sizeof(CREATESTRUCTW
));
227 CsData
= (PCHAR
) (PackedCs
+ 1);
228 PackedCs
->lpszName
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
229 RtlCopyMemory(CsData
, WindowName
->Buffer
, WindowName
->Length
);
230 CsData
+= WindowName
->Length
;
231 *((WCHAR
*) CsData
) = L
'\0';
232 CsData
+= sizeof(WCHAR
);
233 PackedCs
->lpszClass
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
234 if (IS_ATOM(ClassName
->Buffer
))
236 *((WCHAR
*) CsData
) = L
'A';
237 CsData
+= sizeof(WCHAR
);
238 *((ATOM
*) CsData
) = (ATOM
)(DWORD_PTR
) ClassName
->Buffer
;
239 CsData
+= sizeof(ATOM
);
243 *((WCHAR
*) CsData
) = L
'S';
244 CsData
+= sizeof(WCHAR
);
245 RtlCopyMemory(CsData
, ClassName
->Buffer
, ClassName
->Length
);
246 CsData
+= ClassName
->Length
;
247 *((WCHAR
*) CsData
) = L
'\0';
248 CsData
+= sizeof(WCHAR
);
250 ASSERT(CsData
== (PCHAR
) PackedCs
+ Size
);
251 *lParamPacked
= (LPARAM
) PackedCs
;
254 return STATUS_SUCCESS
;
257 static FASTCALL NTSTATUS
258 UnpackParam(LPARAM lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
260 NCCALCSIZE_PARAMS
*UnpackedParams
;
261 NCCALCSIZE_PARAMS
*PackedParams
;
262 PWINDOWPOS UnpackedWindowPos
;
264 if (lParamPacked
== lParam
)
266 return STATUS_SUCCESS
;
269 if (WM_NCCALCSIZE
== Msg
&& wParam
)
271 PackedParams
= (NCCALCSIZE_PARAMS
*) lParamPacked
;
272 UnpackedParams
= (NCCALCSIZE_PARAMS
*) lParam
;
273 UnpackedWindowPos
= UnpackedParams
->lppos
;
274 RtlCopyMemory(UnpackedParams
, PackedParams
, sizeof(NCCALCSIZE_PARAMS
));
275 UnpackedParams
->lppos
= UnpackedWindowPos
;
276 RtlCopyMemory(UnpackedWindowPos
, PackedParams
+ 1, sizeof(WINDOWPOS
));
277 ExFreePool((PVOID
) lParamPacked
);
279 return STATUS_SUCCESS
;
281 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
283 ExFreePool((PVOID
) lParamPacked
);
285 return STATUS_SUCCESS
;
290 return STATUS_INVALID_PARAMETER
;
299 DECLARE_RETURN(BOOL
);
301 DPRINT("Enter NtUserCallMsgFilter\n");
302 UserEnterExclusive();
304 if (co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)msg
)) RETURN( TRUE
);
305 RETURN( co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)msg
));
308 DPRINT("Leave NtUserCallMsgFilter. ret=%i\n", _ret_
);
314 NtUserDispatchMessage(PNTUSERDISPATCHMESSAGEINFO UnsafeMsgInfo
)
317 NTUSERDISPATCHMESSAGEINFO MsgInfo
;
318 PWINDOW_OBJECT WindowObject
;
319 LRESULT Result
= TRUE
;
320 DECLARE_RETURN(LRESULT
);
322 DPRINT("Enter NtUserDispatchMessage\n");
323 UserEnterExclusive();
325 Status
= MmCopyFromCaller(&MsgInfo
, UnsafeMsgInfo
, sizeof(NTUSERDISPATCHMESSAGEINFO
));
326 if (! NT_SUCCESS(Status
))
328 SetLastNtError(Status
);
332 /* Process timer messages. */
333 if (WM_TIMER
== MsgInfo
.Msg
.message
&& 0 != MsgInfo
.Msg
.lParam
)
335 LARGE_INTEGER LargeTickCount
;
336 /* FIXME: Call hooks. */
338 /* FIXME: Check for continuing validity of timer. */
340 MsgInfo
.HandledByKernel
= FALSE
;
341 KeQueryTickCount(&LargeTickCount
);
342 MsgInfo
.Proc
= (WNDPROC
) MsgInfo
.Msg
.lParam
;
343 MsgInfo
.Msg
.lParam
= (LPARAM
)LargeTickCount
.u
.LowPart
;
345 else if (NULL
== MsgInfo
.Msg
.hwnd
)
347 MsgInfo
.HandledByKernel
= TRUE
;
352 /* Get the window object. */
353 WindowObject
= IntGetWindowObject(MsgInfo
.Msg
.hwnd
);
354 if (NULL
== WindowObject
)
356 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
357 MsgInfo
.HandledByKernel
= TRUE
;
362 if (WindowObject
->OwnerThread
!= PsGetCurrentThread())
364 IntReleaseWindowObject(WindowObject
);
365 DPRINT1("Window doesn't belong to the calling thread!\n");
366 MsgInfo
.HandledByKernel
= TRUE
;
371 /* FIXME: Call hook procedures. */
373 MsgInfo
.HandledByKernel
= FALSE
;
375 if (0xFFFF0000 != ((DWORD
) WindowObject
->WndProcW
& 0xFFFF0000))
377 if (0xFFFF0000 != ((DWORD
) WindowObject
->WndProcA
& 0xFFFF0000))
379 /* Both Unicode and Ansi winprocs are real, use whatever
381 MsgInfo
.Proc
= (MsgInfo
.Ansi
? WindowObject
->WndProcA
382 : WindowObject
->WndProcW
);
386 /* Real Unicode winproc */
387 MsgInfo
.Ansi
= FALSE
;
388 MsgInfo
.Proc
= WindowObject
->WndProcW
;
393 /* Must have real Ansi winproc */
395 MsgInfo
.Proc
= WindowObject
->WndProcA
;
398 IntReleaseWindowObject(WindowObject
);
401 Status
= MmCopyToCaller(UnsafeMsgInfo
, &MsgInfo
, sizeof(NTUSERDISPATCHMESSAGEINFO
));
402 if (! NT_SUCCESS(Status
))
404 SetLastNtError(Status
);
411 DPRINT("Leave NtUserDispatchMessage. ret=%i\n", _ret_
);
418 NtUserTranslateMessage(LPMSG lpMsg
,
423 DECLARE_RETURN(BOOL
);
425 DPRINT("Enter NtUserTranslateMessage\n");
426 UserEnterExclusive();
428 Status
= MmCopyFromCaller(&SafeMsg
, lpMsg
, sizeof(MSG
));
429 if(!NT_SUCCESS(Status
))
431 SetLastNtError(Status
);
435 RETURN( IntTranslateKbdMessage(&SafeMsg
, dwhkl
));
438 DPRINT("Leave NtUserTranslateMessage: ret=%i\n",_ret_
);
445 co_IntSendHitTestMessages(PUSER_MESSAGE_QUEUE ThreadQueue
, LPMSG Msg
)
447 if(!Msg
->hwnd
|| ThreadQueue
->CaptureWindow
)
456 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(HTCLIENT
, Msg
->message
));
461 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(Msg
->wParam
, Msg
->message
));
468 case WM_LBUTTONDBLCLK
:
469 case WM_MBUTTONDBLCLK
:
470 case WM_RBUTTONDBLCLK
:
471 case WM_XBUTTONDBLCLK
:
474 PSYSTEM_CURSORINFO CurInfo
;
476 if(!IntGetWindowStationObject(InputWindowStation
))
480 CurInfo
= IntGetSysCursorInfo(InputWindowStation
);
481 wParam
= (WPARAM
)(CurInfo
->ButtonsDown
);
482 ObDereferenceObject(InputWindowStation
);
484 co_IntSendMessage(Msg
->hwnd
, WM_MOUSEMOVE
, wParam
, Msg
->lParam
);
485 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(HTCLIENT
, Msg
->message
));
488 case WM_NCLBUTTONDOWN
:
489 case WM_NCMBUTTONDOWN
:
490 case WM_NCRBUTTONDOWN
:
491 case WM_NCXBUTTONDOWN
:
492 case WM_NCLBUTTONDBLCLK
:
493 case WM_NCMBUTTONDBLCLK
:
494 case WM_NCRBUTTONDBLCLK
:
495 case WM_NCXBUTTONDBLCLK
:
497 co_IntSendMessage(Msg
->hwnd
, WM_NCMOUSEMOVE
, (WPARAM
)Msg
->wParam
, Msg
->lParam
);
498 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(Msg
->wParam
, Msg
->message
));
505 co_IntActivateWindowMouse(PUSER_MESSAGE_QUEUE ThreadQueue
, LPMSG Msg
, PWINDOW_OBJECT MsgWindow
,
510 if(*HitTest
== (USHORT
)HTTRANSPARENT
)
512 /* eat the message, search again! */
516 Result
= co_IntSendMessage(MsgWindow
->Self
, WM_MOUSEACTIVATE
, (WPARAM
)IntGetParent(MsgWindow
), (LPARAM
)MAKELONG(*HitTest
, Msg
->message
));
519 case MA_NOACTIVATEANDEAT
:
523 case MA_ACTIVATEANDEAT
:
524 co_IntMouseActivateWindow(MsgWindow
);
528 co_IntMouseActivateWindow(MsgWindow
);
536 co_IntTranslateMouseMessage(PUSER_MESSAGE_QUEUE ThreadQueue
, LPMSG Msg
, USHORT
*HitTest
, BOOL Remove
)
538 PWINDOW_OBJECT Window
;
540 if(!(Window
= IntGetWindowObject(Msg
->hwnd
)))
542 /* let's just eat the message?! */
546 if(ThreadQueue
== Window
->MessageQueue
&&
547 ThreadQueue
->CaptureWindow
!= Window
->Self
)
549 /* only send WM_NCHITTEST messages if we're not capturing the window! */
550 *HitTest
= co_IntSendMessage(Window
->Self
, WM_NCHITTEST
, 0,
551 MAKELONG(Msg
->pt
.x
, Msg
->pt
.y
));
553 if(*HitTest
== (USHORT
)HTTRANSPARENT
)
555 PWINDOW_OBJECT DesktopWindow
;
556 HWND hDesktop
= IntGetDesktopWindow();
558 if((DesktopWindow
= IntGetWindowObject(hDesktop
)))
562 co_WinPosWindowFromPoint(DesktopWindow
, Window
->MessageQueue
, &Msg
->pt
, &Wnd
);
567 /* post the message to the other window */
568 Msg
->hwnd
= Wnd
->Self
;
569 if(!(Wnd
->Status
& WINDOWSTATUS_DESTROYING
))
571 MsqPostMessage(Wnd
->MessageQueue
, Msg
, FALSE
,
572 Msg
->message
== WM_MOUSEMOVE
? QS_MOUSEMOVE
:
576 /* eat the message */
577 IntReleaseWindowObject(Wnd
);
578 IntReleaseWindowObject(Window
);
579 IntReleaseWindowObject(DesktopWindow
);
582 IntReleaseWindowObject(Wnd
);
585 IntReleaseWindowObject(DesktopWindow
);
594 if(IS_BTN_MESSAGE(Msg
->message
, DOWN
))
596 /* generate double click messages, if necessary */
597 if ((((*HitTest
) != HTCLIENT
) ||
598 (IntGetClassLong(Window
, GCL_STYLE
, FALSE
) & CS_DBLCLKS
)) &&
599 MsqIsDblClk(Msg
, Remove
))
601 Msg
->message
+= WM_LBUTTONDBLCLK
- WM_LBUTTONDOWN
;
605 if(Msg
->message
!= WM_MOUSEWHEEL
)
608 if ((*HitTest
) != HTCLIENT
)
610 Msg
->message
+= WM_NCMOUSEMOVE
- WM_MOUSEMOVE
;
611 if((Msg
->message
== WM_NCRBUTTONUP
) &&
612 (((*HitTest
) == HTCAPTION
) || ((*HitTest
) == HTSYSMENU
)))
614 Msg
->message
= WM_CONTEXTMENU
;
615 Msg
->wParam
= (WPARAM
)Window
->Self
;
619 Msg
->wParam
= *HitTest
;
621 Msg
->lParam
= MAKELONG(Msg
->pt
.x
, Msg
->pt
.y
);
623 else if(ThreadQueue
->MoveSize
== NULL
&&
624 ThreadQueue
->MenuOwner
== NULL
)
626 /* NOTE: Msg->pt should remain in screen coordinates. -- FiN */
627 Msg
->lParam
= MAKELONG(
628 Msg
->pt
.x
- (WORD
)Window
->ClientRect
.left
,
629 Msg
->pt
.y
- (WORD
)Window
->ClientRect
.top
);
633 IntReleaseWindowObject(Window
);
639 * Internal version of PeekMessage() doing all the work
642 co_IntPeekMessage(PUSER_MESSAGE Msg
,
648 LARGE_INTEGER LargeTickCount
;
649 PUSER_MESSAGE_QUEUE ThreadQueue
;
650 PUSER_MESSAGE Message
;
651 BOOL Present
, RemoveMessages
;
653 /* The queues and order in which they are checked are documented in the MSDN
654 article on GetMessage() */
656 ThreadQueue
= (PUSER_MESSAGE_QUEUE
)PsGetWin32Thread()->MessageQueue
;
658 /* Inspect RemoveMsg flags */
659 /* FIXME: The only flag we process is PM_REMOVE - processing of others must still be implemented */
660 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
666 KeQueryTickCount(&LargeTickCount
);
667 ThreadQueue
->LastMsgRead
= LargeTickCount
.u
.LowPart
;
669 /* Dispatch sent messages here. */
670 while (co_MsqDispatchOneSentMessage(ThreadQueue
));
672 /* Now look for a quit message. */
674 if (ThreadQueue
->QuitPosted
)
676 /* According to the PSDK, WM_QUIT messages are always returned, regardless
677 of the filter specified */
678 Msg
->Msg
.hwnd
= NULL
;
679 Msg
->Msg
.message
= WM_QUIT
;
680 Msg
->Msg
.wParam
= ThreadQueue
->QuitExitCode
;
682 Msg
->FreeLParam
= FALSE
;
685 ThreadQueue
->QuitPosted
= FALSE
;
690 /* Now check for normal messages. */
691 Present
= co_MsqFindMessage(ThreadQueue
,
700 RtlCopyMemory(Msg
, Message
, sizeof(USER_MESSAGE
));
703 MsqDestroyMessage(Message
);
708 /* Check for hardware events. */
709 Present
= co_MsqFindMessage(ThreadQueue
,
718 RtlCopyMemory(Msg
, Message
, sizeof(USER_MESSAGE
));
721 MsqDestroyMessage(Message
);
726 /* Check for sent messages again. */
727 while (co_MsqDispatchOneSentMessage(ThreadQueue
));
729 /* Check for paint messages. */
730 if (IntGetPaintMessage(Wnd
, MsgFilterMin
, MsgFilterMax
, PsGetWin32Thread(), &Msg
->Msg
, RemoveMessages
))
732 Msg
->FreeLParam
= FALSE
;
736 /* Check for WM_(SYS)TIMER messages */
737 Present
= MsqGetTimerMessage(ThreadQueue
, Wnd
, MsgFilterMin
, MsgFilterMax
,
738 &Msg
->Msg
, RemoveMessages
);
741 Msg
->FreeLParam
= FALSE
;
751 PWINDOW_OBJECT MsgWindow
= NULL
;
753 if(Msg
->Msg
.hwnd
&& (MsgWindow
= IntGetWindowObject(Msg
->Msg
.hwnd
)) &&
754 Msg
->Msg
.message
>= WM_MOUSEFIRST
&& Msg
->Msg
.message
<= WM_MOUSELAST
)
758 if(co_IntTranslateMouseMessage(ThreadQueue
, &Msg
->Msg
, &HitTest
, TRUE
))
759 /* FIXME - check message filter again, if the message doesn't match anymore,
762 IntReleaseWindowObject(MsgWindow
);
763 /* eat the message, search again */
766 if(ThreadQueue
->CaptureWindow
== NULL
)
768 co_IntSendHitTestMessages(ThreadQueue
, &Msg
->Msg
);
769 if((Msg
->Msg
.message
!= WM_MOUSEMOVE
&& Msg
->Msg
.message
!= WM_NCMOUSEMOVE
) &&
770 IS_BTN_MESSAGE(Msg
->Msg
.message
, DOWN
) &&
771 co_IntActivateWindowMouse(ThreadQueue
, &Msg
->Msg
, MsgWindow
, &HitTest
))
773 IntReleaseWindowObject(MsgWindow
);
774 /* eat the message, search again */
781 co_IntSendHitTestMessages(ThreadQueue
, &Msg
->Msg
);
786 IntReleaseWindowObject(MsgWindow
);
793 if((Msg
->Msg
.hwnd
&& Msg
->Msg
.message
>= WM_MOUSEFIRST
&& Msg
->Msg
.message
<= WM_MOUSELAST
) &&
794 co_IntTranslateMouseMessage(ThreadQueue
, &Msg
->Msg
, &HitTest
, FALSE
))
795 /* FIXME - check message filter again, if the message doesn't match anymore,
798 /* eat the message, search again */
809 NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo
,
817 NTUSERGETMESSAGEINFO Info
;
818 PWINDOW_OBJECT Window
;
819 PMSGMEMORY MsgMemoryEntry
;
823 DECLARE_RETURN(BOOL
);
825 DPRINT("Enter NtUserPeekMessage\n");
826 UserEnterExclusive();
831 Window
= IntGetWindowObject(Wnd
);
838 IntReleaseWindowObject(Window
);
842 if (MsgFilterMax
< MsgFilterMin
)
848 Present
= co_IntPeekMessage(&Msg
, Wnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
);
852 /* See if this message type is present in the table */
853 MsgMemoryEntry
= FindMsgMemory(Info
.Msg
.message
);
854 if (NULL
== MsgMemoryEntry
)
856 /* Not present, no copying needed */
861 /* Determine required size */
862 Size
= MsgMemorySize(MsgMemoryEntry
, Info
.Msg
.wParam
,
864 /* Allocate required amount of user-mode memory */
865 Info
.LParamSize
= Size
;
867 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem
, 0,
868 &Info
.LParamSize
, MEM_COMMIT
, PAGE_READWRITE
);
869 if (! NT_SUCCESS(Status
))
871 SetLastNtError(Status
);
874 /* Transfer lParam data to user-mode mem */
875 Status
= MmCopyToCaller(UserMem
, (PVOID
) Info
.Msg
.lParam
, Size
);
876 if (! NT_SUCCESS(Status
))
878 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &UserMem
,
879 &Info
.LParamSize
, MEM_DECOMMIT
);
880 SetLastNtError(Status
);
883 Info
.Msg
.lParam
= (LPARAM
) UserMem
;
885 if (RemoveMsg
&& Msg
.FreeLParam
&& 0 != Msg
.Msg
.lParam
)
887 ExFreePool((void *) Msg
.Msg
.lParam
);
889 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERGETMESSAGEINFO
));
890 if (! NT_SUCCESS(Status
))
892 SetLastNtError(Status
);
900 DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_
);
906 co_IntWaitMessage(HWND Wnd
,
910 PUSER_MESSAGE_QUEUE ThreadQueue
;
914 ThreadQueue
= (PUSER_MESSAGE_QUEUE
)PsGetWin32Thread()->MessageQueue
;
918 if (co_IntPeekMessage(&Msg
, Wnd
, MsgFilterMin
, MsgFilterMax
, PM_NOREMOVE
))
923 /* Nothing found. Wait for new messages. */
924 Status
= co_MsqWaitForNewMessages(ThreadQueue
, Wnd
, MsgFilterMin
, MsgFilterMax
);
926 while ((STATUS_WAIT_0
<= Status
&& Status
<= STATUS_WAIT_63
) || STATUS_TIMEOUT
== Status
);
928 SetLastNtError(Status
);
934 NtUserGetMessage(PNTUSERGETMESSAGEINFO UnsafeInfo
,
939 * FUNCTION: Get a message from the calling thread's message queue.
941 * UnsafeMsg - Pointer to the structure which receives the returned message.
942 * Wnd - Window whose messages are to be retrieved.
943 * MsgFilterMin - Integer value of the lowest message value to be
945 * MsgFilterMax - Integer value of the highest message value to be
950 NTUSERGETMESSAGEINFO Info
;
952 PWINDOW_OBJECT Window
;
953 PMSGMEMORY MsgMemoryEntry
;
957 DECLARE_RETURN(BOOL
);
959 DPRINT("Enter NtUserGetMessage\n");
960 UserEnterExclusive();
965 Window
= IntGetWindowObject(Wnd
);
969 IntReleaseWindowObject(Window
);
971 if (MsgFilterMax
< MsgFilterMin
)
979 GotMessage
= co_IntPeekMessage(&Msg
, Wnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
);
983 /* See if this message type is present in the table */
984 MsgMemoryEntry
= FindMsgMemory(Info
.Msg
.message
);
985 if (NULL
== MsgMemoryEntry
)
987 /* Not present, no copying needed */
992 /* Determine required size */
993 Size
= MsgMemorySize(MsgMemoryEntry
, Info
.Msg
.wParam
,
995 /* Allocate required amount of user-mode memory */
996 Info
.LParamSize
= Size
;
998 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem
, 0,
999 &Info
.LParamSize
, MEM_COMMIT
, PAGE_READWRITE
);
1001 if (! NT_SUCCESS(Status
))
1003 SetLastNtError(Status
);
1006 /* Transfer lParam data to user-mode mem */
1007 Status
= MmCopyToCaller(UserMem
, (PVOID
) Info
.Msg
.lParam
, Size
);
1008 if (! NT_SUCCESS(Status
))
1010 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &UserMem
,
1011 &Info
.LParamSize
, MEM_DECOMMIT
);
1012 SetLastNtError(Status
);
1015 Info
.Msg
.lParam
= (LPARAM
) UserMem
;
1017 if (Msg
.FreeLParam
&& 0 != Msg
.Msg
.lParam
)
1019 ExFreePool((void *) Msg
.Msg
.lParam
);
1021 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERGETMESSAGEINFO
));
1022 if (! NT_SUCCESS(Status
))
1024 SetLastNtError(Status
);
1028 else if (! co_IntWaitMessage(Wnd
, MsgFilterMin
, MsgFilterMax
))
1033 while (! GotMessage
);
1035 RETURN( WM_QUIT
!= Info
.Msg
.message
);
1038 DPRINT("Leave NtUserGetMessage\n");
1059 static NTSTATUS FASTCALL
1060 CopyMsgToKernelMem(MSG
*KernelModeMsg
, MSG
*UserModeMsg
, PMSGMEMORY MsgMemoryEntry
)
1067 *KernelModeMsg
= *UserModeMsg
;
1069 /* See if this message type is present in the table */
1070 if (NULL
== MsgMemoryEntry
)
1072 /* Not present, no copying needed */
1073 return STATUS_SUCCESS
;
1076 /* Determine required size */
1077 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
1081 /* Allocate kernel mem */
1082 KernelMem
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
1083 if (NULL
== KernelMem
)
1085 DPRINT1("Not enough memory to copy message to kernel mem\n");
1086 return STATUS_NO_MEMORY
;
1088 KernelModeMsg
->lParam
= (LPARAM
) KernelMem
;
1090 /* Copy data if required */
1091 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_READ
))
1093 Status
= MmCopyFromCaller(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
1094 if (! NT_SUCCESS(Status
))
1096 DPRINT1("Failed to copy message to kernel: invalid usermode buffer\n");
1097 ExFreePool(KernelMem
);
1103 /* Make sure we don't pass any secrets to usermode */
1104 RtlZeroMemory(KernelMem
, Size
);
1109 KernelModeMsg
->lParam
= 0;
1112 return STATUS_SUCCESS
;
1115 static NTSTATUS FASTCALL
1116 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
1119 PMSGMEMORY MsgMemoryEntry
;
1122 /* See if this message type is present in the table */
1123 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
1124 if (NULL
== MsgMemoryEntry
)
1126 /* Not present, no copying needed */
1127 return STATUS_SUCCESS
;
1130 /* Determine required size */
1131 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
1135 /* Copy data if required */
1136 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
1138 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
1139 if (! NT_SUCCESS(Status
))
1141 DPRINT1("Failed to copy message from kernel: invalid usermode buffer\n");
1142 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
1147 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
1150 return STATUS_SUCCESS
;
1154 UserPostMessage(HWND Wnd
,
1159 PWINDOW_OBJECT Window
;
1160 MSG UserModeMsg
, KernelModeMsg
;
1161 LARGE_INTEGER LargeTickCount
;
1163 PMSGMEMORY MsgMemoryEntry
;
1167 MsqPostQuitMessage(PsGetWin32Thread()->MessageQueue
, wParam
);
1169 else if (Wnd
== HWND_BROADCAST
)
1172 PWINDOW_OBJECT DesktopWindow
;
1175 DesktopWindow
= IntGetWindowObject(IntGetDesktopWindow());
1176 List
= IntWinListChildren(DesktopWindow
);
1177 IntReleaseWindowObject(DesktopWindow
);
1180 for (i
= 0; List
[i
]; i
++)
1181 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1187 Window
= IntGetWindowObject(Wnd
);
1190 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1193 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
1195 IntReleaseWindowObject(Window
);
1196 DPRINT1("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd
);
1197 /* FIXME - last error code? */
1201 UserModeMsg
.hwnd
= Wnd
;
1202 UserModeMsg
.message
= Msg
;
1203 UserModeMsg
.wParam
= wParam
;
1204 UserModeMsg
.lParam
= lParam
;
1205 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1206 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1207 if (! NT_SUCCESS(Status
))
1209 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1212 IntGetCursorLocation(PsGetWin32Thread()->Desktop
->WindowStation
,
1214 KeQueryTickCount(&LargeTickCount
);
1215 KernelModeMsg
.time
= LargeTickCount
.u
.LowPart
;
1216 MsqPostMessage(Window
->MessageQueue
, &KernelModeMsg
,
1217 NULL
!= MsgMemoryEntry
&& 0 != KernelModeMsg
.lParam
,
1219 IntReleaseWindowObject(Window
);
1227 NtUserPostMessage(HWND hWnd
,
1232 DECLARE_RETURN(BOOL
);
1234 DPRINT("Enter NtUserPostMessage\n");
1235 UserEnterExclusive();
1237 RETURN(UserPostMessage(hWnd
, Msg
, wParam
, lParam
));
1240 DPRINT("Leave NtUserPostMessage, ret=%i\n",_ret_
);
1248 NtUserPostThreadMessage(DWORD idThread
,
1253 MSG UserModeMsg
, KernelModeMsg
;
1257 PMSGMEMORY MsgMemoryEntry
;
1258 DECLARE_RETURN(BOOL
);
1260 DPRINT("Enter NtUserPostThreadMessage\n");
1261 UserEnterExclusive();
1263 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
1265 if( Status
== STATUS_SUCCESS
) {
1266 pThread
= peThread
->Tcb
.Win32Thread
;
1267 if( !pThread
|| !pThread
->MessageQueue
)
1269 ObDereferenceObject( peThread
);
1273 UserModeMsg
.hwnd
= NULL
;
1274 UserModeMsg
.message
= Msg
;
1275 UserModeMsg
.wParam
= wParam
;
1276 UserModeMsg
.lParam
= lParam
;
1277 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1278 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1279 if (! NT_SUCCESS(Status
))
1281 ObDereferenceObject( peThread
);
1282 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1285 MsqPostMessage(pThread
->MessageQueue
, &KernelModeMsg
,
1286 NULL
!= MsgMemoryEntry
&& 0 != KernelModeMsg
.lParam
,
1288 ObDereferenceObject( peThread
);
1291 SetLastNtError( Status
);
1296 DPRINT("Leave NtUserPostThreadMessage, ret=%i\n",_ret_
);
1302 NtUserQuerySendMessage(DWORD Unknown0
)
1310 co_IntSendMessage(HWND hWnd
,
1315 ULONG_PTR Result
= 0;
1316 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1318 return (LRESULT
)Result
;
1323 static LRESULT FASTCALL
1324 co_IntSendMessageTimeoutSingle(HWND hWnd
,
1334 PWINDOW_OBJECT Window
;
1335 PMSGMEMORY MsgMemoryEntry
;
1336 INT lParamBufferSize
;
1337 LPARAM lParamPacked
;
1338 PW32THREAD Win32Thread
;
1340 /* FIXME: Call hooks. */
1341 Window
= IntGetWindowObject(hWnd
);
1344 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1348 Win32Thread
= PsGetWin32Thread();
1350 if (NULL
!= Win32Thread
&&
1351 Window
->MessageQueue
== Win32Thread
->MessageQueue
)
1353 if (Win32Thread
->IsExiting
)
1355 /* Never send messages to exiting threads */
1356 IntReleaseWindowObject(Window
);
1360 /* See if this message type is present in the table */
1361 MsgMemoryEntry
= FindMsgMemory(Msg
);
1362 if (NULL
== MsgMemoryEntry
)
1364 lParamBufferSize
= -1;
1368 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1371 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
)))
1373 IntReleaseWindowObject(Window
);
1374 DPRINT1("Failed to pack message parameters\n");
1377 if (0xFFFF0000 != ((DWORD
) Window
->WndProcW
& 0xFFFF0000))
1379 Result
= (ULONG_PTR
)co_IntCallWindowProc(Window
->WndProcW
, FALSE
, hWnd
, Msg
, wParam
,
1380 lParamPacked
,lParamBufferSize
);
1384 Result
= (ULONG_PTR
)co_IntCallWindowProc(Window
->WndProcA
, TRUE
, hWnd
, Msg
, wParam
,
1385 lParamPacked
,lParamBufferSize
);
1393 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
)))
1395 IntReleaseWindowObject(Window
);
1396 DPRINT1("Failed to unpack message parameters\n");
1400 IntReleaseWindowObject(Window
);
1404 if(uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->MessageQueue
))
1406 IntReleaseWindowObject(Window
);
1407 /* FIXME - Set a LastError? */
1411 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
1413 IntReleaseWindowObject(Window
);
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
);
1421 IntReleaseWindowObject(Window
);
1422 if (STATUS_TIMEOUT
== Status
)
1424 /* MSDN says GetLastError() should return 0 after timeout */
1425 SetLastWin32Error(0);
1428 else if (! NT_SUCCESS(Status
))
1430 SetLastNtError(Status
);
1438 co_IntSendMessageTimeout(HWND hWnd
,
1446 PWINDOW_OBJECT DesktopWindow
;
1450 if (HWND_BROADCAST
!= hWnd
)
1452 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1455 DesktopWindow
= IntGetWindowObject(IntGetDesktopWindow());
1456 if (NULL
== DesktopWindow
)
1458 SetLastWin32Error(ERROR_INTERNAL_ERROR
);
1461 Children
= IntWinListChildren(DesktopWindow
);
1462 IntReleaseWindowObject(DesktopWindow
);
1463 if (NULL
== Children
)
1468 for (Child
= Children
; NULL
!= *Child
; Child
++)
1470 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1473 ExFreePool(Children
);
1475 return (LRESULT
) TRUE
;
1479 /* This function posts a message if the destination's message queue belongs to
1480 another thread, otherwise it sends the message. It does not support broadcast
1483 co_IntPostOrSendMessage(HWND hWnd
,
1489 PWINDOW_OBJECT Window
;
1491 if(hWnd
== HWND_BROADCAST
)
1496 Window
= IntGetWindowObject(hWnd
);
1499 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1503 if(Window
->MessageQueue
!= PsGetWin32Thread()->MessageQueue
)
1505 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1509 if(!co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1515 IntReleaseWindowObject(Window
);
1517 return (LRESULT
)Result
;
1521 co_IntDoSendMessage(HWND Wnd
,
1526 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1528 LRESULT Result
= TRUE
;
1530 PWINDOW_OBJECT Window
;
1531 NTUSERSENDMESSAGEINFO Info
;
1534 PMSGMEMORY MsgMemoryEntry
;
1536 RtlZeroMemory(&Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1538 /* FIXME: Call hooks. */
1539 if (HWND_BROADCAST
!= Wnd
)
1541 Window
= IntGetWindowObject(Wnd
);
1544 /* Tell usermode to not touch this one */
1545 Info
.HandledByKernel
= TRUE
;
1546 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1547 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
1552 /* FIXME: Check for an exiting window. */
1554 /* See if the current thread can handle the message */
1555 if (HWND_BROADCAST
!= Wnd
&& NULL
!= PsGetWin32Thread() &&
1556 Window
->MessageQueue
== PsGetWin32Thread()->MessageQueue
)
1558 /* Gather the information usermode needs to call the window proc directly */
1559 Info
.HandledByKernel
= FALSE
;
1560 if (0xFFFF0000 != ((DWORD
) Window
->WndProcW
& 0xFFFF0000))
1562 if (0xFFFF0000 != ((DWORD
) Window
->WndProcA
& 0xFFFF0000))
1564 /* Both Unicode and Ansi winprocs are real, see what usermode prefers */
1565 Status
= MmCopyFromCaller(&(Info
.Ansi
), &(UnsafeInfo
->Ansi
),
1567 if (! NT_SUCCESS(Status
))
1569 Info
.Ansi
= ! Window
->Unicode
;
1571 Info
.Proc
= (Info
.Ansi
? Window
->WndProcA
: Window
->WndProcW
);
1575 /* Real Unicode winproc */
1577 Info
.Proc
= Window
->WndProcW
;
1582 /* Must have real Ansi winproc */
1584 Info
.Proc
= Window
->WndProcA
;
1586 IntReleaseWindowObject(Window
);
1590 /* Must be handled by other thread */
1591 if (HWND_BROADCAST
!= Wnd
)
1593 IntReleaseWindowObject(Window
);
1595 Info
.HandledByKernel
= TRUE
;
1596 UserModeMsg
.hwnd
= Wnd
;
1597 UserModeMsg
.message
= Msg
;
1598 UserModeMsg
.wParam
= wParam
;
1599 UserModeMsg
.lParam
= lParam
;
1600 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1601 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1602 if (! NT_SUCCESS(Status
))
1604 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1605 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1606 return (dsm
? 0 : -1);
1610 Result
= co_IntSendMessage(KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1611 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
);
1615 Result
= co_IntSendMessageTimeout(KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1616 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
,
1617 dsm
->uFlags
, dsm
->uTimeout
, &dsm
->Result
);
1619 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1620 if (! NT_SUCCESS(Status
))
1622 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1623 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1624 return(dsm
? 0 : -1);
1628 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1629 if (! NT_SUCCESS(Status
))
1631 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1634 return (LRESULT
)Result
;
1638 NtUserSendMessageTimeout(HWND hWnd
,
1645 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1649 DECLARE_RETURN(BOOL
);
1651 DPRINT("Enter NtUserSendMessageTimeout\n");
1652 UserEnterExclusive();
1654 dsm
.uFlags
= uFlags
;
1655 dsm
.uTimeout
= uTimeout
;
1656 Result
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, &dsm
, UnsafeInfo
);
1657 if(uResult
!= NULL
&& Result
!= 0)
1661 Status
= MmCopyToCaller(uResult
, &dsm
.Result
, sizeof(ULONG_PTR
));
1662 if(!NT_SUCCESS(Status
))
1664 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1671 DPRINT("Leave NtUserSendMessageTimeout, ret=%i\n",_ret_
);
1677 NtUserSendMessage(HWND Wnd
,
1681 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1683 DECLARE_RETURN(BOOL
);
1685 DPRINT("Enter NtUserSendMessage\n");
1686 UserEnterExclusive();
1688 RETURN(co_IntDoSendMessage(Wnd
, Msg
, wParam
, lParam
, NULL
, UnsafeInfo
));
1691 DPRINT("Leave NtUserSendMessage, ret=%i\n",_ret_
);
1697 NtUserSendMessageCallback(HWND hWnd
,
1701 SENDASYNCPROC lpCallBack
,
1710 NtUserSendNotifyMessage(HWND hWnd
,
1721 NtUserWaitMessage(VOID
)
1723 DECLARE_RETURN(BOOL
);
1725 DPRINT("EnterNtUserWaitMessage\n");
1726 UserEnterExclusive();
1728 RETURN(co_IntWaitMessage(NULL
, 0, 0));
1731 DPRINT("Leave NtUserWaitMessage, ret=%i\n",_ret_
);
1737 NtUserGetQueueStatus(BOOL ClearChanges
)
1739 PUSER_MESSAGE_QUEUE Queue
;
1741 DECLARE_RETURN(DWORD
);
1743 DPRINT("Enter NtUserGetQueueStatus\n");
1744 UserEnterExclusive();
1746 Queue
= PsGetWin32Thread()->MessageQueue
;
1748 IntLockMessageQueue(Queue
);
1750 Result
= MAKELONG(Queue
->QueueBits
, Queue
->ChangedBits
);
1753 Queue
->ChangedBits
= 0;
1756 IntUnLockMessageQueue(Queue
);
1761 DPRINT("Leave NtUserGetQueueStatus, ret=%i\n",_ret_
);
1767 IntInitMessagePumpHook()
1769 PsGetCurrentThread()->Tcb
.Win32Thread
->MessagePumpHookValue
++;
1774 IntUninitMessagePumpHook()
1776 if (PsGetCurrentThread()->Tcb
.Win32Thread
->MessagePumpHookValue
<= 0)
1780 PsGetCurrentThread()->Tcb
.Win32Thread
->MessagePumpHookValue
--;