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 */
824 NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo
,
832 NTUSERGETMESSAGEINFO Info
;
833 PWINDOW_OBJECT Window
;
834 PMSGMEMORY MsgMemoryEntry
;
838 DECLARE_RETURN(BOOL
);
840 DPRINT("Enter NtUserPeekMessage\n");
841 UserEnterExclusive();
844 if (hWnd
&& hWnd
!= INVALID_HANDLE_VALUE
)
846 if (!(Window
= UserGetWindowObject(hWnd
)))
852 if (MsgFilterMax
< MsgFilterMin
)
858 Present
= co_IntPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
);
862 /* See if this message type is present in the table */
863 MsgMemoryEntry
= FindMsgMemory(Info
.Msg
.message
);
864 if (NULL
== MsgMemoryEntry
)
866 /* Not present, no copying needed */
871 /* Determine required size */
872 Size
= MsgMemorySize(MsgMemoryEntry
, Info
.Msg
.wParam
,
874 /* Allocate required amount of user-mode memory */
875 Info
.LParamSize
= Size
;
877 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem
, 0,
878 &Info
.LParamSize
, MEM_COMMIT
, PAGE_READWRITE
);
879 if (! NT_SUCCESS(Status
))
881 SetLastNtError(Status
);
884 /* Transfer lParam data to user-mode mem */
885 Status
= MmCopyToCaller(UserMem
, (PVOID
) Info
.Msg
.lParam
, Size
);
886 if (! NT_SUCCESS(Status
))
888 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &UserMem
,
889 &Info
.LParamSize
, MEM_RELEASE
);
890 SetLastNtError(Status
);
893 Info
.Msg
.lParam
= (LPARAM
) UserMem
;
895 if (RemoveMsg
&& Msg
.FreeLParam
&& 0 != Msg
.Msg
.lParam
)
897 ExFreePool((void *) Msg
.Msg
.lParam
);
899 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERGETMESSAGEINFO
));
900 if (! NT_SUCCESS(Status
))
902 SetLastNtError(Status
);
910 DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_
);
916 co_IntWaitMessage(HWND Wnd
,
920 PUSER_MESSAGE_QUEUE ThreadQueue
;
924 ThreadQueue
= (PUSER_MESSAGE_QUEUE
)PsGetCurrentThreadWin32Thread()->MessageQueue
;
928 if (co_IntPeekMessage(&Msg
, Wnd
, MsgFilterMin
, MsgFilterMax
, PM_NOREMOVE
))
933 /* Nothing found. Wait for new messages. */
934 Status
= co_MsqWaitForNewMessages(ThreadQueue
, Wnd
, MsgFilterMin
, MsgFilterMax
);
936 while ((STATUS_WAIT_0
<= Status
&& Status
<= STATUS_WAIT_63
) || STATUS_TIMEOUT
== Status
);
938 SetLastNtError(Status
);
944 NtUserGetMessage(PNTUSERGETMESSAGEINFO UnsafeInfo
,
949 * FUNCTION: Get a message from the calling thread's message queue.
951 * UnsafeMsg - Pointer to the structure which receives the returned message.
952 * Wnd - Window whose messages are to be retrieved.
953 * MsgFilterMin - Integer value of the lowest message value to be
955 * MsgFilterMax - Integer value of the highest message value to be
960 NTUSERGETMESSAGEINFO Info
;
962 PWINDOW_OBJECT Window
= NULL
;
963 PMSGMEMORY MsgMemoryEntry
;
967 DECLARE_RETURN(BOOL
);
968 // USER_REFERENCE_ENTRY Ref;
970 DPRINT("Enter NtUserGetMessage\n");
971 UserEnterExclusive();
974 if (hWnd
&& !(Window
= UserGetWindowObject(hWnd
)))
979 // if (Window) UserRefObjectCo(Window, &Ref);
981 if (MsgFilterMax
< MsgFilterMin
)
989 GotMessage
= co_IntPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
);
993 /* See if this message type is present in the table */
994 MsgMemoryEntry
= FindMsgMemory(Info
.Msg
.message
);
995 if (NULL
== MsgMemoryEntry
)
997 /* Not present, no copying needed */
1002 /* Determine required size */
1003 Size
= MsgMemorySize(MsgMemoryEntry
, Info
.Msg
.wParam
,
1005 /* Allocate required amount of user-mode memory */
1006 Info
.LParamSize
= Size
;
1008 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem
, 0,
1009 &Info
.LParamSize
, MEM_COMMIT
, PAGE_READWRITE
);
1011 if (! NT_SUCCESS(Status
))
1013 SetLastNtError(Status
);
1016 /* Transfer lParam data to user-mode mem */
1017 Status
= MmCopyToCaller(UserMem
, (PVOID
) Info
.Msg
.lParam
, Size
);
1018 if (! NT_SUCCESS(Status
))
1020 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &UserMem
,
1021 &Info
.LParamSize
, MEM_DECOMMIT
);
1022 SetLastNtError(Status
);
1025 Info
.Msg
.lParam
= (LPARAM
) UserMem
;
1027 if (Msg
.FreeLParam
&& 0 != Msg
.Msg
.lParam
)
1029 ExFreePool((void *) Msg
.Msg
.lParam
);
1031 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERGETMESSAGEINFO
));
1032 if (! NT_SUCCESS(Status
))
1034 SetLastNtError(Status
);
1038 else if (! co_IntWaitMessage(hWnd
, MsgFilterMin
, MsgFilterMax
))
1043 while (! GotMessage
);
1045 RETURN( WM_QUIT
!= Info
.Msg
.message
);
1048 // if (Window) UserDerefObjectCo(Window);
1050 DPRINT("Leave NtUserGetMessage\n");
1061 ULONG_PTR ResultInfo
,
1070 static NTSTATUS FASTCALL
1071 CopyMsgToKernelMem(MSG
*KernelModeMsg
, MSG
*UserModeMsg
, PMSGMEMORY MsgMemoryEntry
)
1078 *KernelModeMsg
= *UserModeMsg
;
1080 /* See if this message type is present in the table */
1081 if (NULL
== MsgMemoryEntry
)
1083 /* Not present, no copying needed */
1084 return STATUS_SUCCESS
;
1087 /* Determine required size */
1088 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
1092 /* Allocate kernel mem */
1093 KernelMem
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
1094 if (NULL
== KernelMem
)
1096 DPRINT1("Not enough memory to copy message to kernel mem\n");
1097 return STATUS_NO_MEMORY
;
1099 KernelModeMsg
->lParam
= (LPARAM
) KernelMem
;
1101 /* Copy data if required */
1102 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_READ
))
1104 Status
= MmCopyFromCaller(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
1105 if (! NT_SUCCESS(Status
))
1107 DPRINT1("Failed to copy message to kernel: invalid usermode buffer\n");
1108 ExFreePool(KernelMem
);
1114 /* Make sure we don't pass any secrets to usermode */
1115 RtlZeroMemory(KernelMem
, Size
);
1120 KernelModeMsg
->lParam
= 0;
1123 return STATUS_SUCCESS
;
1126 static NTSTATUS FASTCALL
1127 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
1130 PMSGMEMORY MsgMemoryEntry
;
1133 /* See if this message type is present in the table */
1134 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
1135 if (NULL
== MsgMemoryEntry
)
1137 /* Not present, no copying needed */
1138 return STATUS_SUCCESS
;
1141 /* Determine required size */
1142 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
1146 /* Copy data if required */
1147 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
1149 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
1150 if (! NT_SUCCESS(Status
))
1152 DPRINT1("Failed to copy message from kernel: invalid usermode buffer\n");
1153 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
1158 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
1161 return STATUS_SUCCESS
;
1165 UserPostMessage(HWND Wnd
,
1170 MSG UserModeMsg
, KernelModeMsg
;
1171 LARGE_INTEGER LargeTickCount
;
1173 PMSGMEMORY MsgMemoryEntry
;
1177 MsqPostQuitMessage(PsGetCurrentThreadWin32Thread()->MessageQueue
, wParam
);
1179 else if (Wnd
== HWND_BROADCAST
)
1182 PWINDOW_OBJECT DesktopWindow
;
1185 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1186 List
= IntWinListChildren(DesktopWindow
);
1190 for (i
= 0; List
[i
]; i
++)
1191 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1197 PWINDOW_OBJECT Window
;
1199 Window
= UserGetWindowObject(Wnd
);
1204 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
1206 DPRINT1("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd
);
1207 /* FIXME - last error code? */
1211 UserModeMsg
.hwnd
= Wnd
;
1212 UserModeMsg
.message
= Msg
;
1213 UserModeMsg
.wParam
= wParam
;
1214 UserModeMsg
.lParam
= lParam
;
1215 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1216 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1217 if (! NT_SUCCESS(Status
))
1219 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1222 IntGetCursorLocation(PsGetCurrentThreadWin32Thread()->Desktop
->WindowStation
,
1224 KeQueryTickCount(&LargeTickCount
);
1225 KernelModeMsg
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1226 MsqPostMessage(Window
->MessageQueue
, &KernelModeMsg
,
1227 NULL
!= MsgMemoryEntry
&& 0 != KernelModeMsg
.lParam
,
1236 NtUserPostMessage(HWND hWnd
,
1241 DECLARE_RETURN(BOOL
);
1243 DPRINT("Enter NtUserPostMessage\n");
1244 UserEnterExclusive();
1246 RETURN(UserPostMessage(hWnd
, Msg
, wParam
, lParam
));
1249 DPRINT("Leave NtUserPostMessage, ret=%i\n",_ret_
);
1257 NtUserPostThreadMessage(DWORD idThread
,
1262 MSG UserModeMsg
, KernelModeMsg
;
1266 PMSGMEMORY MsgMemoryEntry
;
1267 DECLARE_RETURN(BOOL
);
1269 DPRINT("Enter NtUserPostThreadMessage\n");
1270 UserEnterExclusive();
1272 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
1274 if( Status
== STATUS_SUCCESS
)
1276 pThread
= (PW32THREAD
)peThread
->Tcb
.Win32Thread
;
1277 if( !pThread
|| !pThread
->MessageQueue
)
1279 ObDereferenceObject( peThread
);
1283 UserModeMsg
.hwnd
= NULL
;
1284 UserModeMsg
.message
= Msg
;
1285 UserModeMsg
.wParam
= wParam
;
1286 UserModeMsg
.lParam
= lParam
;
1287 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1288 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1289 if (! NT_SUCCESS(Status
))
1291 ObDereferenceObject( peThread
);
1292 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1295 MsqPostMessage(pThread
->MessageQueue
, &KernelModeMsg
,
1296 NULL
!= MsgMemoryEntry
&& 0 != KernelModeMsg
.lParam
,
1298 ObDereferenceObject( peThread
);
1303 SetLastNtError( Status
);
1308 DPRINT("Leave NtUserPostThreadMessage, ret=%i\n",_ret_
);
1314 NtUserQuerySendMessage(DWORD Unknown0
)
1322 co_IntSendMessage(HWND hWnd
,
1327 ULONG_PTR Result
= 0;
1328 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1330 return (LRESULT
)Result
;
1337 co_IntSendMessageTimeoutSingle(HWND hWnd
,
1347 PWINDOW_OBJECT Window
= NULL
;
1348 PMSGMEMORY MsgMemoryEntry
;
1349 INT lParamBufferSize
;
1350 LPARAM lParamPacked
;
1351 PW32THREAD Win32Thread
;
1352 DECLARE_RETURN(LRESULT
);
1353 USER_REFERENCE_ENTRY Ref
;
1355 /* FIXME: Call hooks. */
1356 if (!(Window
= UserGetWindowObject(hWnd
)))
1361 UserRefObjectCo(Window
, &Ref
);
1363 Win32Thread
= PsGetCurrentThreadWin32Thread();
1365 if (NULL
!= Win32Thread
&&
1366 Window
->MessageQueue
== Win32Thread
->MessageQueue
)
1368 if (Win32Thread
->IsExiting
)
1370 /* Never send messages to exiting threads */
1374 /* See if this message type is present in the table */
1375 MsgMemoryEntry
= FindMsgMemory(Msg
);
1376 if (NULL
== MsgMemoryEntry
)
1378 lParamBufferSize
= -1;
1382 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1385 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
)))
1387 DPRINT1("Failed to pack message parameters\n");
1391 Result
= (ULONG_PTR
)co_IntCallWindowProc(Window
->Wnd
->WndProc
, !Window
->Wnd
->Unicode
, hWnd
, Msg
, wParam
,
1392 lParamPacked
,lParamBufferSize
);
1399 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
)))
1401 DPRINT1("Failed to unpack message parameters\n");
1408 if(uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->MessageQueue
))
1410 /* FIXME - Set a LastError? */
1414 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
1416 /* FIXME - last error? */
1417 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1421 Status
= co_MsqSendMessage(Window
->MessageQueue
, hWnd
, Msg
, wParam
, lParam
,
1422 uTimeout
, (uFlags
& SMTO_BLOCK
), FALSE
, uResult
);
1425 if (STATUS_TIMEOUT
== Status
)
1427 /* MSDN says GetLastError() should return 0 after timeout */
1428 SetLastWin32Error(0);
1431 else if (! NT_SUCCESS(Status
))
1433 SetLastNtError(Status
);
1440 if (Window
) UserDerefObjectCo(Window
);
1445 co_IntSendMessageTimeout(HWND hWnd
,
1453 PWINDOW_OBJECT DesktopWindow
;
1457 if (HWND_BROADCAST
!= hWnd
)
1459 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1462 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1463 if (NULL
== DesktopWindow
)
1465 SetLastWin32Error(ERROR_INTERNAL_ERROR
);
1469 Children
= IntWinListChildren(DesktopWindow
);
1470 if (NULL
== Children
)
1475 for (Child
= Children
; NULL
!= *Child
; Child
++)
1477 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1480 ExFreePool(Children
);
1482 return (LRESULT
) TRUE
;
1486 /* This function posts a message if the destination's message queue belongs to
1487 another thread, otherwise it sends the message. It does not support broadcast
1490 co_IntPostOrSendMessage(HWND hWnd
,
1496 PWINDOW_OBJECT Window
;
1498 if(hWnd
== HWND_BROADCAST
)
1503 if(!(Window
= UserGetWindowObject(hWnd
)))
1508 if(Window
->MessageQueue
!= PsGetCurrentThreadWin32Thread()->MessageQueue
)
1510 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1514 if(!co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1520 return (LRESULT
)Result
;
1524 co_IntDoSendMessage(HWND hWnd
,
1529 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1531 LRESULT Result
= TRUE
;
1533 PWINDOW_OBJECT Window
;
1534 NTUSERSENDMESSAGEINFO Info
;
1537 PMSGMEMORY MsgMemoryEntry
;
1539 RtlZeroMemory(&Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1541 /* FIXME: Call hooks. */
1542 if (HWND_BROADCAST
!= hWnd
)
1544 Window
= UserGetWindowObject(hWnd
);
1547 /* Tell usermode to not touch this one */
1548 Info
.HandledByKernel
= TRUE
;
1549 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1556 /* FIXME: Check for an exiting window. */
1558 /* See if the current thread can handle the message */
1559 if (HWND_BROADCAST
!= hWnd
&& NULL
!= PsGetCurrentThreadWin32Thread() &&
1560 Window
->MessageQueue
== PsGetCurrentThreadWin32Thread()->MessageQueue
)
1562 /* Gather the information usermode needs to call the window proc directly */
1563 Info
.HandledByKernel
= FALSE
;
1565 Status
= MmCopyFromCaller(&(Info
.Ansi
), &(UnsafeInfo
->Ansi
),
1567 if (! NT_SUCCESS(Status
))
1569 Info
.Ansi
= ! Window
->Wnd
->Unicode
;
1572 if (Window
->Wnd
->IsSystem
)
1574 Info
.Proc
= (!Info
.Ansi
? Window
->Wnd
->WndProc
: Window
->Wnd
->WndProcExtra
);
1578 Info
.Ansi
= !Window
->Wnd
->Unicode
;
1579 Info
.Proc
= Window
->Wnd
->WndProc
;
1584 /* Must be handled by other thread */
1585 // if (HWND_BROADCAST != hWnd)
1587 // UserDereferenceObject(Window);
1589 Info
.HandledByKernel
= TRUE
;
1590 UserModeMsg
.hwnd
= hWnd
;
1591 UserModeMsg
.message
= Msg
;
1592 UserModeMsg
.wParam
= wParam
;
1593 UserModeMsg
.lParam
= lParam
;
1594 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1595 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1596 if (! NT_SUCCESS(Status
))
1598 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1599 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1600 return (dsm
? 0 : -1);
1604 Result
= co_IntSendMessage(KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1605 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
);
1609 Result
= co_IntSendMessageTimeout(KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1610 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
,
1611 dsm
->uFlags
, dsm
->uTimeout
, &dsm
->Result
);
1613 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1614 if (! NT_SUCCESS(Status
))
1616 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1617 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1618 return(dsm
? 0 : -1);
1622 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1623 if (! NT_SUCCESS(Status
))
1625 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1628 return (LRESULT
)Result
;
1632 NtUserSendMessageTimeout(HWND hWnd
,
1639 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1643 DECLARE_RETURN(BOOL
);
1645 DPRINT("Enter NtUserSendMessageTimeout\n");
1646 UserEnterExclusive();
1648 dsm
.uFlags
= uFlags
;
1649 dsm
.uTimeout
= uTimeout
;
1650 Result
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, &dsm
, UnsafeInfo
);
1651 if(uResult
!= NULL
&& Result
!= 0)
1655 Status
= MmCopyToCaller(uResult
, &dsm
.Result
, sizeof(ULONG_PTR
));
1656 if(!NT_SUCCESS(Status
))
1658 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1665 DPRINT("Leave NtUserSendMessageTimeout, ret=%i\n",_ret_
);
1671 NtUserSendMessage(HWND Wnd
,
1675 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1677 DECLARE_RETURN(BOOL
);
1679 DPRINT("Enter NtUserSendMessage\n");
1680 UserEnterExclusive();
1682 RETURN(co_IntDoSendMessage(Wnd
, Msg
, wParam
, lParam
, NULL
, UnsafeInfo
));
1685 DPRINT("Leave NtUserSendMessage, ret=%i\n",_ret_
);
1692 UserSendNotifyMessage(HWND hWnd
,
1698 // Basicly the same as IntPostOrSendMessage
1699 if (hWnd
== HWND_BROADCAST
) //Handle Broadcast
1702 PWINDOW_OBJECT DesktopWindow
;
1705 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1706 List
= IntWinListChildren(DesktopWindow
);
1710 for (i
= 0; List
[i
]; i
++)
1712 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1720 PWINDOW_OBJECT Window
;
1724 PMSGMEMORY MsgMemoryEntry
;
1726 if(!(Window
= UserGetWindowObject(hWnd
))) return FALSE
;
1728 if(Window
->MessageQueue
!= PsGetCurrentThreadWin32Thread()->MessageQueue
)
1729 { // Send message w/o waiting for it.
1730 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1733 { // Handle message and callback.
1734 UserModeMsg
.hwnd
= hWnd
;
1735 UserModeMsg
.message
= Msg
;
1736 UserModeMsg
.wParam
= wParam
;
1737 UserModeMsg
.lParam
= lParam
;
1738 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1739 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1740 if (! NT_SUCCESS(Status
))
1742 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1745 Result
= co_IntSendMessageTimeoutSingle(
1746 KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1747 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
,
1748 SMTO_NORMAL
, 0, &PResult
);
1750 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1751 if (! NT_SUCCESS(Status
))
1753 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1763 NtUserSendNotifyMessage(HWND hWnd
,
1768 DECLARE_RETURN(BOOL
);
1770 DPRINT("EnterNtUserSendNotifyMessage\n");
1771 UserEnterExclusive();
1773 RETURN(UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
));
1776 DPRINT("Leave NtUserSendNotifyMessage, ret=%i\n",_ret_
);
1784 NtUserWaitMessage(VOID
)
1786 DECLARE_RETURN(BOOL
);
1788 DPRINT("EnterNtUserWaitMessage\n");
1789 UserEnterExclusive();
1791 RETURN(co_IntWaitMessage(NULL
, 0, 0));
1794 DPRINT("Leave NtUserWaitMessage, ret=%i\n",_ret_
);
1800 IntGetQueueStatus(BOOL ClearChanges
)
1802 PUSER_MESSAGE_QUEUE Queue
;
1804 DECLARE_RETURN(DWORD
);
1806 DPRINT("Enter IntGetQueueStatus\n");
1808 Queue
= PsGetCurrentThreadWin32Thread()->MessageQueue
;
1810 Result
= MAKELONG(Queue
->QueueBits
, Queue
->ChangedBits
);
1813 Queue
->ChangedBits
= 0;
1819 DPRINT("Leave IntGetQueueStatus, ret=%i\n",_ret_
);
1824 IntInitMessagePumpHook()
1826 if (((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->ThreadInfo
)
1828 ((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->ThreadInfo
->ClientThreadInfo
.dwcPumpHook
++;
1835 IntUninitMessagePumpHook()
1837 if (((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->ThreadInfo
)
1839 if (((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->ThreadInfo
->ClientThreadInfo
.dwcPumpHook
<= 0)
1843 ((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->ThreadInfo
->ClientThreadInfo
.dwcPumpHook
--;
1849 #define INFINITE 0xFFFFFFFF
1850 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
1854 NtUserWaitForInputIdle(
1856 IN DWORD dwMilliseconds
,
1860 PW32PROCESS W32Process
;
1863 LARGE_INTEGER Timeout
;
1864 ULONGLONG StartTime
, Run
, Elapsed
= 0;
1866 UserEnterExclusive();
1868 Status
= ObReferenceObjectByHandle(hProcess
,
1869 PROCESS_QUERY_INFORMATION
,
1875 if (!NT_SUCCESS(Status
))
1877 SetLastNtError(Status
);
1881 W32Process
= (PW32PROCESS
)Process
->Win32Process
;
1884 ObDereferenceObject(Process
);
1885 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1889 EngCreateEvent((PEVENT
*)&W32Process
->InputIdleEvent
);
1891 Handles
[0] = hProcess
;
1892 Handles
[1] = W32Process
->InputIdleEvent
;
1894 if (!Handles
[1]) return STATUS_SUCCESS
; /* no event to wait on */
1896 StartTime
= ((ULONGLONG
)SharedUserData
->TickCountLowDeprecated
*
1897 SharedUserData
->TickCountMultiplier
/ 16777216);
1899 Run
= dwMilliseconds
;
1901 DPRINT("WFII: waiting for %p\n", Handles
[1] );
1904 Timeout
.QuadPart
= Run
- Elapsed
;
1906 Status
= KeWaitForMultipleObjects( 2,
1912 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
1914 UserEnterExclusive();
1916 if (!NT_SUCCESS(Status
))
1918 SetLastNtError(Status
);
1919 Status
= WAIT_FAILED
;
1926 Status
= WAIT_FAILED
;
1932 co_IntPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
);
1936 case STATUS_USER_APC
:
1937 case STATUS_ALERTED
:
1938 case STATUS_TIMEOUT
:
1939 DPRINT1("WFII: timeout\n");
1940 Status
= STATUS_TIMEOUT
;
1944 DPRINT1("WFII: finished\n");
1945 Status
= STATUS_SUCCESS
;
1949 if (dwMilliseconds
!= INFINITE
)
1951 Elapsed
= ((ULONGLONG
)SharedUserData
->TickCountLowDeprecated
*
1952 SharedUserData
->TickCountMultiplier
/ 16777216)
1956 Status
= STATUS_TIMEOUT
;
1963 if (W32Process
->InputIdleEvent
)
1965 EngDeleteEvent((PEVENT
)W32Process
->InputIdleEvent
);
1966 W32Process
->InputIdleEvent
= NULL
;
1968 ObDereferenceObject(Process
);