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
;
327 IntCallWndProc( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
329 BOOL SameThread
= FALSE
;
332 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
339 co_HOOK_CallHooks( WH_CALLWNDPROC
, HC_ACTION
, SameThread
, (LPARAM
)&CWP
);
343 IntCallWndProcRet ( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*uResult
)
345 BOOL SameThread
= FALSE
;
348 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
353 CWPR
.wParam
= wParam
;
354 CWPR
.lParam
= lParam
;
355 CWPR
.lResult
= *uResult
;
356 co_HOOK_CallHooks( WH_CALLWNDPROCRET
, HC_ACTION
, SameThread
, (LPARAM
)&CWPR
);
360 IntDispatchMessage(PMSG pMsg
)
362 LARGE_INTEGER TickCount
;
365 PMSGMEMORY MsgMemoryEntry
;
366 INT lParamBufferSize
;
373 Window
= UserGetWindowObject(pMsg
->hwnd
);
374 if (!Window
) return 0;
377 pti
= PsGetCurrentThreadWin32Thread();
379 if (((pMsg
->message
== WM_SYSTIMER
) ||
380 (pMsg
->message
== WM_TIMER
)) &&
383 if (pMsg
->message
== WM_TIMER
)
385 ObReferenceObject(pti
->pEThread
);
386 if (ValidateTimerCallback(pti
,pMsg
->lParam
))
388 KeQueryTickCount(&TickCount
);
389 Time
= MsqCalculateMessageTime(&TickCount
);
390 retval
= co_IntCallWindowProc((WNDPROC
)pMsg
->lParam
,
398 ObDereferenceObject(pti
->pEThread
);
403 PTIMER pTimer
= FindSystemTimer(pMsg
);
404 if (pTimer
&& pTimer
->pfn
)
406 KeQueryTickCount(&TickCount
);
407 Time
= MsqCalculateMessageTime(&TickCount
);
408 pTimer
->pfn(pMsg
->hwnd
, WM_SYSTIMER
, (UINT
)pMsg
->wParam
, Time
);
414 if ( !Window
) return 0;
416 /* See if this message type is present in the table */
417 MsgMemoryEntry
= FindMsgMemory(pMsg
->message
);
418 if ( !MsgMemoryEntry
)
420 lParamBufferSize
= -1;
424 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, pMsg
->wParam
, pMsg
->lParam
);
427 if (! NT_SUCCESS(PackParam(&lParamPacked
, pMsg
->message
, pMsg
->wParam
, pMsg
->lParam
, FALSE
)))
429 DPRINT1("Failed to pack message parameters\n");
432 ObReferenceObject(pti
->pEThread
);
433 retval
= co_IntCallWindowProc( Window
->lpfnWndProc
,
441 if (! NT_SUCCESS(UnpackParam(lParamPacked
, pMsg
->message
, pMsg
->wParam
, pMsg
->lParam
, FALSE
)))
443 DPRINT1("Failed to unpack message parameters\n");
446 if (pMsg
->message
== WM_PAINT
)
448 /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
449 HRGN hrgn
= IntSysCreateRectRgn( 0, 0, 0, 0 );
450 co_UserGetUpdateRgn( Window
, hrgn
, TRUE
);
451 REGION_FreeRgnByHandle( hrgn
);
453 ObDereferenceObject(pti
->pEThread
);
458 co_IntSendHitTestMessages(PUSER_MESSAGE_QUEUE ThreadQueue
, LPMSG Msg
)
460 if(!Msg
->hwnd
|| ThreadQueue
->CaptureWindow
)
469 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(HTCLIENT
, Msg
->message
));
474 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(Msg
->wParam
, Msg
->message
));
481 case WM_LBUTTONDBLCLK
:
482 case WM_MBUTTONDBLCLK
:
483 case WM_RBUTTONDBLCLK
:
484 case WM_XBUTTONDBLCLK
:
487 PSYSTEM_CURSORINFO CurInfo
;
488 CurInfo
= IntGetSysCursorInfo();
490 wParam
= (WPARAM
)(CurInfo
->ButtonsDown
);
492 co_IntSendMessage(Msg
->hwnd
, WM_MOUSEMOVE
, wParam
, Msg
->lParam
);
493 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(HTCLIENT
, Msg
->message
));
496 case WM_NCLBUTTONDOWN
:
497 case WM_NCMBUTTONDOWN
:
498 case WM_NCRBUTTONDOWN
:
499 case WM_NCXBUTTONDOWN
:
500 case WM_NCLBUTTONDBLCLK
:
501 case WM_NCMBUTTONDBLCLK
:
502 case WM_NCRBUTTONDBLCLK
:
503 case WM_NCXBUTTONDBLCLK
:
505 co_IntSendMessage(Msg
->hwnd
, WM_NCMOUSEMOVE
, (WPARAM
)Msg
->wParam
, Msg
->lParam
);
506 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(Msg
->wParam
, Msg
->message
));
513 co_IntActivateWindowMouse( PUSER_MESSAGE_QUEUE ThreadQueue
,
521 ASSERT_REFS_CO(MsgWindow
);
523 if(*HitTest
== (USHORT
)HTTRANSPARENT
)
525 /* eat the message, search again! */
529 Parent
= IntGetParent(MsgWindow
);//fixme: deref retval?
531 /* If no parent window, pass MsgWindows HWND as wParam. Fixes bug #3111 */
532 Result
= co_IntSendMessage(MsgWindow
->head
.h
,
534 (WPARAM
) (Parent
? Parent
->head
.h
: MsgWindow
->head
.h
),
535 (LPARAM
)MAKELONG(*HitTest
, Msg
->message
)
540 case MA_NOACTIVATEANDEAT
:
544 case MA_ACTIVATEANDEAT
:
545 co_IntMouseActivateWindow(MsgWindow
);
549 co_IntMouseActivateWindow(MsgWindow
);
557 co_IntTranslateMouseMessage( PUSER_MESSAGE_QUEUE ThreadQueue
,
563 USER_REFERENCE_ENTRY Ref
, DesktopRef
;
565 if(!(Window
= UserGetWindowObject(Msg
->hwnd
)))
567 /* let's just eat the message?! */
573 UserRefObjectCo(Window
, &Ref
);
575 if ( ThreadQueue
== Window
->head
.pti
->MessageQueue
&&
576 ThreadQueue
->CaptureWindow
!= Window
->head
.h
)
578 /* only send WM_NCHITTEST messages if we're not capturing the window! */
581 *HitTest
= co_IntSendMessage(Window
->head
.h
, WM_NCHITTEST
, 0,
582 MAKELONG(Msg
->pt
.x
, Msg
->pt
.y
));
584 /* else we are going to see this message again, but then with Remove == TRUE */
586 if (*HitTest
== (USHORT
)HTTRANSPARENT
)
589 HWND hDesktop
= IntGetDesktopWindow();
591 if ((DesktopWindow
= UserGetWindowObject(hDesktop
)))
595 UserRefObjectCo(DesktopWindow
, &DesktopRef
);
597 co_WinPosWindowFromPoint(DesktopWindow
, Window
->head
.pti
->MessageQueue
, &Msg
->pt
, &Wnd
);
602 /* post the message to the other window */
603 Msg
->hwnd
= Wnd
->head
.h
;
604 if(!(Wnd
->state
& WNDS_DESTROYED
))
606 MsqPostMessage(Wnd
->head
.pti
->MessageQueue
, Msg
, FALSE
,
607 Msg
->message
== WM_MOUSEMOVE
? QS_MOUSEMOVE
:
611 /* eat the message */
612 UserDereferenceObject(Wnd
);
613 UserDerefObjectCo(DesktopWindow
);
614 UserDerefObjectCo(Window
);
617 UserDereferenceObject(Wnd
);
620 UserDerefObjectCo(DesktopWindow
);
625 if ( gspv
.bMouseClickLock
&&
626 ((Msg
->message
== WM_LBUTTONUP
) ||
627 (Msg
->message
== WM_LBUTTONDOWN
) ) )
629 if (MsqIsClkLck(Msg
, Remove
))
631 // FIXME: drop the message, hack: use WM_NULL
632 Msg
->message
= WM_NULL
;
636 if (IS_BTN_MESSAGE(Msg
->message
, DOWN
))
638 /* generate double click messages, if necessary */
639 if ((((*HitTest
) != HTCLIENT
) ||
640 (Window
->pcls
->style
& CS_DBLCLKS
)) &&
641 MsqIsDblClk(Msg
, Remove
))
643 Msg
->message
+= WM_LBUTTONDBLCLK
- WM_LBUTTONDOWN
;
647 if(Msg
->message
!= WM_MOUSEWHEEL
)
650 if ((*HitTest
) != HTCLIENT
)
652 Msg
->message
+= WM_NCMOUSEMOVE
- WM_MOUSEMOVE
;
653 if ( (Msg
->message
== WM_NCRBUTTONUP
) &&
654 (((*HitTest
) == HTCAPTION
) || ((*HitTest
) == HTSYSMENU
)) )
656 Msg
->message
= WM_CONTEXTMENU
;
657 Msg
->wParam
= (WPARAM
)Window
->head
.h
;
661 Msg
->wParam
= *HitTest
;
663 Msg
->lParam
= MAKELONG(Msg
->pt
.x
, Msg
->pt
.y
);
665 else if ( ThreadQueue
->MoveSize
== NULL
&&
666 ThreadQueue
->MenuOwner
== NULL
)
668 /* NOTE: Msg->pt should remain in screen coordinates. -- FiN */
669 Msg
->lParam
= MAKELONG(
670 Msg
->pt
.x
- (WORD
)Window
->rcClient
.left
,
671 Msg
->pt
.y
- (WORD
)Window
->rcClient
.top
);
675 UserDerefObjectCo(Window
);
679 BOOL
ProcessMouseMessage(MSG
* Msg
, BOOLEAN RemoveMessages
)
681 MOUSEHOOKSTRUCT MHook
;
684 PUSER_MESSAGE_QUEUE ThreadQueue
;
685 USER_REFERENCE_ENTRY Ref
;
686 USHORT HitTest
= HTNOWHERE
;
688 pti
= PsGetCurrentThreadWin32Thread();
689 ThreadQueue
= pti
->MessageQueue
;
693 PWND MsgWindow
= NULL
;
695 /* Mouse message process */
698 ( MsgWindow
= UserGetWindowObject(Msg
->hwnd
) ) &&
699 Msg
->message
>= WM_MOUSEFIRST
&&
700 Msg
->message
<= WM_MOUSELAST
)
704 UserRefObjectCo(MsgWindow
, &Ref
);
706 if ( co_IntTranslateMouseMessage( ThreadQueue
,
710 /* FIXME - check message filter again, if the message doesn't match anymore,
713 UserDerefObjectCo(MsgWindow
);
714 /* eat the message, search again */
718 if(ThreadQueue
->CaptureWindow
== NULL
)
720 co_IntSendHitTestMessages(ThreadQueue
, Msg
);
722 if ( ( Msg
->message
!= WM_MOUSEMOVE
&&
723 Msg
->message
!= WM_NCMOUSEMOVE
) &&
724 IS_BTN_MESSAGE(Msg
->message
, DOWN
) &&
725 co_IntActivateWindowMouse(ThreadQueue
, Msg
, MsgWindow
, &HitTest
) )
727 UserDerefObjectCo(MsgWindow
);
728 /* eat the message, search again */
733 UserDerefObjectCo(MsgWindow
);
737 co_IntSendHitTestMessages(ThreadQueue
, Msg
);
744 Msg
->message
>= WM_MOUSEFIRST
&&
745 Msg
->message
<= WM_MOUSELAST
) &&
746 co_IntTranslateMouseMessage( ThreadQueue
,
750 /* FIXME - check message filter again, if the message doesn't match anymore,
753 /* eat the message, search again */
757 pti
->rpdesk
->htEx
= HitTest
; /* Now set the capture hit. */
759 Event
.message
= Msg
->message
;
760 Event
.time
= Msg
->time
;
761 Event
.hwnd
= Msg
->hwnd
;
762 Event
.paramL
= Msg
->pt
.x
;
763 Event
.paramH
= Msg
->pt
.y
;
764 co_HOOK_CallHooks( WH_JOURNALRECORD
, HC_ACTION
, 0, (LPARAM
)&Event
);
768 MHook
.hwnd
= Msg
->hwnd
;
769 MHook
.wHitTestCode
= HitTest
;
770 MHook
.dwExtraInfo
= 0;
771 if (co_HOOK_CallHooks( WH_MOUSE
,
772 RemoveMessages
? HC_ACTION
: HC_NOREMOVE
,
777 MHook
.hwnd
= Msg
->hwnd
;
778 MHook
.wHitTestCode
= HitTest
;
779 MHook
.dwExtraInfo
= 0;
780 co_HOOK_CallHooks( WH_CBT
,
784 DPRINT1("MouseMessage WH_CBT Call Hook return!\n");
791 BOOL
ProcessKeyboardMessage(MSG
* Msg
, BOOLEAN RemoveMessages
)
795 Event
.message
= Msg
->message
;
796 Event
.hwnd
= Msg
->hwnd
;
797 Event
.time
= Msg
->time
;
798 Event
.paramL
= (Msg
->wParam
& 0xFF) | (HIWORD(Msg
->lParam
) << 8);
799 Event
.paramH
= Msg
->lParam
& 0x7FFF;
800 if (HIWORD(Msg
->lParam
) & 0x0100) Event
.paramH
|= 0x8000;
801 co_HOOK_CallHooks( WH_JOURNALRECORD
, HC_ACTION
, 0, (LPARAM
)&Event
);
803 if (co_HOOK_CallHooks( WH_KEYBOARD
,
804 RemoveMessages
? HC_ACTION
: HC_NOREMOVE
,
808 /* skip this message */
809 co_HOOK_CallHooks( WH_CBT
,
813 DPRINT1("KeyboardMessage WH_CBT Call Hook return!\n");
819 BOOL
ProcessHardwareMessage(MSG
* Msg
, BOOLEAN RemoveMessages
)
821 if ( IS_MOUSE_MESSAGE(Msg
->message
))
823 if (!ProcessMouseMessage(Msg
, RemoveMessages
))
828 else if ( IS_KBD_MESSAGE(Msg
->message
))
830 if(!ProcessKeyboardMessage(Msg
, RemoveMessages
))
839 * Internal version of PeekMessage() doing all the work
842 co_IntPeekMessage( PUSER_MESSAGE Msg
,
849 LARGE_INTEGER LargeTickCount
;
850 PUSER_MESSAGE_QUEUE ThreadQueue
;
851 PUSER_MESSAGE Message
;
854 pti
= PsGetCurrentThreadWin32Thread();
855 ThreadQueue
= pti
->MessageQueue
;
857 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
861 KeQueryTickCount(&LargeTickCount
);
862 ThreadQueue
->LastMsgRead
= LargeTickCount
.u
.LowPart
;
864 /* Dispatch sent messages here. */
865 while (co_MsqDispatchOneSentMessage(ThreadQueue
)) ;
867 /* Now look for a quit message. */
869 if (ThreadQueue
->QuitPosted
)
871 /* According to the PSDK, WM_QUIT messages are always returned, regardless
872 of the filter specified */
873 Msg
->Msg
.hwnd
= NULL
;
874 Msg
->Msg
.message
= WM_QUIT
;
875 Msg
->Msg
.wParam
= ThreadQueue
->QuitExitCode
;
879 ThreadQueue
->QuitPosted
= FALSE
;
885 /* Now check for normal messages. */
886 if (co_MsqFindMessage( ThreadQueue
,
894 RtlCopyMemory(Msg
, Message
, sizeof(USER_MESSAGE
));
897 MsqDestroyMessage(Message
);
902 /* Check for hardware events. */
903 if(co_MsqFindMessage( ThreadQueue
,
911 RtlCopyMemory(Msg
, Message
, sizeof(USER_MESSAGE
));
914 MsqDestroyMessage(Message
);
917 if(!ProcessHardwareMessage(&Msg
->Msg
, RemoveMessages
))
923 /* Check for sent messages again. */
924 while (co_MsqDispatchOneSentMessage(ThreadQueue
))
927 /* Check for paint messages. */
928 if( IntGetPaintMessage( Window
,
938 if (PostTimerMessages(Window
))
947 // The WH_GETMESSAGE hook enables an application to monitor messages about to
948 // be returned by the GetMessage or PeekMessage function.
950 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)&Msg
->Msg
);
954 static NTSTATUS FASTCALL
955 CopyMsgToKernelMem(MSG
*KernelModeMsg
, MSG
*UserModeMsg
, PMSGMEMORY MsgMemoryEntry
)
962 *KernelModeMsg
= *UserModeMsg
;
964 /* See if this message type is present in the table */
965 if (NULL
== MsgMemoryEntry
)
967 /* Not present, no copying needed */
968 return STATUS_SUCCESS
;
971 /* Determine required size */
972 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
976 /* Allocate kernel mem */
977 KernelMem
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
978 if (NULL
== KernelMem
)
980 DPRINT1("Not enough memory to copy message to kernel mem\n");
981 return STATUS_NO_MEMORY
;
983 KernelModeMsg
->lParam
= (LPARAM
) KernelMem
;
985 /* Copy data if required */
986 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_READ
))
988 Status
= MmCopyFromCaller(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
989 if (! NT_SUCCESS(Status
))
991 DPRINT1("Failed to copy message to kernel: invalid usermode buffer\n");
992 ExFreePoolWithTag(KernelMem
, TAG_MSG
);
998 /* Make sure we don't pass any secrets to usermode */
999 RtlZeroMemory(KernelMem
, Size
);
1004 KernelModeMsg
->lParam
= 0;
1007 return STATUS_SUCCESS
;
1010 static NTSTATUS FASTCALL
1011 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
1014 PMSGMEMORY MsgMemoryEntry
;
1017 /* See if this message type is present in the table */
1018 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
1019 if (NULL
== MsgMemoryEntry
)
1021 /* Not present, no copying needed */
1022 return STATUS_SUCCESS
;
1025 /* Determine required size */
1026 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
1030 /* Copy data if required */
1031 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
1033 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
1034 if (! NT_SUCCESS(Status
))
1036 DPRINT1("Failed to copy message from kernel: invalid usermode buffer\n");
1037 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
1042 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
1045 return STATUS_SUCCESS
;
1048 static BOOL FASTCALL
1049 co_IntWaitMessage( PWND Window
,
1054 PUSER_MESSAGE_QUEUE ThreadQueue
;
1055 NTSTATUS Status
= STATUS_SUCCESS
;
1058 pti
= PsGetCurrentThreadWin32Thread();
1059 ThreadQueue
= pti
->MessageQueue
;
1063 if ( co_IntPeekMessage( &Msg
,
1071 /* Nothing found. Wait for new messages. */
1072 Status
= co_MsqWaitForNewMessages( ThreadQueue
,
1077 while ( (STATUS_WAIT_0
<= Status
&& Status
<= STATUS_WAIT_63
) ||
1078 STATUS_TIMEOUT
== Status
);
1080 if (!NT_SUCCESS(Status
))
1082 SetLastNtError(Status
);
1083 DPRINT1("Exit co_IntWaitMessage on error!\n");
1090 co_IntGetPeekMessage( PMSG pMsg
,
1101 if ( hWnd
== HWND_TOPMOST
|| hWnd
== HWND_BROADCAST
)
1104 /* Validate input */
1105 if (hWnd
&& hWnd
!= HWND_BOTTOM
)
1107 if (!(Window
= UserGetWindowObject(hWnd
)))
1117 Window
= (PWND
)hWnd
;
1120 if (MsgFilterMax
< MsgFilterMin
)
1128 Present
= co_IntPeekMessage( &Msg
,
1135 RtlCopyMemory( pMsg
, &Msg
.Msg
, sizeof(MSG
));
1138 return (WM_QUIT
!= pMsg
->message
);
1143 if ( bGMSG
&& !co_IntWaitMessage(Window
, MsgFilterMin
, MsgFilterMax
) )
1149 if (!(RemoveMsg
& PM_NOYIELD
))
1151 // Yield this thread!
1154 UserEnterExclusive();
1155 // Fall through to fail.
1159 while( bGMSG
&& !Present
);
1165 UserPostThreadMessage( DWORD idThread
,
1172 PTHREADINFO pThread
;
1173 LARGE_INTEGER LargeTickCount
;
1176 DPRINT1("UserPostThreadMessage wParam 0x%x lParam 0x%x\n", wParam
,lParam
);
1178 if (FindMsgMemory(Msg
) != 0)
1180 SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY
);
1184 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
1186 if( Status
== STATUS_SUCCESS
)
1188 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
1190 !pThread
->MessageQueue
||
1191 (pThread
->TIF_flags
& TIF_INCLEANUP
))
1193 ObDereferenceObject( peThread
);
1197 Message
.hwnd
= NULL
;
1198 Message
.message
= Msg
;
1199 Message
.wParam
= wParam
;
1200 Message
.lParam
= lParam
;
1201 Message
.pt
= gpsi
->ptCursor
;
1203 KeQueryTickCount(&LargeTickCount
);
1204 pThread
->timeLast
= Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1205 MsqPostMessage(pThread
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
);
1206 ObDereferenceObject( peThread
);
1211 SetLastNtError( Status
);
1217 UserPostMessage( HWND Wnd
,
1224 LARGE_INTEGER LargeTickCount
;
1226 if (FindMsgMemory(Msg
) != 0)
1228 SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY
);
1234 return UserPostThreadMessage( PtrToInt(PsGetCurrentThreadId()),
1239 if (Wnd
== HWND_BROADCAST
)
1245 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1246 List
= IntWinListChildren(DesktopWindow
);
1250 UserPostMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1251 for (i
= 0; List
[i
]; i
++)
1253 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1262 Window
= UserGetWindowObject(Wnd
);
1268 pti
= Window
->head
.pti
;
1269 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1271 DPRINT1("Attempted to post message to window 0x%x when the thread is in cleanup!\n", Wnd
);
1275 if ( Window
->state
& WNDS_DESTROYED
)
1277 DPRINT1("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd
);
1278 /* FIXME - last error code? */
1284 MsqPostQuitMessage(Window
->head
.pti
->MessageQueue
, wParam
);
1289 Message
.message
= Msg
;
1290 Message
.wParam
= wParam
;
1291 Message
.lParam
= lParam
;
1292 Message
.pt
= gpsi
->ptCursor
;
1293 KeQueryTickCount(&LargeTickCount
);
1294 pti
->timeLast
= Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1295 MsqPostMessage(Window
->head
.pti
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
);
1303 co_IntSendMessage( HWND hWnd
,
1308 ULONG_PTR Result
= 0;
1309 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1311 return (LRESULT
)Result
;
1316 static LRESULT FASTCALL
1317 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1323 ULONG_PTR
*uResult
)
1327 PMSGMEMORY MsgMemoryEntry
;
1328 INT lParamBufferSize
;
1329 LPARAM lParamPacked
;
1330 PTHREADINFO Win32Thread
;
1331 ULONG_PTR Result
= 0;
1332 DECLARE_RETURN(LRESULT
);
1333 USER_REFERENCE_ENTRY Ref
;
1335 if (!(Window
= UserGetWindowObject(hWnd
)))
1340 UserRefObjectCo(Window
, &Ref
);
1342 Win32Thread
= PsGetCurrentThreadWin32Thread();
1344 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1346 if ( NULL
!= Win32Thread
&&
1347 Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1349 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1351 /* Never send messages to exiting threads */
1355 /* See if this message type is present in the table */
1356 MsgMemoryEntry
= FindMsgMemory(Msg
);
1357 if (NULL
== MsgMemoryEntry
)
1359 lParamBufferSize
= -1;
1363 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1366 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1368 DPRINT1("Failed to pack message parameters\n");
1372 ObReferenceObject(Win32Thread
->pEThread
);
1373 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1385 ObDereferenceObject(Win32Thread
->pEThread
);
1387 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1389 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1391 DPRINT1("Failed to unpack message parameters\n");
1398 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->head
.pti
->MessageQueue
))
1400 /* FIXME - Set a LastError? */
1404 if (Window
->state
& WNDS_DESTROYED
)
1406 /* FIXME - last error? */
1407 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1413 Status
= co_MsqSendMessage( Window
->head
.pti
->MessageQueue
,
1419 (uFlags
& SMTO_BLOCK
),
1423 while ((STATUS_TIMEOUT
== Status
) &&
1424 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1425 !MsqIsHung(Window
->head
.pti
->MessageQueue
));
1427 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1429 if (STATUS_TIMEOUT
== Status
)
1433 Microsoft Windows 2000: If GetLastError returns zero, then the function
1435 XP+ : If the function fails or times out, the return value is zero.
1436 To get extended error information, call GetLastError. If GetLastError
1437 returns ERROR_TIMEOUT, then the function timed out.
1439 SetLastWin32Error(ERROR_TIMEOUT
);
1442 else if (! NT_SUCCESS(Status
))
1444 SetLastNtError(Status
);
1451 if (Window
) UserDerefObjectCo(Window
);
1456 co_IntSendMessageTimeout( HWND hWnd
,
1462 ULONG_PTR
*uResult
)
1468 if (HWND_BROADCAST
!= hWnd
)
1470 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1473 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1474 if (NULL
== DesktopWindow
)
1476 SetLastWin32Error(ERROR_INTERNAL_ERROR
);
1480 /* Send message to the desktop window too! */
1481 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1483 Children
= IntWinListChildren(DesktopWindow
);
1484 if (NULL
== Children
)
1489 for (Child
= Children
; NULL
!= *Child
; Child
++)
1491 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1494 ExFreePool(Children
);
1496 return (LRESULT
) TRUE
;
1500 co_IntSendMessageNoWait(HWND hWnd
,
1505 ULONG_PTR Result
= 0;
1506 co_IntSendMessageWithCallBack(hWnd
,
1517 co_IntSendMessageWithCallBack( HWND hWnd
,
1521 SENDASYNCPROC CompletionCallback
,
1522 ULONG_PTR CompletionCallbackContext
,
1527 PMSGMEMORY MsgMemoryEntry
;
1528 INT lParamBufferSize
;
1529 LPARAM lParamPacked
;
1530 PTHREADINFO Win32Thread
;
1531 DECLARE_RETURN(LRESULT
);
1532 USER_REFERENCE_ENTRY Ref
;
1533 PUSER_SENT_MESSAGE Message
;
1535 if (!(Window
= UserGetWindowObject(hWnd
)))
1540 UserRefObjectCo(Window
, &Ref
);
1542 if (Window
->state
& WNDS_DESTROYED
)
1544 /* FIXME - last error? */
1545 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1549 Win32Thread
= PsGetCurrentThreadWin32Thread();
1551 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1553 if (Win32Thread
== NULL
)
1559 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1561 /* Never send messages to exiting threads */
1565 /* See if this message type is present in the table */
1566 MsgMemoryEntry
= FindMsgMemory(Msg
);
1567 if (NULL
== MsgMemoryEntry
)
1569 lParamBufferSize
= -1;
1573 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1576 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, Window
->head
.pti
->MessageQueue
!= Win32Thread
->MessageQueue
)))
1578 DPRINT1("Failed to pack message parameters\n");
1582 /* If this is not a callback and it can be sent now, then send it. */
1583 if ((Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
) && (CompletionCallback
== NULL
))
1585 ObReferenceObject(Win32Thread
->pEThread
);
1586 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1597 ObDereferenceObject(Win32Thread
->pEThread
);
1600 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1602 if ((Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
) && (CompletionCallback
== NULL
))
1604 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1606 DPRINT1("Failed to unpack message parameters\n");
1611 if(!(Message
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
1613 DPRINT1("MsqSendMessage(): Not enough memory to allocate a message");
1614 return STATUS_INSUFFICIENT_RESOURCES
;
1617 Message
->Msg
.hwnd
= hWnd
;
1618 Message
->Msg
.message
= Msg
;
1619 Message
->Msg
.wParam
= wParam
;
1620 Message
->Msg
.lParam
= lParamPacked
;
1621 Message
->CompletionEvent
= NULL
;
1622 Message
->Result
= 0;
1623 Message
->SenderQueue
= NULL
; //Win32Thread->MessageQueue;
1625 IntReferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1626 Message
->CompletionCallback
= CompletionCallback
;
1627 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1628 Message
->HookMessage
= MSQ_NORMAL
| MSQ_SENTNOWAIT
;
1629 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1631 InsertTailList(&Window
->head
.pti
->MessageQueue
->SentMessagesListHead
, &Message
->ListEntry
);
1632 IntDereferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1637 if (Window
) UserDerefObjectCo(Window
);
1641 /* This function posts a message if the destination's message queue belongs to
1642 another thread, otherwise it sends the message. It does not support broadcast
1645 co_IntPostOrSendMessage( HWND hWnd
,
1654 if ( hWnd
== HWND_BROADCAST
)
1659 if(!(Window
= UserGetWindowObject(hWnd
)))
1664 pti
= PsGetCurrentThreadWin32Thread();
1666 if ( Window
->head
.pti
->MessageQueue
!= pti
->MessageQueue
&&
1667 FindMsgMemory(Msg
) == 0 )
1669 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1673 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1679 return (LRESULT
)Result
;
1683 co_IntDoSendMessage( HWND hWnd
,
1688 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1691 LRESULT Result
= TRUE
;
1694 NTUSERSENDMESSAGEINFO Info
;
1697 PMSGMEMORY MsgMemoryEntry
;
1699 RtlZeroMemory(&Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1701 /* FIXME: Call hooks. */
1702 if (HWND_BROADCAST
!= hWnd
)
1704 Window
= UserGetWindowObject(hWnd
);
1707 /* Tell usermode to not touch this one */
1708 Info
.HandledByKernel
= TRUE
;
1709 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1714 /* Check for an exiting window. */
1715 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1717 DPRINT1("co_IntDoSendMessage Window Exiting!\n");
1720 /* See if the current thread can handle the message */
1721 pti
= PsGetCurrentThreadWin32Thread();
1723 // This is checked in user mode!!!!!!!
1724 if ( HWND_BROADCAST
!= hWnd
&&
1726 Window
->head
.pti
->MessageQueue
== pti
->MessageQueue
&&
1727 !ISITHOOKED(WH_CALLWNDPROC
) &&
1728 !ISITHOOKED(WH_CALLWNDPROCRET
) &&
1729 ( Msg
< WM_DDE_FIRST
|| Msg
> WM_DDE_LAST
) )
1731 /* Gather the information usermode needs to call the window proc directly */
1732 Info
.HandledByKernel
= FALSE
;
1734 Status
= MmCopyFromCaller(&(Info
.Ansi
), &(UnsafeInfo
->Ansi
), sizeof(BOOL
));
1735 if (! NT_SUCCESS(Status
))
1737 Info
.Ansi
= ! Window
->Unicode
;
1740 Info
.Ansi
= !Window
->Unicode
;
1741 Info
.Proc
= Window
->lpfnWndProc
;
1745 /* Must be handled by other thread */
1746 // if (HWND_BROADCAST != hWnd)
1748 // UserDereferenceObject(Window);
1750 Info
.HandledByKernel
= TRUE
;
1751 UserModeMsg
.hwnd
= hWnd
;
1752 UserModeMsg
.message
= Msg
;
1753 UserModeMsg
.wParam
= wParam
;
1754 UserModeMsg
.lParam
= lParam
;
1755 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1757 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1758 if (! NT_SUCCESS(Status
))
1760 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1761 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1762 return (dsm
? 0 : -1);
1767 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1768 KernelModeMsg
.message
,
1769 KernelModeMsg
.wParam
,
1770 KernelModeMsg
.lParam
);
1774 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1775 KernelModeMsg
.message
,
1776 KernelModeMsg
.wParam
,
1777 KernelModeMsg
.lParam
,
1783 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1784 if (! NT_SUCCESS(Status
))
1786 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1787 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1788 return(dsm
? 0 : -1);
1792 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1793 if (! NT_SUCCESS(Status
))
1795 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1798 return (LRESULT
)Result
;
1803 UserSendNotifyMessage( HWND hWnd
,
1810 if (FindMsgMemory(Msg
) != 0)
1812 SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY
);
1816 // Basicly the same as IntPostOrSendMessage
1817 if (hWnd
== HWND_BROADCAST
) //Handle Broadcast
1823 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1824 List
= IntWinListChildren(DesktopWindow
);
1828 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1829 for (i
= 0; List
[i
]; i
++)
1831 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1842 if ( !(Window
= UserGetWindowObject(hWnd
)) ) return FALSE
;
1844 pti
= PsGetCurrentThreadWin32Thread();
1846 if (Window
->head
.pti
->MessageQueue
!= pti
->MessageQueue
)
1847 { // Send message w/o waiting for it.
1848 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1851 { // Handle message and callback.
1852 Result
= co_IntSendMessageTimeoutSingle( hWnd
,
1866 IntGetQueueStatus(BOOL ClearChanges
)
1869 PUSER_MESSAGE_QUEUE Queue
;
1871 DECLARE_RETURN(DWORD
);
1873 DPRINT("Enter IntGetQueueStatus\n");
1875 pti
= PsGetCurrentThreadWin32Thread();
1876 Queue
= pti
->MessageQueue
;
1878 Result
= MAKELONG(Queue
->QueueBits
, Queue
->ChangedBits
);
1881 Queue
->ChangedBits
= 0;
1887 DPRINT("Leave IntGetQueueStatus, ret=%i\n",_ret_
);
1892 IntInitMessagePumpHook()
1894 if (((PTHREADINFO
)PsGetCurrentThread()->Tcb
.Win32Thread
)->pcti
)
1896 ((PTHREADINFO
)PsGetCurrentThread()->Tcb
.Win32Thread
)->pcti
->dwcPumpHook
++;
1903 IntUninitMessagePumpHook()
1905 if (((PTHREADINFO
)PsGetCurrentThread()->Tcb
.Win32Thread
)->pcti
)
1907 if (((PTHREADINFO
)PsGetCurrentThread()->Tcb
.Win32Thread
)->pcti
->dwcPumpHook
<= 0)
1911 ((PTHREADINFO
)PsGetCurrentThread()->Tcb
.Win32Thread
)->pcti
->dwcPumpHook
--;
1917 /** Functions ******************************************************************/
1920 NtUserPostMessage(HWND hWnd
,
1925 DECLARE_RETURN(BOOL
);
1927 DPRINT("Enter NtUserPostMessage\n");
1928 UserEnterExclusive();
1930 RETURN( UserPostMessage(hWnd
, Msg
, wParam
, lParam
));
1933 DPRINT("Leave NtUserPostMessage, ret=%i\n",_ret_
);
1939 NtUserPostThreadMessage(DWORD idThread
,
1944 DECLARE_RETURN(BOOL
);
1946 DPRINT("Enter NtUserPostThreadMessage\n");
1947 UserEnterExclusive();
1949 RETURN( UserPostThreadMessage( idThread
,
1955 DPRINT("Leave NtUserPostThreadMessage, ret=%i\n",_ret_
);
1961 NtUserQuerySendMessage(DWORD Unknown0
)
1969 ////////// API on the way out!
1971 NtUserSendMessageTimeout( HWND hWnd
,
1978 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1982 DECLARE_RETURN(BOOL
);
1984 DPRINT("Enter NtUserSendMessageTimeout\n");
1985 UserEnterExclusive();
1987 dsm
.uFlags
= uFlags
;
1988 dsm
.uTimeout
= uTimeout
;
1989 Result
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, &dsm
, UnsafeInfo
);
1990 if(uResult
!= NULL
&& Result
!= 0)
1994 Status
= MmCopyToCaller(uResult
, &dsm
.Result
, sizeof(ULONG_PTR
));
1995 if(!NT_SUCCESS(Status
))
1997 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2004 DPRINT("Leave NtUserSendMessageTimeout, ret=%i\n",_ret_
);
2010 NtUserSendMessage( HWND Wnd
,
2014 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
2016 DECLARE_RETURN(BOOL
);
2018 DPRINT("Enter NtUserSendMessage\n");
2019 UserEnterExclusive();
2021 RETURN(co_IntDoSendMessage(Wnd
, Msg
, wParam
, lParam
, NULL
, UnsafeInfo
));
2024 DPRINT("Leave NtUserSendMessage, ret=%i\n",_ret_
);
2031 NtUserWaitMessage(VOID
)
2033 DECLARE_RETURN(BOOL
);
2035 DPRINT("EnterNtUserWaitMessage\n");
2036 UserEnterExclusive();
2038 RETURN(co_IntWaitMessage(NULL
, 0, 0));
2041 DPRINT("Leave NtUserWaitMessage, ret=%i\n",_ret_
);
2048 NtUserGetMessage( PNTUSERGETMESSAGEINFO UnsafeInfo
,
2053 * FUNCTION: Get a message from the calling thread's message queue.
2055 * UnsafeMsg - Pointer to the structure which receives the returned message.
2056 * Wnd - Window whose messages are to be retrieved.
2057 * MsgFilterMin - Integer value of the lowest message value to be
2059 * MsgFilterMax - Integer value of the highest message value to be
2064 NTUSERGETMESSAGEINFO Info
;
2066 /* FIXME: if initialization is removed, gcc complains that this may be used before initialization. Please review */
2068 PMSGMEMORY MsgMemoryEntry
;
2072 DECLARE_RETURN(BOOL
);
2073 // USER_REFERENCE_ENTRY Ref;
2075 DPRINT("Enter NtUserGetMessage\n");
2076 UserEnterExclusive();
2078 /* Validate input */
2079 if (hWnd
&& !(Window
= UserGetWindowObject(hWnd
)))
2084 // if (Window) UserRefObjectCo(Window, &Ref);
2086 if (MsgFilterMax
< MsgFilterMin
)
2094 GotMessage
= co_IntPeekMessage(&Msg
, Window
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
);
2098 /* See if this message type is present in the table */
2099 MsgMemoryEntry
= FindMsgMemory(Info
.Msg
.message
);
2100 if (NULL
== MsgMemoryEntry
)
2102 /* Not present, no copying needed */
2103 Info
.LParamSize
= 0;
2107 /* Determine required size */
2108 Size
= MsgMemorySize(MsgMemoryEntry
, Info
.Msg
.wParam
,
2110 /* Allocate required amount of user-mode memory */
2111 Info
.LParamSize
= Size
;
2113 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem
, 0,
2114 &Info
.LParamSize
, MEM_COMMIT
, PAGE_READWRITE
);
2116 if (! NT_SUCCESS(Status
))
2118 SetLastNtError(Status
);
2121 /* Transfer lParam data to user-mode mem */
2122 Status
= MmCopyToCaller(UserMem
, (PVOID
) Info
.Msg
.lParam
, Size
);
2123 if (! NT_SUCCESS(Status
))
2125 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &UserMem
,
2126 &Info
.LParamSize
, MEM_DECOMMIT
);
2127 SetLastNtError(Status
);
2130 Info
.Msg
.lParam
= (LPARAM
) UserMem
;
2132 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERGETMESSAGEINFO
));
2133 if (! NT_SUCCESS(Status
))
2135 SetLastNtError(Status
);
2139 else if (! co_IntWaitMessage(Window
, MsgFilterMin
, MsgFilterMax
))
2144 while (! GotMessage
);
2146 RETURN( WM_QUIT
!= Info
.Msg
.message
);
2149 // if (Window) UserDerefObjectCo(Window);
2151 DPRINT("Leave NtUserGetMessage\n");
2158 NtUserGetMessageX(PMSG pMsg
,
2165 DECLARE_RETURN(BOOL
);
2167 DPRINT("Enter NtUserGetMessage\n");
2168 UserEnterExclusive();
2170 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
2172 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2176 RtlZeroMemory(&Msg
, sizeof(MSG
));
2178 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
2184 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2185 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2187 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2189 SetLastNtError(_SEH2_GetExceptionCode());
2197 DPRINT("Leave NtUserGetMessage\n");
2203 NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo
,
2211 NTUSERGETMESSAGEINFO Info
;
2213 PMSGMEMORY MsgMemoryEntry
;
2217 DECLARE_RETURN(BOOL
);
2219 DPRINT("Enter NtUserPeekMessage\n");
2220 UserEnterExclusive();
2222 if (hWnd
== (HWND
)-1 || hWnd
== (HWND
)0x0000FFFF || hWnd
== (HWND
)0xFFFFFFFF)
2225 /* Validate input */
2226 if (hWnd
&& hWnd
!= (HWND
)1)
2228 if (!(Window
= UserGetWindowObject(hWnd
)))
2235 Window
= (PWND
)hWnd
;
2238 if (MsgFilterMax
< MsgFilterMin
)
2244 Present
= co_IntPeekMessage(&Msg
, Window
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
);
2249 /* See if this message type is present in the table */
2250 MsgMemoryEntry
= FindMsgMemory(Info
.Msg
.message
);
2251 if (NULL
== MsgMemoryEntry
)
2253 /* Not present, no copying needed */
2254 Info
.LParamSize
= 0;
2258 /* Determine required size */
2259 Size
= MsgMemorySize(MsgMemoryEntry
, Info
.Msg
.wParam
,
2261 /* Allocate required amount of user-mode memory */
2262 Info
.LParamSize
= Size
;
2264 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem
, 0,
2265 &Info
.LParamSize
, MEM_COMMIT
, PAGE_READWRITE
);
2266 if (! NT_SUCCESS(Status
))
2268 SetLastNtError(Status
);
2271 /* Transfer lParam data to user-mode mem */
2272 Status
= MmCopyToCaller(UserMem
, (PVOID
) Info
.Msg
.lParam
, Size
);
2273 if (! NT_SUCCESS(Status
))
2275 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &UserMem
,
2276 &Info
.LParamSize
, MEM_RELEASE
);
2277 SetLastNtError(Status
);
2280 Info
.Msg
.lParam
= (LPARAM
) UserMem
;
2282 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERGETMESSAGEINFO
));
2283 if (! NT_SUCCESS(Status
))
2285 SetLastNtError(Status
);
2293 DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_
);
2299 NtUserPeekMessageX( PMSG pMsg
,
2307 DECLARE_RETURN(BOOL
);
2309 DPRINT("Enter NtUserPeekMessage\n");
2310 UserEnterExclusive();
2312 if ( RemoveMsg
& PM_BADMSGFLAGS
)
2314 SetLastWin32Error(ERROR_INVALID_FLAGS
);
2318 RtlZeroMemory(&Msg
, sizeof(MSG
));
2320 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
2326 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2327 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2329 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2331 SetLastNtError(_SEH2_GetExceptionCode());
2339 DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_
);
2345 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
2347 BOOL BadChk
= FALSE
, Ret
= FALSE
;
2349 DECLARE_RETURN(BOOL
);
2351 DPRINT("Enter NtUserCallMsgFilter\n");
2352 UserEnterExclusive();
2357 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
2358 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
2360 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2369 if (BadChk
) RETURN( FALSE
);
2371 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
2377 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
2382 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
2383 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
2385 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2390 if (BadChk
) RETURN( FALSE
);
2394 DPRINT("Leave NtUserCallMsgFilter. ret=%i\n", _ret_
);
2400 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
2406 UserEnterExclusive();
2409 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
2410 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
2412 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2414 SetLastNtError(_SEH2_GetExceptionCode());
2419 if (!Hit
) Res
= IntDispatchMessage(&SafeMsg
);
2427 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
2431 DECLARE_RETURN(BOOL
);
2433 DPRINT("Enter NtUserTranslateMessage\n");
2434 UserEnterExclusive();
2436 Status
= MmCopyFromCaller(&SafeMsg
, lpMsg
, sizeof(MSG
));
2437 if(!NT_SUCCESS(Status
))
2439 SetLastNtError(Status
);
2443 RETURN( IntTranslateKbdMessage(&SafeMsg
, flags
));
2446 DPRINT("Leave NtUserTranslateMessage: ret=%i\n",_ret_
);
2452 NtUserMessageCall( HWND hWnd
,
2456 ULONG_PTR ResultInfo
,
2457 DWORD dwType
, // fnID?
2460 LRESULT lResult
= 0;
2462 BOOL BadChk
= FALSE
;
2464 USER_REFERENCE_ENTRY Ref
;
2466 UserEnterExclusive();
2468 /* Validate input */
2469 if (hWnd
&& (hWnd
!= INVALID_HANDLE_VALUE
))
2471 Window
= UserGetWindowObject(hWnd
);
2481 case FNID_DEFWINDOWPROC
:
2482 if (Window
) UserRefObjectCo(Window
, &Ref
);
2483 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2485 if (Window
) UserDerefObjectCo(Window
);
2487 case FNID_SENDNOTIFYMESSAGE
:
2488 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2490 case FNID_BROADCASTSYSTEMMESSAGE
:
2493 DWORD_PTR RetVal
= 0;
2499 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2500 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2502 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2512 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2513 parm
.recipients
== BSM_ALLCOMPONENTS
)
2516 else if (parm
.recipients
& BSM_APPLICATIONS
)
2518 if (parm
.flags
& BSF_QUERY
)
2520 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2522 co_IntSendMessageTimeout( HWND_BROADCAST
,
2530 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2532 co_IntSendMessageTimeout( HWND_BROADCAST
,
2536 SMTO_NOTIMEOUTIFNOTHUNG
,
2542 co_IntSendMessageTimeout( HWND_BROADCAST
,
2552 else if (parm
.flags
& BSF_POSTMESSAGE
)
2554 Ret
= UserPostMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2556 else //Everything else,,,, if ( parm.flags & BSF_SENDNOTIFYMESSAGE)
2558 Ret
= UserSendNotifyMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2563 case FNID_SENDMESSAGECALLBACK
:
2565 PCALL_BACK_INFO CallBackInfo
= (PCALL_BACK_INFO
)ResultInfo
;
2571 if (!co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2572 CallBackInfo
->CallBack
, CallBackInfo
->Context
, &uResult
))
2574 DPRINT1("Callback failure!\n");
2578 // CallNextHook bypass.
2579 case FNID_CALLWNDPROC
:
2580 case FNID_CALLWNDPROCRET
:
2583 PCLIENTINFO ClientInfo
;
2584 PHOOK NextObj
, Hook
;
2586 pti
= GetW32ThreadInfo();
2588 Hook
= pti
->sphkCurrent
;
2592 NextObj
= Hook
->phkNext
;
2593 ClientInfo
= pti
->pClientInfo
;
2596 ClientInfo
->phkCurrent
= NextObj
;
2598 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2604 if (!ClientInfo
|| !NextObj
) break;
2606 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2608 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2613 CWP
.wParam
= wParam
;
2614 CWP
.lParam
= lParam
;
2615 DPRINT("WH_CALLWNDPROC: Hook %x NextHook %x\n", Hook
, NextObj
);
2617 lResult
= co_IntCallHookProc( Hook
->HookId
,
2619 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2630 CWPR
.wParam
= wParam
;
2631 CWPR
.lParam
= lParam
;
2632 CWPR
.lResult
= ClientInfo
->dwHookData
;
2634 lResult
= co_IntCallHookProc( Hook
->HookId
,
2636 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2648 case FNID_DEFWINDOWPROC
:
2649 case FNID_CALLWNDPROC
:
2650 case FNID_CALLWNDPROCRET
:
2655 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2656 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2658 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2671 return BadChk
? FALSE
: Ret
;
2674 #define INFINITE 0xFFFFFFFF
2675 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2679 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2680 IN DWORD dwMilliseconds
,
2684 PPROCESSINFO W32Process
;
2687 LARGE_INTEGER Timeout
;
2688 ULONGLONG StartTime
, Run
, Elapsed
= 0;
2690 UserEnterExclusive();
2692 Status
= ObReferenceObjectByHandle(hProcess
,
2693 PROCESS_QUERY_INFORMATION
,
2699 if (!NT_SUCCESS(Status
))
2702 SetLastNtError(Status
);
2706 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2709 ObDereferenceObject(Process
);
2711 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
2715 EngCreateEvent((PEVENT
*)&W32Process
->InputIdleEvent
);
2717 Handles
[0] = Process
;
2718 Handles
[1] = W32Process
->InputIdleEvent
;
2722 ObDereferenceObject(Process
);
2724 return STATUS_SUCCESS
; /* no event to wait on */
2727 StartTime
= EngGetTickCount();
2729 Run
= dwMilliseconds
;
2731 DPRINT("WFII: waiting for %p\n", Handles
[1] );
2734 Timeout
.QuadPart
= Run
- Elapsed
;
2736 Status
= KeWaitForMultipleObjects( 2,
2742 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2744 UserEnterExclusive();
2746 if (!NT_SUCCESS(Status
))
2748 SetLastNtError(Status
);
2749 Status
= WAIT_FAILED
;
2756 Status
= WAIT_FAILED
;
2762 co_IntPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
);
2766 case STATUS_USER_APC
:
2767 case STATUS_ALERTED
:
2768 case STATUS_TIMEOUT
:
2769 DPRINT1("WFII: timeout\n");
2770 Status
= STATUS_TIMEOUT
;
2774 DPRINT1("WFII: finished\n");
2775 Status
= STATUS_SUCCESS
;
2779 if (dwMilliseconds
!= INFINITE
)
2781 Elapsed
= EngGetTickCount() - StartTime
;
2784 Status
= STATUS_TIMEOUT
;
2791 if (W32Process
->InputIdleEvent
)
2793 EngFreeMem((PVOID
)W32Process
->InputIdleEvent
);
2794 W32Process
->InputIdleEvent
= NULL
;
2796 ObDereferenceObject(Process
);