2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
5 * FILE: subsystems/win32/win32k/ntuser/message.c
6 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
10 DBG_DEFAULT_CHANNEL(UserMsg
);
12 #define PM_BADMSGFLAGS ~((QS_RAWINPUT << 16)|PM_QS_SENDMESSAGE|PM_QS_PAINT|PM_QS_POSTMESSAGE|PM_QS_INPUT|PM_NOYIELD|PM_REMOVE)
14 /* FUNCTIONS *****************************************************************/
17 IntInitMessageImpl(VOID
)
19 return STATUS_SUCCESS
;
23 IntCleanupMessageImpl(VOID
)
25 return STATUS_SUCCESS
;
29 /* flag for messages that contain pointers */
30 /* 32 messages per entry, messages 0..31 map to bits 0..31 */
32 #define SET(msg) (1 << ((msg) & 31))
34 static const unsigned int message_pointer_flags
[] =
37 SET(WM_CREATE
) | SET(WM_SETTEXT
) | SET(WM_GETTEXT
) |
38 SET(WM_WININICHANGE
) | SET(WM_DEVMODECHANGE
),
40 SET(WM_GETMINMAXINFO
) | SET(WM_DRAWITEM
) | SET(WM_MEASUREITEM
) | SET(WM_DELETEITEM
) |
43 SET(WM_WINDOWPOSCHANGING
) | SET(WM_WINDOWPOSCHANGED
) | SET(WM_COPYDATA
) |
44 SET(WM_COPYGLOBALDATA
) | SET(WM_NOTIFY
) | SET(WM_HELP
),
46 SET(WM_STYLECHANGING
) | SET(WM_STYLECHANGED
),
48 SET(WM_NCCREATE
) | SET(WM_NCCALCSIZE
) | SET(WM_GETDLGCODE
),
50 SET(EM_GETSEL
) | SET(EM_GETRECT
) | SET(EM_SETRECT
) | SET(EM_SETRECTNP
),
52 SET(EM_REPLACESEL
) | SET(EM_GETLINE
) | SET(EM_SETTABSTOPS
),
54 SET(SBM_GETRANGE
) | SET(SBM_SETSCROLLINFO
) | SET(SBM_GETSCROLLINFO
) | SET(SBM_GETSCROLLBARINFO
),
60 SET(CB_GETEDITSEL
) | SET(CB_ADDSTRING
) | SET(CB_DIR
) | SET(CB_GETLBTEXT
) |
61 SET(CB_INSERTSTRING
) | SET(CB_FINDSTRING
) | SET(CB_SELECTSTRING
) |
62 SET(CB_GETDROPPEDCONTROLRECT
) | SET(CB_FINDSTRINGEXACT
),
66 SET(LB_ADDSTRING
) | SET(LB_INSERTSTRING
) | SET(LB_GETTEXT
) | SET(LB_SELECTSTRING
) |
67 SET(LB_DIR
) | SET(LB_FINDSTRING
) |
68 SET(LB_GETSELITEMS
) | SET(LB_SETTABSTOPS
) | SET(LB_ADDFILE
) | SET(LB_GETITEMRECT
),
70 SET(LB_FINDSTRINGEXACT
),
76 SET(WM_NEXTMENU
) | SET(WM_SIZING
) | SET(WM_MOVING
) | SET(WM_DEVICECHANGE
),
78 SET(WM_MDICREATE
) | SET(WM_MDIGETACTIVE
) | SET(WM_DROPOBJECT
) |
79 SET(WM_QUERYDROPOBJECT
) | SET(WM_DRAGLOOP
) | SET(WM_DRAGSELECT
) | SET(WM_DRAGMOVE
),
93 SET(WM_ASKCBFORMATNAME
)
96 /* check whether a given message type includes pointers */
97 static inline int is_pointer_message( UINT message
)
99 if (message
>= 8*sizeof(message_pointer_flags
)) return FALSE
;
100 return (message_pointer_flags
[message
/ 32] & SET(message
)) != 0;
104 #define MMS_SIZE_WPARAM -1
105 #define MMS_SIZE_WPARAMWCHAR -2
106 #define MMS_SIZE_LPARAMSZ -3
107 #define MMS_SIZE_SPECIAL -4
108 #define MMS_FLAG_READ 0x01
109 #define MMS_FLAG_WRITE 0x02
110 #define MMS_FLAG_READWRITE (MMS_FLAG_READ | MMS_FLAG_WRITE)
111 typedef struct tagMSGMEMORY
117 MSGMEMORY
, *PMSGMEMORY
;
119 static MSGMEMORY MsgMemory
[] =
121 { WM_CREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
122 { WM_DDE_ACK
, sizeof(KMDDELPARAM
), MMS_FLAG_READ
},
123 { WM_DDE_EXECUTE
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
124 { WM_GETMINMAXINFO
, sizeof(MINMAXINFO
), MMS_FLAG_READWRITE
},
125 { WM_GETTEXT
, MMS_SIZE_WPARAMWCHAR
, MMS_FLAG_WRITE
},
126 { WM_NCCALCSIZE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
127 { WM_NCCREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
128 { WM_SETTEXT
, MMS_SIZE_LPARAMSZ
, MMS_FLAG_READ
},
129 { WM_STYLECHANGED
, sizeof(STYLESTRUCT
), MMS_FLAG_READ
},
130 { WM_STYLECHANGING
, sizeof(STYLESTRUCT
), MMS_FLAG_READWRITE
},
131 { WM_COPYDATA
, MMS_SIZE_SPECIAL
, MMS_FLAG_READ
},
132 { WM_COPYGLOBALDATA
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
133 { WM_WINDOWPOSCHANGED
, sizeof(WINDOWPOS
), MMS_FLAG_READ
},
134 { WM_WINDOWPOSCHANGING
, sizeof(WINDOWPOS
), MMS_FLAG_READWRITE
},
137 static PMSGMEMORY FASTCALL
138 FindMsgMemory(UINT Msg
)
140 PMSGMEMORY MsgMemoryEntry
;
142 /* See if this message type is present in the table */
143 for (MsgMemoryEntry
= MsgMemory
;
144 MsgMemoryEntry
< MsgMemory
+ sizeof(MsgMemory
) / sizeof(MSGMEMORY
);
147 if (Msg
== MsgMemoryEntry
->Message
)
149 return MsgMemoryEntry
;
157 MsgMemorySize(PMSGMEMORY MsgMemoryEntry
, WPARAM wParam
, LPARAM lParam
)
160 PUNICODE_STRING WindowName
;
161 PUNICODE_STRING ClassName
;
166 if (MMS_SIZE_WPARAM
== MsgMemoryEntry
->Size
)
170 else if (MMS_SIZE_WPARAMWCHAR
== MsgMemoryEntry
->Size
)
172 Size
= (UINT
) (wParam
* sizeof(WCHAR
));
174 else if (MMS_SIZE_LPARAMSZ
== MsgMemoryEntry
->Size
)
176 Size
= (UINT
) ((wcslen((PWSTR
) lParam
) + 1) * sizeof(WCHAR
));
178 else if (MMS_SIZE_SPECIAL
== MsgMemoryEntry
->Size
)
180 switch(MsgMemoryEntry
->Message
)
184 Cs
= (CREATESTRUCTW
*) lParam
;
185 WindowName
= (PUNICODE_STRING
) Cs
->lpszName
;
186 ClassName
= (PUNICODE_STRING
) Cs
->lpszClass
;
187 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
188 if (IS_ATOM(ClassName
->Buffer
))
190 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
194 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
199 Size
= wParam
? sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
) : sizeof(RECT
);
203 Size
= sizeof(COPYDATASTRUCT
) + ((PCOPYDATASTRUCT
)lParam
)->cbData
;
214 Size
= MsgMemoryEntry
->Size
;
217 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
219 ERR("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH2_GetExceptionCode());
227 PackParam(LPARAM
*lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolNeeded
)
229 NCCALCSIZE_PARAMS
*UnpackedNcCalcsize
;
230 NCCALCSIZE_PARAMS
*PackedNcCalcsize
;
231 CREATESTRUCTW
*UnpackedCs
;
232 CREATESTRUCTW
*PackedCs
;
233 PLARGE_STRING WindowName
;
234 PUNICODE_STRING ClassName
;
239 *lParamPacked
= lParam
;
241 if (NonPagedPoolNeeded
)
242 PoolType
= NonPagedPool
;
244 PoolType
= PagedPool
;
246 if (WM_NCCALCSIZE
== Msg
&& wParam
)
249 UnpackedNcCalcsize
= (NCCALCSIZE_PARAMS
*) lParam
;
250 PackedNcCalcsize
= ExAllocatePoolWithTag(PoolType
,
251 sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
),
254 if (NULL
== PackedNcCalcsize
)
256 ERR("Not enough memory to pack lParam\n");
257 return STATUS_NO_MEMORY
;
259 RtlCopyMemory(PackedNcCalcsize
, UnpackedNcCalcsize
, sizeof(NCCALCSIZE_PARAMS
));
260 PackedNcCalcsize
->lppos
= (PWINDOWPOS
) (PackedNcCalcsize
+ 1);
261 RtlCopyMemory(PackedNcCalcsize
->lppos
, UnpackedNcCalcsize
->lppos
, sizeof(WINDOWPOS
));
262 *lParamPacked
= (LPARAM
) PackedNcCalcsize
;
264 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
266 UnpackedCs
= (CREATESTRUCTW
*) lParam
;
267 WindowName
= (PLARGE_STRING
) UnpackedCs
->lpszName
;
268 ClassName
= (PUNICODE_STRING
) UnpackedCs
->lpszClass
;
269 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
270 if (IS_ATOM(ClassName
->Buffer
))
272 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
276 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
278 PackedCs
= ExAllocatePoolWithTag(PoolType
, Size
, TAG_MSG
);
279 if (NULL
== PackedCs
)
281 ERR("Not enough memory to pack lParam\n");
282 return STATUS_NO_MEMORY
;
284 RtlCopyMemory(PackedCs
, UnpackedCs
, sizeof(CREATESTRUCTW
));
285 CsData
= (PCHAR
) (PackedCs
+ 1);
286 PackedCs
->lpszName
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
287 RtlCopyMemory(CsData
, WindowName
->Buffer
, WindowName
->Length
);
288 CsData
+= WindowName
->Length
;
289 *((WCHAR
*) CsData
) = L
'\0';
290 CsData
+= sizeof(WCHAR
);
291 PackedCs
->lpszClass
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
292 if (IS_ATOM(ClassName
->Buffer
))
294 *((WCHAR
*) CsData
) = L
'A';
295 CsData
+= sizeof(WCHAR
);
296 *((ATOM
*) CsData
) = (ATOM
)(DWORD_PTR
) ClassName
->Buffer
;
297 CsData
+= sizeof(ATOM
);
301 *((WCHAR
*) CsData
) = L
'S';
302 CsData
+= sizeof(WCHAR
);
303 RtlCopyMemory(CsData
, ClassName
->Buffer
, ClassName
->Length
);
304 CsData
+= ClassName
->Length
;
305 *((WCHAR
*) CsData
) = L
'\0';
306 CsData
+= sizeof(WCHAR
);
308 ASSERT(CsData
== (PCHAR
) PackedCs
+ Size
);
309 *lParamPacked
= (LPARAM
) PackedCs
;
311 else if (PoolType
== NonPagedPool
)
313 PMSGMEMORY MsgMemoryEntry
;
317 MsgMemoryEntry
= FindMsgMemory(Msg
);
319 if ((!MsgMemoryEntry
) || (MsgMemoryEntry
->Size
< 0))
321 /* Keep previous behavior */
322 return STATUS_SUCCESS
;
324 size
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
327 ERR("No size for lParamPacked\n");
328 return STATUS_SUCCESS
;
330 PackedData
= ExAllocatePoolWithTag(NonPagedPool
, size
, TAG_MSG
);
331 if (PackedData
== NULL
)
333 ERR("Not enough memory to pack lParam\n");
334 return STATUS_NO_MEMORY
;
336 RtlCopyMemory(PackedData
, (PVOID
)lParam
, MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
));
337 *lParamPacked
= (LPARAM
)PackedData
;
340 return STATUS_SUCCESS
;
344 UnpackParam(LPARAM lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolUsed
)
346 NCCALCSIZE_PARAMS
*UnpackedParams
;
347 NCCALCSIZE_PARAMS
*PackedParams
;
348 PWINDOWPOS UnpackedWindowPos
;
350 if (lParamPacked
== lParam
)
352 return STATUS_SUCCESS
;
355 if (WM_NCCALCSIZE
== Msg
&& wParam
)
357 PackedParams
= (NCCALCSIZE_PARAMS
*) lParamPacked
;
358 UnpackedParams
= (NCCALCSIZE_PARAMS
*) lParam
;
359 UnpackedWindowPos
= UnpackedParams
->lppos
;
360 RtlCopyMemory(UnpackedParams
, PackedParams
, sizeof(NCCALCSIZE_PARAMS
));
361 UnpackedParams
->lppos
= UnpackedWindowPos
;
362 RtlCopyMemory(UnpackedWindowPos
, PackedParams
+ 1, sizeof(WINDOWPOS
));
363 ExFreePool((PVOID
) lParamPacked
);
365 return STATUS_SUCCESS
;
367 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
369 ExFreePool((PVOID
) lParamPacked
);
371 return STATUS_SUCCESS
;
373 else if (NonPagedPoolUsed
)
375 PMSGMEMORY MsgMemoryEntry
;
376 MsgMemoryEntry
= FindMsgMemory(Msg
);
377 ASSERT(MsgMemoryEntry
);
378 if (MsgMemoryEntry
->Size
< 0)
380 /* Keep previous behavior */
381 return STATUS_INVALID_PARAMETER
;
384 if (MsgMemory
->Flags
== MMS_FLAG_READWRITE
)
386 //RtlCopyMemory((PVOID)lParam, (PVOID)lParamPacked, MsgMemory->Size);
388 ExFreePool((PVOID
) lParamPacked
);
389 return STATUS_SUCCESS
;
394 return STATUS_INVALID_PARAMETER
;
397 static NTSTATUS FASTCALL
398 CopyMsgToKernelMem(MSG
*KernelModeMsg
, MSG
*UserModeMsg
, PMSGMEMORY MsgMemoryEntry
)
405 *KernelModeMsg
= *UserModeMsg
;
407 /* See if this message type is present in the table */
408 if (NULL
== MsgMemoryEntry
)
410 /* Not present, no copying needed */
411 return STATUS_SUCCESS
;
414 /* Determine required size */
415 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
419 /* Allocate kernel mem */
420 KernelMem
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
421 if (NULL
== KernelMem
)
423 ERR("Not enough memory to copy message to kernel mem\n");
424 return STATUS_NO_MEMORY
;
426 KernelModeMsg
->lParam
= (LPARAM
) KernelMem
;
428 /* Copy data if required */
429 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_READ
))
431 Status
= MmCopyFromCaller(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
432 if (! NT_SUCCESS(Status
))
434 ERR("Failed to copy message to kernel: invalid usermode buffer\n");
435 ExFreePoolWithTag(KernelMem
, TAG_MSG
);
441 /* Make sure we don't pass any secrets to usermode */
442 RtlZeroMemory(KernelMem
, Size
);
447 KernelModeMsg
->lParam
= 0;
450 return STATUS_SUCCESS
;
453 static NTSTATUS FASTCALL
454 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
457 PMSGMEMORY MsgMemoryEntry
;
460 /* See if this message type is present in the table */
461 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
462 if (NULL
== MsgMemoryEntry
)
464 /* Not present, no copying needed */
465 return STATUS_SUCCESS
;
468 /* Determine required size */
469 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
473 /* Copy data if required */
474 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
476 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
477 if (! NT_SUCCESS(Status
))
479 ERR("Failed to copy message from kernel: invalid usermode buffer\n");
480 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
485 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
488 return STATUS_SUCCESS
;
492 // Wakeup any thread/process waiting on idle input.
497 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
498 PUSER_MESSAGE_QUEUE ForegroundQueue
;
499 PTHREADINFO pti
, ptiForeground
= NULL
;
501 ForegroundQueue
= IntGetFocusMessageQueue();
504 ptiForeground
= ForegroundQueue
->Thread
->Tcb
.Win32Thread
;
506 pti
= PsGetCurrentThreadWin32Thread();
510 pti
->pClientInfo
->cSpins
= 0; // Reset spins.
512 if ( pti
->pDeskInfo
&& pti
== ptiForeground
)
514 if ( pti
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) ||
515 pti
->pDeskInfo
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) )
517 co_HOOK_CallHooks(WH_FOREGROUNDIDLE
,HC_ACTION
,0,0);
522 TRACE("IdlePing ppi 0x%x\n",ppi
);
523 if ( ppi
&& ppi
->InputIdleEvent
)
525 TRACE("InputIdleEvent\n");
526 KeSetEvent( ppi
->InputIdleEvent
, IO_NO_INCREMENT
, FALSE
);
533 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
535 TRACE("IdlePong ppi 0x%x\n",ppi
);
536 if ( ppi
&& ppi
->InputIdleEvent
)
538 KeClearEvent(ppi
->InputIdleEvent
);
543 GetWakeMask(UINT first
, UINT last
)
545 UINT mask
= QS_POSTMESSAGE
| QS_SENDMESSAGE
; /* Always selected */
549 if ((first
<= WM_KEYLAST
) && (last
>= WM_KEYFIRST
)) mask
|= QS_KEY
;
550 if ( ((first
<= WM_MOUSELAST
) && (last
>= WM_MOUSEFIRST
)) ||
551 ((first
<= WM_NCMOUSELAST
) && (last
>= WM_NCMOUSEFIRST
)) ) mask
|= QS_MOUSE
;
552 if ((first
<= WM_TIMER
) && (last
>= WM_TIMER
)) mask
|= QS_TIMER
;
553 if ((first
<= WM_SYSTIMER
) && (last
>= WM_SYSTIMER
)) mask
|= QS_TIMER
;
554 if ((first
<= WM_PAINT
) && (last
>= WM_PAINT
)) mask
|= QS_PAINT
;
556 else mask
= QS_ALLINPUT
;
562 IntCallWndProc( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
564 BOOL SameThread
= FALSE
;
567 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
574 co_HOOK_CallHooks( WH_CALLWNDPROC
, HC_ACTION
, SameThread
, (LPARAM
)&CWP
);
578 IntCallWndProcRet ( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*uResult
)
580 BOOL SameThread
= FALSE
;
583 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
588 CWPR
.wParam
= wParam
;
589 CWPR
.lParam
= lParam
;
590 CWPR
.lResult
= uResult
? (*uResult
) : 0;
591 co_HOOK_CallHooks( WH_CALLWNDPROCRET
, HC_ACTION
, SameThread
, (LPARAM
)&CWPR
);
594 static LRESULT
handle_internal_message( PWND pWnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
597 USER_REFERENCE_ENTRY Ref
;
600 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
601 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
604 TRACE("Internal Event Msg %p\n",msg
);
608 case WM_ASYNC_SHOWWINDOW
:
609 return co_WinPosShowWindow( pWnd
, wparam
);
610 case WM_ASYNC_SETWINDOWPOS
:
612 PWINDOWPOS winpos
= (PWINDOWPOS
)lparam
;
613 if (!winpos
) return 0;
614 lRes
= co_WinPosSetWindowPos( pWnd
,
615 winpos
->hwndInsertAfter
,
621 ExFreePoolWithTag(winpos
, USERTAG_SWP
);
624 case WM_ASYNC_SETACTIVEWINDOW
:
626 PWND Window
= (PWND
)wparam
;
627 if (wparam
) UserRefObjectCo(Window
, &Ref
);
628 lRes
= (LRESULT
)co_IntSetActiveWindow(Window
,NULL
,(BOOL
)lparam
,TRUE
);
629 if (wparam
) UserDerefObjectCo(Window
);
637 IntDispatchMessage(PMSG pMsg
)
639 LARGE_INTEGER TickCount
;
648 Window
= UserGetWindowObject(pMsg
->hwnd
);
649 if (!Window
) return 0;
652 pti
= PsGetCurrentThreadWin32Thread();
654 if ( Window
&& Window
->head
.pti
!= pti
)
656 EngSetLastError( ERROR_MESSAGE_SYNC_ONLY
);
660 if (((pMsg
->message
== WM_SYSTIMER
) ||
661 (pMsg
->message
== WM_TIMER
)) &&
664 if (pMsg
->message
== WM_TIMER
)
666 if (ValidateTimerCallback(pti
,pMsg
->lParam
))
668 KeQueryTickCount(&TickCount
);
669 Time
= MsqCalculateMessageTime(&TickCount
);
670 retval
= co_IntCallWindowProc((WNDPROC
)pMsg
->lParam
,
682 PTIMER pTimer
= FindSystemTimer(pMsg
);
683 if (pTimer
&& pTimer
->pfn
)
685 KeQueryTickCount(&TickCount
);
686 Time
= MsqCalculateMessageTime(&TickCount
);
687 pTimer
->pfn(pMsg
->hwnd
, WM_SYSTIMER
, (UINT
)pMsg
->wParam
, Time
);
693 if ( !Window
) return 0;
695 if (pMsg
->message
== WM_PAINT
) Window
->state
|= WNDS_PAINTNOTPROCESSED
;
697 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
699 TRACE("Dispatch: Server Side Window Procedure\n");
702 /* Since we are doing a callback on the same thread right away, there is
703 no need to copy the lparam to kernel mode and then back to usermode.
704 We just pretend it isn't a pointer */
706 retval
= co_IntCallWindowProc( Window
->lpfnWndProc
,
714 if (pMsg
->message
== WM_PAINT
)
716 Window
->state2
&= ~WNDS2_WMPAINTSENT
;
717 /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
718 hrgn
= IntSysCreateRectRgn( 0, 0, 0, 0 );
719 co_UserGetUpdateRgn( Window
, hrgn
, TRUE
);
720 GreDeleteObject(hrgn
);
727 * Internal version of PeekMessage() doing all the work
730 co_IntPeekMessage( PMSG Msg
,
739 LARGE_INTEGER LargeTickCount
;
740 PUSER_MESSAGE_QUEUE ThreadQueue
;
745 pti
= PsGetCurrentThreadWin32Thread();
746 ThreadQueue
= pti
->MessageQueue
;
747 //pci = pti->pClientInfo;
749 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
750 ProcessMask
= HIWORD(RemoveMsg
);
752 /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns
753 all available messages (that is, no range filtering is performed)". */
754 if (!ProcessMask
) ProcessMask
= (QS_ALLPOSTMESSAGE
|QS_ALLINPUT
);
760 KeQueryTickCount(&LargeTickCount
);
761 ThreadQueue
->LastMsgRead
= LargeTickCount
.u
.LowPart
;
762 pti
->pcti
->tickLastMsgChecked
= LargeTickCount
.u
.LowPart
;
764 /* Dispatch sent messages here. */
765 while ( co_MsqDispatchOneSentMessage(ThreadQueue
) )
767 /* if some PM_QS* flags were specified, only handle sent messages from now on */
768 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
; // wine does this; ProcessMask = QS_SENDMESSAGE;
770 if (Hit
) return FALSE
;
772 /* Clear changed bits so we can wait on them if we don't find a message */
773 if (ProcessMask
& QS_POSTMESSAGE
)
775 pti
->pcti
->fsChangeBits
&= ~(QS_POSTMESSAGE
| QS_HOTKEY
| QS_TIMER
);
776 if (MsgFilterMin
== 0 && MsgFilterMax
== 0) // Wine hack does this; ~0U)
778 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
782 if (ProcessMask
& QS_INPUT
)
784 pti
->pcti
->fsChangeBits
&= ~QS_INPUT
;
787 /* Now check for normal messages. */
788 if (( (ProcessMask
& QS_POSTMESSAGE
) ||
789 (ProcessMask
& QS_HOTKEY
) ) &&
790 MsqPeekMessage( ThreadQueue
,
801 /* Now look for a quit message. */
802 if (ThreadQueue
->QuitPosted
)
804 /* According to the PSDK, WM_QUIT messages are always returned, regardless
805 of the filter specified */
807 Msg
->message
= WM_QUIT
;
808 Msg
->wParam
= ThreadQueue
->QuitExitCode
;
812 ThreadQueue
->QuitPosted
= FALSE
;
813 ClearMsgBitsMask(ThreadQueue
, QS_POSTMESSAGE
);
814 pti
->pcti
->fsWakeBits
&= ~QS_ALLPOSTMESSAGE
;
815 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
820 /* Check for hardware events. */
821 if ((ProcessMask
& QS_MOUSE
) &&
822 co_MsqPeekMouseMove( ThreadQueue
,
832 if ((ProcessMask
& QS_INPUT
) &&
833 co_MsqPeekHardwareMessage( ThreadQueue
,
844 /* Check for sent messages again. */
845 while ( co_MsqDispatchOneSentMessage(ThreadQueue
) )
847 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
;
849 if (Hit
) return FALSE
;
851 /* Check for paint messages. */
852 if ((ProcessMask
& QS_PAINT
) &&
854 IntGetPaintMessage( Window
,
864 /* This is correct, check for the current threads timers waiting to be
865 posted to this threads message queue. If any we loop again.
867 if ((ProcessMask
& QS_TIMER
) &&
868 PostTimerMessages(Window
))
881 co_IntWaitMessage( PWND Window
,
886 PUSER_MESSAGE_QUEUE ThreadQueue
;
887 NTSTATUS Status
= STATUS_SUCCESS
;
890 pti
= PsGetCurrentThreadWin32Thread();
891 ThreadQueue
= pti
->MessageQueue
;
895 if ( co_IntPeekMessage( &Msg
, // Dont reenter!
899 MAKELONG( PM_NOREMOVE
, GetWakeMask( MsgFilterMin
, MsgFilterMax
)),
900 TRUE
) ) // act like GetMessage.
905 /* Nothing found. Wait for new messages. */
906 Status
= co_MsqWaitForNewMessages( ThreadQueue
,
910 if (!NT_SUCCESS(Status
))
912 SetLastNtError(Status
);
913 ERR("Exit co_IntWaitMessage on error!\n");
916 if (Status
== STATUS_USER_APC
|| Status
== STATUS_TIMEOUT
)
927 co_IntGetPeekMessage( PMSG pMsg
,
936 BOOL Present
= FALSE
;
939 if ( hWnd
== HWND_TOPMOST
|| hWnd
== HWND_BROADCAST
)
943 if (hWnd
&& hWnd
!= HWND_BOTTOM
)
945 if (!(Window
= UserGetWindowObject(hWnd
)))
958 if (MsgFilterMax
< MsgFilterMin
)
966 RemoveMsg
|= ((GetWakeMask( MsgFilterMin
, MsgFilterMax
))<< 16);
969 pti
= PsGetCurrentThreadWin32Thread();
970 pti
->pClientInfo
->cSpins
++; // Bump up the spin count.
974 Present
= co_IntPeekMessage( pMsg
,
982 /* GetMessage or PostMessage must never get messages that contain pointers */
983 ASSERT(FindMsgMemory(pMsg
->message
) == NULL
);
985 if (pMsg
->message
!= WM_PAINT
&& pMsg
->message
!= WM_QUIT
)
987 pti
->timeLast
= pMsg
->time
;
988 pti
->ptLast
= pMsg
->pt
;
991 // The WH_GETMESSAGE hook enables an application to monitor messages about to
992 // be returned by the GetMessage or PeekMessage function.
994 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)pMsg
);
1001 Status
= co_MsqWaitForNewMessages( pti
->MessageQueue
,
1005 if ( !NT_SUCCESS(Status
) ||
1006 Status
== STATUS_USER_APC
||
1007 Status
== STATUS_TIMEOUT
)
1015 if (!(RemoveMsg
& PM_NOYIELD
))
1018 // Yield this thread!
1021 UserEnterExclusive();
1022 // Fall through to exit.
1028 while( bGMSG
&& !Present
);
1030 // Been spinning, time to swap vinyl...
1031 if (pti
->pClientInfo
->cSpins
>= 100)
1033 // Clear the spin cycle to fix the mix.
1034 pti
->pClientInfo
->cSpins
= 0;
1035 //if (!(pti->TIF_flags & TIF_SPINNING)) // FIXME: Need to swap vinyl...
1041 UserPostThreadMessage( DWORD idThread
,
1048 PTHREADINFO pThread
;
1049 LARGE_INTEGER LargeTickCount
;
1052 if (is_pointer_message(Msg
))
1054 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1058 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
1060 if( Status
== STATUS_SUCCESS
)
1062 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
1064 !pThread
->MessageQueue
||
1065 (pThread
->TIF_flags
& TIF_INCLEANUP
))
1067 ObDereferenceObject( peThread
);
1071 Message
.hwnd
= NULL
;
1072 Message
.message
= Msg
;
1073 Message
.wParam
= wParam
;
1074 Message
.lParam
= lParam
;
1075 Message
.pt
= gpsi
->ptCursor
;
1077 KeQueryTickCount(&LargeTickCount
);
1078 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1079 MsqPostMessage(pThread
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
);
1080 ObDereferenceObject( peThread
);
1085 SetLastNtError( Status
);
1091 UserPostMessage( HWND Wnd
,
1097 MSG Message
, KernelModeMsg
;
1098 LARGE_INTEGER LargeTickCount
;
1101 Message
.message
= Msg
;
1102 Message
.wParam
= wParam
;
1103 Message
.lParam
= lParam
;
1104 Message
.pt
= gpsi
->ptCursor
;
1105 KeQueryTickCount(&LargeTickCount
);
1106 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1108 if (is_pointer_message(Message
.message
))
1110 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1114 if( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1117 PMSGMEMORY MsgMemoryEntry
;
1119 MsgMemoryEntry
= FindMsgMemory(Message
.message
);
1121 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &Message
, MsgMemoryEntry
);
1122 if (! NT_SUCCESS(Status
))
1124 EngSetLastError(ERROR_INVALID_PARAMETER
);
1127 co_IntSendMessageNoWait(KernelModeMsg
.hwnd
,
1128 KernelModeMsg
.message
,
1129 KernelModeMsg
.wParam
,
1130 KernelModeMsg
.lParam
);
1132 if (MsgMemoryEntry
&& KernelModeMsg
.lParam
)
1133 ExFreePool((PVOID
) KernelModeMsg
.lParam
);
1140 return UserPostThreadMessage( PtrToInt(PsGetCurrentThreadId()),
1145 if (Wnd
== HWND_BROADCAST
)
1151 DesktopWindow
= UserGetDesktopWindow();
1152 List
= IntWinListChildren(DesktopWindow
);
1156 UserPostMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1157 for (i
= 0; List
[i
]; i
++)
1159 PWND pwnd
= UserGetWindowObject(List
[i
]);
1160 if (!pwnd
) continue;
1162 if ( pwnd
->fnid
== FNID_MENU
|| // Also need pwnd->pcls->atomClassName == gaOleMainThreadWndClass
1163 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1166 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1168 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1175 Window
= UserGetWindowObject(Wnd
);
1181 pti
= Window
->head
.pti
;
1182 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1184 ERR("Attempted to post message to window 0x%x when the thread is in cleanup!\n", Wnd
);
1188 if ( Window
->state
& WNDS_DESTROYED
)
1190 ERR("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd
);
1191 /* FIXME: Last error code? */
1197 MsqPostQuitMessage(Window
->head
.pti
->MessageQueue
, wParam
);
1201 MsqPostMessage(Window
->head
.pti
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
);
1208 co_IntSendMessage( HWND hWnd
,
1213 ULONG_PTR Result
= 0;
1214 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1216 return (LRESULT
)Result
;
1221 static LRESULT FASTCALL
1222 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1228 ULONG_PTR
*uResult
)
1232 PMSGMEMORY MsgMemoryEntry
;
1233 INT lParamBufferSize
;
1234 LPARAM lParamPacked
;
1235 PTHREADINFO Win32Thread
;
1236 ULONG_PTR Hi
, Lo
, Result
= 0;
1237 DECLARE_RETURN(LRESULT
);
1238 USER_REFERENCE_ENTRY Ref
;
1240 if (!(Window
= UserGetWindowObject(hWnd
)))
1245 UserRefObjectCo(Window
, &Ref
);
1247 Win32Thread
= PsGetCurrentThreadWin32Thread();
1250 Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1252 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1254 /* Never send messages to exiting threads */
1258 if (Msg
& 0x80000000)
1260 TRACE("SMTS: Internal Message!\n");
1261 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1262 if (uResult
) *uResult
= Result
;
1266 // Only happens when calling the client!
1267 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1269 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1271 TRACE("SMT: Server Side Window Procedure\n");
1272 IoGetStackLimits(&Lo
, &Hi
);
1273 // Handle it here. Safeguard against excessive recursions.
1274 if (((ULONG_PTR
)&uResult
- Lo
) < 4096 )
1276 ERR("Server Callback Exceeded Stack!\n");
1279 /* Return after server side call, IntCallWndProcRet will not be called. */
1281 /* See if this message type is present in the table */
1282 MsgMemoryEntry
= FindMsgMemory(Msg
);
1283 if (NULL
== MsgMemoryEntry
)
1285 lParamBufferSize
= -1;
1289 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1292 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1294 ERR("Failed to pack message parameters\n");
1298 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1310 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1312 ERR("Failed to unpack message parameters\n");
1316 // Only happens when calling the client!
1317 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1322 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->head
.pti
->MessageQueue
))
1324 // FIXME: Set window hung and add to a list.
1325 /* FIXME: Set a LastError? */
1329 if (Window
->state
& WNDS_DESTROYED
)
1331 /* FIXME: Last error? */
1332 ERR("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1338 Status
= co_MsqSendMessage( Window
->head
.pti
->MessageQueue
,
1344 (uFlags
& SMTO_BLOCK
),
1348 while ((STATUS_TIMEOUT
== Status
) &&
1349 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1350 !MsqIsHung(Window
->head
.pti
->MessageQueue
)); // FIXME: Set window hung and add to a list.
1352 if (STATUS_TIMEOUT
== Status
)
1356 * Microsoft Windows 2000: If GetLastError returns zero, then the function
1358 * XP+ : If the function fails or times out, the return value is zero.
1359 * To get extended error information, call GetLastError. If GetLastError
1360 * returns ERROR_TIMEOUT, then the function timed out.
1362 EngSetLastError(ERROR_TIMEOUT
);
1365 else if (!NT_SUCCESS(Status
))
1367 SetLastNtError(Status
);
1374 if (Window
) UserDerefObjectCo(Window
);
1379 co_IntSendMessageTimeout( HWND hWnd
,
1385 ULONG_PTR
*uResult
)
1391 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1393 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1396 DesktopWindow
= UserGetDesktopWindow();
1397 if (NULL
== DesktopWindow
)
1399 EngSetLastError(ERROR_INTERNAL_ERROR
);
1403 if (hWnd
!= HWND_TOPMOST
)
1405 /* Send message to the desktop window too! */
1406 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1409 Children
= IntWinListChildren(DesktopWindow
);
1410 if (NULL
== Children
)
1415 for (Child
= Children
; NULL
!= *Child
; Child
++)
1417 if (hWnd
== HWND_TOPMOST
)
1419 DesktopWindow
= UserGetWindowObject(*Child
);
1420 if (DesktopWindow
&& DesktopWindow
->ExStyle
& WS_EX_TOPMOST
)
1422 ERR("HWND_TOPMOST Found\n");
1423 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1428 PWND pwnd
= UserGetWindowObject(*Child
);
1429 if (!pwnd
) continue;
1431 if ( pwnd
->fnid
== FNID_MENU
||
1432 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1435 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1439 ExFreePool(Children
);
1441 return (LRESULT
) TRUE
;
1445 co_IntSendMessageNoWait(HWND hWnd
,
1450 ULONG_PTR Result
= 0;
1451 return co_IntSendMessageWithCallBack( hWnd
,
1460 If you send a message in the range below WM_USER to the asynchronous message
1461 functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its
1462 message parameters cannot include pointers. Otherwise, the operation will fail.
1463 The functions will return before the receiving thread has had a chance to
1464 process the message and the sender will free the memory before it is used.
1467 co_IntSendMessageWithCallBack( HWND hWnd
,
1471 SENDASYNCPROC CompletionCallback
,
1472 ULONG_PTR CompletionCallbackContext
,
1477 PMSGMEMORY MsgMemoryEntry
;
1478 INT lParamBufferSize
;
1479 LPARAM lParamPacked
;
1480 PTHREADINFO Win32Thread
;
1481 DECLARE_RETURN(LRESULT
);
1482 USER_REFERENCE_ENTRY Ref
;
1483 PUSER_SENT_MESSAGE Message
;
1485 if (!(Window
= UserGetWindowObject(hWnd
)))
1490 UserRefObjectCo(Window
, &Ref
);
1492 if (Window
->state
& WNDS_DESTROYED
)
1494 /* FIXME: last error? */
1495 ERR("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1499 Win32Thread
= PsGetCurrentThreadWin32Thread();
1501 if (Win32Thread
== NULL
||
1502 Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1507 if (Msg
& 0x80000000 &&
1508 Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1510 ERR("SMWCB: Internal Message!\n");
1511 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1512 if (uResult
) *uResult
= Result
;
1516 /* See if this message type is present in the table */
1517 MsgMemoryEntry
= FindMsgMemory(Msg
);
1518 if (NULL
== MsgMemoryEntry
)
1520 lParamBufferSize
= -1;
1524 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1527 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, Window
->head
.pti
->MessageQueue
!= Win32Thread
->MessageQueue
)))
1529 ERR("Failed to pack message parameters\n");
1533 /* If it can be sent now, then send it. */
1534 if (Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1536 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1538 UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
);
1539 /* Never send messages to exiting threads */
1543 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1545 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1547 TRACE("SMWCB: Server Side Window Procedure\n");
1550 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1562 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1564 if (CompletionCallback
)
1566 co_IntCallSentMessageCallback(CompletionCallback
,
1569 CompletionCallbackContext
,
1574 if (Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1576 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1578 ERR("Failed to unpack message parameters\n");
1583 if(!(Message
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
1585 ERR("MsqSendMessage(): Not enough memory to allocate a message");
1589 IntReferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1590 /* Take reference on this MessageQueue if its a callback. It will be released
1591 when message is processed or removed from target hwnd MessageQueue */
1592 if (CompletionCallback
)
1593 IntReferenceMessageQueue(Win32Thread
->MessageQueue
);
1595 Message
->Msg
.hwnd
= hWnd
;
1596 Message
->Msg
.message
= Msg
;
1597 Message
->Msg
.wParam
= wParam
;
1598 Message
->Msg
.lParam
= lParamPacked
;
1599 Message
->CompletionEvent
= NULL
;
1600 Message
->Result
= 0;
1601 Message
->lResult
= 0;
1602 Message
->QS_Flags
= 0;
1603 Message
->SenderQueue
= NULL
; // mjmartin, you are right! This is null.
1604 Message
->CallBackSenderQueue
= Win32Thread
->MessageQueue
;
1605 Message
->DispatchingListEntry
.Flink
= NULL
;
1606 Message
->CompletionCallback
= CompletionCallback
;
1607 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1608 Message
->HookMessage
= MSQ_NORMAL
;
1609 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1610 Message
->QS_Flags
= QS_SENDMESSAGE
;
1612 InsertTailList(&Window
->head
.pti
->MessageQueue
->SentMessagesListHead
, &Message
->ListEntry
);
1613 MsqWakeQueue(Window
->head
.pti
->MessageQueue
, QS_SENDMESSAGE
, TRUE
);
1614 IntDereferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1619 if (Window
) UserDerefObjectCo(Window
);
1625 This HACK function posts a message if the destination's message queue belongs to
1626 another thread, otherwise it sends the message. It does not support broadcast
1630 co_IntPostOrSendMessage( HWND hWnd
,
1639 if ( hWnd
== HWND_BROADCAST
)
1644 if(!(Window
= UserGetWindowObject(hWnd
)))
1649 pti
= PsGetCurrentThreadWin32Thread();
1651 if ( Window
->head
.pti
->MessageQueue
!= pti
->MessageQueue
&&
1652 FindMsgMemory(Msg
) == 0 )
1654 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1658 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1664 return (LRESULT
)Result
;
1668 co_IntDoSendMessage( HWND hWnd
,
1675 LRESULT Result
= TRUE
;
1680 PMSGMEMORY MsgMemoryEntry
;
1682 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1684 Window
= UserGetWindowObject(hWnd
);
1691 /* Check for an exiting window. */
1692 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1694 ERR("co_IntDoSendMessage Window Exiting!\n");
1697 /* See if the current thread can handle the message */
1698 //pti = PsGetCurrentThreadWin32Thread();
1700 UserModeMsg
.hwnd
= hWnd
;
1701 UserModeMsg
.message
= Msg
;
1702 UserModeMsg
.wParam
= wParam
;
1703 UserModeMsg
.lParam
= lParam
;
1704 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1706 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1707 if (! NT_SUCCESS(Status
))
1709 EngSetLastError(ERROR_INVALID_PARAMETER
);
1710 return (dsm
? 0 : -1);
1715 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1716 KernelModeMsg
.message
,
1717 KernelModeMsg
.wParam
,
1718 KernelModeMsg
.lParam
);
1722 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1723 KernelModeMsg
.message
,
1724 KernelModeMsg
.wParam
,
1725 KernelModeMsg
.lParam
,
1731 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1732 if (! NT_SUCCESS(Status
))
1734 EngSetLastError(ERROR_INVALID_PARAMETER
);
1735 return(dsm
? 0 : -1);
1738 return (LRESULT
)Result
;
1742 UserSendNotifyMessage( HWND hWnd
,
1749 if (is_pointer_message(Msg
))
1751 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1755 // Basicly the same as IntPostOrSendMessage
1756 if (hWnd
== HWND_BROADCAST
) // Handle Broadcast
1762 DesktopWindow
= UserGetDesktopWindow();
1763 List
= IntWinListChildren(DesktopWindow
);
1767 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1768 for (i
= 0; List
[i
]; i
++)
1770 PWND pwnd
= UserGetWindowObject(List
[i
]);
1771 if (!pwnd
) continue;
1773 if ( pwnd
->fnid
== FNID_MENU
||
1774 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1777 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1784 Ret
= co_IntSendMessageNoWait( hWnd
, Msg
, wParam
, lParam
);
1791 IntGetQueueStatus(DWORD Changes
)
1794 //PUSER_MESSAGE_QUEUE Queue;
1797 pti
= PsGetCurrentThreadWin32Thread();
1798 //Queue = pti->MessageQueue;
1800 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1802 /* High word, types of messages currently in the queue.
1803 Low word, types of messages that have been added to the queue and that
1804 are still in the queue
1806 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1808 pti
->pcti
->fsChangeBits
&= ~Changes
;
1814 IntInitMessagePumpHook()
1816 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1820 pti
->pcti
->dwcPumpHook
++;
1827 IntUninitMessagePumpHook()
1829 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1833 if (pti
->pcti
->dwcPumpHook
<= 0)
1837 pti
->pcti
->dwcPumpHook
--;
1843 /** Functions ******************************************************************/
1849 POINT pt
) // Just like the User call.
1853 ULONG wDragWidth
, wDragHeight
;
1854 DECLARE_RETURN(BOOL
);
1856 TRACE("Enter NtUserDragDetect(%x)\n", hWnd
);
1857 UserEnterExclusive();
1859 wDragWidth
= UserGetSystemMetrics(SM_CXDRAG
);
1860 wDragHeight
= UserGetSystemMetrics(SM_CYDRAG
);
1862 rect
.left
= pt
.x
- wDragWidth
;
1863 rect
.right
= pt
.x
+ wDragWidth
;
1865 rect
.top
= pt
.y
- wDragHeight
;
1866 rect
.bottom
= pt
.y
+ wDragHeight
;
1868 co_UserSetCapture(hWnd
);
1872 while (co_IntGetPeekMessage( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, FALSE
) ||
1873 co_IntGetPeekMessage( &msg
, 0, WM_QUEUESYNC
, WM_QUEUESYNC
, PM_REMOVE
, FALSE
) ||
1874 co_IntGetPeekMessage( &msg
, 0, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
, FALSE
) )
1876 if ( msg
.message
== WM_LBUTTONUP
)
1878 co_UserSetCapture(NULL
);
1881 if ( msg
.message
== WM_MOUSEMOVE
)
1884 tmp
.x
= (short)LOWORD(msg
.lParam
);
1885 tmp
.y
= (short)HIWORD(msg
.lParam
);
1886 if( !RECTL_bPointInRect( &rect
, tmp
.x
, tmp
.y
) )
1888 co_UserSetCapture(NULL
);
1892 if ( msg
.message
== WM_KEYDOWN
)
1894 if ( msg
.wParam
== VK_ESCAPE
)
1896 co_UserSetCapture(NULL
);
1900 if ( msg
.message
== WM_QUEUESYNC
)
1902 co_HOOK_CallHooks( WH_CBT
, HCBT_QS
, 0, 0 );
1905 co_IntWaitMessage(NULL
, 0, 0);
1910 TRACE("Leave NtUserDragDetect, ret=%i\n",_ret_
);
1916 NtUserPostMessage(HWND hWnd
,
1923 UserEnterExclusive();
1925 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1933 NtUserPostThreadMessage(DWORD idThread
,
1940 UserEnterExclusive();
1942 ret
= UserPostThreadMessage( idThread
, Msg
, wParam
, lParam
);
1950 NtUserWaitMessage(VOID
)
1954 UserEnterExclusive();
1955 TRACE("NtUserWaitMessage Enter\n");
1956 ret
= co_IntWaitMessage(NULL
, 0, 0);
1957 TRACE("NtUserWaitMessage Leave\n");
1964 NtUserGetMessage(PMSG pMsg
,
1972 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
1974 EngSetLastError(ERROR_INVALID_PARAMETER
);
1978 UserEnterExclusive();
1980 RtlZeroMemory(&Msg
, sizeof(MSG
));
1982 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
1990 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
1991 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
1993 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1995 SetLastNtError(_SEH2_GetExceptionCode());
2002 Ret
= Ret
? (WM_QUIT
!= pMsg
->message
) : FALSE
;
2008 NtUserPeekMessage( PMSG pMsg
,
2017 if ( RemoveMsg
& PM_BADMSGFLAGS
)
2019 EngSetLastError(ERROR_INVALID_FLAGS
);
2023 UserEnterExclusive();
2025 RtlZeroMemory(&Msg
, sizeof(MSG
));
2027 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
2035 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2036 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2038 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2040 SetLastNtError(_SEH2_GetExceptionCode());
2050 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
2057 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
2058 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
2060 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2062 _SEH2_YIELD(return FALSE
);
2066 UserEnterExclusive();
2068 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
2074 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
2081 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
2082 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
2084 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2094 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
2101 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
2102 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
2104 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2106 SetLastNtError(_SEH2_GetExceptionCode());
2107 _SEH2_YIELD(return FALSE
);
2111 UserEnterExclusive();
2113 Res
= IntDispatchMessage(&SafeMsg
);
2121 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
2128 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
2129 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
2131 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2133 SetLastNtError(_SEH2_GetExceptionCode());
2134 _SEH2_YIELD(return FALSE
);
2138 UserEnterExclusive();
2140 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
2148 NtUserMessageCall( HWND hWnd
,
2152 ULONG_PTR ResultInfo
,
2153 DWORD dwType
, // fnID?
2156 LRESULT lResult
= 0;
2159 USER_REFERENCE_ENTRY Ref
;
2161 UserEnterExclusive();
2165 case FNID_SCROLLBAR
:
2171 Window
= UserGetWindowObject(hWnd
);
2172 if (Window
->pSBInfo
)
2174 Window
->pSBInfo
->WSBflags
= wParam
? ESB_ENABLE_BOTH
: ESB_DISABLE_BOTH
;
2181 case FNID_DEFWINDOWPROC
:
2182 /* Validate input */
2185 Window
= UserGetWindowObject(hWnd
);
2191 UserRefObjectCo(Window
, &Ref
);
2193 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2196 UserDerefObjectCo(Window
);
2198 case FNID_SENDNOTIFYMESSAGE
:
2199 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2201 case FNID_BROADCASTSYSTEMMESSAGE
:
2203 BROADCASTPARM parm
, *retparam
;
2204 DWORD_PTR RetVal
= 0;
2210 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2211 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2213 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2222 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2223 parm
.recipients
== BSM_ALLCOMPONENTS
)
2225 PLIST_ENTRY DesktopEntry
;
2227 HWND
*List
, hwndDenied
= NULL
;
2229 PWND pwnd
, pwndDesk
;
2233 for (DesktopEntry
= InputWindowStation
->DesktopListHead
.Flink
;
2234 DesktopEntry
!= &InputWindowStation
->DesktopListHead
;
2235 DesktopEntry
= DesktopEntry
->Flink
)
2237 rpdesk
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
2238 pwndDesk
= rpdesk
->pDeskInfo
->spwnd
;
2239 List
= IntWinListChildren(pwndDesk
);
2241 if (parm
.flags
& BSF_QUERY
)
2245 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2247 fuFlags
= SMTO_ABORTIFHUNG
;
2249 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2251 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2255 fuFlags
= SMTO_NORMAL
;
2257 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2265 for (i
= 0; List
[i
]; i
++)
2267 pwnd
= UserGetWindowObject(List
[i
]);
2268 if (!pwnd
) continue;
2270 if ( pwnd
->fnid
== FNID_MENU
||
2271 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2274 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2276 if ( pwnd
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
2279 co_IntSendMessageTimeout( List
[i
],
2287 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2289 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2292 if (RetVal
== BROADCAST_QUERY_DENY
)
2294 hwndDenied
= List
[i
];
2295 hDesk
= UserHMGetHandle(pwndDesk
);
2299 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2302 retparam
= (PBROADCASTPARM
) ResultInfo
;
2303 retparam
->hDesk
= hDesk
;
2304 retparam
->hWnd
= hwndDenied
;
2306 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2311 if (!Ret
) break; // Have a hit! Let everyone know!
2314 else if (parm
.flags
& BSF_POSTMESSAGE
)
2318 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2320 for (i
= 0; List
[i
]; i
++)
2322 pwnd
= UserGetWindowObject(List
[i
]);
2323 if (!pwnd
) continue;
2325 if ( pwnd
->fnid
== FNID_MENU
||
2326 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2329 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2331 if ( pwnd
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
2334 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2336 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2344 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2346 for (i
= 0; List
[i
]; i
++)
2348 pwnd
= UserGetWindowObject(List
[i
]);
2349 if (!pwnd
) continue;
2351 if ( pwnd
->fnid
== FNID_MENU
||
2352 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2355 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2357 if ( pwnd
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
2360 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2362 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2368 else if (parm
.recipients
& BSM_APPLICATIONS
)
2370 HWND
*List
, hwndDenied
= NULL
;
2372 PWND pwnd
, pwndDesk
;
2376 pwndDesk
= UserGetDesktopWindow();
2377 List
= IntWinListChildren(pwndDesk
);
2379 if (parm
.flags
& BSF_QUERY
)
2383 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2385 fuFlags
= SMTO_ABORTIFHUNG
;
2387 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2389 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2393 fuFlags
= SMTO_NORMAL
;
2395 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2403 for (i
= 0; List
[i
]; i
++)
2405 pwnd
= UserGetWindowObject(List
[i
]);
2406 if (!pwnd
) continue;
2408 if ( pwnd
->fnid
== FNID_MENU
||
2409 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2412 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2414 if ( pwnd
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
2417 co_IntSendMessageTimeout( List
[i
],
2425 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2427 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2430 if (RetVal
== BROADCAST_QUERY_DENY
)
2432 hwndDenied
= List
[i
];
2433 hDesk
= UserHMGetHandle(pwndDesk
);
2437 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2440 retparam
= (PBROADCASTPARM
) ResultInfo
;
2441 retparam
->hDesk
= hDesk
;
2442 retparam
->hWnd
= hwndDenied
;
2444 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2451 else if (parm
.flags
& BSF_POSTMESSAGE
)
2455 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2457 for (i
= 0; List
[i
]; i
++)
2459 pwnd
= UserGetWindowObject(List
[i
]);
2460 if (!pwnd
) continue;
2462 if ( pwnd
->fnid
== FNID_MENU
||
2463 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2466 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2468 if ( pwnd
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
2471 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2473 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2481 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2483 for (i
= 0; List
[i
]; i
++)
2485 pwnd
= UserGetWindowObject(List
[i
]);
2486 if (!pwnd
) continue;
2488 if ( pwnd
->fnid
== FNID_MENU
||
2489 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2492 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2494 if ( pwnd
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
2497 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2499 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2506 case FNID_SENDMESSAGECALLBACK
:
2508 CALL_BACK_INFO CallBackInfo
;
2513 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2514 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2516 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2522 if (is_pointer_message(Msg
))
2524 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
2528 if (!(Ret
= co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2529 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
)))
2531 ERR("Callback failure!\n");
2535 case FNID_SENDMESSAGE
:
2537 Ret
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2543 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2544 RtlCopyMemory((PVOID
)ResultInfo
, &Ret
, sizeof(ULONG_PTR
));
2546 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2555 case FNID_SENDMESSAGEFF
:
2556 case FNID_SENDMESSAGEWTOOPTION
:
2558 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2563 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2564 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2566 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2573 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, &dsm
);
2579 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2580 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2582 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2591 // CallNextHook bypass.
2592 case FNID_CALLWNDPROC
:
2593 case FNID_CALLWNDPROCRET
:
2596 PCLIENTINFO ClientInfo
;
2597 PHOOK NextObj
, Hook
;
2599 pti
= GetW32ThreadInfo();
2601 Hook
= pti
->sphkCurrent
;
2605 NextObj
= Hook
->phkNext
;
2606 ClientInfo
= pti
->pClientInfo
;
2609 ClientInfo
->phkCurrent
= NextObj
;
2611 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2617 if (!ClientInfo
|| !NextObj
) break;
2619 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2621 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2626 CWP
.wParam
= wParam
;
2627 CWP
.lParam
= lParam
;
2628 TRACE("WH_CALLWNDPROC: Hook %x NextHook %x\n", Hook
, NextObj
);
2630 lResult
= co_IntCallHookProc( Hook
->HookId
,
2632 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2643 CWPR
.wParam
= wParam
;
2644 CWPR
.lParam
= lParam
;
2645 CWPR
.lResult
= ClientInfo
->dwHookData
;
2647 lResult
= co_IntCallHookProc( Hook
->HookId
,
2649 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2661 case FNID_DEFWINDOWPROC
:
2662 case FNID_CALLWNDPROC
:
2663 case FNID_CALLWNDPROCRET
:
2668 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2669 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2671 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2687 #define INFINITE 0xFFFFFFFF
2688 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2692 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2693 IN DWORD dwMilliseconds
,
2697 PPROCESSINFO W32Process
;
2701 LARGE_INTEGER Timeout
;
2703 UserEnterExclusive();
2705 Status
= ObReferenceObjectByHandle(hProcess
,
2706 PROCESS_QUERY_INFORMATION
,
2712 if (!NT_SUCCESS(Status
))
2715 SetLastNtError(Status
);
2719 pti
= PsGetCurrentThreadWin32Thread();
2721 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2723 if ( PsGetProcessExitProcessCalled(Process
) ||
2725 pti
->ppi
== W32Process
)
2727 ObDereferenceObject(Process
);
2729 EngSetLastError(ERROR_INVALID_PARAMETER
);
2733 Handles
[0] = Process
;
2734 Handles
[1] = W32Process
->InputIdleEvent
;
2735 Handles
[2] = pti
->MessageQueue
->NewMessages
; // pEventQueueServer; IntMsqSetWakeMask returns hEventQueueClient
2739 ObDereferenceObject(Process
);
2741 return STATUS_SUCCESS
; /* no event to wait on */
2744 if (dwMilliseconds
!= INFINITE
)
2745 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2747 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2748 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2750 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2751 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2754 TRACE("WFII: ppi 0x%x\n",W32Process
);
2755 TRACE("WFII: waiting for %p\n", Handles
[1] );
2759 Status
= KeWaitForMultipleObjects( 3,
2765 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2767 UserEnterExclusive();
2769 if (!NT_SUCCESS(Status
))
2771 SetLastNtError(Status
);
2772 Status
= WAIT_FAILED
;
2784 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2785 ERR("WFII: WAIT 2\n");
2789 case STATUS_TIMEOUT
:
2790 ERR("WFII: timeout\n");
2795 ERR("WFII: finished\n");
2796 Status
= STATUS_SUCCESS
;
2803 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2805 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
2806 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2808 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
2809 ObDereferenceObject(Process
);