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
)
599 pWnd
== IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
600 pWnd
== IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
603 ERR("Internal Event Msg %p\n",msg
);
607 case WM_ASYNC_SHOWWINDOW
:
608 return co_WinPosShowWindow( pWnd
, wparam
);
609 case WM_ASYNC_SETWINDOWPOS
:
611 PWINDOWPOS winpos
= (PWINDOWPOS
)lparam
;
612 if (!winpos
) return 0;
613 lRes
= co_WinPosSetWindowPos( pWnd
,
614 winpos
->hwndInsertAfter
,
620 ExFreePoolWithTag(winpos
, USERTAG_SWP
);
628 IntDispatchMessage(PMSG pMsg
)
630 LARGE_INTEGER TickCount
;
639 Window
= UserGetWindowObject(pMsg
->hwnd
);
640 if (!Window
) return 0;
643 pti
= PsGetCurrentThreadWin32Thread();
645 if ( Window
&& Window
->head
.pti
!= pti
)
647 EngSetLastError( ERROR_MESSAGE_SYNC_ONLY
);
651 if (((pMsg
->message
== WM_SYSTIMER
) ||
652 (pMsg
->message
== WM_TIMER
)) &&
655 if (pMsg
->message
== WM_TIMER
)
657 if (ValidateTimerCallback(pti
,pMsg
->lParam
))
659 KeQueryTickCount(&TickCount
);
660 Time
= MsqCalculateMessageTime(&TickCount
);
661 retval
= co_IntCallWindowProc((WNDPROC
)pMsg
->lParam
,
673 PTIMER pTimer
= FindSystemTimer(pMsg
);
674 if (pTimer
&& pTimer
->pfn
)
676 KeQueryTickCount(&TickCount
);
677 Time
= MsqCalculateMessageTime(&TickCount
);
678 pTimer
->pfn(pMsg
->hwnd
, WM_SYSTIMER
, (UINT
)pMsg
->wParam
, Time
);
684 if ( !Window
) return 0;
686 if (pMsg
->message
== WM_PAINT
) Window
->state
|= WNDS_PAINTNOTPROCESSED
;
688 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
690 TRACE("Dispatch: Server Side Window Procedure\n");
693 /* Since we are doing a callback on the same thread right away, there is
694 no need to copy the lparam to kernel mode and then back to usermode.
695 We just pretend it isn't a pointer */
697 retval
= co_IntCallWindowProc( Window
->lpfnWndProc
,
705 if (pMsg
->message
== WM_PAINT
)
707 Window
->state2
&= ~WNDS2_WMPAINTSENT
;
708 /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
709 hrgn
= IntSysCreateRectRgn( 0, 0, 0, 0 );
710 co_UserGetUpdateRgn( Window
, hrgn
, TRUE
);
711 GreDeleteObject(hrgn
);
718 * Internal version of PeekMessage() doing all the work
721 co_IntPeekMessage( PMSG Msg
,
730 LARGE_INTEGER LargeTickCount
;
731 PUSER_MESSAGE_QUEUE ThreadQueue
;
736 pti
= PsGetCurrentThreadWin32Thread();
737 ThreadQueue
= pti
->MessageQueue
;
738 //pci = pti->pClientInfo;
740 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
741 ProcessMask
= HIWORD(RemoveMsg
);
743 /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns
744 all available messages (that is, no range filtering is performed)". */
745 if (!ProcessMask
) ProcessMask
= (QS_ALLPOSTMESSAGE
|QS_ALLINPUT
);
751 KeQueryTickCount(&LargeTickCount
);
752 ThreadQueue
->LastMsgRead
= LargeTickCount
.u
.LowPart
;
753 pti
->pcti
->tickLastMsgChecked
= LargeTickCount
.u
.LowPart
;
755 /* Dispatch sent messages here. */
756 while ( co_MsqDispatchOneSentMessage(ThreadQueue
) )
758 /* if some PM_QS* flags were specified, only handle sent messages from now on */
759 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
; // wine does this; ProcessMask = QS_SENDMESSAGE;
761 if (Hit
) return FALSE
;
763 /* Clear changed bits so we can wait on them if we don't find a message */
764 if (ProcessMask
& QS_POSTMESSAGE
)
766 pti
->pcti
->fsChangeBits
&= ~(QS_POSTMESSAGE
| QS_HOTKEY
| QS_TIMER
);
767 if (MsgFilterMin
== 0 && MsgFilterMax
== 0) // Wine hack does this; ~0U)
769 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
773 if (ProcessMask
& QS_INPUT
)
775 pti
->pcti
->fsChangeBits
&= ~QS_INPUT
;
778 /* Now check for normal messages. */
779 if (( (ProcessMask
& QS_POSTMESSAGE
) ||
780 (ProcessMask
& QS_HOTKEY
) ) &&
781 MsqPeekMessage( ThreadQueue
,
792 /* Now look for a quit message. */
793 if (ThreadQueue
->QuitPosted
)
795 /* According to the PSDK, WM_QUIT messages are always returned, regardless
796 of the filter specified */
798 Msg
->message
= WM_QUIT
;
799 Msg
->wParam
= ThreadQueue
->QuitExitCode
;
803 ThreadQueue
->QuitPosted
= FALSE
;
804 ClearMsgBitsMask(ThreadQueue
, QS_POSTMESSAGE
);
805 pti
->pcti
->fsWakeBits
&= ~QS_ALLPOSTMESSAGE
;
806 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
811 /* Check for hardware events. */
812 if ((ProcessMask
& QS_MOUSE
) &&
813 co_MsqPeekMouseMove( ThreadQueue
,
823 if ((ProcessMask
& QS_INPUT
) &&
824 co_MsqPeekHardwareMessage( ThreadQueue
,
835 /* Check for sent messages again. */
836 while ( co_MsqDispatchOneSentMessage(ThreadQueue
) )
838 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
;
840 if (Hit
) return FALSE
;
842 /* Check for paint messages. */
843 if ((ProcessMask
& QS_PAINT
) &&
845 IntGetPaintMessage( Window
,
855 /* This is correct, check for the current threads timers waiting to be
856 posted to this threads message queue. If any we loop again.
858 if ((ProcessMask
& QS_TIMER
) &&
859 PostTimerMessages(Window
))
872 co_IntWaitMessage( PWND Window
,
877 PUSER_MESSAGE_QUEUE ThreadQueue
;
878 NTSTATUS Status
= STATUS_SUCCESS
;
881 pti
= PsGetCurrentThreadWin32Thread();
882 ThreadQueue
= pti
->MessageQueue
;
886 if ( co_IntPeekMessage( &Msg
, // Dont reenter!
890 MAKELONG( PM_NOREMOVE
, GetWakeMask( MsgFilterMin
, MsgFilterMax
)),
891 TRUE
) ) // act like GetMessage.
896 /* Nothing found. Wait for new messages. */
897 Status
= co_MsqWaitForNewMessages( ThreadQueue
,
901 if (!NT_SUCCESS(Status
))
903 SetLastNtError(Status
);
904 ERR("Exit co_IntWaitMessage on error!\n");
907 if (Status
== STATUS_USER_APC
|| Status
== STATUS_TIMEOUT
)
918 co_IntGetPeekMessage( PMSG pMsg
,
927 BOOL Present
= FALSE
;
930 if ( hWnd
== HWND_TOPMOST
|| hWnd
== HWND_BROADCAST
)
934 if (hWnd
&& hWnd
!= HWND_BOTTOM
)
936 if (!(Window
= UserGetWindowObject(hWnd
)))
949 if (MsgFilterMax
< MsgFilterMin
)
957 RemoveMsg
|= ((GetWakeMask( MsgFilterMin
, MsgFilterMax
))<< 16);
960 pti
= PsGetCurrentThreadWin32Thread();
961 pti
->pClientInfo
->cSpins
++; // Bump up the spin count.
965 Present
= co_IntPeekMessage( pMsg
,
973 /* GetMessage or PostMessage must never get messages that contain pointers */
974 ASSERT(FindMsgMemory(pMsg
->message
) == NULL
);
976 if (pMsg
->message
!= WM_PAINT
&& pMsg
->message
!= WM_QUIT
)
978 pti
->timeLast
= pMsg
->time
;
979 pti
->ptLast
= pMsg
->pt
;
982 // The WH_GETMESSAGE hook enables an application to monitor messages about to
983 // be returned by the GetMessage or PeekMessage function.
985 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)pMsg
);
992 Status
= co_MsqWaitForNewMessages( pti
->MessageQueue
,
996 if ( !NT_SUCCESS(Status
) ||
997 Status
== STATUS_USER_APC
||
998 Status
== STATUS_TIMEOUT
)
1006 if (!(RemoveMsg
& PM_NOYIELD
))
1009 // Yield this thread!
1012 UserEnterExclusive();
1013 // Fall through to exit.
1019 while( bGMSG
&& !Present
);
1021 // Been spinning, time to swap vinyl...
1022 if (pti
->pClientInfo
->cSpins
>= 100)
1024 // Clear the spin cycle to fix the mix.
1025 pti
->pClientInfo
->cSpins
= 0;
1026 //if (!(pti->TIF_flags & TIF_SPINNING)) // FIXME: Need to swap vinyl...
1032 UserPostThreadMessage( DWORD idThread
,
1039 PTHREADINFO pThread
;
1040 LARGE_INTEGER LargeTickCount
;
1043 if (is_pointer_message(Msg
))
1045 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1049 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
1051 if( Status
== STATUS_SUCCESS
)
1053 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
1055 !pThread
->MessageQueue
||
1056 (pThread
->TIF_flags
& TIF_INCLEANUP
))
1058 ObDereferenceObject( peThread
);
1062 Message
.hwnd
= NULL
;
1063 Message
.message
= Msg
;
1064 Message
.wParam
= wParam
;
1065 Message
.lParam
= lParam
;
1066 Message
.pt
= gpsi
->ptCursor
;
1068 KeQueryTickCount(&LargeTickCount
);
1069 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1070 MsqPostMessage(pThread
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
);
1071 ObDereferenceObject( peThread
);
1076 SetLastNtError( Status
);
1082 UserPostMessage( HWND Wnd
,
1088 MSG Message
, KernelModeMsg
;
1089 LARGE_INTEGER LargeTickCount
;
1092 Message
.message
= Msg
;
1093 Message
.wParam
= wParam
;
1094 Message
.lParam
= lParam
;
1095 Message
.pt
= gpsi
->ptCursor
;
1096 KeQueryTickCount(&LargeTickCount
);
1097 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1099 if (is_pointer_message(Message
.message
))
1101 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1105 if( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1108 PMSGMEMORY MsgMemoryEntry
;
1110 MsgMemoryEntry
= FindMsgMemory(Message
.message
);
1112 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &Message
, MsgMemoryEntry
);
1113 if (! NT_SUCCESS(Status
))
1115 EngSetLastError(ERROR_INVALID_PARAMETER
);
1118 co_IntSendMessageNoWait(KernelModeMsg
.hwnd
,
1119 KernelModeMsg
.message
,
1120 KernelModeMsg
.wParam
,
1121 KernelModeMsg
.lParam
);
1123 if (MsgMemoryEntry
&& KernelModeMsg
.lParam
)
1124 ExFreePool((PVOID
) KernelModeMsg
.lParam
);
1131 return UserPostThreadMessage( PtrToInt(PsGetCurrentThreadId()),
1136 if (Wnd
== HWND_BROADCAST
)
1142 DesktopWindow
= UserGetDesktopWindow();
1143 List
= IntWinListChildren(DesktopWindow
);
1147 UserPostMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1148 for (i
= 0; List
[i
]; i
++)
1150 PWND pwnd
= UserGetWindowObject(List
[i
]);
1151 if (!pwnd
) continue;
1153 if ( pwnd
->fnid
== FNID_MENU
|| // Also need pwnd->pcls->atomClassName == gaOleMainThreadWndClass
1154 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1157 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1159 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1166 Window
= UserGetWindowObject(Wnd
);
1172 pti
= Window
->head
.pti
;
1173 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1175 ERR("Attempted to post message to window 0x%x when the thread is in cleanup!\n", Wnd
);
1179 if ( Window
->state
& WNDS_DESTROYED
)
1181 ERR("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd
);
1182 /* FIXME: Last error code? */
1188 MsqPostQuitMessage(Window
->head
.pti
->MessageQueue
, wParam
);
1192 MsqPostMessage(Window
->head
.pti
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
);
1199 co_IntSendMessage( HWND hWnd
,
1204 ULONG_PTR Result
= 0;
1205 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1207 return (LRESULT
)Result
;
1212 static LRESULT FASTCALL
1213 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1219 ULONG_PTR
*uResult
)
1223 PMSGMEMORY MsgMemoryEntry
;
1224 INT lParamBufferSize
;
1225 LPARAM lParamPacked
;
1226 PTHREADINFO Win32Thread
;
1227 ULONG_PTR Hi
, Lo
, Result
= 0;
1228 DECLARE_RETURN(LRESULT
);
1229 USER_REFERENCE_ENTRY Ref
;
1231 if (!(Window
= UserGetWindowObject(hWnd
)))
1236 UserRefObjectCo(Window
, &Ref
);
1238 Win32Thread
= PsGetCurrentThreadWin32Thread();
1241 Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1243 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1245 /* Never send messages to exiting threads */
1249 if (Msg
& 0x80000000)
1251 ERR("SMTS: Internal Message!\n");
1252 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1253 if (uResult
) *uResult
= Result
;
1257 // Only happens when calling the client!
1258 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1260 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1262 TRACE("SMT: Server Side Window Procedure\n");
1263 IoGetStackLimits(&Lo
, &Hi
);
1264 // Handle it here. Safeguard against excessive recursions.
1265 if (((ULONG_PTR
)&uResult
- Lo
) < 4096 )
1267 ERR("Server Callback Exceeded Stack!\n");
1270 /* Return after server side call, IntCallWndProcRet will not be called. */
1272 /* See if this message type is present in the table */
1273 MsgMemoryEntry
= FindMsgMemory(Msg
);
1274 if (NULL
== MsgMemoryEntry
)
1276 lParamBufferSize
= -1;
1280 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1283 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1285 ERR("Failed to pack message parameters\n");
1289 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1301 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1303 ERR("Failed to unpack message parameters\n");
1307 // Only happens when calling the client!
1308 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1313 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->head
.pti
->MessageQueue
))
1315 // FIXME: Set window hung and add to a list.
1316 /* FIXME: Set a LastError? */
1320 if (Window
->state
& WNDS_DESTROYED
)
1322 /* FIXME: Last error? */
1323 ERR("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1329 Status
= co_MsqSendMessage( Window
->head
.pti
->MessageQueue
,
1335 (uFlags
& SMTO_BLOCK
),
1339 while ((STATUS_TIMEOUT
== Status
) &&
1340 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1341 !MsqIsHung(Window
->head
.pti
->MessageQueue
)); // FIXME: Set window hung and add to a list.
1343 if (STATUS_TIMEOUT
== Status
)
1347 * Microsoft Windows 2000: If GetLastError returns zero, then the function
1349 * XP+ : If the function fails or times out, the return value is zero.
1350 * To get extended error information, call GetLastError. If GetLastError
1351 * returns ERROR_TIMEOUT, then the function timed out.
1353 EngSetLastError(ERROR_TIMEOUT
);
1356 else if (!NT_SUCCESS(Status
))
1358 SetLastNtError(Status
);
1365 if (Window
) UserDerefObjectCo(Window
);
1370 co_IntSendMessageTimeout( HWND hWnd
,
1376 ULONG_PTR
*uResult
)
1382 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1384 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1387 DesktopWindow
= UserGetDesktopWindow();
1388 if (NULL
== DesktopWindow
)
1390 EngSetLastError(ERROR_INTERNAL_ERROR
);
1394 if (hWnd
!= HWND_TOPMOST
)
1396 /* Send message to the desktop window too! */
1397 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1400 Children
= IntWinListChildren(DesktopWindow
);
1401 if (NULL
== Children
)
1406 for (Child
= Children
; NULL
!= *Child
; Child
++)
1408 if (hWnd
== HWND_TOPMOST
)
1410 DesktopWindow
= UserGetWindowObject(*Child
);
1411 if (DesktopWindow
&& DesktopWindow
->ExStyle
& WS_EX_TOPMOST
)
1413 ERR("HWND_TOPMOST Found\n");
1414 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1419 PWND pwnd
= UserGetWindowObject(*Child
);
1420 if (!pwnd
) continue;
1422 if ( pwnd
->fnid
== FNID_MENU
||
1423 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1426 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1430 ExFreePool(Children
);
1432 return (LRESULT
) TRUE
;
1436 co_IntSendMessageNoWait(HWND hWnd
,
1441 ULONG_PTR Result
= 0;
1442 if (!co_IntSendMessageWithCallBack( hWnd
,
1450 Result
= ((ULONG_PTR
)-1);
1455 If you send a message in the range below WM_USER to the asynchronous message
1456 functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its
1457 message parameters cannot include pointers. Otherwise, the operation will fail.
1458 The functions will return before the receiving thread has had a chance to
1459 process the message and the sender will free the memory before it is used.
1462 co_IntSendMessageWithCallBack( HWND hWnd
,
1466 SENDASYNCPROC CompletionCallback
,
1467 ULONG_PTR CompletionCallbackContext
,
1472 PMSGMEMORY MsgMemoryEntry
;
1473 INT lParamBufferSize
;
1474 LPARAM lParamPacked
;
1475 PTHREADINFO Win32Thread
;
1476 DECLARE_RETURN(LRESULT
);
1477 USER_REFERENCE_ENTRY Ref
;
1478 PUSER_SENT_MESSAGE Message
;
1480 if (!(Window
= UserGetWindowObject(hWnd
)))
1485 UserRefObjectCo(Window
, &Ref
);
1487 if (Window
->state
& WNDS_DESTROYED
)
1489 /* FIXME: last error? */
1490 ERR("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1494 Win32Thread
= PsGetCurrentThreadWin32Thread();
1496 if (Win32Thread
== NULL
)
1501 /* See if this message type is present in the table */
1502 MsgMemoryEntry
= FindMsgMemory(Msg
);
1503 if (NULL
== MsgMemoryEntry
)
1505 lParamBufferSize
= -1;
1509 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1512 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, Window
->head
.pti
->MessageQueue
!= Win32Thread
->MessageQueue
)))
1514 ERR("Failed to pack message parameters\n");
1518 /* If it can be sent now, then send it. */
1519 if (Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1521 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1523 UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
);
1524 /* Never send messages to exiting threads */
1528 if (Msg
& 0x80000000)
1530 ERR("SMWCB: Internal Message!\n");
1531 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1532 if (uResult
) *uResult
= Result
;
1536 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1538 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1540 TRACE("SMWCB: Server Side Window Procedure\n");
1543 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1555 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1557 if (CompletionCallback
)
1559 co_IntCallSentMessageCallback(CompletionCallback
,
1562 CompletionCallbackContext
,
1567 if (Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1569 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1571 ERR("Failed to unpack message parameters\n");
1576 if(!(Message
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
1578 ERR("MsqSendMessage(): Not enough memory to allocate a message");
1582 IntReferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1583 /* Take reference on this MessageQueue if its a callback. It will be released
1584 when message is processed or removed from target hwnd MessageQueue */
1585 if (CompletionCallback
)
1586 IntReferenceMessageQueue(Win32Thread
->MessageQueue
);
1588 Message
->Msg
.hwnd
= hWnd
;
1589 Message
->Msg
.message
= Msg
;
1590 Message
->Msg
.wParam
= wParam
;
1591 Message
->Msg
.lParam
= lParamPacked
;
1592 Message
->CompletionEvent
= NULL
;
1593 Message
->Result
= 0;
1594 Message
->lResult
= 0;
1595 Message
->QS_Flags
= 0;
1596 Message
->SenderQueue
= NULL
; // mjmartin, you are right! This is null.
1597 Message
->CallBackSenderQueue
= Win32Thread
->MessageQueue
;
1598 Message
->DispatchingListEntry
.Flink
= NULL
;
1599 Message
->CompletionCallback
= CompletionCallback
;
1600 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1601 Message
->HookMessage
= MSQ_NORMAL
;
1602 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1603 Message
->QS_Flags
= QS_SENDMESSAGE
;
1605 InsertTailList(&Window
->head
.pti
->MessageQueue
->SentMessagesListHead
, &Message
->ListEntry
);
1606 MsqWakeQueue(Window
->head
.pti
->MessageQueue
, QS_SENDMESSAGE
, TRUE
);
1607 IntDereferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1612 if (Window
) UserDerefObjectCo(Window
);
1618 This HACK function posts a message if the destination's message queue belongs to
1619 another thread, otherwise it sends the message. It does not support broadcast
1623 co_IntPostOrSendMessage( HWND hWnd
,
1632 if ( hWnd
== HWND_BROADCAST
)
1637 if(!(Window
= UserGetWindowObject(hWnd
)))
1642 pti
= PsGetCurrentThreadWin32Thread();
1644 if ( Window
->head
.pti
->MessageQueue
!= pti
->MessageQueue
&&
1645 FindMsgMemory(Msg
) == 0 )
1647 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1651 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1657 return (LRESULT
)Result
;
1661 co_IntDoSendMessage( HWND hWnd
,
1668 LRESULT Result
= TRUE
;
1673 PMSGMEMORY MsgMemoryEntry
;
1675 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1677 Window
= UserGetWindowObject(hWnd
);
1684 /* Check for an exiting window. */
1685 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1687 ERR("co_IntDoSendMessage Window Exiting!\n");
1690 /* See if the current thread can handle the message */
1691 //pti = PsGetCurrentThreadWin32Thread();
1693 UserModeMsg
.hwnd
= hWnd
;
1694 UserModeMsg
.message
= Msg
;
1695 UserModeMsg
.wParam
= wParam
;
1696 UserModeMsg
.lParam
= lParam
;
1697 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1699 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1700 if (! NT_SUCCESS(Status
))
1702 EngSetLastError(ERROR_INVALID_PARAMETER
);
1703 return (dsm
? 0 : -1);
1708 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1709 KernelModeMsg
.message
,
1710 KernelModeMsg
.wParam
,
1711 KernelModeMsg
.lParam
);
1715 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1716 KernelModeMsg
.message
,
1717 KernelModeMsg
.wParam
,
1718 KernelModeMsg
.lParam
,
1724 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1725 if (! NT_SUCCESS(Status
))
1727 EngSetLastError(ERROR_INVALID_PARAMETER
);
1728 return(dsm
? 0 : -1);
1731 return (LRESULT
)Result
;
1735 UserSendNotifyMessage( HWND hWnd
,
1742 if (is_pointer_message(Msg
))
1744 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1748 // Basicly the same as IntPostOrSendMessage
1749 if (hWnd
== HWND_BROADCAST
) // Handle Broadcast
1755 DesktopWindow
= UserGetDesktopWindow();
1756 List
= IntWinListChildren(DesktopWindow
);
1760 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1761 for (i
= 0; List
[i
]; i
++)
1763 PWND pwnd
= UserGetWindowObject(List
[i
]);
1764 if (!pwnd
) continue;
1766 if ( pwnd
->fnid
== FNID_MENU
||
1767 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1770 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1777 Ret
= co_IntSendMessageNoWait( hWnd
, Msg
, wParam
, lParam
);
1778 if (-1 == (int) Ret
|| !Ret
) Ret
= FALSE
;
1785 IntGetQueueStatus(DWORD Changes
)
1788 //PUSER_MESSAGE_QUEUE Queue;
1791 pti
= PsGetCurrentThreadWin32Thread();
1792 //Queue = pti->MessageQueue;
1794 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1796 /* High word, types of messages currently in the queue.
1797 Low word, types of messages that have been added to the queue and that
1798 are still in the queue
1800 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1802 pti
->pcti
->fsChangeBits
&= ~Changes
;
1808 IntInitMessagePumpHook()
1810 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1814 pti
->pcti
->dwcPumpHook
++;
1821 IntUninitMessagePumpHook()
1823 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1827 if (pti
->pcti
->dwcPumpHook
<= 0)
1831 pti
->pcti
->dwcPumpHook
--;
1837 /** Functions ******************************************************************/
1843 POINT pt
) // Just like the User call.
1847 WORD wDragWidth
, wDragHeight
;
1848 DECLARE_RETURN(BOOL
);
1850 TRACE("Enter NtUserDragDetect(%x)\n", hWnd
);
1851 UserEnterExclusive();
1853 wDragWidth
= UserGetSystemMetrics(SM_CXDRAG
);
1854 wDragHeight
= UserGetSystemMetrics(SM_CYDRAG
);
1856 rect
.left
= pt
.x
- wDragWidth
;
1857 rect
.right
= pt
.x
+ wDragWidth
;
1859 rect
.top
= pt
.y
- wDragHeight
;
1860 rect
.bottom
= pt
.y
+ wDragHeight
;
1862 co_UserSetCapture(hWnd
);
1866 while (co_IntGetPeekMessage( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, FALSE
) ||
1867 co_IntGetPeekMessage( &msg
, 0, WM_QUEUESYNC
, WM_QUEUESYNC
, PM_REMOVE
, FALSE
) ||
1868 co_IntGetPeekMessage( &msg
, 0, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
, FALSE
) )
1870 if ( msg
.message
== WM_LBUTTONUP
)
1872 co_UserSetCapture(NULL
);
1875 if ( msg
.message
== WM_MOUSEMOVE
)
1878 tmp
.x
= (short)LOWORD(msg
.lParam
);
1879 tmp
.y
= (short)HIWORD(msg
.lParam
);
1880 if( !RECTL_bPointInRect( &rect
, tmp
.x
, tmp
.y
) )
1882 co_UserSetCapture(NULL
);
1886 if ( msg
.message
== WM_KEYDOWN
)
1888 if ( msg
.wParam
== VK_ESCAPE
)
1890 co_UserSetCapture(NULL
);
1894 if ( msg
.message
== WM_QUEUESYNC
)
1896 co_HOOK_CallHooks( WH_CBT
, HCBT_QS
, 0, 0 );
1899 co_IntWaitMessage(NULL
, 0, 0);
1904 TRACE("Leave NtUserDragDetect, ret=%i\n",_ret_
);
1910 NtUserPostMessage(HWND hWnd
,
1917 UserEnterExclusive();
1919 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1927 NtUserPostThreadMessage(DWORD idThread
,
1934 UserEnterExclusive();
1936 ret
= UserPostThreadMessage( idThread
, Msg
, wParam
, lParam
);
1944 NtUserWaitMessage(VOID
)
1948 UserEnterExclusive();
1949 TRACE("NtUserWaitMessage Enter\n");
1950 ret
= co_IntWaitMessage(NULL
, 0, 0);
1951 TRACE("NtUserWaitMessage Leave\n");
1958 NtUserGetMessage(PMSG pMsg
,
1966 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
1968 EngSetLastError(ERROR_INVALID_PARAMETER
);
1972 UserEnterExclusive();
1974 RtlZeroMemory(&Msg
, sizeof(MSG
));
1976 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
1984 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
1985 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
1987 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1989 SetLastNtError(_SEH2_GetExceptionCode());
1996 Ret
= Ret
? (WM_QUIT
!= pMsg
->message
) : FALSE
;
2002 NtUserPeekMessage( PMSG pMsg
,
2011 if ( RemoveMsg
& PM_BADMSGFLAGS
)
2013 EngSetLastError(ERROR_INVALID_FLAGS
);
2017 UserEnterExclusive();
2019 RtlZeroMemory(&Msg
, sizeof(MSG
));
2021 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
2029 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2030 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2032 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2034 SetLastNtError(_SEH2_GetExceptionCode());
2044 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
2051 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
2052 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
2054 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2056 _SEH2_YIELD(return FALSE
);
2060 UserEnterExclusive();
2062 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
2068 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
2075 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
2076 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
2078 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2088 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
2095 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
2096 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
2098 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2100 SetLastNtError(_SEH2_GetExceptionCode());
2101 _SEH2_YIELD(return FALSE
);
2105 UserEnterExclusive();
2107 Res
= IntDispatchMessage(&SafeMsg
);
2115 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
2122 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
2123 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
2125 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2127 SetLastNtError(_SEH2_GetExceptionCode());
2128 _SEH2_YIELD(return FALSE
);
2132 UserEnterExclusive();
2134 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
2142 NtUserMessageCall( HWND hWnd
,
2146 ULONG_PTR ResultInfo
,
2147 DWORD dwType
, // fnID?
2150 LRESULT lResult
= 0;
2153 USER_REFERENCE_ENTRY Ref
;
2155 UserEnterExclusive();
2159 case FNID_SCROLLBAR
:
2165 Window
= UserGetWindowObject(hWnd
);
2166 if (Window
->pSBInfo
)
2168 Window
->pSBInfo
->WSBflags
= wParam
? ESB_ENABLE_BOTH
: ESB_DISABLE_BOTH
;
2175 case FNID_DEFWINDOWPROC
:
2176 /* Validate input */
2179 Window
= UserGetWindowObject(hWnd
);
2185 UserRefObjectCo(Window
, &Ref
);
2187 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2190 UserDerefObjectCo(Window
);
2192 case FNID_SENDNOTIFYMESSAGE
:
2193 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2195 case FNID_BROADCASTSYSTEMMESSAGE
:
2197 BROADCASTPARM parm
, *retparam
;
2198 DWORD_PTR RetVal
= 0;
2204 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2205 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2207 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2216 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2217 parm
.recipients
== BSM_ALLCOMPONENTS
)
2219 PLIST_ENTRY DesktopEntry
;
2221 HWND
*List
, hwndDenied
= NULL
;
2223 PWND pwnd
, pwndDesk
;
2227 for (DesktopEntry
= InputWindowStation
->DesktopListHead
.Flink
;
2228 DesktopEntry
!= &InputWindowStation
->DesktopListHead
;
2229 DesktopEntry
= DesktopEntry
->Flink
)
2231 rpdesk
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
2232 pwndDesk
= rpdesk
->pDeskInfo
->spwnd
;
2233 List
= IntWinListChildren(pwndDesk
);
2235 if (parm
.flags
& BSF_QUERY
)
2239 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2241 fuFlags
= SMTO_ABORTIFHUNG
;
2243 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2245 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2249 fuFlags
= SMTO_NORMAL
;
2251 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2259 for (i
= 0; List
[i
]; i
++)
2261 pwnd
= UserGetWindowObject(List
[i
]);
2262 if (!pwnd
) continue;
2264 if ( pwnd
->fnid
== FNID_MENU
||
2265 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2268 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2270 if ( pwnd
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
2273 co_IntSendMessageTimeout( List
[i
],
2281 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2283 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2286 if (RetVal
== BROADCAST_QUERY_DENY
)
2288 hwndDenied
= List
[i
];
2289 hDesk
= UserHMGetHandle(pwndDesk
);
2293 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2296 retparam
= (PBROADCASTPARM
) ResultInfo
;
2297 retparam
->hDesk
= hDesk
;
2298 retparam
->hWnd
= hwndDenied
;
2300 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2305 if (!Ret
) break; // Have a hit! Let everyone know!
2308 else if (parm
.flags
& BSF_POSTMESSAGE
)
2312 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2314 for (i
= 0; List
[i
]; i
++)
2316 pwnd
= UserGetWindowObject(List
[i
]);
2317 if (!pwnd
) continue;
2319 if ( pwnd
->fnid
== FNID_MENU
||
2320 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2323 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2325 if ( pwnd
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
2328 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2330 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2338 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2340 for (i
= 0; List
[i
]; i
++)
2342 pwnd
= UserGetWindowObject(List
[i
]);
2343 if (!pwnd
) continue;
2345 if ( pwnd
->fnid
== FNID_MENU
||
2346 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2349 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2351 if ( pwnd
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
2354 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2356 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2362 else if (parm
.recipients
& BSM_APPLICATIONS
)
2364 HWND
*List
, hwndDenied
= NULL
;
2366 PWND pwnd
, pwndDesk
;
2370 pwndDesk
= UserGetDesktopWindow();
2371 List
= IntWinListChildren(pwndDesk
);
2373 if (parm
.flags
& BSF_QUERY
)
2377 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2379 fuFlags
= SMTO_ABORTIFHUNG
;
2381 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2383 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2387 fuFlags
= SMTO_NORMAL
;
2389 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2397 for (i
= 0; List
[i
]; i
++)
2399 pwnd
= UserGetWindowObject(List
[i
]);
2400 if (!pwnd
) continue;
2402 if ( pwnd
->fnid
== FNID_MENU
||
2403 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2406 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2408 if ( pwnd
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
2411 co_IntSendMessageTimeout( List
[i
],
2419 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2421 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2424 if (RetVal
== BROADCAST_QUERY_DENY
)
2426 hwndDenied
= List
[i
];
2427 hDesk
= UserHMGetHandle(pwndDesk
);
2431 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2434 retparam
= (PBROADCASTPARM
) ResultInfo
;
2435 retparam
->hDesk
= hDesk
;
2436 retparam
->hWnd
= hwndDenied
;
2438 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2445 else if (parm
.flags
& BSF_POSTMESSAGE
)
2449 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2451 for (i
= 0; List
[i
]; i
++)
2453 pwnd
= UserGetWindowObject(List
[i
]);
2454 if (!pwnd
) continue;
2456 if ( pwnd
->fnid
== FNID_MENU
||
2457 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2460 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2462 if ( pwnd
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
2465 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2467 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2475 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2477 for (i
= 0; List
[i
]; i
++)
2479 pwnd
= UserGetWindowObject(List
[i
]);
2480 if (!pwnd
) continue;
2482 if ( pwnd
->fnid
== FNID_MENU
||
2483 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2486 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2488 if ( pwnd
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
2491 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2493 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2500 case FNID_SENDMESSAGECALLBACK
:
2502 CALL_BACK_INFO CallBackInfo
;
2507 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2508 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2510 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2516 if (is_pointer_message(Msg
))
2518 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
2522 if (!(Ret
= co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2523 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
)))
2525 ERR("Callback failure!\n");
2529 case FNID_SENDMESSAGE
:
2531 Ret
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2537 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2538 RtlCopyMemory((PVOID
)ResultInfo
, &Ret
, sizeof(ULONG_PTR
));
2540 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2549 case FNID_SENDMESSAGEFF
:
2550 case FNID_SENDMESSAGEWTOOPTION
:
2552 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2557 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2558 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2560 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2567 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, &dsm
);
2573 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2574 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2576 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2585 // CallNextHook bypass.
2586 case FNID_CALLWNDPROC
:
2587 case FNID_CALLWNDPROCRET
:
2590 PCLIENTINFO ClientInfo
;
2591 PHOOK NextObj
, Hook
;
2593 pti
= GetW32ThreadInfo();
2595 Hook
= pti
->sphkCurrent
;
2599 NextObj
= Hook
->phkNext
;
2600 ClientInfo
= pti
->pClientInfo
;
2603 ClientInfo
->phkCurrent
= NextObj
;
2605 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2611 if (!ClientInfo
|| !NextObj
) break;
2613 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2615 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2620 CWP
.wParam
= wParam
;
2621 CWP
.lParam
= lParam
;
2622 TRACE("WH_CALLWNDPROC: Hook %x NextHook %x\n", Hook
, NextObj
);
2624 lResult
= co_IntCallHookProc( Hook
->HookId
,
2626 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2637 CWPR
.wParam
= wParam
;
2638 CWPR
.lParam
= lParam
;
2639 CWPR
.lResult
= ClientInfo
->dwHookData
;
2641 lResult
= co_IntCallHookProc( Hook
->HookId
,
2643 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2655 case FNID_DEFWINDOWPROC
:
2656 case FNID_CALLWNDPROC
:
2657 case FNID_CALLWNDPROCRET
:
2662 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2663 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2665 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2681 #define INFINITE 0xFFFFFFFF
2682 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2686 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2687 IN DWORD dwMilliseconds
,
2691 PPROCESSINFO W32Process
;
2695 LARGE_INTEGER Timeout
;
2697 UserEnterExclusive();
2699 Status
= ObReferenceObjectByHandle(hProcess
,
2700 PROCESS_QUERY_INFORMATION
,
2706 if (!NT_SUCCESS(Status
))
2709 SetLastNtError(Status
);
2713 pti
= PsGetCurrentThreadWin32Thread();
2715 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2717 if ( PsGetProcessExitProcessCalled(Process
) ||
2719 pti
->ppi
== W32Process
)
2721 ObDereferenceObject(Process
);
2723 EngSetLastError(ERROR_INVALID_PARAMETER
);
2727 Handles
[0] = Process
;
2728 Handles
[1] = W32Process
->InputIdleEvent
;
2729 Handles
[2] = pti
->MessageQueue
->NewMessages
; // pEventQueueServer; IntMsqSetWakeMask returns hEventQueueClient
2733 ObDereferenceObject(Process
);
2735 return STATUS_SUCCESS
; /* no event to wait on */
2738 if (dwMilliseconds
!= INFINITE
)
2739 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2741 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2742 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2744 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2745 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2748 TRACE("WFII: ppi 0x%x\n",W32Process
);
2749 TRACE("WFII: waiting for %p\n", Handles
[1] );
2753 Status
= KeWaitForMultipleObjects( 3,
2759 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2761 UserEnterExclusive();
2763 if (!NT_SUCCESS(Status
))
2765 SetLastNtError(Status
);
2766 Status
= WAIT_FAILED
;
2778 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2779 ERR("WFII: WAIT 2\n");
2783 case STATUS_TIMEOUT
:
2784 ERR("WFII: timeout\n");
2789 ERR("WFII: finished\n");
2790 Status
= STATUS_SUCCESS
;
2797 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2799 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
2800 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2802 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
2803 ObDereferenceObject(Process
);