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.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
23 * FILE: subsys/win32k/ntuser/message.c
24 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * 06-06-2001 CSH Created
29 /* 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
71 MSGMEMORY
, *PMSGMEMORY
;
73 static MSGMEMORY MsgMemory
[] =
75 { WM_CREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
76 { WM_DDE_ACK
, sizeof(KMDDELPARAM
), MMS_FLAG_READ
},
77 { WM_DDE_EXECUTE
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
78 { WM_GETMINMAXINFO
, sizeof(MINMAXINFO
), MMS_FLAG_READWRITE
},
79 { WM_GETTEXT
, MMS_SIZE_WPARAMWCHAR
, MMS_FLAG_WRITE
},
80 { WM_NCCALCSIZE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
81 { WM_NCCREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
82 { WM_SETTEXT
, MMS_SIZE_LPARAMSZ
, MMS_FLAG_READ
},
83 { WM_STYLECHANGED
, sizeof(STYLESTRUCT
), MMS_FLAG_READ
},
84 { WM_STYLECHANGING
, sizeof(STYLESTRUCT
), MMS_FLAG_READWRITE
},
85 { WM_COPYDATA
, MMS_SIZE_SPECIAL
, MMS_FLAG_READ
},
86 { WM_WINDOWPOSCHANGED
, sizeof(WINDOWPOS
), MMS_FLAG_READ
},
87 { WM_WINDOWPOSCHANGING
, sizeof(WINDOWPOS
), MMS_FLAG_READWRITE
},
90 static PMSGMEMORY FASTCALL
91 FindMsgMemory(UINT Msg
)
93 PMSGMEMORY MsgMemoryEntry
;
95 /* See if this message type is present in the table */
96 for (MsgMemoryEntry
= MsgMemory
;
97 MsgMemoryEntry
< MsgMemory
+ sizeof(MsgMemory
) / sizeof(MSGMEMORY
);
100 if (Msg
== MsgMemoryEntry
->Message
)
102 return MsgMemoryEntry
;
110 MsgMemorySize(PMSGMEMORY MsgMemoryEntry
, WPARAM wParam
, LPARAM lParam
)
113 PUNICODE_STRING WindowName
;
114 PUNICODE_STRING ClassName
;
119 if (MMS_SIZE_WPARAM
== MsgMemoryEntry
->Size
)
123 else if (MMS_SIZE_WPARAMWCHAR
== MsgMemoryEntry
->Size
)
125 Size
= (UINT
) (wParam
* sizeof(WCHAR
));
127 else if (MMS_SIZE_LPARAMSZ
== MsgMemoryEntry
->Size
)
129 Size
= (UINT
) ((wcslen((PWSTR
) lParam
) + 1) * sizeof(WCHAR
));
131 else if (MMS_SIZE_SPECIAL
== MsgMemoryEntry
->Size
)
133 switch(MsgMemoryEntry
->Message
)
137 Cs
= (CREATESTRUCTW
*) lParam
;
138 WindowName
= (PUNICODE_STRING
) Cs
->lpszName
;
139 ClassName
= (PUNICODE_STRING
) Cs
->lpszClass
;
140 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
141 if (IS_ATOM(ClassName
->Buffer
))
143 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
147 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
152 Size
= wParam
? sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
) : sizeof(RECT
);
156 Size
= sizeof(COPYDATASTRUCT
) + ((PCOPYDATASTRUCT
)lParam
)->cbData
;
167 Size
= MsgMemoryEntry
->Size
;
172 DPRINT1("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH_GetExceptionCode());
180 PackParam(LPARAM
*lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
182 NCCALCSIZE_PARAMS
*UnpackedNcCalcsize
;
183 NCCALCSIZE_PARAMS
*PackedNcCalcsize
;
184 CREATESTRUCTW
*UnpackedCs
;
185 CREATESTRUCTW
*PackedCs
;
186 PUNICODE_STRING WindowName
;
187 PUNICODE_STRING ClassName
;
191 *lParamPacked
= lParam
;
192 if (WM_NCCALCSIZE
== Msg
&& wParam
)
194 UnpackedNcCalcsize
= (NCCALCSIZE_PARAMS
*) lParam
;
195 if (UnpackedNcCalcsize
->lppos
!= (PWINDOWPOS
) (UnpackedNcCalcsize
+ 1))
197 PackedNcCalcsize
= ExAllocatePoolWithTag(PagedPool
,
198 sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
),
200 if (NULL
== PackedNcCalcsize
)
202 DPRINT1("Not enough memory to pack lParam\n");
203 return STATUS_NO_MEMORY
;
205 RtlCopyMemory(PackedNcCalcsize
, UnpackedNcCalcsize
, sizeof(NCCALCSIZE_PARAMS
));
206 PackedNcCalcsize
->lppos
= (PWINDOWPOS
) (PackedNcCalcsize
+ 1);
207 RtlCopyMemory(PackedNcCalcsize
->lppos
, UnpackedNcCalcsize
->lppos
, sizeof(WINDOWPOS
));
208 *lParamPacked
= (LPARAM
) PackedNcCalcsize
;
211 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
213 UnpackedCs
= (CREATESTRUCTW
*) lParam
;
214 WindowName
= (PUNICODE_STRING
) UnpackedCs
->lpszName
;
215 ClassName
= (PUNICODE_STRING
) UnpackedCs
->lpszClass
;
216 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
217 if (IS_ATOM(ClassName
->Buffer
))
219 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
223 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
225 PackedCs
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
226 if (NULL
== PackedCs
)
228 DPRINT1("Not enough memory to pack lParam\n");
229 return STATUS_NO_MEMORY
;
231 RtlCopyMemory(PackedCs
, UnpackedCs
, sizeof(CREATESTRUCTW
));
232 CsData
= (PCHAR
) (PackedCs
+ 1);
233 PackedCs
->lpszName
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
234 RtlCopyMemory(CsData
, WindowName
->Buffer
, WindowName
->Length
);
235 CsData
+= WindowName
->Length
;
236 *((WCHAR
*) CsData
) = L
'\0';
237 CsData
+= sizeof(WCHAR
);
238 PackedCs
->lpszClass
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
239 if (IS_ATOM(ClassName
->Buffer
))
241 *((WCHAR
*) CsData
) = L
'A';
242 CsData
+= sizeof(WCHAR
);
243 *((ATOM
*) CsData
) = (ATOM
)(DWORD_PTR
) ClassName
->Buffer
;
244 CsData
+= sizeof(ATOM
);
248 *((WCHAR
*) CsData
) = L
'S';
249 CsData
+= sizeof(WCHAR
);
250 RtlCopyMemory(CsData
, ClassName
->Buffer
, ClassName
->Length
);
251 CsData
+= ClassName
->Length
;
252 *((WCHAR
*) CsData
) = L
'\0';
253 CsData
+= sizeof(WCHAR
);
255 ASSERT(CsData
== (PCHAR
) PackedCs
+ Size
);
256 *lParamPacked
= (LPARAM
) PackedCs
;
259 return STATUS_SUCCESS
;
263 UnpackParam(LPARAM lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
265 NCCALCSIZE_PARAMS
*UnpackedParams
;
266 NCCALCSIZE_PARAMS
*PackedParams
;
267 PWINDOWPOS UnpackedWindowPos
;
269 if (lParamPacked
== lParam
)
271 return STATUS_SUCCESS
;
274 if (WM_NCCALCSIZE
== Msg
&& wParam
)
276 PackedParams
= (NCCALCSIZE_PARAMS
*) lParamPacked
;
277 UnpackedParams
= (NCCALCSIZE_PARAMS
*) lParam
;
278 UnpackedWindowPos
= UnpackedParams
->lppos
;
279 RtlCopyMemory(UnpackedParams
, PackedParams
, sizeof(NCCALCSIZE_PARAMS
));
280 UnpackedParams
->lppos
= UnpackedWindowPos
;
281 RtlCopyMemory(UnpackedWindowPos
, PackedParams
+ 1, sizeof(WINDOWPOS
));
282 ExFreePool((PVOID
) lParamPacked
);
284 return STATUS_SUCCESS
;
286 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
288 ExFreePool((PVOID
) lParamPacked
);
290 return STATUS_SUCCESS
;
295 return STATUS_INVALID_PARAMETER
;
304 DECLARE_RETURN(BOOL
);
306 DPRINT("Enter NtUserCallMsgFilter\n");
307 UserEnterExclusive();
309 if (co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)msg
))
311 RETURN( co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)msg
));
314 DPRINT("Leave NtUserCallMsgFilter. ret=%i\n", _ret_
);
320 NtUserDispatchMessage(PNTUSERDISPATCHMESSAGEINFO UnsafeMsgInfo
)
323 NTUSERDISPATCHMESSAGEINFO MsgInfo
;
324 LRESULT Result
= TRUE
;
325 DECLARE_RETURN(LRESULT
);
327 DPRINT("Enter NtUserDispatchMessage\n");
328 UserEnterExclusive();
330 Status
= MmCopyFromCaller(&MsgInfo
, UnsafeMsgInfo
, sizeof(NTUSERDISPATCHMESSAGEINFO
));
331 if (! NT_SUCCESS(Status
))
333 SetLastNtError(Status
);
337 /* Process timer messages. */
338 if (WM_TIMER
== MsgInfo
.Msg
.message
&& 0 != MsgInfo
.Msg
.lParam
)
340 LARGE_INTEGER LargeTickCount
;
341 /* FIXME: Call hooks. */
343 /* FIXME: Check for continuing validity of timer. */
345 MsgInfo
.HandledByKernel
= FALSE
;
346 KeQueryTickCount(&LargeTickCount
);
347 MsgInfo
.Proc
= (WNDPROC
) MsgInfo
.Msg
.lParam
;
348 MsgInfo
.Msg
.lParam
= (LPARAM
)LargeTickCount
.u
.LowPart
;
350 else if (NULL
== MsgInfo
.Msg
.hwnd
)
352 MsgInfo
.HandledByKernel
= TRUE
;
357 PWINDOW_OBJECT Window
;
359 /* Get the window object. */
360 Window
= UserGetWindowObject(MsgInfo
.Msg
.hwnd
);
363 MsgInfo
.HandledByKernel
= TRUE
;
368 if (Window
->OwnerThread
!= PsGetCurrentThread())
370 DPRINT1("Window doesn't belong to the calling thread!\n");
371 MsgInfo
.HandledByKernel
= TRUE
;
376 /* FIXME: Call hook procedures. */
378 MsgInfo
.HandledByKernel
= FALSE
;
381 if (Window
->Wnd
->IsSystem
)
383 MsgInfo
.Proc
= (!MsgInfo
.Ansi
? Window
->Wnd
->WndProc
: Window
->Wnd
->WndProcExtra
);
387 MsgInfo
.Ansi
= !Window
->Wnd
->Unicode
;
388 MsgInfo
.Proc
= Window
->Wnd
->WndProc
;
393 Status
= MmCopyToCaller(UnsafeMsgInfo
, &MsgInfo
, sizeof(NTUSERDISPATCHMESSAGEINFO
));
394 if (! NT_SUCCESS(Status
))
396 SetLastNtError(Status
);
403 DPRINT("Leave NtUserDispatchMessage. ret=%i\n", _ret_
);
410 NtUserTranslateMessage(LPMSG lpMsg
,
415 DECLARE_RETURN(BOOL
);
417 DPRINT("Enter NtUserTranslateMessage\n");
418 UserEnterExclusive();
420 Status
= MmCopyFromCaller(&SafeMsg
, lpMsg
, sizeof(MSG
));
421 if(!NT_SUCCESS(Status
))
423 SetLastNtError(Status
);
427 RETURN( IntTranslateKbdMessage(&SafeMsg
, dwhkl
));
430 DPRINT("Leave NtUserTranslateMessage: ret=%i\n",_ret_
);
437 co_IntSendHitTestMessages(PUSER_MESSAGE_QUEUE ThreadQueue
, LPMSG Msg
)
439 if(!Msg
->hwnd
|| ThreadQueue
->CaptureWindow
)
448 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(HTCLIENT
, Msg
->message
));
453 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(Msg
->wParam
, Msg
->message
));
460 case WM_LBUTTONDBLCLK
:
461 case WM_MBUTTONDBLCLK
:
462 case WM_RBUTTONDBLCLK
:
463 case WM_XBUTTONDBLCLK
:
466 PSYSTEM_CURSORINFO CurInfo
;
468 if(!IntGetWindowStationObject(InputWindowStation
))
472 CurInfo
= IntGetSysCursorInfo(InputWindowStation
);
473 wParam
= (WPARAM
)(CurInfo
->ButtonsDown
);
474 ObDereferenceObject(InputWindowStation
);
476 co_IntSendMessage(Msg
->hwnd
, WM_MOUSEMOVE
, wParam
, Msg
->lParam
);
477 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(HTCLIENT
, Msg
->message
));
480 case WM_NCLBUTTONDOWN
:
481 case WM_NCMBUTTONDOWN
:
482 case WM_NCRBUTTONDOWN
:
483 case WM_NCXBUTTONDOWN
:
484 case WM_NCLBUTTONDBLCLK
:
485 case WM_NCMBUTTONDBLCLK
:
486 case WM_NCRBUTTONDBLCLK
:
487 case WM_NCXBUTTONDBLCLK
:
489 co_IntSendMessage(Msg
->hwnd
, WM_NCMOUSEMOVE
, (WPARAM
)Msg
->wParam
, Msg
->lParam
);
490 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(Msg
->wParam
, Msg
->message
));
497 co_IntActivateWindowMouse(PUSER_MESSAGE_QUEUE ThreadQueue
, LPMSG Msg
, PWINDOW_OBJECT MsgWindow
,
501 PWINDOW_OBJECT Parent
;
503 ASSERT_REFS_CO(MsgWindow
);
505 if(*HitTest
== (USHORT
)HTTRANSPARENT
)
507 /* eat the message, search again! */
511 Parent
= IntGetParent(MsgWindow
);//fixme: deref retval?
512 /* fixme: abort if no parent ? */
513 Result
= co_IntSendMessage(MsgWindow
->hSelf
,
515 (WPARAM
) (Parent
? Parent
->hSelf
: NULL
),
516 (LPARAM
)MAKELONG(*HitTest
, Msg
->message
)
521 case MA_NOACTIVATEANDEAT
:
525 case MA_ACTIVATEANDEAT
:
526 co_IntMouseActivateWindow(MsgWindow
);
530 co_IntMouseActivateWindow(MsgWindow
);
538 co_IntTranslateMouseMessage(PUSER_MESSAGE_QUEUE ThreadQueue
, LPMSG Msg
, USHORT
*HitTest
, BOOL Remove
)
540 PWINDOW_OBJECT Window
;
541 USER_REFERENCE_ENTRY Ref
, DesktopRef
;
543 if(!(Window
= UserGetWindowObject(Msg
->hwnd
)))
545 /* let's just eat the message?! */
549 UserRefObjectCo(Window
, &Ref
);
551 if(ThreadQueue
== Window
->MessageQueue
&&
552 ThreadQueue
->CaptureWindow
!= Window
->hSelf
)
554 /* only send WM_NCHITTEST messages if we're not capturing the window! */
555 *HitTest
= co_IntSendMessage(Window
->hSelf
, WM_NCHITTEST
, 0,
556 MAKELONG(Msg
->pt
.x
, Msg
->pt
.y
));
558 if(*HitTest
== (USHORT
)HTTRANSPARENT
)
560 PWINDOW_OBJECT DesktopWindow
;
561 HWND hDesktop
= IntGetDesktopWindow();
563 if((DesktopWindow
= UserGetWindowObject(hDesktop
)))
567 UserRefObjectCo(DesktopWindow
, &DesktopRef
);
569 co_WinPosWindowFromPoint(DesktopWindow
, Window
->MessageQueue
, &Msg
->pt
, &Wnd
);
574 /* post the message to the other window */
575 Msg
->hwnd
= Wnd
->hSelf
;
576 if(!(Wnd
->Status
& WINDOWSTATUS_DESTROYING
))
578 MsqPostMessage(Wnd
->MessageQueue
, Msg
, FALSE
,
579 Msg
->message
== WM_MOUSEMOVE
? QS_MOUSEMOVE
:
583 /* eat the message */
584 UserDereferenceObject(Wnd
);
585 UserDerefObjectCo(DesktopWindow
);
586 UserDerefObjectCo(Window
);
589 UserDereferenceObject(Wnd
);
592 UserDerefObjectCo(DesktopWindow
);
601 if(IS_BTN_MESSAGE(Msg
->message
, DOWN
))
603 /* generate double click messages, if necessary */
604 if ((((*HitTest
) != HTCLIENT
) ||
605 (Window
->Wnd
->Class
->Style
& CS_DBLCLKS
)) &&
606 MsqIsDblClk(Msg
, Remove
))
608 Msg
->message
+= WM_LBUTTONDBLCLK
- WM_LBUTTONDOWN
;
612 if(Msg
->message
!= WM_MOUSEWHEEL
)
615 if ((*HitTest
) != HTCLIENT
)
617 Msg
->message
+= WM_NCMOUSEMOVE
- WM_MOUSEMOVE
;
618 if((Msg
->message
== WM_NCRBUTTONUP
) &&
619 (((*HitTest
) == HTCAPTION
) || ((*HitTest
) == HTSYSMENU
)))
621 Msg
->message
= WM_CONTEXTMENU
;
622 Msg
->wParam
= (WPARAM
)Window
->hSelf
;
626 Msg
->wParam
= *HitTest
;
628 Msg
->lParam
= MAKELONG(Msg
->pt
.x
, Msg
->pt
.y
);
630 else if(ThreadQueue
->MoveSize
== NULL
&&
631 ThreadQueue
->MenuOwner
== NULL
)
633 /* NOTE: Msg->pt should remain in screen coordinates. -- FiN */
634 Msg
->lParam
= MAKELONG(
635 Msg
->pt
.x
- (WORD
)Window
->Wnd
->ClientRect
.left
,
636 Msg
->pt
.y
- (WORD
)Window
->Wnd
->ClientRect
.top
);
640 UserDerefObjectCo(Window
);
646 * Internal version of PeekMessage() doing all the work
649 co_IntPeekMessage(PUSER_MESSAGE Msg
,
655 LARGE_INTEGER LargeTickCount
;
656 PUSER_MESSAGE_QUEUE ThreadQueue
;
657 PUSER_MESSAGE Message
;
658 BOOL Present
, RemoveMessages
;
659 USER_REFERENCE_ENTRY Ref
;
662 /* The queues and order in which they are checked are documented in the MSDN
663 article on GetMessage() */
665 ThreadQueue
= (PUSER_MESSAGE_QUEUE
)PsGetCurrentThreadWin32Thread()->MessageQueue
;
667 /* Inspect RemoveMsg flags */
668 /* FIXME: The only flag we process is PM_REMOVE - processing of others must still be implemented */
669 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
675 KeQueryTickCount(&LargeTickCount
);
676 ThreadQueue
->LastMsgRead
= LargeTickCount
.u
.LowPart
;
678 /* Dispatch sent messages here. */
679 while (co_MsqDispatchOneSentMessage(ThreadQueue
))
682 /* Now look for a quit message. */
684 if (ThreadQueue
->QuitPosted
)
686 /* According to the PSDK, WM_QUIT messages are always returned, regardless
687 of the filter specified */
688 Msg
->Msg
.hwnd
= NULL
;
689 Msg
->Msg
.message
= WM_QUIT
;
690 Msg
->Msg
.wParam
= ThreadQueue
->QuitExitCode
;
692 Msg
->FreeLParam
= FALSE
;
695 ThreadQueue
->QuitPosted
= FALSE
;
700 /* Now check for normal messages. */
701 Present
= co_MsqFindMessage(ThreadQueue
,
710 RtlCopyMemory(Msg
, Message
, sizeof(USER_MESSAGE
));
713 MsqDestroyMessage(Message
);
718 /* Check for hardware events. */
719 Present
= co_MsqFindMessage(ThreadQueue
,
728 RtlCopyMemory(Msg
, Message
, sizeof(USER_MESSAGE
));
731 MsqDestroyMessage(Message
);
736 /* Check for sent messages again. */
737 while (co_MsqDispatchOneSentMessage(ThreadQueue
))
740 /* Check for paint messages. */
741 if (IntGetPaintMessage(hWnd
, MsgFilterMin
, MsgFilterMax
, PsGetCurrentThreadWin32Thread(), &Msg
->Msg
, RemoveMessages
))
743 Msg
->FreeLParam
= FALSE
;
747 /* Check for WM_(SYS)TIMER messages */
748 Present
= MsqGetTimerMessage(ThreadQueue
, hWnd
, MsgFilterMin
, MsgFilterMax
,
749 &Msg
->Msg
, RemoveMessages
);
752 Msg
->FreeLParam
= FALSE
;
762 PWINDOW_OBJECT MsgWindow
= NULL
;
764 if(Msg
->Msg
.hwnd
&& (MsgWindow
= UserGetWindowObject(Msg
->Msg
.hwnd
)) &&
765 Msg
->Msg
.message
>= WM_MOUSEFIRST
&& Msg
->Msg
.message
<= WM_MOUSELAST
)
769 UserRefObjectCo(MsgWindow
, &Ref
);
771 if(co_IntTranslateMouseMessage(ThreadQueue
, &Msg
->Msg
, &HitTest
, TRUE
))
772 /* FIXME - check message filter again, if the message doesn't match anymore,
775 UserDerefObjectCo(MsgWindow
);
776 /* eat the message, search again */
780 if(ThreadQueue
->CaptureWindow
== NULL
)
782 co_IntSendHitTestMessages(ThreadQueue
, &Msg
->Msg
);
783 if((Msg
->Msg
.message
!= WM_MOUSEMOVE
&& Msg
->Msg
.message
!= WM_NCMOUSEMOVE
) &&
784 IS_BTN_MESSAGE(Msg
->Msg
.message
, DOWN
) &&
785 co_IntActivateWindowMouse(ThreadQueue
, &Msg
->Msg
, MsgWindow
, &HitTest
))
787 UserDerefObjectCo(MsgWindow
);
788 /* eat the message, search again */
793 UserDerefObjectCo(MsgWindow
);
797 co_IntSendHitTestMessages(ThreadQueue
, &Msg
->Msg
);
802 // UserDereferenceObject(MsgWindow);
808 if((Msg
->Msg
.hwnd
&& Msg
->Msg
.message
>= WM_MOUSEFIRST
&& Msg
->Msg
.message
<= WM_MOUSELAST
) &&
809 co_IntTranslateMouseMessage(ThreadQueue
, &Msg
->Msg
, &HitTest
, FALSE
))
810 /* FIXME - check message filter again, if the message doesn't match anymore,
813 /* eat the message, search again */
817 // The WH_GETMESSAGE hook enables an application to monitor messages about to
818 // be returned by the GetMessage or PeekMessage function.
819 if(ISITHOOKED(WH_GETMESSAGE
))
821 DPRINT1("Peek WH_GETMESSAGE -> %x\n",&Msg
);
822 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)&Msg
);
831 NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo
,
839 NTUSERGETMESSAGEINFO Info
;
840 PWINDOW_OBJECT Window
;
841 PMSGMEMORY MsgMemoryEntry
;
845 DECLARE_RETURN(BOOL
);
847 DPRINT("Enter NtUserPeekMessage\n");
848 UserEnterExclusive();
851 if (hWnd
&& hWnd
!= INVALID_HANDLE_VALUE
)
853 if (!(Window
= UserGetWindowObject(hWnd
)))
859 if (MsgFilterMax
< MsgFilterMin
)
865 Present
= co_IntPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
);
871 /* See if this message type is present in the table */
872 MsgMemoryEntry
= FindMsgMemory(Info
.Msg
.message
);
873 if (NULL
== MsgMemoryEntry
)
875 /* Not present, no copying needed */
880 /* Determine required size */
881 Size
= MsgMemorySize(MsgMemoryEntry
, Info
.Msg
.wParam
,
883 /* Allocate required amount of user-mode memory */
884 Info
.LParamSize
= Size
;
886 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem
, 0,
887 &Info
.LParamSize
, MEM_COMMIT
, PAGE_READWRITE
);
888 if (! NT_SUCCESS(Status
))
890 SetLastNtError(Status
);
893 /* Transfer lParam data to user-mode mem */
894 Status
= MmCopyToCaller(UserMem
, (PVOID
) Info
.Msg
.lParam
, Size
);
895 if (! NT_SUCCESS(Status
))
897 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &UserMem
,
898 &Info
.LParamSize
, MEM_RELEASE
);
899 SetLastNtError(Status
);
902 Info
.Msg
.lParam
= (LPARAM
) UserMem
;
904 if (RemoveMsg
&& Msg
.FreeLParam
&& 0 != Msg
.Msg
.lParam
)
906 ExFreePool((void *) Msg
.Msg
.lParam
);
908 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERGETMESSAGEINFO
));
909 if (! NT_SUCCESS(Status
))
911 SetLastNtError(Status
);
919 DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_
);
925 co_IntWaitMessage(HWND Wnd
,
929 PUSER_MESSAGE_QUEUE ThreadQueue
;
933 ThreadQueue
= (PUSER_MESSAGE_QUEUE
)PsGetCurrentThreadWin32Thread()->MessageQueue
;
937 if (co_IntPeekMessage(&Msg
, Wnd
, MsgFilterMin
, MsgFilterMax
, PM_NOREMOVE
))
942 /* Nothing found. Wait for new messages. */
943 Status
= co_MsqWaitForNewMessages(ThreadQueue
, Wnd
, MsgFilterMin
, MsgFilterMax
);
945 while ((STATUS_WAIT_0
<= Status
&& Status
<= STATUS_WAIT_63
) || STATUS_TIMEOUT
== Status
);
947 SetLastNtError(Status
);
953 NtUserGetMessage(PNTUSERGETMESSAGEINFO UnsafeInfo
,
958 * FUNCTION: Get a message from the calling thread's message queue.
960 * UnsafeMsg - Pointer to the structure which receives the returned message.
961 * Wnd - Window whose messages are to be retrieved.
962 * MsgFilterMin - Integer value of the lowest message value to be
964 * MsgFilterMax - Integer value of the highest message value to be
969 NTUSERGETMESSAGEINFO Info
;
971 PWINDOW_OBJECT Window
= NULL
;
972 PMSGMEMORY MsgMemoryEntry
;
976 DECLARE_RETURN(BOOL
);
977 // USER_REFERENCE_ENTRY Ref;
979 DPRINT("Enter NtUserGetMessage\n");
980 UserEnterExclusive();
983 if (hWnd
&& !(Window
= UserGetWindowObject(hWnd
)))
988 // if (Window) UserRefObjectCo(Window, &Ref);
990 if (MsgFilterMax
< MsgFilterMin
)
998 GotMessage
= co_IntPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
);
1002 /* See if this message type is present in the table */
1003 MsgMemoryEntry
= FindMsgMemory(Info
.Msg
.message
);
1004 if (NULL
== MsgMemoryEntry
)
1006 /* Not present, no copying needed */
1007 Info
.LParamSize
= 0;
1011 /* Determine required size */
1012 Size
= MsgMemorySize(MsgMemoryEntry
, Info
.Msg
.wParam
,
1014 /* Allocate required amount of user-mode memory */
1015 Info
.LParamSize
= Size
;
1017 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem
, 0,
1018 &Info
.LParamSize
, MEM_COMMIT
, PAGE_READWRITE
);
1020 if (! NT_SUCCESS(Status
))
1022 SetLastNtError(Status
);
1025 /* Transfer lParam data to user-mode mem */
1026 Status
= MmCopyToCaller(UserMem
, (PVOID
) Info
.Msg
.lParam
, Size
);
1027 if (! NT_SUCCESS(Status
))
1029 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &UserMem
,
1030 &Info
.LParamSize
, MEM_DECOMMIT
);
1031 SetLastNtError(Status
);
1034 Info
.Msg
.lParam
= (LPARAM
) UserMem
;
1036 if (Msg
.FreeLParam
&& 0 != Msg
.Msg
.lParam
)
1038 ExFreePool((void *) Msg
.Msg
.lParam
);
1040 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERGETMESSAGEINFO
));
1041 if (! NT_SUCCESS(Status
))
1043 SetLastNtError(Status
);
1047 else if (! co_IntWaitMessage(hWnd
, MsgFilterMin
, MsgFilterMax
))
1052 while (! GotMessage
);
1054 RETURN( WM_QUIT
!= Info
.Msg
.message
);
1057 // if (Window) UserDerefObjectCo(Window);
1059 DPRINT("Leave NtUserGetMessage\n");
1065 static NTSTATUS FASTCALL
1066 CopyMsgToKernelMem(MSG
*KernelModeMsg
, MSG
*UserModeMsg
, PMSGMEMORY MsgMemoryEntry
)
1073 *KernelModeMsg
= *UserModeMsg
;
1075 /* See if this message type is present in the table */
1076 if (NULL
== MsgMemoryEntry
)
1078 /* Not present, no copying needed */
1079 return STATUS_SUCCESS
;
1082 /* Determine required size */
1083 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
1087 /* Allocate kernel mem */
1088 KernelMem
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
1089 if (NULL
== KernelMem
)
1091 DPRINT1("Not enough memory to copy message to kernel mem\n");
1092 return STATUS_NO_MEMORY
;
1094 KernelModeMsg
->lParam
= (LPARAM
) KernelMem
;
1096 /* Copy data if required */
1097 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_READ
))
1099 Status
= MmCopyFromCaller(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
1100 if (! NT_SUCCESS(Status
))
1102 DPRINT1("Failed to copy message to kernel: invalid usermode buffer\n");
1103 ExFreePool(KernelMem
);
1109 /* Make sure we don't pass any secrets to usermode */
1110 RtlZeroMemory(KernelMem
, Size
);
1115 KernelModeMsg
->lParam
= 0;
1118 return STATUS_SUCCESS
;
1121 static NTSTATUS FASTCALL
1122 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
1125 PMSGMEMORY MsgMemoryEntry
;
1128 /* See if this message type is present in the table */
1129 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
1130 if (NULL
== MsgMemoryEntry
)
1132 /* Not present, no copying needed */
1133 return STATUS_SUCCESS
;
1136 /* Determine required size */
1137 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
1141 /* Copy data if required */
1142 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
1144 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
1145 if (! NT_SUCCESS(Status
))
1147 DPRINT1("Failed to copy message from kernel: invalid usermode buffer\n");
1148 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
1153 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
1156 return STATUS_SUCCESS
;
1160 UserPostMessage(HWND Wnd
,
1165 MSG UserModeMsg
, KernelModeMsg
;
1166 LARGE_INTEGER LargeTickCount
;
1168 PMSGMEMORY MsgMemoryEntry
;
1172 MsqPostQuitMessage(PsGetCurrentThreadWin32Thread()->MessageQueue
, wParam
);
1174 else if (Wnd
== HWND_BROADCAST
)
1177 PWINDOW_OBJECT DesktopWindow
;
1180 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1181 List
= IntWinListChildren(DesktopWindow
);
1185 for (i
= 0; List
[i
]; i
++)
1186 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1192 PWINDOW_OBJECT Window
;
1194 Window
= UserGetWindowObject(Wnd
);
1199 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
1201 DPRINT1("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd
);
1202 /* FIXME - last error code? */
1206 UserModeMsg
.hwnd
= Wnd
;
1207 UserModeMsg
.message
= Msg
;
1208 UserModeMsg
.wParam
= wParam
;
1209 UserModeMsg
.lParam
= lParam
;
1210 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1211 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1212 if (! NT_SUCCESS(Status
))
1214 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1217 IntGetCursorLocation(PsGetCurrentThreadWin32Thread()->Desktop
->WindowStation
,
1219 KeQueryTickCount(&LargeTickCount
);
1220 KernelModeMsg
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1221 MsqPostMessage(Window
->MessageQueue
, &KernelModeMsg
,
1222 NULL
!= MsgMemoryEntry
&& 0 != KernelModeMsg
.lParam
,
1231 NtUserPostMessage(HWND hWnd
,
1236 DECLARE_RETURN(BOOL
);
1238 DPRINT("Enter NtUserPostMessage\n");
1239 UserEnterExclusive();
1241 RETURN(UserPostMessage(hWnd
, Msg
, wParam
, lParam
));
1244 DPRINT("Leave NtUserPostMessage, ret=%i\n",_ret_
);
1252 NtUserPostThreadMessage(DWORD idThread
,
1257 MSG UserModeMsg
, KernelModeMsg
;
1261 PMSGMEMORY MsgMemoryEntry
;
1262 DECLARE_RETURN(BOOL
);
1264 DPRINT("Enter NtUserPostThreadMessage\n");
1265 UserEnterExclusive();
1267 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
1269 if( Status
== STATUS_SUCCESS
)
1271 pThread
= (PW32THREAD
)peThread
->Tcb
.Win32Thread
;
1272 if( !pThread
|| !pThread
->MessageQueue
)
1274 ObDereferenceObject( peThread
);
1278 UserModeMsg
.hwnd
= NULL
;
1279 UserModeMsg
.message
= Msg
;
1280 UserModeMsg
.wParam
= wParam
;
1281 UserModeMsg
.lParam
= lParam
;
1282 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1283 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1284 if (! NT_SUCCESS(Status
))
1286 ObDereferenceObject( peThread
);
1287 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1290 MsqPostMessage(pThread
->MessageQueue
, &KernelModeMsg
,
1291 NULL
!= MsgMemoryEntry
&& 0 != KernelModeMsg
.lParam
,
1293 ObDereferenceObject( peThread
);
1298 SetLastNtError( Status
);
1303 DPRINT("Leave NtUserPostThreadMessage, ret=%i\n",_ret_
);
1309 NtUserQuerySendMessage(DWORD Unknown0
)
1317 co_IntSendMessage(HWND hWnd
,
1322 ULONG_PTR Result
= 0;
1323 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1325 return (LRESULT
)Result
;
1332 co_IntSendMessageTimeoutSingle(HWND hWnd
,
1342 PWINDOW_OBJECT Window
= NULL
;
1343 PMSGMEMORY MsgMemoryEntry
;
1344 INT lParamBufferSize
;
1345 LPARAM lParamPacked
;
1346 PW32THREAD Win32Thread
;
1347 DECLARE_RETURN(LRESULT
);
1348 USER_REFERENCE_ENTRY Ref
;
1350 /* FIXME: Call hooks. */
1351 if (!(Window
= UserGetWindowObject(hWnd
)))
1356 UserRefObjectCo(Window
, &Ref
);
1358 Win32Thread
= PsGetCurrentThreadWin32Thread();
1360 if (NULL
!= Win32Thread
&&
1361 Window
->MessageQueue
== Win32Thread
->MessageQueue
)
1363 if (Win32Thread
->IsExiting
)
1365 /* Never send messages to exiting threads */
1369 /* See if this message type is present in the table */
1370 MsgMemoryEntry
= FindMsgMemory(Msg
);
1371 if (NULL
== MsgMemoryEntry
)
1373 lParamBufferSize
= -1;
1377 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1380 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
)))
1382 DPRINT1("Failed to pack message parameters\n");
1386 Result
= (ULONG_PTR
)co_IntCallWindowProc(Window
->Wnd
->WndProc
, !Window
->Wnd
->Unicode
, hWnd
, Msg
, wParam
,
1387 lParamPacked
,lParamBufferSize
);
1394 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
)))
1396 DPRINT1("Failed to unpack message parameters\n");
1403 if(uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->MessageQueue
))
1405 /* FIXME - Set a LastError? */
1409 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
1411 /* FIXME - last error? */
1412 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1416 Status
= co_MsqSendMessage(Window
->MessageQueue
, hWnd
, Msg
, wParam
, lParam
,
1417 uTimeout
, (uFlags
& SMTO_BLOCK
), FALSE
, uResult
);
1420 if (STATUS_TIMEOUT
== Status
)
1422 /* MSDN says GetLastError() should return 0 after timeout */
1423 SetLastWin32Error(0);
1426 else if (! NT_SUCCESS(Status
))
1428 SetLastNtError(Status
);
1435 if (Window
) UserDerefObjectCo(Window
);
1440 co_IntSendMessageTimeout(HWND hWnd
,
1448 PWINDOW_OBJECT DesktopWindow
;
1452 if (HWND_BROADCAST
!= hWnd
)
1454 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1457 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1458 if (NULL
== DesktopWindow
)
1460 SetLastWin32Error(ERROR_INTERNAL_ERROR
);
1464 Children
= IntWinListChildren(DesktopWindow
);
1465 if (NULL
== Children
)
1470 for (Child
= Children
; NULL
!= *Child
; Child
++)
1472 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1475 ExFreePool(Children
);
1477 return (LRESULT
) TRUE
;
1481 /* This function posts a message if the destination's message queue belongs to
1482 another thread, otherwise it sends the message. It does not support broadcast
1485 co_IntPostOrSendMessage(HWND hWnd
,
1491 PWINDOW_OBJECT Window
;
1493 if(hWnd
== HWND_BROADCAST
)
1498 if(!(Window
= UserGetWindowObject(hWnd
)))
1503 if(Window
->MessageQueue
!= PsGetCurrentThreadWin32Thread()->MessageQueue
)
1505 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1509 if(!co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1515 return (LRESULT
)Result
;
1519 co_IntDoSendMessage(HWND hWnd
,
1524 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1526 LRESULT Result
= TRUE
;
1528 PWINDOW_OBJECT Window
;
1529 NTUSERSENDMESSAGEINFO Info
;
1532 PMSGMEMORY MsgMemoryEntry
;
1534 RtlZeroMemory(&Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1536 /* FIXME: Call hooks. */
1537 if (HWND_BROADCAST
!= hWnd
)
1539 Window
= UserGetWindowObject(hWnd
);
1542 /* Tell usermode to not touch this one */
1543 Info
.HandledByKernel
= TRUE
;
1544 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1551 /* FIXME: Check for an exiting window. */
1553 /* See if the current thread can handle the message */
1554 if (HWND_BROADCAST
!= hWnd
&& NULL
!= PsGetCurrentThreadWin32Thread() &&
1555 Window
->MessageQueue
== PsGetCurrentThreadWin32Thread()->MessageQueue
)
1557 /* Gather the information usermode needs to call the window proc directly */
1558 Info
.HandledByKernel
= FALSE
;
1560 Status
= MmCopyFromCaller(&(Info
.Ansi
), &(UnsafeInfo
->Ansi
),
1562 if (! NT_SUCCESS(Status
))
1564 Info
.Ansi
= ! Window
->Wnd
->Unicode
;
1567 if (Window
->Wnd
->IsSystem
)
1569 Info
.Proc
= (!Info
.Ansi
? Window
->Wnd
->WndProc
: Window
->Wnd
->WndProcExtra
);
1573 Info
.Ansi
= !Window
->Wnd
->Unicode
;
1574 Info
.Proc
= Window
->Wnd
->WndProc
;
1579 /* Must be handled by other thread */
1580 // if (HWND_BROADCAST != hWnd)
1582 // UserDereferenceObject(Window);
1584 Info
.HandledByKernel
= TRUE
;
1585 UserModeMsg
.hwnd
= hWnd
;
1586 UserModeMsg
.message
= Msg
;
1587 UserModeMsg
.wParam
= wParam
;
1588 UserModeMsg
.lParam
= lParam
;
1589 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1590 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1591 if (! NT_SUCCESS(Status
))
1593 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1594 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1595 return (dsm
? 0 : -1);
1599 Result
= co_IntSendMessage(KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1600 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
);
1604 Result
= co_IntSendMessageTimeout(KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1605 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
,
1606 dsm
->uFlags
, dsm
->uTimeout
, &dsm
->Result
);
1608 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1609 if (! NT_SUCCESS(Status
))
1611 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1612 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1613 return(dsm
? 0 : -1);
1617 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1618 if (! NT_SUCCESS(Status
))
1620 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1623 return (LRESULT
)Result
;
1627 NtUserSendMessageTimeout(HWND hWnd
,
1634 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1638 DECLARE_RETURN(BOOL
);
1640 DPRINT("Enter NtUserSendMessageTimeout\n");
1641 UserEnterExclusive();
1643 dsm
.uFlags
= uFlags
;
1644 dsm
.uTimeout
= uTimeout
;
1645 Result
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, &dsm
, UnsafeInfo
);
1646 if(uResult
!= NULL
&& Result
!= 0)
1650 Status
= MmCopyToCaller(uResult
, &dsm
.Result
, sizeof(ULONG_PTR
));
1651 if(!NT_SUCCESS(Status
))
1653 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1660 DPRINT("Leave NtUserSendMessageTimeout, ret=%i\n",_ret_
);
1666 NtUserSendMessage(HWND Wnd
,
1670 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1672 DECLARE_RETURN(BOOL
);
1674 DPRINT("Enter NtUserSendMessage\n");
1675 UserEnterExclusive();
1677 RETURN(co_IntDoSendMessage(Wnd
, Msg
, wParam
, lParam
, NULL
, UnsafeInfo
));
1680 DPRINT("Leave NtUserSendMessage, ret=%i\n",_ret_
);
1687 UserSendNotifyMessage(HWND hWnd
,
1693 // Basicly the same as IntPostOrSendMessage
1694 if (hWnd
== HWND_BROADCAST
) //Handle Broadcast
1697 PWINDOW_OBJECT DesktopWindow
;
1700 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1701 List
= IntWinListChildren(DesktopWindow
);
1705 for (i
= 0; List
[i
]; i
++)
1707 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1715 PWINDOW_OBJECT Window
;
1719 PMSGMEMORY MsgMemoryEntry
;
1721 if(!(Window
= UserGetWindowObject(hWnd
))) return FALSE
;
1723 if(Window
->MessageQueue
!= PsGetCurrentThreadWin32Thread()->MessageQueue
)
1724 { // Send message w/o waiting for it.
1725 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1728 { // Handle message and callback.
1729 UserModeMsg
.hwnd
= hWnd
;
1730 UserModeMsg
.message
= Msg
;
1731 UserModeMsg
.wParam
= wParam
;
1732 UserModeMsg
.lParam
= lParam
;
1733 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1734 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1735 if (! NT_SUCCESS(Status
))
1737 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1740 Result
= co_IntSendMessageTimeoutSingle(
1741 KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1742 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
,
1743 SMTO_NORMAL
, 0, &PResult
);
1745 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1746 if (! NT_SUCCESS(Status
))
1748 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1758 NtUserSendNotifyMessage(HWND hWnd
,
1763 DECLARE_RETURN(BOOL
);
1765 DPRINT("EnterNtUserSendNotifyMessage\n");
1766 UserEnterExclusive();
1768 RETURN(UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
));
1771 DPRINT("Leave NtUserSendNotifyMessage, ret=%i\n",_ret_
);
1779 NtUserWaitMessage(VOID
)
1781 DECLARE_RETURN(BOOL
);
1783 DPRINT("EnterNtUserWaitMessage\n");
1784 UserEnterExclusive();
1786 RETURN(co_IntWaitMessage(NULL
, 0, 0));
1789 DPRINT("Leave NtUserWaitMessage, ret=%i\n",_ret_
);
1795 IntGetQueueStatus(BOOL ClearChanges
)
1797 PUSER_MESSAGE_QUEUE Queue
;
1799 DECLARE_RETURN(DWORD
);
1801 DPRINT("Enter IntGetQueueStatus\n");
1803 Queue
= PsGetCurrentThreadWin32Thread()->MessageQueue
;
1805 Result
= MAKELONG(Queue
->QueueBits
, Queue
->ChangedBits
);
1808 Queue
->ChangedBits
= 0;
1814 DPRINT("Leave IntGetQueueStatus, ret=%i\n",_ret_
);
1819 IntInitMessagePumpHook()
1821 if (((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->ThreadInfo
)
1823 ((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->ThreadInfo
->ClientThreadInfo
.dwcPumpHook
++;
1830 IntUninitMessagePumpHook()
1832 if (((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->ThreadInfo
)
1834 if (((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->ThreadInfo
->ClientThreadInfo
.dwcPumpHook
<= 0)
1838 ((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->ThreadInfo
->ClientThreadInfo
.dwcPumpHook
--;
1851 ULONG_PTR ResultInfo
,
1852 DWORD dwType
, // fnID?
1855 LRESULT lResult
= 0;
1856 PWINDOW_OBJECT Window
= NULL
;
1857 USER_REFERENCE_ENTRY Ref
;
1859 UserEnterExclusive();
1861 /* Validate input */
1862 if (hWnd
&& (hWnd
!= INVALID_HANDLE_VALUE
) && !(Window
= UserGetWindowObject(hWnd
)))
1866 UserRefObjectCo(Window
, &Ref
);
1869 case FNID_DEFWINDOWPROC
:
1870 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
1873 UserDerefObjectCo(Window
);
1878 #define INFINITE 0xFFFFFFFF
1879 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
1883 NtUserWaitForInputIdle(
1885 IN DWORD dwMilliseconds
,
1889 PW32PROCESS W32Process
;
1892 LARGE_INTEGER Timeout
;
1893 ULONGLONG StartTime
, Run
, Elapsed
= 0;
1895 UserEnterExclusive();
1897 Status
= ObReferenceObjectByHandle(hProcess
,
1898 PROCESS_QUERY_INFORMATION
,
1904 if (!NT_SUCCESS(Status
))
1907 SetLastNtError(Status
);
1911 W32Process
= (PW32PROCESS
)Process
->Win32Process
;
1914 ObDereferenceObject(Process
);
1916 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1920 EngCreateEvent((PEVENT
*)&W32Process
->InputIdleEvent
);
1922 Handles
[0] = Process
;
1923 Handles
[1] = W32Process
->InputIdleEvent
;
1927 ObDereferenceObject(Process
);
1929 return STATUS_SUCCESS
; /* no event to wait on */
1932 StartTime
= ((ULONGLONG
)SharedUserData
->TickCountLowDeprecated
*
1933 SharedUserData
->TickCountMultiplier
/ 16777216);
1935 Run
= dwMilliseconds
;
1937 DPRINT("WFII: waiting for %p\n", Handles
[1] );
1940 Timeout
.QuadPart
= Run
- Elapsed
;
1942 Status
= KeWaitForMultipleObjects( 2,
1948 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
1950 UserEnterExclusive();
1952 if (!NT_SUCCESS(Status
))
1954 SetLastNtError(Status
);
1955 Status
= WAIT_FAILED
;
1962 Status
= WAIT_FAILED
;
1968 co_IntPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
);
1972 case STATUS_USER_APC
:
1973 case STATUS_ALERTED
:
1974 case STATUS_TIMEOUT
:
1975 DPRINT1("WFII: timeout\n");
1976 Status
= STATUS_TIMEOUT
;
1980 DPRINT1("WFII: finished\n");
1981 Status
= STATUS_SUCCESS
;
1985 if (dwMilliseconds
!= INFINITE
)
1987 Elapsed
= ((ULONGLONG
)SharedUserData
->TickCountLowDeprecated
*
1988 SharedUserData
->TickCountMultiplier
/ 16777216)
1992 Status
= STATUS_TIMEOUT
;
1999 if (W32Process
->InputIdleEvent
)
2001 EngDeleteEvent((PEVENT
)W32Process
->InputIdleEvent
);
2002 W32Process
->InputIdleEvent
= NULL
;
2004 ObDereferenceObject(Process
);