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
;
1392 /* FIXME: Call hooks. */
1393 if (!(Window
= UserGetWindowObject(hWnd
)))
1398 UserRefObjectCo(Window
, &Ref
);
1400 Win32Thread
= PsGetCurrentThreadWin32Thread();
1402 if (NULL
!= Win32Thread
&&
1403 Window
->MessageQueue
== Win32Thread
->MessageQueue
)
1405 if (Win32Thread
->IsExiting
)
1407 /* Never send messages to exiting threads */
1411 /* See if this message type is present in the table */
1412 MsgMemoryEntry
= FindMsgMemory(Msg
);
1413 if (NULL
== MsgMemoryEntry
)
1415 lParamBufferSize
= -1;
1419 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1422 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
)))
1424 DPRINT1("Failed to pack message parameters\n");
1428 Result
= (ULONG_PTR
)co_IntCallWindowProc(Window
->Wnd
->WndProc
, !Window
->Wnd
->Unicode
, hWnd
, Msg
, wParam
,
1429 lParamPacked
,lParamBufferSize
);
1436 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
)))
1438 DPRINT1("Failed to unpack message parameters\n");
1445 if(uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->MessageQueue
))
1447 /* FIXME - Set a LastError? */
1451 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
1453 /* FIXME - last error? */
1454 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1458 Status
= co_MsqSendMessage(Window
->MessageQueue
, hWnd
, Msg
, wParam
, lParam
,
1459 uTimeout
, (uFlags
& SMTO_BLOCK
), FALSE
, uResult
);
1462 if (STATUS_TIMEOUT
== Status
)
1464 /* MSDN says GetLastError() should return 0 after timeout */
1465 SetLastWin32Error(0);
1468 else if (! NT_SUCCESS(Status
))
1470 SetLastNtError(Status
);
1477 if (Window
) UserDerefObjectCo(Window
);
1482 co_IntSendMessageTimeout(HWND hWnd
,
1490 PWINDOW_OBJECT DesktopWindow
;
1494 if (HWND_BROADCAST
!= hWnd
)
1496 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1499 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1500 if (NULL
== DesktopWindow
)
1502 SetLastWin32Error(ERROR_INTERNAL_ERROR
);
1506 Children
= IntWinListChildren(DesktopWindow
);
1507 if (NULL
== Children
)
1512 for (Child
= Children
; NULL
!= *Child
; Child
++)
1514 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1517 ExFreePool(Children
);
1519 return (LRESULT
) TRUE
;
1523 /* This function posts a message if the destination's message queue belongs to
1524 another thread, otherwise it sends the message. It does not support broadcast
1527 co_IntPostOrSendMessage(HWND hWnd
,
1533 PWINDOW_OBJECT Window
;
1535 if(hWnd
== HWND_BROADCAST
)
1540 if(!(Window
= UserGetWindowObject(hWnd
)))
1545 if(Window
->MessageQueue
!= PsGetCurrentThreadWin32Thread()->MessageQueue
)
1547 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1551 if(!co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
)) {
1556 return (LRESULT
)Result
;
1560 co_IntDoSendMessage(HWND hWnd
,
1565 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1567 LRESULT Result
= TRUE
;
1569 PWINDOW_OBJECT Window
;
1570 NTUSERSENDMESSAGEINFO Info
;
1573 PMSGMEMORY MsgMemoryEntry
;
1575 RtlZeroMemory(&Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1577 /* FIXME: Call hooks. */
1578 if (HWND_BROADCAST
!= hWnd
)
1580 Window
= UserGetWindowObject(hWnd
);
1583 /* Tell usermode to not touch this one */
1584 Info
.HandledByKernel
= TRUE
;
1585 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1592 /* FIXME: Check for an exiting window. */
1594 /* See if the current thread can handle the message */
1595 if (HWND_BROADCAST
!= hWnd
&& NULL
!= PsGetCurrentThreadWin32Thread() &&
1596 Window
->MessageQueue
== PsGetCurrentThreadWin32Thread()->MessageQueue
)
1598 /* Gather the information usermode needs to call the window proc directly */
1599 Info
.HandledByKernel
= FALSE
;
1601 Status
= MmCopyFromCaller(&(Info
.Ansi
), &(UnsafeInfo
->Ansi
),
1603 if (! NT_SUCCESS(Status
))
1605 Info
.Ansi
= ! Window
->Wnd
->Unicode
;
1608 if (Window
->Wnd
->IsSystem
)
1610 Info
.Proc
= (!Info
.Ansi
? Window
->Wnd
->WndProc
: Window
->Wnd
->WndProcExtra
);
1614 Info
.Ansi
= !Window
->Wnd
->Unicode
;
1615 Info
.Proc
= Window
->Wnd
->WndProc
;
1620 /* Must be handled by other thread */
1621 // if (HWND_BROADCAST != hWnd)
1623 // UserDereferenceObject(Window);
1625 Info
.HandledByKernel
= TRUE
;
1626 UserModeMsg
.hwnd
= hWnd
;
1627 UserModeMsg
.message
= Msg
;
1628 UserModeMsg
.wParam
= wParam
;
1629 UserModeMsg
.lParam
= lParam
;
1630 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1631 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1632 if (! NT_SUCCESS(Status
))
1634 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1635 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1636 return (dsm
? 0 : -1);
1640 Result
= co_IntSendMessage(KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1641 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
);
1645 Result
= co_IntSendMessageTimeout(KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1646 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
,
1647 dsm
->uFlags
, dsm
->uTimeout
, &dsm
->Result
);
1649 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1650 if (! NT_SUCCESS(Status
))
1652 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1653 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1654 return(dsm
? 0 : -1);
1658 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1659 if (! NT_SUCCESS(Status
))
1661 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1664 return (LRESULT
)Result
;
1668 NtUserSendMessageTimeout(HWND hWnd
,
1675 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1679 DECLARE_RETURN(BOOL
);
1681 DPRINT("Enter NtUserSendMessageTimeout\n");
1682 UserEnterExclusive();
1684 dsm
.uFlags
= uFlags
;
1685 dsm
.uTimeout
= uTimeout
;
1686 Result
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, &dsm
, UnsafeInfo
);
1687 if(uResult
!= NULL
&& Result
!= 0)
1691 Status
= MmCopyToCaller(uResult
, &dsm
.Result
, sizeof(ULONG_PTR
));
1692 if(!NT_SUCCESS(Status
))
1694 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1701 DPRINT("Leave NtUserSendMessageTimeout, ret=%i\n",_ret_
);
1707 NtUserSendMessage(HWND Wnd
,
1711 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1713 DECLARE_RETURN(BOOL
);
1715 DPRINT("Enter NtUserSendMessage\n");
1716 UserEnterExclusive();
1718 RETURN(co_IntDoSendMessage(Wnd
, Msg
, wParam
, lParam
, NULL
, UnsafeInfo
));
1721 DPRINT("Leave NtUserSendMessage, ret=%i\n",_ret_
);
1728 UserSendNotifyMessage(HWND hWnd
,
1734 // Basicly the same as IntPostOrSendMessage
1735 if (hWnd
== HWND_BROADCAST
) //Handle Broadcast
1738 PWINDOW_OBJECT DesktopWindow
;
1741 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1742 List
= IntWinListChildren(DesktopWindow
);
1746 for (i
= 0; List
[i
]; i
++)
1748 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1756 PWINDOW_OBJECT Window
;
1760 PMSGMEMORY MsgMemoryEntry
;
1762 if(!(Window
= UserGetWindowObject(hWnd
))) return FALSE
;
1764 if(Window
->MessageQueue
!= PsGetCurrentThreadWin32Thread()->MessageQueue
)
1765 { // Send message w/o waiting for it.
1766 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1769 { // Handle message and callback.
1770 UserModeMsg
.hwnd
= hWnd
;
1771 UserModeMsg
.message
= Msg
;
1772 UserModeMsg
.wParam
= wParam
;
1773 UserModeMsg
.lParam
= lParam
;
1774 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1775 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1776 if (! NT_SUCCESS(Status
))
1778 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1781 Result
= co_IntSendMessageTimeoutSingle(
1782 KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1783 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
,
1784 SMTO_NORMAL
, 0, &PResult
);
1786 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1787 if (! NT_SUCCESS(Status
))
1789 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1799 NtUserSendNotifyMessage(HWND hWnd
,
1804 DECLARE_RETURN(BOOL
);
1806 DPRINT("EnterNtUserSendNotifyMessage\n");
1807 UserEnterExclusive();
1809 RETURN(UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
));
1812 DPRINT("Leave NtUserSendNotifyMessage, ret=%i\n",_ret_
);
1820 NtUserWaitMessage(VOID
)
1822 DECLARE_RETURN(BOOL
);
1824 DPRINT("EnterNtUserWaitMessage\n");
1825 UserEnterExclusive();
1827 RETURN(co_IntWaitMessage(NULL
, 0, 0));
1830 DPRINT("Leave NtUserWaitMessage, ret=%i\n",_ret_
);
1836 IntGetQueueStatus(BOOL ClearChanges
)
1838 PUSER_MESSAGE_QUEUE Queue
;
1840 DECLARE_RETURN(DWORD
);
1842 DPRINT("Enter IntGetQueueStatus\n");
1844 Queue
= PsGetCurrentThreadWin32Thread()->MessageQueue
;
1846 Result
= MAKELONG(Queue
->QueueBits
, Queue
->ChangedBits
);
1849 Queue
->ChangedBits
= 0;
1855 DPRINT("Leave IntGetQueueStatus, ret=%i\n",_ret_
);
1860 IntInitMessagePumpHook()
1862 if (((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->ThreadInfo
)
1864 ((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->ThreadInfo
->ClientThreadInfo
.dwcPumpHook
++;
1871 IntUninitMessagePumpHook()
1873 if (((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->ThreadInfo
)
1875 if (((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->ThreadInfo
->ClientThreadInfo
.dwcPumpHook
<= 0)
1879 ((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->ThreadInfo
->ClientThreadInfo
.dwcPumpHook
--;
1892 ULONG_PTR ResultInfo
,
1893 DWORD dwType
, // fnID?
1896 LRESULT lResult
= 0;
1897 PWINDOW_OBJECT Window
= NULL
;
1898 USER_REFERENCE_ENTRY Ref
;
1900 UserEnterExclusive();
1902 /* Validate input */
1903 if (hWnd
&& (hWnd
!= INVALID_HANDLE_VALUE
) && !(Window
= UserGetWindowObject(hWnd
)))
1909 case FNID_DEFWINDOWPROC
:
1910 UserRefObjectCo(Window
, &Ref
);
1911 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
1912 UserDerefObjectCo(Window
);
1914 case FNID_BROADCASTSYSTEMMESSAGE
:
1916 PBROADCASTPARM parm
;
1917 BOOL BadChk
= FALSE
;
1918 DWORD_PTR RetVal
= 0;
1925 ProbeForWrite((PVOID
)ResultInfo
,
1926 sizeof(BROADCASTPARM
),
1928 parm
= (PBROADCASTPARM
)ResultInfo
;
1940 if ( parm
->recipients
& BSM_ALLDESKTOPS
||
1941 parm
->recipients
== BSM_ALLCOMPONENTS
)
1944 else if (parm
->recipients
& BSM_APPLICATIONS
)
1946 if (parm
->flags
& BSF_QUERY
)
1948 if (parm
->flags
& BSF_FORCEIFHUNG
|| parm
->flags
& BSF_NOHANG
)
1950 co_IntSendMessageTimeout( HWND_BROADCAST
,
1958 else if (parm
->flags
& BSF_NOTIMEOUTIFNOTHUNG
)
1960 #define SMTO_NOTIMEOUTIFNOTHUNG 0x0008
1961 co_IntSendMessageTimeout( HWND_BROADCAST
,
1965 SMTO_NOTIMEOUTIFNOTHUNG
,
1971 co_IntSendMessageTimeout( HWND_BROADCAST
,
1980 else if (parm
->flags
& BSF_POSTMESSAGE
)
1982 lResult
= UserPostMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
1984 else if ( parm
->flags
& BSF_SENDNOTIFYMESSAGE
)
1986 lResult
= UserSendNotifyMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
1991 case FNID_SENDMESSAGECALLBACK
:
1998 #define INFINITE 0xFFFFFFFF
1999 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2003 NtUserWaitForInputIdle(
2005 IN DWORD dwMilliseconds
,
2009 PW32PROCESS W32Process
;
2012 LARGE_INTEGER Timeout
;
2013 ULONGLONG StartTime
, Run
, Elapsed
= 0;
2015 UserEnterExclusive();
2017 Status
= ObReferenceObjectByHandle(hProcess
,
2018 PROCESS_QUERY_INFORMATION
,
2024 if (!NT_SUCCESS(Status
))
2027 SetLastNtError(Status
);
2031 W32Process
= (PW32PROCESS
)Process
->Win32Process
;
2034 ObDereferenceObject(Process
);
2036 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2040 EngCreateEvent((PEVENT
*)&W32Process
->InputIdleEvent
);
2042 Handles
[0] = Process
;
2043 Handles
[1] = W32Process
->InputIdleEvent
;
2047 ObDereferenceObject(Process
);
2049 return STATUS_SUCCESS
; /* no event to wait on */
2052 StartTime
= ((ULONGLONG
)SharedUserData
->TickCountLowDeprecated
*
2053 SharedUserData
->TickCountMultiplier
/ 16777216);
2055 Run
= dwMilliseconds
;
2057 DPRINT("WFII: waiting for %p\n", Handles
[1] );
2060 Timeout
.QuadPart
= Run
- Elapsed
;
2062 Status
= KeWaitForMultipleObjects( 2,
2068 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2070 UserEnterExclusive();
2072 if (!NT_SUCCESS(Status
))
2074 SetLastNtError(Status
);
2075 Status
= WAIT_FAILED
;
2082 Status
= WAIT_FAILED
;
2088 co_IntPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
);
2092 case STATUS_USER_APC
:
2093 case STATUS_ALERTED
:
2094 case STATUS_TIMEOUT
:
2095 DPRINT1("WFII: timeout\n");
2096 Status
= STATUS_TIMEOUT
;
2100 DPRINT1("WFII: finished\n");
2101 Status
= STATUS_SUCCESS
;
2105 if (dwMilliseconds
!= INFINITE
)
2107 Elapsed
= ((ULONGLONG
)SharedUserData
->TickCountLowDeprecated
*
2108 SharedUserData
->TickCountMultiplier
/ 16777216)
2112 Status
= STATUS_TIMEOUT
;
2119 if (W32Process
->InputIdleEvent
)
2121 EngDeleteEvent((PEVENT
)W32Process
->InputIdleEvent
);
2122 W32Process
->InputIdleEvent
= NULL
;
2124 ObDereferenceObject(Process
);