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 ( UserCallNextHookEx( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)msg
, FALSE
))
311 RETURN( UserCallNextHookEx( WH_MSGFILTER
, code
, 0, (LPARAM
)msg
, FALSE
));
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
;
661 MOUSEHOOKSTRUCT MHook
;
663 /* The queues and order in which they are checked are documented in the MSDN
664 article on GetMessage() */
666 ThreadQueue
= (PUSER_MESSAGE_QUEUE
)PsGetCurrentThreadWin32Thread()->MessageQueue
;
668 /* Inspect RemoveMsg flags */
669 /* FIXME: The only flag we process is PM_REMOVE - processing of others must still be implemented */
670 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
676 KeQueryTickCount(&LargeTickCount
);
677 ThreadQueue
->LastMsgRead
= LargeTickCount
.u
.LowPart
;
679 /* Dispatch sent messages here. */
680 while (co_MsqDispatchOneSentMessage(ThreadQueue
))
683 /* Now look for a quit message. */
685 if (ThreadQueue
->QuitPosted
)
687 /* According to the PSDK, WM_QUIT messages are always returned, regardless
688 of the filter specified */
689 Msg
->Msg
.hwnd
= NULL
;
690 Msg
->Msg
.message
= WM_QUIT
;
691 Msg
->Msg
.wParam
= ThreadQueue
->QuitExitCode
;
693 Msg
->FreeLParam
= FALSE
;
696 ThreadQueue
->QuitPosted
= FALSE
;
701 /* Now check for normal messages. */
702 Present
= co_MsqFindMessage(ThreadQueue
,
711 RtlCopyMemory(Msg
, Message
, sizeof(USER_MESSAGE
));
714 MsqDestroyMessage(Message
);
719 /* Check for hardware events. */
720 Present
= co_MsqFindMessage(ThreadQueue
,
729 RtlCopyMemory(Msg
, Message
, sizeof(USER_MESSAGE
));
732 MsqDestroyMessage(Message
);
737 /* Check for sent messages again. */
738 while (co_MsqDispatchOneSentMessage(ThreadQueue
))
741 /* Check for paint messages. */
742 if (IntGetPaintMessage(hWnd
, MsgFilterMin
, MsgFilterMax
, PsGetCurrentThreadWin32Thread(), &Msg
->Msg
, RemoveMessages
))
744 Msg
->FreeLParam
= FALSE
;
748 /* Check for WM_(SYS)TIMER messages */
749 Present
= MsqGetTimerMessage(ThreadQueue
, hWnd
, MsgFilterMin
, MsgFilterMax
,
750 &Msg
->Msg
, RemoveMessages
);
753 Msg
->FreeLParam
= FALSE
;
763 PWINDOW_OBJECT MsgWindow
= NULL
;
765 if(Msg
->Msg
.hwnd
&& (MsgWindow
= UserGetWindowObject(Msg
->Msg
.hwnd
)) &&
766 Msg
->Msg
.message
>= WM_MOUSEFIRST
&& Msg
->Msg
.message
<= WM_MOUSELAST
)
770 UserRefObjectCo(MsgWindow
, &Ref
);
772 if(co_IntTranslateMouseMessage(ThreadQueue
, &Msg
->Msg
, &HitTest
, TRUE
))
773 /* FIXME - check message filter again, if the message doesn't match anymore,
776 UserDerefObjectCo(MsgWindow
);
777 /* eat the message, search again */
781 if(ThreadQueue
->CaptureWindow
== NULL
)
783 co_IntSendHitTestMessages(ThreadQueue
, &Msg
->Msg
);
784 if((Msg
->Msg
.message
!= WM_MOUSEMOVE
&& Msg
->Msg
.message
!= WM_NCMOUSEMOVE
) &&
785 IS_BTN_MESSAGE(Msg
->Msg
.message
, DOWN
) &&
786 co_IntActivateWindowMouse(ThreadQueue
, &Msg
->Msg
, MsgWindow
, &HitTest
))
788 UserDerefObjectCo(MsgWindow
);
789 /* eat the message, search again */
794 UserDerefObjectCo(MsgWindow
);
798 co_IntSendHitTestMessages(ThreadQueue
, &Msg
->Msg
);
803 // UserDereferenceObject(MsgWindow);
809 if((Msg
->Msg
.hwnd
&& Msg
->Msg
.message
>= WM_MOUSEFIRST
&& Msg
->Msg
.message
<= WM_MOUSELAST
) &&
810 co_IntTranslateMouseMessage(ThreadQueue
, &Msg
->Msg
, &HitTest
, FALSE
))
811 /* FIXME - check message filter again, if the message doesn't match anymore,
814 /* eat the message, search again */
818 if ( ISITHOOKED(WH_MOUSE
) &&
819 Msg
->Msg
.message
>= WM_MOUSEFIRST
&&
820 Msg
->Msg
.message
<= WM_MOUSELAST
)
822 MHook
.pt
= Msg
->Msg
.pt
;
823 MHook
.hwnd
= Msg
->Msg
.hwnd
;
824 MHook
.wHitTestCode
= HitTest
;
825 MHook
.dwExtraInfo
= 0;
826 if (co_HOOK_CallHooks( WH_MOUSE
,
827 RemoveMsg
? HC_ACTION
: HC_NOREMOVE
,
831 if (ISITHOOKED(WH_CBT
))
833 MHook
.pt
= Msg
->Msg
.pt
;
834 MHook
.hwnd
= Msg
->Msg
.hwnd
;
835 MHook
.wHitTestCode
= HitTest
;
836 MHook
.dwExtraInfo
= 0;
837 co_HOOK_CallHooks( WH_CBT
, HCBT_CLICKSKIPPED
,
838 Msg
->Msg
.message
, (LPARAM
)&MHook
);
843 if ( ISITHOOKED(WH_KEYBOARD
) &&
844 (Msg
->Msg
.message
== WM_KEYDOWN
|| Msg
->Msg
.message
== WM_KEYUP
) )
846 if (co_HOOK_CallHooks( WH_KEYBOARD
,
847 RemoveMsg
? HC_ACTION
: HC_NOREMOVE
,
848 LOWORD(Msg
->Msg
.wParam
),
851 if (ISITHOOKED(WH_CBT
))
853 /* skip this message */
854 co_HOOK_CallHooks( WH_CBT
, HCBT_KEYSKIPPED
,
855 LOWORD(Msg
->Msg
.wParam
), Msg
->Msg
.lParam
);
860 // The WH_GETMESSAGE hook enables an application to monitor messages about to
861 // be returned by the GetMessage or PeekMessage function.
862 if (ISITHOOKED(WH_GETMESSAGE
))
864 //DPRINT1("Peek WH_GETMESSAGE -> %x\n",&Msg);
865 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)&Msg
->Msg
);
874 NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo
,
882 NTUSERGETMESSAGEINFO Info
;
883 PWINDOW_OBJECT Window
;
884 PMSGMEMORY MsgMemoryEntry
;
888 DECLARE_RETURN(BOOL
);
890 DPRINT("Enter NtUserPeekMessage\n");
891 UserEnterExclusive();
894 if (hWnd
&& hWnd
!= INVALID_HANDLE_VALUE
)
896 if (!(Window
= UserGetWindowObject(hWnd
)))
902 if (MsgFilterMax
< MsgFilterMin
)
908 Present
= co_IntPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
);
913 /* See if this message type is present in the table */
914 MsgMemoryEntry
= FindMsgMemory(Info
.Msg
.message
);
915 if (NULL
== MsgMemoryEntry
)
917 /* Not present, no copying needed */
922 /* Determine required size */
923 Size
= MsgMemorySize(MsgMemoryEntry
, Info
.Msg
.wParam
,
925 /* Allocate required amount of user-mode memory */
926 Info
.LParamSize
= Size
;
928 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem
, 0,
929 &Info
.LParamSize
, MEM_COMMIT
, PAGE_READWRITE
);
930 if (! NT_SUCCESS(Status
))
932 SetLastNtError(Status
);
935 /* Transfer lParam data to user-mode mem */
936 Status
= MmCopyToCaller(UserMem
, (PVOID
) Info
.Msg
.lParam
, Size
);
937 if (! NT_SUCCESS(Status
))
939 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &UserMem
,
940 &Info
.LParamSize
, MEM_RELEASE
);
941 SetLastNtError(Status
);
944 Info
.Msg
.lParam
= (LPARAM
) UserMem
;
946 if (RemoveMsg
&& Msg
.FreeLParam
&& 0 != Msg
.Msg
.lParam
)
948 ExFreePool((void *) Msg
.Msg
.lParam
);
950 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERGETMESSAGEINFO
));
951 if (! NT_SUCCESS(Status
))
953 SetLastNtError(Status
);
961 DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_
);
967 co_IntWaitMessage(HWND Wnd
,
971 PUSER_MESSAGE_QUEUE ThreadQueue
;
975 ThreadQueue
= (PUSER_MESSAGE_QUEUE
)PsGetCurrentThreadWin32Thread()->MessageQueue
;
979 if (co_IntPeekMessage(&Msg
, Wnd
, MsgFilterMin
, MsgFilterMax
, PM_NOREMOVE
))
984 /* Nothing found. Wait for new messages. */
985 Status
= co_MsqWaitForNewMessages(ThreadQueue
, Wnd
, MsgFilterMin
, MsgFilterMax
);
987 while ((STATUS_WAIT_0
<= Status
&& Status
<= STATUS_WAIT_63
) || STATUS_TIMEOUT
== Status
);
989 SetLastNtError(Status
);
995 NtUserGetMessage(PNTUSERGETMESSAGEINFO UnsafeInfo
,
1000 * FUNCTION: Get a message from the calling thread's message queue.
1002 * UnsafeMsg - Pointer to the structure which receives the returned message.
1003 * Wnd - Window whose messages are to be retrieved.
1004 * MsgFilterMin - Integer value of the lowest message value to be
1006 * MsgFilterMax - Integer value of the highest message value to be
1011 NTUSERGETMESSAGEINFO Info
;
1013 PWINDOW_OBJECT Window
= NULL
;
1014 PMSGMEMORY MsgMemoryEntry
;
1018 DECLARE_RETURN(BOOL
);
1019 // USER_REFERENCE_ENTRY Ref;
1021 DPRINT("Enter NtUserGetMessage\n");
1022 UserEnterExclusive();
1024 /* Validate input */
1025 if (hWnd
&& !(Window
= UserGetWindowObject(hWnd
)))
1030 // if (Window) UserRefObjectCo(Window, &Ref);
1032 if (MsgFilterMax
< MsgFilterMin
)
1040 GotMessage
= co_IntPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
);
1044 /* See if this message type is present in the table */
1045 MsgMemoryEntry
= FindMsgMemory(Info
.Msg
.message
);
1046 if (NULL
== MsgMemoryEntry
)
1048 /* Not present, no copying needed */
1049 Info
.LParamSize
= 0;
1053 /* Determine required size */
1054 Size
= MsgMemorySize(MsgMemoryEntry
, Info
.Msg
.wParam
,
1056 /* Allocate required amount of user-mode memory */
1057 Info
.LParamSize
= Size
;
1059 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem
, 0,
1060 &Info
.LParamSize
, MEM_COMMIT
, PAGE_READWRITE
);
1062 if (! NT_SUCCESS(Status
))
1064 SetLastNtError(Status
);
1067 /* Transfer lParam data to user-mode mem */
1068 Status
= MmCopyToCaller(UserMem
, (PVOID
) Info
.Msg
.lParam
, Size
);
1069 if (! NT_SUCCESS(Status
))
1071 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &UserMem
,
1072 &Info
.LParamSize
, MEM_DECOMMIT
);
1073 SetLastNtError(Status
);
1076 Info
.Msg
.lParam
= (LPARAM
) UserMem
;
1078 if (Msg
.FreeLParam
&& 0 != Msg
.Msg
.lParam
)
1080 ExFreePool((void *) Msg
.Msg
.lParam
);
1082 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERGETMESSAGEINFO
));
1083 if (! NT_SUCCESS(Status
))
1085 SetLastNtError(Status
);
1089 else if (! co_IntWaitMessage(hWnd
, MsgFilterMin
, MsgFilterMax
))
1094 while (! GotMessage
);
1096 RETURN( WM_QUIT
!= Info
.Msg
.message
);
1099 // if (Window) UserDerefObjectCo(Window);
1101 DPRINT("Leave NtUserGetMessage\n");
1107 static NTSTATUS FASTCALL
1108 CopyMsgToKernelMem(MSG
*KernelModeMsg
, MSG
*UserModeMsg
, PMSGMEMORY MsgMemoryEntry
)
1115 *KernelModeMsg
= *UserModeMsg
;
1117 /* See if this message type is present in the table */
1118 if (NULL
== MsgMemoryEntry
)
1120 /* Not present, no copying needed */
1121 return STATUS_SUCCESS
;
1124 /* Determine required size */
1125 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
1129 /* Allocate kernel mem */
1130 KernelMem
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
1131 if (NULL
== KernelMem
)
1133 DPRINT1("Not enough memory to copy message to kernel mem\n");
1134 return STATUS_NO_MEMORY
;
1136 KernelModeMsg
->lParam
= (LPARAM
) KernelMem
;
1138 /* Copy data if required */
1139 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_READ
))
1141 Status
= MmCopyFromCaller(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
1142 if (! NT_SUCCESS(Status
))
1144 DPRINT1("Failed to copy message to kernel: invalid usermode buffer\n");
1145 ExFreePool(KernelMem
);
1151 /* Make sure we don't pass any secrets to usermode */
1152 RtlZeroMemory(KernelMem
, Size
);
1157 KernelModeMsg
->lParam
= 0;
1160 return STATUS_SUCCESS
;
1163 static NTSTATUS FASTCALL
1164 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
1167 PMSGMEMORY MsgMemoryEntry
;
1170 /* See if this message type is present in the table */
1171 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
1172 if (NULL
== MsgMemoryEntry
)
1174 /* Not present, no copying needed */
1175 return STATUS_SUCCESS
;
1178 /* Determine required size */
1179 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
1183 /* Copy data if required */
1184 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
1186 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
1187 if (! NT_SUCCESS(Status
))
1189 DPRINT1("Failed to copy message from kernel: invalid usermode buffer\n");
1190 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
1195 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
1198 return STATUS_SUCCESS
;
1202 UserPostMessage(HWND Wnd
,
1207 MSG UserModeMsg
, KernelModeMsg
;
1208 LARGE_INTEGER LargeTickCount
;
1210 PMSGMEMORY MsgMemoryEntry
;
1214 MsqPostQuitMessage(PsGetCurrentThreadWin32Thread()->MessageQueue
, wParam
);
1216 else if (Wnd
== HWND_BROADCAST
)
1219 PWINDOW_OBJECT DesktopWindow
;
1222 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1223 List
= IntWinListChildren(DesktopWindow
);
1227 for (i
= 0; List
[i
]; i
++)
1228 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1234 PWINDOW_OBJECT Window
;
1236 Window
= UserGetWindowObject(Wnd
);
1241 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
1243 DPRINT1("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd
);
1244 /* FIXME - last error code? */
1248 UserModeMsg
.hwnd
= Wnd
;
1249 UserModeMsg
.message
= Msg
;
1250 UserModeMsg
.wParam
= wParam
;
1251 UserModeMsg
.lParam
= lParam
;
1252 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1253 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1254 if (! NT_SUCCESS(Status
))
1256 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1259 IntGetCursorLocation(PsGetCurrentThreadWin32Thread()->Desktop
->WindowStation
,
1261 KeQueryTickCount(&LargeTickCount
);
1262 KernelModeMsg
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1263 MsqPostMessage(Window
->MessageQueue
, &KernelModeMsg
,
1264 NULL
!= MsgMemoryEntry
&& 0 != KernelModeMsg
.lParam
,
1273 NtUserPostMessage(HWND hWnd
,
1278 DECLARE_RETURN(BOOL
);
1280 DPRINT("Enter NtUserPostMessage\n");
1281 UserEnterExclusive();
1283 RETURN(UserPostMessage(hWnd
, Msg
, wParam
, lParam
));
1286 DPRINT("Leave NtUserPostMessage, ret=%i\n",_ret_
);
1294 NtUserPostThreadMessage(DWORD idThread
,
1299 MSG UserModeMsg
, KernelModeMsg
;
1303 PMSGMEMORY MsgMemoryEntry
;
1304 DECLARE_RETURN(BOOL
);
1306 DPRINT("Enter NtUserPostThreadMessage\n");
1307 UserEnterExclusive();
1309 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
1311 if( Status
== STATUS_SUCCESS
)
1313 pThread
= (PW32THREAD
)peThread
->Tcb
.Win32Thread
;
1314 if( !pThread
|| !pThread
->MessageQueue
)
1316 ObDereferenceObject( peThread
);
1320 UserModeMsg
.hwnd
= NULL
;
1321 UserModeMsg
.message
= Msg
;
1322 UserModeMsg
.wParam
= wParam
;
1323 UserModeMsg
.lParam
= lParam
;
1324 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1325 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1326 if (! NT_SUCCESS(Status
))
1328 ObDereferenceObject( peThread
);
1329 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1332 MsqPostMessage(pThread
->MessageQueue
, &KernelModeMsg
,
1333 NULL
!= MsgMemoryEntry
&& 0 != KernelModeMsg
.lParam
,
1335 ObDereferenceObject( peThread
);
1340 SetLastNtError( Status
);
1345 DPRINT("Leave NtUserPostThreadMessage, ret=%i\n",_ret_
);
1351 NtUserQuerySendMessage(DWORD Unknown0
)
1359 co_IntSendMessage(HWND hWnd
,
1364 ULONG_PTR Result
= 0;
1365 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1367 return (LRESULT
)Result
;
1374 co_IntSendMessageTimeoutSingle(HWND hWnd
,
1384 PWINDOW_OBJECT Window
= NULL
;
1385 PMSGMEMORY MsgMemoryEntry
;
1386 INT lParamBufferSize
;
1387 LPARAM lParamPacked
;
1388 PW32THREAD Win32Thread
;
1389 DECLARE_RETURN(LRESULT
);
1390 USER_REFERENCE_ENTRY Ref
;
1391 BOOL SameThread
= FALSE
;
1393 /* FIXME: Call hooks. */
1394 if (!(Window
= UserGetWindowObject(hWnd
)))
1399 UserRefObjectCo(Window
, &Ref
);
1401 Win32Thread
= PsGetCurrentThreadWin32Thread();
1403 if (NULL
!= Win32Thread
&&
1404 Window
->MessageQueue
== Win32Thread
->MessageQueue
)
1406 if (Win32Thread
->IsExiting
)
1408 /* Never send messages to exiting threads */
1412 /* See if this message type is present in the table */
1413 MsgMemoryEntry
= FindMsgMemory(Msg
);
1414 if (NULL
== MsgMemoryEntry
)
1416 lParamBufferSize
= -1;
1420 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1423 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
)))
1425 DPRINT1("Failed to pack message parameters\n");
1429 if (Window
->ti
== Win32Thread
->ThreadInfo
)
1432 if ((!SameThread
&& (Window
->ti
->Hooks
& HOOKID_TO_FLAG(WH_CALLWNDPROC
))) ||
1433 (SameThread
&& ISITHOOKED(WH_CALLWNDPROC
)) )
1438 CWP
.wParam
= wParam
;
1439 CWP
.lParam
= lParam
;
1440 co_HOOK_CallHooks( WH_CALLWNDPROC
, HC_ACTION
, SameThread
, (LPARAM
)&CWP
);
1443 Result
= (ULONG_PTR
)co_IntCallWindowProc(Window
->Wnd
->WndProc
, !Window
->Wnd
->Unicode
, hWnd
, Msg
, wParam
,
1444 lParamPacked
,lParamBufferSize
);
1451 if ((!SameThread
&& (Window
->ti
->Hooks
& HOOKID_TO_FLAG(WH_CALLWNDPROCRET
))) ||
1452 (SameThread
&& ISITHOOKED(WH_CALLWNDPROCRET
)) )
1457 CWPR
.wParam
= wParam
;
1458 CWPR
.lParam
= lParam
;
1459 CWPR
.lResult
= Result
;
1460 co_HOOK_CallHooks( WH_CALLWNDPROCRET
, HC_ACTION
, SameThread
, (LPARAM
)&CWPR
);
1463 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
)))
1465 DPRINT1("Failed to unpack message parameters\n");
1472 if(uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->MessageQueue
))
1474 /* FIXME - Set a LastError? */
1478 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
1480 /* FIXME - last error? */
1481 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1485 Status
= co_MsqSendMessage(Window
->MessageQueue
, hWnd
, Msg
, wParam
, lParam
,
1486 uTimeout
, (uFlags
& SMTO_BLOCK
), FALSE
, uResult
);
1489 if (STATUS_TIMEOUT
== Status
)
1491 /* MSDN says GetLastError() should return 0 after timeout */
1492 SetLastWin32Error(0);
1495 else if (! NT_SUCCESS(Status
))
1497 SetLastNtError(Status
);
1504 if (Window
) UserDerefObjectCo(Window
);
1509 co_IntSendMessageTimeout(HWND hWnd
,
1517 PWINDOW_OBJECT DesktopWindow
;
1521 if (HWND_BROADCAST
!= hWnd
)
1523 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1526 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1527 if (NULL
== DesktopWindow
)
1529 SetLastWin32Error(ERROR_INTERNAL_ERROR
);
1533 Children
= IntWinListChildren(DesktopWindow
);
1534 if (NULL
== Children
)
1539 for (Child
= Children
; NULL
!= *Child
; Child
++)
1541 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1544 ExFreePool(Children
);
1546 return (LRESULT
) TRUE
;
1550 /* This function posts a message if the destination's message queue belongs to
1551 another thread, otherwise it sends the message. It does not support broadcast
1554 co_IntPostOrSendMessage(HWND hWnd
,
1560 PWINDOW_OBJECT Window
;
1562 if(hWnd
== HWND_BROADCAST
)
1567 if(!(Window
= UserGetWindowObject(hWnd
)))
1572 if(Window
->MessageQueue
!= PsGetCurrentThreadWin32Thread()->MessageQueue
)
1574 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1578 if(!co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
)) {
1583 return (LRESULT
)Result
;
1587 co_IntDoSendMessage(HWND hWnd
,
1592 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1594 LRESULT Result
= TRUE
;
1596 PWINDOW_OBJECT Window
;
1597 NTUSERSENDMESSAGEINFO Info
;
1600 PMSGMEMORY MsgMemoryEntry
;
1602 RtlZeroMemory(&Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1604 /* FIXME: Call hooks. */
1605 if (HWND_BROADCAST
!= hWnd
)
1607 Window
= UserGetWindowObject(hWnd
);
1610 /* Tell usermode to not touch this one */
1611 Info
.HandledByKernel
= TRUE
;
1612 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1619 /* FIXME: Check for an exiting window. */
1621 /* See if the current thread can handle the message */
1622 if (HWND_BROADCAST
!= hWnd
&& NULL
!= PsGetCurrentThreadWin32Thread() &&
1623 Window
->MessageQueue
== PsGetCurrentThreadWin32Thread()->MessageQueue
)
1625 /* Gather the information usermode needs to call the window proc directly */
1626 Info
.HandledByKernel
= FALSE
;
1628 Status
= MmCopyFromCaller(&(Info
.Ansi
), &(UnsafeInfo
->Ansi
),
1630 if (! NT_SUCCESS(Status
))
1632 Info
.Ansi
= ! Window
->Wnd
->Unicode
;
1635 if (Window
->Wnd
->IsSystem
)
1637 Info
.Proc
= (!Info
.Ansi
? Window
->Wnd
->WndProc
: Window
->Wnd
->WndProcExtra
);
1641 Info
.Ansi
= !Window
->Wnd
->Unicode
;
1642 Info
.Proc
= Window
->Wnd
->WndProc
;
1647 /* Must be handled by other thread */
1648 // if (HWND_BROADCAST != hWnd)
1650 // UserDereferenceObject(Window);
1652 Info
.HandledByKernel
= TRUE
;
1653 UserModeMsg
.hwnd
= hWnd
;
1654 UserModeMsg
.message
= Msg
;
1655 UserModeMsg
.wParam
= wParam
;
1656 UserModeMsg
.lParam
= lParam
;
1657 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1658 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1659 if (! NT_SUCCESS(Status
))
1661 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1662 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1663 return (dsm
? 0 : -1);
1667 Result
= co_IntSendMessage(KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1668 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
);
1672 Result
= co_IntSendMessageTimeout(KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1673 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
,
1674 dsm
->uFlags
, dsm
->uTimeout
, &dsm
->Result
);
1676 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1677 if (! NT_SUCCESS(Status
))
1679 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1680 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1681 return(dsm
? 0 : -1);
1685 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1686 if (! NT_SUCCESS(Status
))
1688 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1691 return (LRESULT
)Result
;
1695 NtUserSendMessageTimeout(HWND hWnd
,
1702 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1706 DECLARE_RETURN(BOOL
);
1708 DPRINT("Enter NtUserSendMessageTimeout\n");
1709 UserEnterExclusive();
1711 dsm
.uFlags
= uFlags
;
1712 dsm
.uTimeout
= uTimeout
;
1713 Result
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, &dsm
, UnsafeInfo
);
1714 if(uResult
!= NULL
&& Result
!= 0)
1718 Status
= MmCopyToCaller(uResult
, &dsm
.Result
, sizeof(ULONG_PTR
));
1719 if(!NT_SUCCESS(Status
))
1721 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1728 DPRINT("Leave NtUserSendMessageTimeout, ret=%i\n",_ret_
);
1734 NtUserSendMessage(HWND Wnd
,
1738 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1740 DECLARE_RETURN(BOOL
);
1742 DPRINT("Enter NtUserSendMessage\n");
1743 UserEnterExclusive();
1745 RETURN(co_IntDoSendMessage(Wnd
, Msg
, wParam
, lParam
, NULL
, UnsafeInfo
));
1748 DPRINT("Leave NtUserSendMessage, ret=%i\n",_ret_
);
1755 UserSendNotifyMessage(HWND hWnd
,
1761 // Basicly the same as IntPostOrSendMessage
1762 if (hWnd
== HWND_BROADCAST
) //Handle Broadcast
1765 PWINDOW_OBJECT DesktopWindow
;
1768 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1769 List
= IntWinListChildren(DesktopWindow
);
1773 for (i
= 0; List
[i
]; i
++)
1775 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1783 PWINDOW_OBJECT Window
;
1787 PMSGMEMORY MsgMemoryEntry
;
1789 if(!(Window
= UserGetWindowObject(hWnd
))) return FALSE
;
1791 if(Window
->MessageQueue
!= PsGetCurrentThreadWin32Thread()->MessageQueue
)
1792 { // Send message w/o waiting for it.
1793 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1796 { // Handle message and callback.
1797 UserModeMsg
.hwnd
= hWnd
;
1798 UserModeMsg
.message
= Msg
;
1799 UserModeMsg
.wParam
= wParam
;
1800 UserModeMsg
.lParam
= lParam
;
1801 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1802 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1803 if (! NT_SUCCESS(Status
))
1805 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1808 Result
= co_IntSendMessageTimeoutSingle(
1809 KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1810 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
,
1811 SMTO_NORMAL
, 0, &PResult
);
1813 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1814 if (! NT_SUCCESS(Status
))
1816 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1826 NtUserSendNotifyMessage(HWND hWnd
,
1831 DECLARE_RETURN(BOOL
);
1833 DPRINT("EnterNtUserSendNotifyMessage\n");
1834 UserEnterExclusive();
1836 RETURN(UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
));
1839 DPRINT("Leave NtUserSendNotifyMessage, ret=%i\n",_ret_
);
1847 NtUserWaitMessage(VOID
)
1849 DECLARE_RETURN(BOOL
);
1851 DPRINT("EnterNtUserWaitMessage\n");
1852 UserEnterExclusive();
1854 RETURN(co_IntWaitMessage(NULL
, 0, 0));
1857 DPRINT("Leave NtUserWaitMessage, ret=%i\n",_ret_
);
1863 IntGetQueueStatus(BOOL ClearChanges
)
1865 PUSER_MESSAGE_QUEUE Queue
;
1867 DECLARE_RETURN(DWORD
);
1869 DPRINT("Enter IntGetQueueStatus\n");
1871 Queue
= PsGetCurrentThreadWin32Thread()->MessageQueue
;
1873 Result
= MAKELONG(Queue
->QueueBits
, Queue
->ChangedBits
);
1876 Queue
->ChangedBits
= 0;
1882 DPRINT("Leave IntGetQueueStatus, ret=%i\n",_ret_
);
1887 IntInitMessagePumpHook()
1889 if (((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->ThreadInfo
)
1891 ((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->ThreadInfo
->ClientThreadInfo
.dwcPumpHook
++;
1898 IntUninitMessagePumpHook()
1900 if (((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->ThreadInfo
)
1902 if (((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->ThreadInfo
->ClientThreadInfo
.dwcPumpHook
<= 0)
1906 ((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->ThreadInfo
->ClientThreadInfo
.dwcPumpHook
--;
1919 ULONG_PTR ResultInfo
,
1920 DWORD dwType
, // fnID?
1923 LRESULT lResult
= 0;
1924 PWINDOW_OBJECT Window
= NULL
;
1925 USER_REFERENCE_ENTRY Ref
;
1927 UserEnterExclusive();
1929 /* Validate input */
1930 if (hWnd
&& (hWnd
!= INVALID_HANDLE_VALUE
) && !(Window
= UserGetWindowObject(hWnd
)))
1936 case FNID_DEFWINDOWPROC
:
1937 UserRefObjectCo(Window
, &Ref
);
1938 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
1939 UserDerefObjectCo(Window
);
1941 case FNID_BROADCASTSYSTEMMESSAGE
:
1943 PBROADCASTPARM parm
;
1944 BOOL BadChk
= FALSE
;
1945 DWORD_PTR RetVal
= 0;
1952 ProbeForWrite((PVOID
)ResultInfo
,
1953 sizeof(BROADCASTPARM
),
1955 parm
= (PBROADCASTPARM
)ResultInfo
;
1967 if ( parm
->recipients
& BSM_ALLDESKTOPS
||
1968 parm
->recipients
== BSM_ALLCOMPONENTS
)
1971 else if (parm
->recipients
& BSM_APPLICATIONS
)
1973 if (parm
->flags
& BSF_QUERY
)
1975 if (parm
->flags
& BSF_FORCEIFHUNG
|| parm
->flags
& BSF_NOHANG
)
1977 co_IntSendMessageTimeout( HWND_BROADCAST
,
1985 else if (parm
->flags
& BSF_NOTIMEOUTIFNOTHUNG
)
1987 co_IntSendMessageTimeout( HWND_BROADCAST
,
1991 SMTO_NOTIMEOUTIFNOTHUNG
,
1997 co_IntSendMessageTimeout( HWND_BROADCAST
,
2006 else if (parm
->flags
& BSF_POSTMESSAGE
)
2008 lResult
= UserPostMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2010 else if ( parm
->flags
& BSF_SENDNOTIFYMESSAGE
)
2012 lResult
= UserSendNotifyMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2017 case FNID_SENDMESSAGECALLBACK
:
2019 case FNID_CALLWNDPROC
:
2022 PW32CLIENTINFO ClientInfo
= GetWin32ClientInfo();
2025 CWP
.wParam
= wParam
;
2026 CWP
.lParam
= lParam
;
2027 lResult
= co_HOOK_CallHooks( WH_CALLWNDPROC
,
2029 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2033 case FNID_CALLWNDPROCRET
:
2036 PW32CLIENTINFO ClientInfo
= GetWin32ClientInfo();
2039 CWPR
.wParam
= wParam
;
2040 CWPR
.lParam
= lParam
;
2041 CWPR
.lResult
= ClientInfo
->dwHookData
;
2042 lResult
= co_HOOK_CallHooks( WH_CALLWNDPROCRET
,
2044 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2053 #define INFINITE 0xFFFFFFFF
2054 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2058 NtUserWaitForInputIdle(
2060 IN DWORD dwMilliseconds
,
2064 PW32PROCESS W32Process
;
2067 LARGE_INTEGER Timeout
;
2068 ULONGLONG StartTime
, Run
, Elapsed
= 0;
2070 UserEnterExclusive();
2072 Status
= ObReferenceObjectByHandle(hProcess
,
2073 PROCESS_QUERY_INFORMATION
,
2079 if (!NT_SUCCESS(Status
))
2082 SetLastNtError(Status
);
2086 W32Process
= (PW32PROCESS
)Process
->Win32Process
;
2089 ObDereferenceObject(Process
);
2091 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2095 EngCreateEvent((PEVENT
*)&W32Process
->InputIdleEvent
);
2097 Handles
[0] = Process
;
2098 Handles
[1] = W32Process
->InputIdleEvent
;
2102 ObDereferenceObject(Process
);
2104 return STATUS_SUCCESS
; /* no event to wait on */
2107 StartTime
= ((ULONGLONG
)SharedUserData
->TickCountLowDeprecated
*
2108 SharedUserData
->TickCountMultiplier
/ 16777216);
2110 Run
= dwMilliseconds
;
2112 DPRINT("WFII: waiting for %p\n", Handles
[1] );
2115 Timeout
.QuadPart
= Run
- Elapsed
;
2117 Status
= KeWaitForMultipleObjects( 2,
2123 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2125 UserEnterExclusive();
2127 if (!NT_SUCCESS(Status
))
2129 SetLastNtError(Status
);
2130 Status
= WAIT_FAILED
;
2137 Status
= WAIT_FAILED
;
2143 co_IntPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
);
2147 case STATUS_USER_APC
:
2148 case STATUS_ALERTED
:
2149 case STATUS_TIMEOUT
:
2150 DPRINT1("WFII: timeout\n");
2151 Status
= STATUS_TIMEOUT
;
2155 DPRINT1("WFII: finished\n");
2156 Status
= STATUS_SUCCESS
;
2160 if (dwMilliseconds
!= INFINITE
)
2162 Elapsed
= ((ULONGLONG
)SharedUserData
->TickCountLowDeprecated
*
2163 SharedUserData
->TickCountMultiplier
/ 16777216)
2167 Status
= STATUS_TIMEOUT
;
2174 if (W32Process
->InputIdleEvent
)
2176 EngDeleteEvent((PEVENT
)W32Process
->InputIdleEvent
);
2177 W32Process
->InputIdleEvent
= NULL
;
2179 ObDereferenceObject(Process
);