2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
5 * FILE: subsys/win32k/ntuser/message.c
6 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * 06-06-2001 CSH Created
11 /* INCLUDES ******************************************************************/
18 #define PM_BADMSGFLAGS ~((QS_RAWINPUT << 16)|PM_QS_SENDMESSAGE|PM_QS_PAINT|PM_QS_POSTMESSAGE|PM_QS_INPUT|PM_NOYIELD|PM_REMOVE)
26 DOSENDMESSAGE
, *PDOSENDMESSAGE
;
28 /* FUNCTIONS *****************************************************************/
31 IntInitMessageImpl(VOID
)
33 return STATUS_SUCCESS
;
37 IntCleanupMessageImpl(VOID
)
39 return STATUS_SUCCESS
;
42 #define MMS_SIZE_WPARAM -1
43 #define MMS_SIZE_WPARAMWCHAR -2
44 #define MMS_SIZE_LPARAMSZ -3
45 #define MMS_SIZE_SPECIAL -4
46 #define MMS_FLAG_READ 0x01
47 #define MMS_FLAG_WRITE 0x02
48 #define MMS_FLAG_READWRITE (MMS_FLAG_READ | MMS_FLAG_WRITE)
49 typedef struct tagMSGMEMORY
55 MSGMEMORY
, *PMSGMEMORY
;
57 static MSGMEMORY MsgMemory
[] =
59 { WM_CREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
60 { WM_DDE_ACK
, sizeof(KMDDELPARAM
), MMS_FLAG_READ
},
61 { WM_DDE_EXECUTE
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
62 { WM_GETMINMAXINFO
, sizeof(MINMAXINFO
), MMS_FLAG_READWRITE
},
63 { WM_GETTEXT
, MMS_SIZE_WPARAMWCHAR
, MMS_FLAG_WRITE
},
64 { WM_NCCALCSIZE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
65 { WM_NCCREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
66 { WM_SETTEXT
, MMS_SIZE_LPARAMSZ
, MMS_FLAG_READ
},
67 { WM_STYLECHANGED
, sizeof(STYLESTRUCT
), MMS_FLAG_READ
},
68 { WM_STYLECHANGING
, sizeof(STYLESTRUCT
), MMS_FLAG_READWRITE
},
69 { WM_COPYDATA
, MMS_SIZE_SPECIAL
, MMS_FLAG_READ
},
70 { WM_WINDOWPOSCHANGED
, sizeof(WINDOWPOS
), MMS_FLAG_READ
},
71 { WM_WINDOWPOSCHANGING
, sizeof(WINDOWPOS
), MMS_FLAG_READWRITE
},
74 static PMSGMEMORY FASTCALL
75 FindMsgMemory(UINT Msg
)
77 PMSGMEMORY MsgMemoryEntry
;
79 /* See if this message type is present in the table */
80 for (MsgMemoryEntry
= MsgMemory
;
81 MsgMemoryEntry
< MsgMemory
+ sizeof(MsgMemory
) / sizeof(MSGMEMORY
);
84 if (Msg
== MsgMemoryEntry
->Message
)
86 return MsgMemoryEntry
;
94 MsgMemorySize(PMSGMEMORY MsgMemoryEntry
, WPARAM wParam
, LPARAM lParam
)
97 PUNICODE_STRING WindowName
;
98 PUNICODE_STRING ClassName
;
103 if (MMS_SIZE_WPARAM
== MsgMemoryEntry
->Size
)
107 else if (MMS_SIZE_WPARAMWCHAR
== MsgMemoryEntry
->Size
)
109 Size
= (UINT
) (wParam
* sizeof(WCHAR
));
111 else if (MMS_SIZE_LPARAMSZ
== MsgMemoryEntry
->Size
)
113 Size
= (UINT
) ((wcslen((PWSTR
) lParam
) + 1) * sizeof(WCHAR
));
115 else if (MMS_SIZE_SPECIAL
== MsgMemoryEntry
->Size
)
117 switch(MsgMemoryEntry
->Message
)
121 Cs
= (CREATESTRUCTW
*) lParam
;
122 WindowName
= (PUNICODE_STRING
) Cs
->lpszName
;
123 ClassName
= (PUNICODE_STRING
) Cs
->lpszClass
;
124 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
125 if (IS_ATOM(ClassName
->Buffer
))
127 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
131 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
136 Size
= wParam
? sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
) : sizeof(RECT
);
140 Size
= sizeof(COPYDATASTRUCT
) + ((PCOPYDATASTRUCT
)lParam
)->cbData
;
143 case WM_COPYGLOBALDATA
:
155 Size
= MsgMemoryEntry
->Size
;
158 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
160 DPRINT1("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH2_GetExceptionCode());
168 PackParam(LPARAM
*lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolNeeded
)
170 NCCALCSIZE_PARAMS
*UnpackedNcCalcsize
;
171 NCCALCSIZE_PARAMS
*PackedNcCalcsize
;
172 CREATESTRUCTW
*UnpackedCs
;
173 CREATESTRUCTW
*PackedCs
;
174 PLARGE_STRING WindowName
;
175 PUNICODE_STRING ClassName
;
180 *lParamPacked
= lParam
;
182 if (NonPagedPoolNeeded
)
183 PoolType
= NonPagedPool
;
185 PoolType
= PagedPool
;
187 if (WM_NCCALCSIZE
== Msg
&& wParam
)
190 UnpackedNcCalcsize
= (NCCALCSIZE_PARAMS
*) lParam
;
191 PackedNcCalcsize
= ExAllocatePoolWithTag(PoolType
,
192 sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
),
195 if (NULL
== PackedNcCalcsize
)
197 DPRINT1("Not enough memory to pack lParam\n");
198 return STATUS_NO_MEMORY
;
200 RtlCopyMemory(PackedNcCalcsize
, UnpackedNcCalcsize
, sizeof(NCCALCSIZE_PARAMS
));
201 PackedNcCalcsize
->lppos
= (PWINDOWPOS
) (PackedNcCalcsize
+ 1);
202 RtlCopyMemory(PackedNcCalcsize
->lppos
, UnpackedNcCalcsize
->lppos
, sizeof(WINDOWPOS
));
203 *lParamPacked
= (LPARAM
) PackedNcCalcsize
;
205 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
207 UnpackedCs
= (CREATESTRUCTW
*) lParam
;
208 WindowName
= (PLARGE_STRING
) UnpackedCs
->lpszName
;
209 ClassName
= (PUNICODE_STRING
) UnpackedCs
->lpszClass
;
210 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
211 if (IS_ATOM(ClassName
->Buffer
))
213 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
217 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
219 PackedCs
= ExAllocatePoolWithTag(PoolType
, Size
, TAG_MSG
);
220 if (NULL
== PackedCs
)
222 DPRINT1("Not enough memory to pack lParam\n");
223 return STATUS_NO_MEMORY
;
225 RtlCopyMemory(PackedCs
, UnpackedCs
, sizeof(CREATESTRUCTW
));
226 CsData
= (PCHAR
) (PackedCs
+ 1);
227 PackedCs
->lpszName
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
228 RtlCopyMemory(CsData
, WindowName
->Buffer
, WindowName
->Length
);
229 CsData
+= WindowName
->Length
;
230 *((WCHAR
*) CsData
) = L
'\0';
231 CsData
+= sizeof(WCHAR
);
232 PackedCs
->lpszClass
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
233 if (IS_ATOM(ClassName
->Buffer
))
235 *((WCHAR
*) CsData
) = L
'A';
236 CsData
+= sizeof(WCHAR
);
237 *((ATOM
*) CsData
) = (ATOM
)(DWORD_PTR
) ClassName
->Buffer
;
238 CsData
+= sizeof(ATOM
);
242 *((WCHAR
*) CsData
) = L
'S';
243 CsData
+= sizeof(WCHAR
);
244 RtlCopyMemory(CsData
, ClassName
->Buffer
, ClassName
->Length
);
245 CsData
+= ClassName
->Length
;
246 *((WCHAR
*) CsData
) = L
'\0';
247 CsData
+= sizeof(WCHAR
);
249 ASSERT(CsData
== (PCHAR
) PackedCs
+ Size
);
250 *lParamPacked
= (LPARAM
) PackedCs
;
253 else if (PoolType
== NonPagedPool
)
255 PMSGMEMORY MsgMemoryEntry
;
258 MsgMemoryEntry
= FindMsgMemory(Msg
);
260 if ((!MsgMemoryEntry
) || (MsgMemoryEntry
->Size
< 0))
262 /* Keep previous behavior */
263 return STATUS_SUCCESS
;
265 PackedData
= ExAllocatePoolWithTag(NonPagedPool
, MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
), TAG_MSG
);
266 RtlCopyMemory(PackedData
, (PVOID
)lParam
, MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
));
267 *lParamPacked
= (LPARAM
)PackedData
;
270 return STATUS_SUCCESS
;
274 UnpackParam(LPARAM lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolUsed
)
276 NCCALCSIZE_PARAMS
*UnpackedParams
;
277 NCCALCSIZE_PARAMS
*PackedParams
;
278 PWINDOWPOS UnpackedWindowPos
;
280 if (lParamPacked
== lParam
)
282 return STATUS_SUCCESS
;
285 if (WM_NCCALCSIZE
== Msg
&& wParam
)
287 PackedParams
= (NCCALCSIZE_PARAMS
*) lParamPacked
;
288 UnpackedParams
= (NCCALCSIZE_PARAMS
*) lParam
;
289 UnpackedWindowPos
= UnpackedParams
->lppos
;
290 RtlCopyMemory(UnpackedParams
, PackedParams
, sizeof(NCCALCSIZE_PARAMS
));
291 UnpackedParams
->lppos
= UnpackedWindowPos
;
292 RtlCopyMemory(UnpackedWindowPos
, PackedParams
+ 1, sizeof(WINDOWPOS
));
293 ExFreePool((PVOID
) lParamPacked
);
295 return STATUS_SUCCESS
;
297 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
299 ExFreePool((PVOID
) lParamPacked
);
301 return STATUS_SUCCESS
;
303 else if (NonPagedPoolUsed
)
305 PMSGMEMORY MsgMemoryEntry
;
306 MsgMemoryEntry
= FindMsgMemory(Msg
);
307 if (MsgMemoryEntry
->Size
< 0)
309 /* Keep previous behavior */
310 return STATUS_INVALID_PARAMETER
;
313 if (MsgMemory
->Flags
== MMS_FLAG_READWRITE
)
315 //RtlCopyMemory((PVOID)lParam, (PVOID)lParamPacked, MsgMemory->Size);
317 ExFreePool((PVOID
) lParamPacked
);
318 return STATUS_SUCCESS
;
323 return STATUS_INVALID_PARAMETER
;
330 ( PWINDOW_OBJECT Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
332 BOOL SameThread
= FALSE
;
334 if (Window
->pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
337 if ((!SameThread
&& (Window
->pti
->fsHooks
& HOOKID_TO_FLAG(WH_CALLWNDPROC
))) ||
338 (SameThread
&& ISITHOOKED(WH_CALLWNDPROC
)) )
345 co_HOOK_CallHooks( WH_CALLWNDPROC
, HC_ACTION
, SameThread
, (LPARAM
)&CWP
);
353 ( PWINDOW_OBJECT Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*uResult
)
355 BOOL SameThread
= FALSE
;
357 if (Window
->pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
360 if ((!SameThread
&& (Window
->pti
->fsHooks
& HOOKID_TO_FLAG(WH_CALLWNDPROCRET
))) ||
361 (SameThread
&& ISITHOOKED(WH_CALLWNDPROCRET
)) )
366 CWPR
.wParam
= wParam
;
367 CWPR
.lParam
= lParam
;
368 CWPR
.lResult
= *uResult
;
369 co_HOOK_CallHooks( WH_CALLWNDPROCRET
, HC_ACTION
, SameThread
, (LPARAM
)&CWPR
);
375 IntDispatchMessage(PMSG pMsg
)
377 LARGE_INTEGER TickCount
;
380 PMSGMEMORY MsgMemoryEntry
;
381 INT lParamBufferSize
;
383 PWINDOW_OBJECT Window
= NULL
;
387 Window
= UserGetWindowObject(pMsg
->hwnd
);
388 if (!Window
|| !Window
->Wnd
) return 0;
391 if (((pMsg
->message
== WM_SYSTIMER
) ||
392 (pMsg
->message
== WM_TIMER
)) &&
395 if (pMsg
->message
== WM_TIMER
)
397 if (ValidateTimerCallback(PsGetCurrentThreadWin32Thread(),Window
,pMsg
->wParam
,pMsg
->lParam
))
399 KeQueryTickCount(&TickCount
);
400 Time
= MsqCalculateMessageTime(&TickCount
);
401 return co_IntCallWindowProc((WNDPROC
)pMsg
->lParam
,
413 PTIMER pTimer
= FindSystemTimer(pMsg
);
414 if (pTimer
&& pTimer
->pfn
)
416 KeQueryTickCount(&TickCount
);
417 Time
= MsqCalculateMessageTime(&TickCount
);
418 pTimer
->pfn(pMsg
->hwnd
, WM_SYSTIMER
, (UINT
)pMsg
->wParam
, Time
);
424 if ( !Window
|| !Window
->Wnd
) return 0;
426 /* See if this message type is present in the table */
427 MsgMemoryEntry
= FindMsgMemory(pMsg
->message
);
428 if ( !MsgMemoryEntry
)
430 lParamBufferSize
= -1;
434 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, pMsg
->wParam
, pMsg
->lParam
);
437 if (! NT_SUCCESS(PackParam(&lParamPacked
, pMsg
->message
, pMsg
->wParam
, pMsg
->lParam
, FALSE
)))
439 DPRINT1("Failed to pack message parameters\n");
443 retval
= co_IntCallWindowProc( Window
->Wnd
->lpfnWndProc
,
444 !Window
->Wnd
->Unicode
,
451 if (! NT_SUCCESS(UnpackParam(lParamPacked
, pMsg
->message
, pMsg
->wParam
, pMsg
->lParam
, FALSE
)))
453 DPRINT1("Failed to unpack message parameters\n");
456 if (pMsg
->message
== WM_PAINT
)
458 /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
459 HRGN hrgn
= IntSysCreateRectRgn( 0, 0, 0, 0 );
460 co_UserGetUpdateRgn( Window
, hrgn
, TRUE
);
461 REGION_FreeRgnByHandle( hrgn
);
467 co_IntSendHitTestMessages(PUSER_MESSAGE_QUEUE ThreadQueue
, LPMSG Msg
)
469 if(!Msg
->hwnd
|| ThreadQueue
->CaptureWindow
)
478 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(HTCLIENT
, Msg
->message
));
483 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(Msg
->wParam
, Msg
->message
));
490 case WM_LBUTTONDBLCLK
:
491 case WM_MBUTTONDBLCLK
:
492 case WM_RBUTTONDBLCLK
:
493 case WM_XBUTTONDBLCLK
:
496 PSYSTEM_CURSORINFO CurInfo
;
497 CurInfo
= IntGetSysCursorInfo();
499 wParam
= (WPARAM
)(CurInfo
->ButtonsDown
);
501 co_IntSendMessage(Msg
->hwnd
, WM_MOUSEMOVE
, wParam
, Msg
->lParam
);
502 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(HTCLIENT
, Msg
->message
));
505 case WM_NCLBUTTONDOWN
:
506 case WM_NCMBUTTONDOWN
:
507 case WM_NCRBUTTONDOWN
:
508 case WM_NCXBUTTONDOWN
:
509 case WM_NCLBUTTONDBLCLK
:
510 case WM_NCMBUTTONDBLCLK
:
511 case WM_NCRBUTTONDBLCLK
:
512 case WM_NCXBUTTONDBLCLK
:
514 co_IntSendMessage(Msg
->hwnd
, WM_NCMOUSEMOVE
, (WPARAM
)Msg
->wParam
, Msg
->lParam
);
515 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(Msg
->wParam
, Msg
->message
));
522 co_IntActivateWindowMouse(
523 PUSER_MESSAGE_QUEUE ThreadQueue
,
525 PWINDOW_OBJECT MsgWindow
,
529 PWINDOW_OBJECT Parent
;
531 ASSERT_REFS_CO(MsgWindow
);
533 if(*HitTest
== (USHORT
)HTTRANSPARENT
)
535 /* eat the message, search again! */
539 Parent
= IntGetParent(MsgWindow
);//fixme: deref retval?
541 /* If no parent window, pass MsgWindows HWND as wParam. Fixes bug #3111 */
542 Result
= co_IntSendMessage(MsgWindow
->hSelf
,
544 (WPARAM
) (Parent
? Parent
->hSelf
: MsgWindow
->hSelf
),
545 (LPARAM
)MAKELONG(*HitTest
, Msg
->message
)
550 case MA_NOACTIVATEANDEAT
:
554 case MA_ACTIVATEANDEAT
:
555 co_IntMouseActivateWindow(MsgWindow
);
559 co_IntMouseActivateWindow(MsgWindow
);
567 co_IntTranslateMouseMessage(
568 PUSER_MESSAGE_QUEUE ThreadQueue
,
573 PWINDOW_OBJECT Window
;
574 USER_REFERENCE_ENTRY Ref
, DesktopRef
;
576 if(!(Window
= UserGetWindowObject(Msg
->hwnd
)))
578 /* let's just eat the message?! */
582 UserRefObjectCo(Window
, &Ref
);
584 if ( ThreadQueue
== Window
->pti
->MessageQueue
&&
585 ThreadQueue
->CaptureWindow
!= Window
->hSelf
)
587 /* only send WM_NCHITTEST messages if we're not capturing the window! */
588 *HitTest
= co_IntSendMessage(Window
->hSelf
, WM_NCHITTEST
, 0,
589 MAKELONG(Msg
->pt
.x
, Msg
->pt
.y
));
591 if (*HitTest
== (USHORT
)HTTRANSPARENT
)
593 PWINDOW_OBJECT DesktopWindow
;
594 HWND hDesktop
= IntGetDesktopWindow();
596 if ((DesktopWindow
= UserGetWindowObject(hDesktop
)))
600 UserRefObjectCo(DesktopWindow
, &DesktopRef
);
602 co_WinPosWindowFromPoint(DesktopWindow
, Window
->pti
->MessageQueue
, &Msg
->pt
, &Wnd
);
607 /* post the message to the other window */
608 Msg
->hwnd
= Wnd
->hSelf
;
609 if(!(Wnd
->state
& WINDOWSTATUS_DESTROYING
))
611 MsqPostMessage(Wnd
->pti
->MessageQueue
, Msg
, FALSE
,
612 Msg
->message
== WM_MOUSEMOVE
? QS_MOUSEMOVE
:
616 /* eat the message */
617 UserDereferenceObject(Wnd
);
618 UserDerefObjectCo(DesktopWindow
);
619 UserDerefObjectCo(Window
);
622 UserDereferenceObject(Wnd
);
625 UserDerefObjectCo(DesktopWindow
);
634 if ( gspv
.bMouseClickLock
&&
635 ( (Msg
->message
== WM_LBUTTONUP
) ||
636 (Msg
->message
== WM_LBUTTONDOWN
) ) )
638 if (MsqIsClkLck(Msg
, Remove
))
640 // FIXME: drop the message, hack: use WM_NULL
641 Msg
->message
= WM_NULL
;
645 if (IS_BTN_MESSAGE(Msg
->message
, DOWN
))
647 /* generate double click messages, if necessary */
648 if ((((*HitTest
) != HTCLIENT
) ||
649 (Window
->Wnd
->pcls
->style
& CS_DBLCLKS
)) &&
650 MsqIsDblClk(Msg
, Remove
))
652 Msg
->message
+= WM_LBUTTONDBLCLK
- WM_LBUTTONDOWN
;
656 if(Msg
->message
!= WM_MOUSEWHEEL
)
659 if ((*HitTest
) != HTCLIENT
)
661 Msg
->message
+= WM_NCMOUSEMOVE
- WM_MOUSEMOVE
;
662 if ( (Msg
->message
== WM_NCRBUTTONUP
) &&
663 (((*HitTest
) == HTCAPTION
) || ((*HitTest
) == HTSYSMENU
)) )
665 Msg
->message
= WM_CONTEXTMENU
;
666 Msg
->wParam
= (WPARAM
)Window
->hSelf
;
670 Msg
->wParam
= *HitTest
;
672 Msg
->lParam
= MAKELONG(Msg
->pt
.x
, Msg
->pt
.y
);
674 else if ( ThreadQueue
->MoveSize
== NULL
&&
675 ThreadQueue
->MenuOwner
== NULL
)
677 /* NOTE: Msg->pt should remain in screen coordinates. -- FiN */
678 Msg
->lParam
= MAKELONG(
679 Msg
->pt
.x
- (WORD
)Window
->Wnd
->rcClient
.left
,
680 Msg
->pt
.y
- (WORD
)Window
->Wnd
->rcClient
.top
);
684 UserDerefObjectCo(Window
);
688 BOOL
ProcessMouseMessage(MSG
* Msg
, USHORT HitTest
, UINT RemoveMsg
)
690 MOUSEHOOKSTRUCT MHook
;
693 Event
.message
= Msg
->message
;
694 Event
.time
= Msg
->time
;
695 Event
.hwnd
= Msg
->hwnd
;
696 Event
.paramL
= Msg
->pt
.x
;
697 Event
.paramH
= Msg
->pt
.y
;
698 co_HOOK_CallHooks( WH_JOURNALRECORD
, HC_ACTION
, 0, (LPARAM
)&Event
);
702 MHook
.hwnd
= Msg
->hwnd
;
703 MHook
.wHitTestCode
= HitTest
;
704 MHook
.dwExtraInfo
= 0;
705 if (co_HOOK_CallHooks( WH_MOUSE
,
706 RemoveMsg
? HC_ACTION
: HC_NOREMOVE
,
710 if (ISITHOOKED(WH_CBT
))
713 MHook
.hwnd
= Msg
->hwnd
;
714 MHook
.wHitTestCode
= HitTest
;
715 MHook
.dwExtraInfo
= 0;
716 co_HOOK_CallHooks( WH_CBT
,
727 BOOL
ProcessKeyboardMessage(MSG
* Msg
, UINT RemoveMsg
)
731 Event
.message
= Msg
->message
;
732 Event
.hwnd
= Msg
->hwnd
;
733 Event
.time
= Msg
->time
;
734 Event
.paramL
= (Msg
->wParam
& 0xFF) | (HIWORD(Msg
->lParam
) << 8);
735 Event
.paramH
= Msg
->lParam
& 0x7FFF;
736 if (HIWORD(Msg
->lParam
) & 0x0100) Event
.paramH
|= 0x8000;
737 co_HOOK_CallHooks( WH_JOURNALRECORD
, HC_ACTION
, 0, (LPARAM
)&Event
);
739 if (co_HOOK_CallHooks( WH_KEYBOARD
,
740 RemoveMsg
? HC_ACTION
: HC_NOREMOVE
,
744 if (ISITHOOKED(WH_CBT
))
746 /* skip this message */
747 co_HOOK_CallHooks( WH_CBT
,
757 * Internal version of PeekMessage() doing all the work
760 co_IntPeekMessage( PUSER_MESSAGE Msg
,
761 PWINDOW_OBJECT Window
,
767 LARGE_INTEGER LargeTickCount
;
768 PUSER_MESSAGE_QUEUE ThreadQueue
;
769 PUSER_MESSAGE Message
;
770 BOOL Present
, RemoveMessages
;
771 USER_REFERENCE_ENTRY Ref
;
774 /* The queues and order in which they are checked are documented in the MSDN
775 article on GetMessage() */
777 pti
= PsGetCurrentThreadWin32Thread();
778 ThreadQueue
= pti
->MessageQueue
;
780 /* Inspect RemoveMsg flags */
782 The only flag we process is PM_REMOVE.
783 Processing (High word) PM_QS_Xx Is needed. This and MsgFilterXxx can result
784 with QS_Xx flags to be used to isolate which message check to test for.
785 ATM, we look at all messages and the filters are sent to co_MsqFindMessage
786 and there, it is cross checked.
787 Example: Wine server/queue.c is_keyboard_msg, check_msg_filter and
788 filter_contains_hw_range.
790 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
793 If no filter is specified, messages are processed in the following order:
797 * Input (hardware) messages and system internal events
798 * Sent messages (again)
806 KeQueryTickCount(&LargeTickCount
);
807 ThreadQueue
->LastMsgRead
= LargeTickCount
.u
.LowPart
;
809 /* Dispatch sent messages here. */
810 while (co_MsqDispatchOneSentMessage(ThreadQueue
))
813 /* Now look for a quit message. */
815 if (ThreadQueue
->QuitPosted
)
817 /* According to the PSDK, WM_QUIT messages are always returned, regardless
818 of the filter specified */
819 Msg
->Msg
.hwnd
= NULL
;
820 Msg
->Msg
.message
= WM_QUIT
;
821 Msg
->Msg
.wParam
= ThreadQueue
->QuitExitCode
;
823 Msg
->FreeLParam
= FALSE
;
826 ThreadQueue
->QuitPosted
= FALSE
;
831 /* Now check for normal messages. */
832 Present
= co_MsqFindMessage( ThreadQueue
,
841 RtlCopyMemory(Msg
, Message
, sizeof(USER_MESSAGE
));
844 MsqDestroyMessage(Message
);
849 /* Check for hardware events. */
850 Present
= co_MsqFindMessage( ThreadQueue
,
859 RtlCopyMemory(Msg
, Message
, sizeof(USER_MESSAGE
));
862 MsqDestroyMessage(Message
);
867 /* Check for sent messages again. */
868 while (co_MsqDispatchOneSentMessage(ThreadQueue
))
871 /* Check for paint messages. */
872 if ( IntGetPaintMessage( Window
,
879 Msg
->FreeLParam
= FALSE
;
883 if (PostTimerMessages(Window
))
892 PWINDOW_OBJECT MsgWindow
= NULL
;
894 /* Mouse message process */
897 ( MsgWindow
= UserGetWindowObject(Msg
->Msg
.hwnd
) ) &&
898 Msg
->Msg
.message
>= WM_MOUSEFIRST
&&
899 Msg
->Msg
.message
<= WM_MOUSELAST
)
903 UserRefObjectCo(MsgWindow
, &Ref
);
905 if ( co_IntTranslateMouseMessage( ThreadQueue
,
909 /* FIXME - check message filter again, if the message doesn't match anymore,
912 UserDerefObjectCo(MsgWindow
);
913 /* eat the message, search again */
917 if(ThreadQueue
->CaptureWindow
== NULL
)
919 co_IntSendHitTestMessages(ThreadQueue
, &Msg
->Msg
);
921 if ( ( Msg
->Msg
.message
!= WM_MOUSEMOVE
&&
922 Msg
->Msg
.message
!= WM_NCMOUSEMOVE
) &&
923 IS_BTN_MESSAGE(Msg
->Msg
.message
, DOWN
) &&
924 co_IntActivateWindowMouse(ThreadQueue
, &Msg
->Msg
, MsgWindow
, &HitTest
) )
926 UserDerefObjectCo(MsgWindow
);
927 /* eat the message, search again */
932 UserDerefObjectCo(MsgWindow
);
936 co_IntSendHitTestMessages(ThreadQueue
, &Msg
->Msg
);
941 // UserDereferenceObject(MsgWindow);
947 if ( ( Msg
->Msg
.hwnd
&&
948 Msg
->Msg
.message
>= WM_MOUSEFIRST
&&
949 Msg
->Msg
.message
<= WM_MOUSELAST
) &&
950 co_IntTranslateMouseMessage( ThreadQueue
,
954 /* FIXME - check message filter again, if the message doesn't match anymore,
957 /* eat the message, search again */
962 if ( ISITHOOKED(WH_MOUSE
) && IS_MOUSE_MESSAGE(Msg
->Msg
.message
))
964 if(!ProcessMouseMessage(&Msg
->Msg
, HitTest
, RemoveMsg
))
970 if ( ISITHOOKED(WH_KEYBOARD
) && IS_KBD_MESSAGE(Msg
->Msg
.message
))
972 if(!ProcessKeyboardMessage(&Msg
->Msg
, RemoveMsg
))
977 // The WH_GETMESSAGE hook enables an application to monitor messages about to
978 // be returned by the GetMessage or PeekMessage function.
979 if (ISITHOOKED(WH_GETMESSAGE
))
981 //DPRINT1("Peek WH_GETMESSAGE -> %x\n",&Msg);
982 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)&Msg
->Msg
);
990 static NTSTATUS FASTCALL
991 CopyMsgToKernelMem(MSG
*KernelModeMsg
, MSG
*UserModeMsg
, PMSGMEMORY MsgMemoryEntry
)
998 *KernelModeMsg
= *UserModeMsg
;
1000 /* See if this message type is present in the table */
1001 if (NULL
== MsgMemoryEntry
)
1003 /* Not present, no copying needed */
1004 return STATUS_SUCCESS
;
1007 /* Determine required size */
1008 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
1012 /* Allocate kernel mem */
1013 KernelMem
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
1014 if (NULL
== KernelMem
)
1016 DPRINT1("Not enough memory to copy message to kernel mem\n");
1017 return STATUS_NO_MEMORY
;
1019 KernelModeMsg
->lParam
= (LPARAM
) KernelMem
;
1021 /* Copy data if required */
1022 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_READ
))
1024 Status
= MmCopyFromCaller(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
1025 if (! NT_SUCCESS(Status
))
1027 DPRINT1("Failed to copy message to kernel: invalid usermode buffer\n");
1028 ExFreePoolWithTag(KernelMem
, TAG_MSG
);
1034 /* Make sure we don't pass any secrets to usermode */
1035 RtlZeroMemory(KernelMem
, Size
);
1040 KernelModeMsg
->lParam
= 0;
1043 return STATUS_SUCCESS
;
1046 static NTSTATUS FASTCALL
1047 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
1050 PMSGMEMORY MsgMemoryEntry
;
1053 /* See if this message type is present in the table */
1054 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
1055 if (NULL
== MsgMemoryEntry
)
1057 /* Not present, no copying needed */
1058 return STATUS_SUCCESS
;
1061 /* Determine required size */
1062 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
1066 /* Copy data if required */
1067 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
1069 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
1070 if (! NT_SUCCESS(Status
))
1072 DPRINT1("Failed to copy message from kernel: invalid usermode buffer\n");
1073 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
1078 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
1081 return STATUS_SUCCESS
;
1084 static BOOL FASTCALL
1085 co_IntWaitMessage( PWINDOW_OBJECT Window
,
1090 PUSER_MESSAGE_QUEUE ThreadQueue
;
1091 NTSTATUS Status
= STATUS_SUCCESS
;
1094 pti
= PsGetCurrentThreadWin32Thread();
1095 ThreadQueue
= pti
->MessageQueue
;
1099 if ( co_IntPeekMessage( &Msg
,
1107 /* Nothing found. Wait for new messages. */
1108 Status
= co_MsqWaitForNewMessages( ThreadQueue
,
1113 while ( (STATUS_WAIT_0
<= Status
&& Status
<= STATUS_WAIT_63
) ||
1114 STATUS_TIMEOUT
== Status
);
1116 if (!NT_SUCCESS(Status
))
1118 SetLastNtError(Status
);
1119 DPRINT1("Exit co_IntWaitMessage on error!\n");
1126 co_IntGetPeekMessage( PMSG pMsg
,
1134 PWINDOW_OBJECT Window
;
1137 if ( hWnd
== HWND_TOPMOST
||
1138 hWnd
== HWND_BROADCAST
)
1141 /* Validate input */
1142 if (hWnd
&& hWnd
!= HWND_BOTTOM
)
1144 if (!(Window
= UserGetWindowObject(hWnd
)))
1154 Window
= (PWINDOW_OBJECT
)hWnd
;
1157 if (MsgFilterMax
< MsgFilterMin
)
1165 Present
= co_IntPeekMessage( &Msg
,
1172 RtlCopyMemory( pMsg
, &Msg
.Msg
, sizeof(MSG
));
1175 return (WM_QUIT
!= pMsg
->message
);
1180 if ( bGMSG
&& !co_IntWaitMessage(Window
, MsgFilterMin
, MsgFilterMax
) )
1186 if (!(RemoveMsg
& PM_NOYIELD
))
1188 // Yield this thread!
1191 UserEnterExclusive();
1192 // Fall through to fail.
1196 while( bGMSG
&& !Present
);
1202 UserPostThreadMessage( DWORD idThread
,
1209 PTHREADINFO pThread
;
1210 LARGE_INTEGER LargeTickCount
;
1213 DPRINT1("UserPostThreadMessage wParam 0x%x lParam 0x%x\n", wParam
,lParam
);
1215 if (FindMsgMemory(Msg
) != 0)
1217 SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY
);
1221 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
1223 if( Status
== STATUS_SUCCESS
)
1225 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
1227 !pThread
->MessageQueue
||
1228 (pThread
->TIF_flags
& TIF_INCLEANUP
))
1230 ObDereferenceObject( peThread
);
1234 Message
.hwnd
= NULL
;
1235 Message
.message
= Msg
;
1236 Message
.wParam
= wParam
;
1237 Message
.lParam
= lParam
;
1238 Message
.pt
= gpsi
->ptCursor
;
1240 KeQueryTickCount(&LargeTickCount
);
1241 pThread
->timeLast
= Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1242 MsqPostMessage(pThread
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
);
1243 ObDereferenceObject( peThread
);
1248 SetLastNtError( Status
);
1254 UserPostMessage( HWND Wnd
,
1261 LARGE_INTEGER LargeTickCount
;
1263 if (FindMsgMemory(Msg
) != 0)
1265 SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY
);
1270 return UserPostThreadMessage( PtrToInt(PsGetCurrentThreadId()),
1275 if (Wnd
== HWND_BROADCAST
)
1278 PWINDOW_OBJECT DesktopWindow
;
1281 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1282 List
= IntWinListChildren(DesktopWindow
);
1286 UserPostMessage(DesktopWindow
->hSelf
, Msg
, wParam
, lParam
);
1287 for (i
= 0; List
[i
]; i
++)
1288 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1294 PWINDOW_OBJECT Window
;
1296 Window
= UserGetWindowObject(Wnd
);
1297 if ( !Window
|| !Window
->Wnd
)
1302 pti
= Window
->Wnd
->head
.pti
;
1303 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1305 DPRINT1("Attempted to post message to window 0x%x when the thread is in cleanup!\n", Wnd
);
1309 if ( Window
->state
& WINDOWSTATUS_DESTROYING
)
1311 DPRINT1("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd
);
1312 /* FIXME - last error code? */
1318 MsqPostQuitMessage(Window
->pti
->MessageQueue
, wParam
);
1323 Message
.message
= Msg
;
1324 Message
.wParam
= wParam
;
1325 Message
.lParam
= lParam
;
1326 Message
.pt
= gpsi
->ptCursor
;
1327 KeQueryTickCount(&LargeTickCount
);
1328 pti
->timeLast
= Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1329 MsqPostMessage(Window
->pti
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
);
1337 co_IntSendMessage( HWND hWnd
,
1342 ULONG_PTR Result
= 0;
1343 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1345 return (LRESULT
)Result
;
1352 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1358 ULONG_PTR
*uResult
)
1362 PWINDOW_OBJECT Window
= NULL
;
1363 PMSGMEMORY MsgMemoryEntry
;
1364 INT lParamBufferSize
;
1365 LPARAM lParamPacked
;
1366 PTHREADINFO Win32Thread
;
1367 DECLARE_RETURN(LRESULT
);
1368 USER_REFERENCE_ENTRY Ref
;
1370 if (!(Window
= UserGetWindowObject(hWnd
)))
1375 UserRefObjectCo(Window
, &Ref
);
1377 Win32Thread
= PsGetCurrentThreadWin32Thread();
1379 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1381 if ( NULL
!= Win32Thread
&&
1382 Window
->pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1384 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1386 /* Never send messages to exiting threads */
1390 /* See if this message type is present in the table */
1391 MsgMemoryEntry
= FindMsgMemory(Msg
);
1392 if (NULL
== MsgMemoryEntry
)
1394 lParamBufferSize
= -1;
1398 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1401 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1403 DPRINT1("Failed to pack message parameters\n");
1407 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->Wnd
->lpfnWndProc
,
1408 !Window
->Wnd
->Unicode
,
1419 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1421 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1423 DPRINT1("Failed to unpack message parameters\n");
1430 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->pti
->MessageQueue
))
1432 /* FIXME - Set a LastError? */
1436 if (Window
->state
& WINDOWSTATUS_DESTROYING
)
1438 /* FIXME - last error? */
1439 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1445 Status
= co_MsqSendMessage( Window
->pti
->MessageQueue
,
1451 (uFlags
& SMTO_BLOCK
),
1455 while ((STATUS_TIMEOUT
== Status
) &&
1456 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1457 !MsqIsHung(Window
->pti
->MessageQueue
));
1459 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1461 if (STATUS_TIMEOUT
== Status
)
1465 Microsoft Windows 2000: If GetLastError returns zero, then the function
1467 XP+ : If the function fails or times out, the return value is zero.
1468 To get extended error information, call GetLastError. If GetLastError
1469 returns ERROR_TIMEOUT, then the function timed out.
1471 SetLastWin32Error(ERROR_TIMEOUT
);
1474 else if (! NT_SUCCESS(Status
))
1476 SetLastNtError(Status
);
1483 if (Window
) UserDerefObjectCo(Window
);
1488 co_IntSendMessageTimeout( HWND hWnd
,
1494 ULONG_PTR
*uResult
)
1496 PWINDOW_OBJECT DesktopWindow
;
1500 if (HWND_BROADCAST
!= hWnd
)
1502 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1505 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1506 if (NULL
== DesktopWindow
)
1508 SetLastWin32Error(ERROR_INTERNAL_ERROR
);
1512 /* Send message to the desktop window too! */
1513 co_IntSendMessageTimeoutSingle(DesktopWindow
->hSelf
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1515 Children
= IntWinListChildren(DesktopWindow
);
1516 if (NULL
== Children
)
1521 for (Child
= Children
; NULL
!= *Child
; Child
++)
1523 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1526 ExFreePool(Children
);
1528 return (LRESULT
) TRUE
;
1531 LRESULT FASTCALL
co_IntSendMessageNoWait(HWND hWnd
,
1536 ULONG_PTR Result
= 0;
1537 co_IntSendMessageWithCallBack(hWnd
,
1548 co_IntSendMessageWithCallBack( HWND hWnd
,
1552 SENDASYNCPROC CompletionCallback
,
1553 ULONG_PTR CompletionCallbackContext
,
1557 PWINDOW_OBJECT Window
= NULL
;
1558 PMSGMEMORY MsgMemoryEntry
;
1559 INT lParamBufferSize
;
1560 LPARAM lParamPacked
;
1561 PTHREADINFO Win32Thread
;
1562 DECLARE_RETURN(LRESULT
);
1563 USER_REFERENCE_ENTRY Ref
;
1564 PUSER_SENT_MESSAGE Message
;
1566 if (!(Window
= UserGetWindowObject(hWnd
)))
1571 UserRefObjectCo(Window
, &Ref
);
1573 if (Window
->state
& WINDOWSTATUS_DESTROYING
)
1575 /* FIXME - last error? */
1576 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1580 Win32Thread
= PsGetCurrentThreadWin32Thread();
1582 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1584 if (Win32Thread
== NULL
)
1590 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1592 /* Never send messages to exiting threads */
1596 /* See if this message type is present in the table */
1597 MsgMemoryEntry
= FindMsgMemory(Msg
);
1598 if (NULL
== MsgMemoryEntry
)
1600 lParamBufferSize
= -1;
1604 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1607 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, Window
->pti
->MessageQueue
!= Win32Thread
->MessageQueue
)))
1609 DPRINT1("Failed to pack message parameters\n");
1613 /* If this is not a callback and it can be sent now, then send it. */
1614 if ((Window
->pti
->MessageQueue
== Win32Thread
->MessageQueue
) && (CompletionCallback
== NULL
))
1617 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->Wnd
->lpfnWndProc
,
1618 !Window
->Wnd
->Unicode
,
1630 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1632 if ((Window
->pti
->MessageQueue
== Win32Thread
->MessageQueue
) && (CompletionCallback
== NULL
))
1634 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1636 DPRINT1("Failed to unpack message parameters\n");
1641 if(!(Message
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
1643 DPRINT1("MsqSendMessage(): Not enough memory to allocate a message");
1644 return STATUS_INSUFFICIENT_RESOURCES
;
1647 Message
->Msg
.hwnd
= hWnd
;
1648 Message
->Msg
.message
= Msg
;
1649 Message
->Msg
.wParam
= wParam
;
1650 Message
->Msg
.lParam
= lParamPacked
;
1651 Message
->CompletionEvent
= NULL
;
1652 Message
->Result
= 0;
1653 Message
->SenderQueue
= NULL
; //Win32Thread->MessageQueue;
1655 IntReferenceMessageQueue(Window
->pti
->MessageQueue
);
1656 Message
->CompletionCallback
= CompletionCallback
;
1657 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1658 Message
->HookMessage
= MSQ_NORMAL
| MSQ_SENTNOWAIT
;
1659 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1661 InsertTailList(&Window
->pti
->MessageQueue
->SentMessagesListHead
, &Message
->ListEntry
);
1662 IntDereferenceMessageQueue(Window
->pti
->MessageQueue
);
1667 if (Window
) UserDerefObjectCo(Window
);
1671 /* This function posts a message if the destination's message queue belongs to
1672 another thread, otherwise it sends the message. It does not support broadcast
1675 co_IntPostOrSendMessage( HWND hWnd
,
1682 PWINDOW_OBJECT Window
;
1684 if ( hWnd
== HWND_BROADCAST
)
1689 if(!(Window
= UserGetWindowObject(hWnd
)))
1694 pti
= PsGetCurrentThreadWin32Thread();
1696 if ( Window
->pti
->MessageQueue
!= pti
->MessageQueue
&&
1697 FindMsgMemory(Msg
) == 0 )
1699 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1703 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1709 return (LRESULT
)Result
;
1713 co_IntDoSendMessage( HWND hWnd
,
1718 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1721 LRESULT Result
= TRUE
;
1723 PWINDOW_OBJECT Window
= NULL
;
1724 NTUSERSENDMESSAGEINFO Info
;
1727 PMSGMEMORY MsgMemoryEntry
;
1729 RtlZeroMemory(&Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1731 /* FIXME: Call hooks. */
1732 if (HWND_BROADCAST
!= hWnd
)
1734 Window
= UserGetWindowObject(hWnd
);
1735 if ( !Window
|| !Window
->Wnd
)
1737 /* Tell usermode to not touch this one */
1738 Info
.HandledByKernel
= TRUE
;
1739 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1744 /* Check for an exiting window. */
1745 if (Window
&& Window
->state
& WINDOWSTATUS_DESTROYING
)
1747 DPRINT1("co_IntDoSendMessage Window Exiting!\n");
1750 /* See if the current thread can handle the message */
1751 pti
= PsGetCurrentThreadWin32Thread();
1753 // This is checked in user mode!!!!!!!
1754 if ( HWND_BROADCAST
!= hWnd
&&
1756 Window
->pti
->MessageQueue
== pti
->MessageQueue
&&
1757 !ISITHOOKED(WH_CALLWNDPROC
) &&
1758 !ISITHOOKED(WH_CALLWNDPROCRET
) &&
1759 ( Msg
< WM_DDE_FIRST
|| Msg
> WM_DDE_LAST
) )
1761 /* Gather the information usermode needs to call the window proc directly */
1762 Info
.HandledByKernel
= FALSE
;
1764 Status
= MmCopyFromCaller(&(Info
.Ansi
), &(UnsafeInfo
->Ansi
),
1766 if (! NT_SUCCESS(Status
))
1768 Info
.Ansi
= ! Window
->Wnd
->Unicode
;
1771 Info
.Ansi
= !Window
->Wnd
->Unicode
;
1772 Info
.Proc
= Window
->Wnd
->lpfnWndProc
;
1776 /* Must be handled by other thread */
1777 // if (HWND_BROADCAST != hWnd)
1779 // UserDereferenceObject(Window);
1781 Info
.HandledByKernel
= TRUE
;
1782 UserModeMsg
.hwnd
= hWnd
;
1783 UserModeMsg
.message
= Msg
;
1784 UserModeMsg
.wParam
= wParam
;
1785 UserModeMsg
.lParam
= lParam
;
1786 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1788 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1789 if (! NT_SUCCESS(Status
))
1791 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1792 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1793 return (dsm
? 0 : -1);
1798 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1799 KernelModeMsg
.message
,
1800 KernelModeMsg
.wParam
,
1801 KernelModeMsg
.lParam
);
1805 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1806 KernelModeMsg
.message
,
1807 KernelModeMsg
.wParam
,
1808 KernelModeMsg
.lParam
,
1814 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1815 if (! NT_SUCCESS(Status
))
1817 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1818 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1819 return(dsm
? 0 : -1);
1823 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1824 if (! NT_SUCCESS(Status
))
1826 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1829 return (LRESULT
)Result
;
1834 UserSendNotifyMessage( HWND hWnd
,
1841 if (FindMsgMemory(Msg
) != 0)
1843 SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY
);
1847 // Basicly the same as IntPostOrSendMessage
1848 if (hWnd
== HWND_BROADCAST
) //Handle Broadcast
1851 PWINDOW_OBJECT DesktopWindow
;
1854 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1855 List
= IntWinListChildren(DesktopWindow
);
1859 UserSendNotifyMessage(DesktopWindow
->hSelf
, Msg
, wParam
, lParam
);
1860 for (i
= 0; List
[i
]; i
++)
1862 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1871 PWINDOW_OBJECT Window
;
1874 if ( !(Window
= UserGetWindowObject(hWnd
)) ) return FALSE
;
1876 pti
= PsGetCurrentThreadWin32Thread();
1878 if (Window
->pti
->MessageQueue
!= pti
->MessageQueue
)
1879 { // Send message w/o waiting for it.
1880 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1883 { // Handle message and callback.
1884 Message
.hwnd
= hWnd
;
1885 Message
.message
= Msg
;
1886 Message
.wParam
= wParam
;
1887 Message
.lParam
= lParam
;
1889 Result
= co_IntSendMessageTimeoutSingle( hWnd
,
1903 IntGetQueueStatus(BOOL ClearChanges
)
1906 PUSER_MESSAGE_QUEUE Queue
;
1908 DECLARE_RETURN(DWORD
);
1910 DPRINT("Enter IntGetQueueStatus\n");
1912 pti
= PsGetCurrentThreadWin32Thread();
1913 Queue
= pti
->MessageQueue
;
1915 Result
= MAKELONG(Queue
->QueueBits
, Queue
->ChangedBits
);
1918 Queue
->ChangedBits
= 0;
1924 DPRINT("Leave IntGetQueueStatus, ret=%i\n",_ret_
);
1929 IntInitMessagePumpHook()
1931 if (((PTHREADINFO
)PsGetCurrentThread()->Tcb
.Win32Thread
)->pcti
)
1933 ((PTHREADINFO
)PsGetCurrentThread()->Tcb
.Win32Thread
)->pcti
->dwcPumpHook
++;
1940 IntUninitMessagePumpHook()
1942 if (((PTHREADINFO
)PsGetCurrentThread()->Tcb
.Win32Thread
)->pcti
)
1944 if (((PTHREADINFO
)PsGetCurrentThread()->Tcb
.Win32Thread
)->pcti
->dwcPumpHook
<= 0)
1948 ((PTHREADINFO
)PsGetCurrentThread()->Tcb
.Win32Thread
)->pcti
->dwcPumpHook
--;
1954 /** Functions ******************************************************************/
1957 NtUserPostMessage(HWND hWnd
,
1962 DECLARE_RETURN(BOOL
);
1964 DPRINT("Enter NtUserPostMessage\n");
1965 UserEnterExclusive();
1967 RETURN( UserPostMessage(hWnd
, Msg
, wParam
, lParam
));
1970 DPRINT("Leave NtUserPostMessage, ret=%i\n",_ret_
);
1976 NtUserPostThreadMessage(DWORD idThread
,
1981 DECLARE_RETURN(BOOL
);
1983 DPRINT("Enter NtUserPostThreadMessage\n");
1984 UserEnterExclusive();
1986 RETURN( UserPostThreadMessage( idThread
,
1992 DPRINT("Leave NtUserPostThreadMessage, ret=%i\n",_ret_
);
1998 NtUserQuerySendMessage(DWORD Unknown0
)
2006 ////////// API on the way out!
2008 NtUserSendMessageTimeout( HWND hWnd
,
2015 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
2019 DECLARE_RETURN(BOOL
);
2021 DPRINT("Enter NtUserSendMessageTimeout\n");
2022 UserEnterExclusive();
2024 dsm
.uFlags
= uFlags
;
2025 dsm
.uTimeout
= uTimeout
;
2026 Result
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, &dsm
, UnsafeInfo
);
2027 if(uResult
!= NULL
&& Result
!= 0)
2031 Status
= MmCopyToCaller(uResult
, &dsm
.Result
, sizeof(ULONG_PTR
));
2032 if(!NT_SUCCESS(Status
))
2034 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2041 DPRINT("Leave NtUserSendMessageTimeout, ret=%i\n",_ret_
);
2047 NtUserSendMessage( HWND Wnd
,
2051 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
2053 DECLARE_RETURN(BOOL
);
2055 DPRINT("Enter NtUserSendMessage\n");
2056 UserEnterExclusive();
2058 RETURN(co_IntDoSendMessage(Wnd
, Msg
, wParam
, lParam
, NULL
, UnsafeInfo
));
2061 DPRINT("Leave NtUserSendMessage, ret=%i\n",_ret_
);
2068 NtUserWaitMessage(VOID
)
2070 DECLARE_RETURN(BOOL
);
2072 DPRINT("EnterNtUserWaitMessage\n");
2073 UserEnterExclusive();
2075 RETURN(co_IntWaitMessage(NULL
, 0, 0));
2078 DPRINT("Leave NtUserWaitMessage, ret=%i\n",_ret_
);
2085 NtUserGetMessage( PNTUSERGETMESSAGEINFO UnsafeInfo
,
2090 * FUNCTION: Get a message from the calling thread's message queue.
2092 * UnsafeMsg - Pointer to the structure which receives the returned message.
2093 * Wnd - Window whose messages are to be retrieved.
2094 * MsgFilterMin - Integer value of the lowest message value to be
2096 * MsgFilterMax - Integer value of the highest message value to be
2101 NTUSERGETMESSAGEINFO Info
;
2103 /* FIXME: if initialization is removed, gcc complains that this may be used before initialization. Please review */
2104 PWINDOW_OBJECT Window
= NULL
;
2105 PMSGMEMORY MsgMemoryEntry
;
2109 DECLARE_RETURN(BOOL
);
2110 // USER_REFERENCE_ENTRY Ref;
2112 DPRINT("Enter NtUserGetMessage\n");
2113 UserEnterExclusive();
2115 /* Validate input */
2116 if (hWnd
&& !(Window
= UserGetWindowObject(hWnd
)))
2121 // if (Window) UserRefObjectCo(Window, &Ref);
2123 if (MsgFilterMax
< MsgFilterMin
)
2131 GotMessage
= co_IntPeekMessage(&Msg
, Window
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
);
2135 /* See if this message type is present in the table */
2136 MsgMemoryEntry
= FindMsgMemory(Info
.Msg
.message
);
2137 if (NULL
== MsgMemoryEntry
)
2139 /* Not present, no copying needed */
2140 Info
.LParamSize
= 0;
2144 /* Determine required size */
2145 Size
= MsgMemorySize(MsgMemoryEntry
, Info
.Msg
.wParam
,
2147 /* Allocate required amount of user-mode memory */
2148 Info
.LParamSize
= Size
;
2150 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem
, 0,
2151 &Info
.LParamSize
, MEM_COMMIT
, PAGE_READWRITE
);
2153 if (! NT_SUCCESS(Status
))
2155 SetLastNtError(Status
);
2158 /* Transfer lParam data to user-mode mem */
2159 Status
= MmCopyToCaller(UserMem
, (PVOID
) Info
.Msg
.lParam
, Size
);
2160 if (! NT_SUCCESS(Status
))
2162 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &UserMem
,
2163 &Info
.LParamSize
, MEM_DECOMMIT
);
2164 SetLastNtError(Status
);
2167 Info
.Msg
.lParam
= (LPARAM
) UserMem
;
2169 if (Msg
.FreeLParam
&& 0 != Msg
.Msg
.lParam
)
2171 ExFreePool((void *) Msg
.Msg
.lParam
);
2173 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERGETMESSAGEINFO
));
2174 if (! NT_SUCCESS(Status
))
2176 SetLastNtError(Status
);
2180 else if (! co_IntWaitMessage(Window
, MsgFilterMin
, MsgFilterMax
))
2185 while (! GotMessage
);
2187 RETURN( WM_QUIT
!= Info
.Msg
.message
);
2190 // if (Window) UserDerefObjectCo(Window);
2192 DPRINT("Leave NtUserGetMessage\n");
2208 DECLARE_RETURN(BOOL
);
2210 DPRINT("Enter NtUserGetMessage\n");
2211 UserEnterExclusive();
2213 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
2215 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2219 RtlZeroMemory(&Msg
, sizeof(MSG
));
2221 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
2227 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2228 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2230 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2232 SetLastNtError(_SEH2_GetExceptionCode());
2240 DPRINT("Leave NtUserGetMessage\n");
2246 NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo
,
2254 NTUSERGETMESSAGEINFO Info
;
2255 PWINDOW_OBJECT Window
;
2256 PMSGMEMORY MsgMemoryEntry
;
2260 DECLARE_RETURN(BOOL
);
2262 DPRINT("Enter NtUserPeekMessage\n");
2263 UserEnterExclusive();
2265 if (hWnd
== (HWND
)-1 || hWnd
== (HWND
)0x0000FFFF || hWnd
== (HWND
)0xFFFFFFFF)
2268 /* Validate input */
2269 if (hWnd
&& hWnd
!= (HWND
)1)
2271 if (!(Window
= UserGetWindowObject(hWnd
)))
2278 Window
= (PWINDOW_OBJECT
)hWnd
;
2281 if (MsgFilterMax
< MsgFilterMin
)
2287 Present
= co_IntPeekMessage(&Msg
, Window
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
);
2292 /* See if this message type is present in the table */
2293 MsgMemoryEntry
= FindMsgMemory(Info
.Msg
.message
);
2294 if (NULL
== MsgMemoryEntry
)
2296 /* Not present, no copying needed */
2297 Info
.LParamSize
= 0;
2301 /* Determine required size */
2302 Size
= MsgMemorySize(MsgMemoryEntry
, Info
.Msg
.wParam
,
2304 /* Allocate required amount of user-mode memory */
2305 Info
.LParamSize
= Size
;
2307 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem
, 0,
2308 &Info
.LParamSize
, MEM_COMMIT
, PAGE_READWRITE
);
2309 if (! NT_SUCCESS(Status
))
2311 SetLastNtError(Status
);
2314 /* Transfer lParam data to user-mode mem */
2315 Status
= MmCopyToCaller(UserMem
, (PVOID
) Info
.Msg
.lParam
, Size
);
2316 if (! NT_SUCCESS(Status
))
2318 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &UserMem
,
2319 &Info
.LParamSize
, MEM_RELEASE
);
2320 SetLastNtError(Status
);
2323 Info
.Msg
.lParam
= (LPARAM
) UserMem
;
2325 if (RemoveMsg
&& Msg
.FreeLParam
&& 0 != Msg
.Msg
.lParam
)
2327 ExFreePool((void *) Msg
.Msg
.lParam
);
2329 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERGETMESSAGEINFO
));
2330 if (! NT_SUCCESS(Status
))
2332 SetLastNtError(Status
);
2340 DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_
);
2356 DECLARE_RETURN(BOOL
);
2358 DPRINT("Enter NtUserPeekMessage\n");
2359 UserEnterExclusive();
2361 if ( RemoveMsg
& PM_BADMSGFLAGS
)
2363 SetLastWin32Error(ERROR_INVALID_FLAGS
);
2367 RtlZeroMemory(&Msg
, sizeof(MSG
));
2369 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
2375 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2376 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2378 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2380 SetLastNtError(_SEH2_GetExceptionCode());
2388 DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_
);
2395 NtUserCallMsgFilter(
2399 BOOL BadChk
= FALSE
, Ret
= FALSE
;
2401 DECLARE_RETURN(BOOL
);
2403 DPRINT("Enter NtUserCallMsgFilter\n");
2404 UserEnterExclusive();
2409 ProbeForRead((PVOID
)lpmsg
,
2412 RtlCopyMemory( &Msg
,
2416 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2425 if (BadChk
) RETURN( FALSE
);
2427 if ( ISITHOOKED(WH_SYSMSGFILTER
) &&
2428 co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
2434 if ( ISITHOOKED(WH_MSGFILTER
) )
2436 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
2442 ProbeForWrite((PVOID
)lpmsg
,
2445 RtlCopyMemory((PVOID
)lpmsg
,
2449 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2454 if (BadChk
) RETURN( FALSE
);
2458 DPRINT("Leave NtUserCallMsgFilter. ret=%i\n", _ret_
);
2464 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
2470 UserEnterExclusive();
2473 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
2474 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
2476 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2478 SetLastNtError(_SEH2_GetExceptionCode());
2483 if (!Hit
) Res
= IntDispatchMessage(&SafeMsg
);
2491 NtUserTranslateMessage(LPMSG lpMsg
,
2496 DECLARE_RETURN(BOOL
);
2498 DPRINT("Enter NtUserTranslateMessage\n");
2499 UserEnterExclusive();
2501 Status
= MmCopyFromCaller(&SafeMsg
, lpMsg
, sizeof(MSG
));
2502 if(!NT_SUCCESS(Status
))
2504 SetLastNtError(Status
);
2508 RETURN( IntTranslateKbdMessage(&SafeMsg
, flags
));
2511 DPRINT("Leave NtUserTranslateMessage: ret=%i\n",_ret_
);
2522 ULONG_PTR ResultInfo
,
2523 DWORD dwType
, // fnID?
2526 LRESULT lResult
= 0;
2528 BOOL BadChk
= FALSE
;
2529 PWINDOW_OBJECT Window
= NULL
;
2530 USER_REFERENCE_ENTRY Ref
;
2532 UserEnterExclusive();
2534 /* Validate input */
2535 if (hWnd
&& (hWnd
!= INVALID_HANDLE_VALUE
) && !(Window
= UserGetWindowObject(hWnd
)))
2542 case FNID_DEFWINDOWPROC
:
2543 UserRefObjectCo(Window
, &Ref
);
2544 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2546 UserDerefObjectCo(Window
);
2548 case FNID_SENDNOTIFYMESSAGE
:
2549 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2551 case FNID_BROADCASTSYSTEMMESSAGE
:
2554 DWORD_PTR RetVal
= 0;
2560 ProbeForWrite((PVOID
)ResultInfo
,
2561 sizeof(BROADCASTPARM
),
2563 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2565 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2575 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2576 parm
.recipients
== BSM_ALLCOMPONENTS
)
2579 else if (parm
.recipients
& BSM_APPLICATIONS
)
2581 if (parm
.flags
& BSF_QUERY
)
2583 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2585 co_IntSendMessageTimeout( HWND_BROADCAST
,
2593 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2595 co_IntSendMessageTimeout( HWND_BROADCAST
,
2599 SMTO_NOTIMEOUTIFNOTHUNG
,
2605 co_IntSendMessageTimeout( HWND_BROADCAST
,
2614 else if (parm
.flags
& BSF_POSTMESSAGE
)
2616 Ret
= UserPostMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2618 else if ( parm
.flags
& BSF_SENDNOTIFYMESSAGE
)
2620 Ret
= UserSendNotifyMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2625 case FNID_SENDMESSAGECALLBACK
:
2627 PCALL_BACK_INFO CallBackInfo
= (PCALL_BACK_INFO
)ResultInfo
;
2632 if (!co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2633 CallBackInfo
->CallBack
, CallBackInfo
->Context
, NULL
))
2635 DPRINT1("Callback failure!\n");
2639 // CallNextHook bypass.
2640 case FNID_CALLWNDPROC
:
2641 case FNID_CALLWNDPROCRET
:
2643 PCLIENTINFO ClientInfo
= GetWin32ClientInfo();
2644 PHOOK NextObj
, Hook
= ClientInfo
->phkCurrent
;
2646 if (!ClientInfo
|| !Hook
) break;
2648 UserReferenceObject(Hook
);
2650 if (Hook
->Thread
&& (Hook
->Thread
!= PsGetCurrentThread()))
2652 UserDereferenceObject(Hook
);
2656 NextObj
= IntGetNextHook(Hook
);
2657 ClientInfo
->phkCurrent
= NextObj
;
2659 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2664 CWP
.wParam
= wParam
;
2665 CWP
.lParam
= lParam
;
2666 DPRINT("WH_CALLWNDPROC: Hook %x NextHook %x\n", Hook
, NextObj
);
2668 lResult
= co_IntCallHookProc( Hook
->HookId
,
2670 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2681 CWPR
.wParam
= wParam
;
2682 CWPR
.lParam
= lParam
;
2683 CWPR
.lResult
= ClientInfo
->dwHookData
;
2685 lResult
= co_IntCallHookProc( Hook
->HookId
,
2687 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2693 UserDereferenceObject(Hook
);
2694 lResult
= (LRESULT
) NextObj
;
2701 case FNID_DEFWINDOWPROC
:
2702 case FNID_CALLWNDPROC
:
2703 case FNID_CALLWNDPROCRET
:
2708 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2709 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2711 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2724 return BadChk
? FALSE
: Ret
;
2727 #define INFINITE 0xFFFFFFFF
2728 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2732 NtUserWaitForInputIdle(
2734 IN DWORD dwMilliseconds
,
2738 PPROCESSINFO W32Process
;
2741 LARGE_INTEGER Timeout
;
2742 ULONGLONG StartTime
, Run
, Elapsed
= 0;
2744 UserEnterExclusive();
2746 Status
= ObReferenceObjectByHandle(hProcess
,
2747 PROCESS_QUERY_INFORMATION
,
2753 if (!NT_SUCCESS(Status
))
2756 SetLastNtError(Status
);
2760 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2763 ObDereferenceObject(Process
);
2765 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2769 EngCreateEvent((PEVENT
*)&W32Process
->InputIdleEvent
);
2771 Handles
[0] = Process
;
2772 Handles
[1] = W32Process
->InputIdleEvent
;
2776 ObDereferenceObject(Process
);
2778 return STATUS_SUCCESS
; /* no event to wait on */
2781 StartTime
= EngGetTickCount();
2783 Run
= dwMilliseconds
;
2785 DPRINT("WFII: waiting for %p\n", Handles
[1] );
2788 Timeout
.QuadPart
= Run
- Elapsed
;
2790 Status
= KeWaitForMultipleObjects( 2,
2796 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2798 UserEnterExclusive();
2800 if (!NT_SUCCESS(Status
))
2802 SetLastNtError(Status
);
2803 Status
= WAIT_FAILED
;
2810 Status
= WAIT_FAILED
;
2816 co_IntPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
);
2820 case STATUS_USER_APC
:
2821 case STATUS_ALERTED
:
2822 case STATUS_TIMEOUT
:
2823 DPRINT1("WFII: timeout\n");
2824 Status
= STATUS_TIMEOUT
;
2828 DPRINT1("WFII: finished\n");
2829 Status
= STATUS_SUCCESS
;
2833 if (dwMilliseconds
!= INFINITE
)
2835 Elapsed
= EngGetTickCount() - StartTime
;
2838 Status
= STATUS_TIMEOUT
;
2845 if (W32Process
->InputIdleEvent
)
2847 EngFreeMem((PVOID
)W32Process
->InputIdleEvent
);
2848 W32Process
->InputIdleEvent
= NULL
;
2850 ObDereferenceObject(Process
);