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 g_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
= g_MsgMemory
;
144 MsgMemoryEntry
< g_MsgMemory
+ sizeof(g_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());
226 UINT
lParamMemorySize(UINT Msg
, WPARAM wParam
, LPARAM lParam
)
228 PMSGMEMORY MsgMemoryEntry
= FindMsgMemory(Msg
);
229 if(MsgMemoryEntry
== NULL
) return 0;
230 return MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
234 PackParam(LPARAM
*lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolNeeded
)
236 NCCALCSIZE_PARAMS
*UnpackedNcCalcsize
;
237 NCCALCSIZE_PARAMS
*PackedNcCalcsize
;
238 CREATESTRUCTW
*UnpackedCs
;
239 CREATESTRUCTW
*PackedCs
;
240 PLARGE_STRING WindowName
;
241 PUNICODE_STRING ClassName
;
246 *lParamPacked
= lParam
;
248 if (NonPagedPoolNeeded
)
249 PoolType
= NonPagedPool
;
251 PoolType
= PagedPool
;
253 if (WM_NCCALCSIZE
== Msg
&& wParam
)
256 UnpackedNcCalcsize
= (NCCALCSIZE_PARAMS
*) lParam
;
257 PackedNcCalcsize
= ExAllocatePoolWithTag(PoolType
,
258 sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
),
261 if (NULL
== PackedNcCalcsize
)
263 ERR("Not enough memory to pack lParam\n");
264 return STATUS_NO_MEMORY
;
266 RtlCopyMemory(PackedNcCalcsize
, UnpackedNcCalcsize
, sizeof(NCCALCSIZE_PARAMS
));
267 PackedNcCalcsize
->lppos
= (PWINDOWPOS
) (PackedNcCalcsize
+ 1);
268 RtlCopyMemory(PackedNcCalcsize
->lppos
, UnpackedNcCalcsize
->lppos
, sizeof(WINDOWPOS
));
269 *lParamPacked
= (LPARAM
) PackedNcCalcsize
;
271 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
273 UnpackedCs
= (CREATESTRUCTW
*) lParam
;
274 WindowName
= (PLARGE_STRING
) UnpackedCs
->lpszName
;
275 ClassName
= (PUNICODE_STRING
) UnpackedCs
->lpszClass
;
276 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
277 if (IS_ATOM(ClassName
->Buffer
))
279 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
283 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
285 PackedCs
= ExAllocatePoolWithTag(PoolType
, Size
, TAG_MSG
);
286 if (NULL
== PackedCs
)
288 ERR("Not enough memory to pack lParam\n");
289 return STATUS_NO_MEMORY
;
291 RtlCopyMemory(PackedCs
, UnpackedCs
, sizeof(CREATESTRUCTW
));
292 CsData
= (PCHAR
) (PackedCs
+ 1);
293 PackedCs
->lpszName
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
294 RtlCopyMemory(CsData
, WindowName
->Buffer
, WindowName
->Length
);
295 CsData
+= WindowName
->Length
;
296 *((WCHAR
*) CsData
) = L
'\0';
297 CsData
+= sizeof(WCHAR
);
298 PackedCs
->lpszClass
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
299 if (IS_ATOM(ClassName
->Buffer
))
301 *((WCHAR
*) CsData
) = L
'A';
302 CsData
+= sizeof(WCHAR
);
303 *((ATOM
*) CsData
) = (ATOM
)(DWORD_PTR
) ClassName
->Buffer
;
304 CsData
+= sizeof(ATOM
);
308 *((WCHAR
*) CsData
) = L
'S';
309 CsData
+= sizeof(WCHAR
);
310 RtlCopyMemory(CsData
, ClassName
->Buffer
, ClassName
->Length
);
311 CsData
+= ClassName
->Length
;
312 *((WCHAR
*) CsData
) = L
'\0';
313 CsData
+= sizeof(WCHAR
);
315 ASSERT(CsData
== (PCHAR
) PackedCs
+ Size
);
316 *lParamPacked
= (LPARAM
) PackedCs
;
318 else if (PoolType
== NonPagedPool
)
320 PMSGMEMORY MsgMemoryEntry
;
324 MsgMemoryEntry
= FindMsgMemory(Msg
);
326 if ((!MsgMemoryEntry
) || (MsgMemoryEntry
->Size
< 0))
328 /* Keep previous behavior */
329 return STATUS_SUCCESS
;
331 size
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
334 ERR("No size for lParamPacked\n");
335 return STATUS_SUCCESS
;
337 PackedData
= ExAllocatePoolWithTag(NonPagedPool
, size
, TAG_MSG
);
338 if (PackedData
== NULL
)
340 ERR("Not enough memory to pack lParam\n");
341 return STATUS_NO_MEMORY
;
343 RtlCopyMemory(PackedData
, (PVOID
)lParam
, MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
));
344 *lParamPacked
= (LPARAM
)PackedData
;
347 return STATUS_SUCCESS
;
351 UnpackParam(LPARAM lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolUsed
)
353 NCCALCSIZE_PARAMS
*UnpackedParams
;
354 NCCALCSIZE_PARAMS
*PackedParams
;
355 PWINDOWPOS UnpackedWindowPos
;
357 if (lParamPacked
== lParam
)
359 return STATUS_SUCCESS
;
362 if (WM_NCCALCSIZE
== Msg
&& wParam
)
364 PackedParams
= (NCCALCSIZE_PARAMS
*) lParamPacked
;
365 UnpackedParams
= (NCCALCSIZE_PARAMS
*) lParam
;
366 UnpackedWindowPos
= UnpackedParams
->lppos
;
367 RtlCopyMemory(UnpackedParams
, PackedParams
, sizeof(NCCALCSIZE_PARAMS
));
368 UnpackedParams
->lppos
= UnpackedWindowPos
;
369 RtlCopyMemory(UnpackedWindowPos
, PackedParams
+ 1, sizeof(WINDOWPOS
));
370 ExFreePool((PVOID
) lParamPacked
);
372 return STATUS_SUCCESS
;
374 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
376 ExFreePool((PVOID
) lParamPacked
);
378 return STATUS_SUCCESS
;
380 else if (NonPagedPoolUsed
)
382 PMSGMEMORY MsgMemoryEntry
;
383 MsgMemoryEntry
= FindMsgMemory(Msg
);
384 ASSERT(MsgMemoryEntry
);
385 if (MsgMemoryEntry
->Size
< 0)
387 /* Keep previous behavior */
388 return STATUS_INVALID_PARAMETER
;
391 if (MsgMemoryEntry
->Flags
== MMS_FLAG_READWRITE
)
393 //RtlCopyMemory((PVOID)lParam, (PVOID)lParamPacked, MsgMemoryEntry->Size);
395 ExFreePool((PVOID
) lParamPacked
);
396 return STATUS_SUCCESS
;
401 return STATUS_INVALID_PARAMETER
;
404 static NTSTATUS FASTCALL
405 CopyMsgToKernelMem(MSG
*KernelModeMsg
, MSG
*UserModeMsg
, PMSGMEMORY MsgMemoryEntry
)
412 *KernelModeMsg
= *UserModeMsg
;
414 /* See if this message type is present in the table */
415 if (NULL
== MsgMemoryEntry
)
417 /* Not present, no copying needed */
418 return STATUS_SUCCESS
;
421 /* Determine required size */
422 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
426 /* Allocate kernel mem */
427 KernelMem
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
428 if (NULL
== KernelMem
)
430 ERR("Not enough memory to copy message to kernel mem\n");
431 return STATUS_NO_MEMORY
;
433 KernelModeMsg
->lParam
= (LPARAM
) KernelMem
;
435 /* Copy data if required */
436 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_READ
))
438 Status
= MmCopyFromCaller(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
439 if (! NT_SUCCESS(Status
))
441 ERR("Failed to copy message to kernel: invalid usermode buffer\n");
442 ExFreePoolWithTag(KernelMem
, TAG_MSG
);
448 /* Make sure we don't pass any secrets to usermode */
449 RtlZeroMemory(KernelMem
, Size
);
454 KernelModeMsg
->lParam
= 0;
457 return STATUS_SUCCESS
;
460 static NTSTATUS FASTCALL
461 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
464 PMSGMEMORY MsgMemoryEntry
;
467 /* See if this message type is present in the table */
468 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
469 if (NULL
== MsgMemoryEntry
)
471 /* Not present, no copying needed */
472 return STATUS_SUCCESS
;
475 /* Determine required size */
476 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
480 /* Copy data if required */
481 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
483 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
484 if (! NT_SUCCESS(Status
))
486 ERR("Failed to copy message from kernel: invalid usermode buffer\n");
487 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
492 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
495 return STATUS_SUCCESS
;
499 // Wakeup any thread/process waiting on idle input.
504 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
505 PUSER_MESSAGE_QUEUE ForegroundQueue
;
506 PTHREADINFO pti
, ptiForeground
= NULL
;
508 ForegroundQueue
= IntGetFocusMessageQueue();
511 ptiForeground
= ForegroundQueue
->Thread
->Tcb
.Win32Thread
;
513 pti
= PsGetCurrentThreadWin32Thread();
517 pti
->pClientInfo
->cSpins
= 0; // Reset spins.
519 if ( pti
->pDeskInfo
&& pti
== ptiForeground
)
521 if ( pti
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) ||
522 pti
->pDeskInfo
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) )
524 co_HOOK_CallHooks(WH_FOREGROUNDIDLE
,HC_ACTION
,0,0);
529 TRACE("IdlePing ppi 0x%x\n",ppi
);
530 if ( ppi
&& ppi
->InputIdleEvent
)
532 TRACE("InputIdleEvent\n");
533 KeSetEvent( ppi
->InputIdleEvent
, IO_NO_INCREMENT
, FALSE
);
540 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
542 TRACE("IdlePong ppi 0x%x\n",ppi
);
543 if ( ppi
&& ppi
->InputIdleEvent
)
545 KeClearEvent(ppi
->InputIdleEvent
);
550 GetWakeMask(UINT first
, UINT last
)
552 UINT mask
= QS_POSTMESSAGE
| QS_SENDMESSAGE
; /* Always selected */
556 if ((first
<= WM_KEYLAST
) && (last
>= WM_KEYFIRST
)) mask
|= QS_KEY
;
557 if ( ((first
<= WM_MOUSELAST
) && (last
>= WM_MOUSEFIRST
)) ||
558 ((first
<= WM_NCMOUSELAST
) && (last
>= WM_NCMOUSEFIRST
)) ) mask
|= QS_MOUSE
;
559 if ((first
<= WM_TIMER
) && (last
>= WM_TIMER
)) mask
|= QS_TIMER
;
560 if ((first
<= WM_SYSTIMER
) && (last
>= WM_SYSTIMER
)) mask
|= QS_TIMER
;
561 if ((first
<= WM_PAINT
) && (last
>= WM_PAINT
)) mask
|= QS_PAINT
;
563 else mask
= QS_ALLINPUT
;
569 IntCallWndProc( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
571 BOOL SameThread
= FALSE
;
574 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
581 co_HOOK_CallHooks( WH_CALLWNDPROC
, HC_ACTION
, SameThread
, (LPARAM
)&CWP
);
585 IntCallWndProcRet ( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*uResult
)
587 BOOL SameThread
= FALSE
;
590 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
595 CWPR
.wParam
= wParam
;
596 CWPR
.lParam
= lParam
;
597 CWPR
.lResult
= uResult
? (*uResult
) : 0;
598 co_HOOK_CallHooks( WH_CALLWNDPROCRET
, HC_ACTION
, SameThread
, (LPARAM
)&CWPR
);
601 static LRESULT
handle_internal_message( PWND pWnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
604 USER_REFERENCE_ENTRY Ref
;
607 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
608 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
611 TRACE("Internal Event Msg %p hWnd 0x%x\n",msg
,pWnd
->head
.h
);
615 case WM_ASYNC_SHOWWINDOW
:
616 return co_WinPosShowWindow( pWnd
, wparam
);
617 case WM_ASYNC_SETWINDOWPOS
:
619 PWINDOWPOS winpos
= (PWINDOWPOS
)lparam
;
620 if (!winpos
) return 0;
621 lRes
= co_WinPosSetWindowPos( pWnd
,
622 winpos
->hwndInsertAfter
,
628 ExFreePoolWithTag(winpos
, USERTAG_SWP
);
631 case WM_ASYNC_SETACTIVEWINDOW
:
633 PWND Window
= (PWND
)wparam
;
634 if (wparam
) UserRefObjectCo(Window
, &Ref
);
635 lRes
= (LRESULT
)co_IntSetActiveWindow(Window
,NULL
,(BOOL
)lparam
,TRUE
,TRUE
);
636 if (wparam
) UserDerefObjectCo(Window
);
644 IntDispatchMessage(PMSG pMsg
)
646 LARGE_INTEGER TickCount
;
652 BOOL DoCallBack
= TRUE
;
656 Window
= UserGetWindowObject(pMsg
->hwnd
);
657 if (!Window
) return 0;
660 pti
= PsGetCurrentThreadWin32Thread();
662 if ( Window
&& Window
->head
.pti
!= pti
)
664 EngSetLastError( ERROR_MESSAGE_SYNC_ONLY
);
668 if (((pMsg
->message
== WM_SYSTIMER
) ||
669 (pMsg
->message
== WM_TIMER
)) &&
672 if (pMsg
->message
== WM_TIMER
)
674 if (ValidateTimerCallback(pti
,pMsg
->lParam
))
676 KeQueryTickCount(&TickCount
);
677 Time
= MsqCalculateMessageTime(&TickCount
);
678 retval
= co_IntCallWindowProc((WNDPROC
)pMsg
->lParam
,
690 PTIMER pTimer
= FindSystemTimer(pMsg
);
691 if (pTimer
&& pTimer
->pfn
)
693 KeQueryTickCount(&TickCount
);
694 Time
= MsqCalculateMessageTime(&TickCount
);
695 pTimer
->pfn(pMsg
->hwnd
, WM_SYSTIMER
, (UINT
)pMsg
->wParam
, Time
);
701 if ( !Window
) return 0;
703 if (pMsg
->message
== WM_PAINT
) Window
->state
|= WNDS_PAINTNOTPROCESSED
;
705 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
707 TRACE("Dispatch: Server Side Window Procedure\n");
711 DoCallBack
= !DesktopWindowProc( Window
,
717 case FNID_MESSAGEWND
:
718 DoCallBack
= !UserMessageWindowProc( Window
,
727 /* Since we are doing a callback on the same thread right away, there is
728 no need to copy the lparam to kernel mode and then back to usermode.
729 We just pretend it isn't a pointer */
732 retval
= co_IntCallWindowProc( Window
->lpfnWndProc
,
740 if (pMsg
->message
== WM_PAINT
)
742 Window
->state2
&= ~WNDS2_WMPAINTSENT
;
743 /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
744 hrgn
= IntSysCreateRectRgn( 0, 0, 0, 0 );
745 co_UserGetUpdateRgn( Window
, hrgn
, TRUE
);
746 GreDeleteObject(hrgn
);
753 * Internal version of PeekMessage() doing all the work
756 co_IntPeekMessage( PMSG Msg
,
764 LARGE_INTEGER LargeTickCount
;
765 PUSER_MESSAGE_QUEUE ThreadQueue
;
770 pti
= PsGetCurrentThreadWin32Thread();
771 ThreadQueue
= pti
->MessageQueue
;
773 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
774 ProcessMask
= HIWORD(RemoveMsg
);
776 if (ThreadQueue
->ptiSysLock
&& ThreadQueue
->ptiSysLock
!= pti
)
778 ERR("PeekMessage: Thread Q 0x%p is locked 0x%p to another pti 0x%p!\n", ThreadQueue
, ThreadQueue
->ptiSysLock
, pti
);
781 /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns
782 all available messages (that is, no range filtering is performed)". */
783 if (!ProcessMask
) ProcessMask
= (QS_ALLPOSTMESSAGE
|QS_ALLINPUT
);
789 KeQueryTickCount(&LargeTickCount
);
790 ThreadQueue
->LastMsgRead
= LargeTickCount
.u
.LowPart
;
791 pti
->pcti
->tickLastMsgChecked
= LargeTickCount
.u
.LowPart
;
793 /* Dispatch sent messages here. */
794 while ( co_MsqDispatchOneSentMessage(ThreadQueue
) )
796 /* if some PM_QS* flags were specified, only handle sent messages from now on */
797 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
; // wine does this; ProcessMask = QS_SENDMESSAGE;
799 if (Hit
) return FALSE
;
801 /* Clear changed bits so we can wait on them if we don't find a message */
802 if (ProcessMask
& QS_POSTMESSAGE
)
804 pti
->pcti
->fsChangeBits
&= ~(QS_POSTMESSAGE
| QS_HOTKEY
| QS_TIMER
);
805 if (MsgFilterMin
== 0 && MsgFilterMax
== 0) // Wine hack does this; ~0U)
807 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
811 if (ProcessMask
& QS_INPUT
)
813 pti
->pcti
->fsChangeBits
&= ~QS_INPUT
;
816 /* Now check for normal messages. */
817 if (( (ProcessMask
& QS_POSTMESSAGE
) ||
818 (ProcessMask
& QS_HOTKEY
) ) &&
819 MsqPeekMessage( ThreadQueue
,
830 /* Now look for a quit message. */
831 if (ThreadQueue
->QuitPosted
)
833 /* According to the PSDK, WM_QUIT messages are always returned, regardless
834 of the filter specified */
836 Msg
->message
= WM_QUIT
;
837 Msg
->wParam
= ThreadQueue
->QuitExitCode
;
841 ThreadQueue
->QuitPosted
= FALSE
;
842 ClearMsgBitsMask(ThreadQueue
, QS_POSTMESSAGE
);
843 pti
->pcti
->fsWakeBits
&= ~QS_ALLPOSTMESSAGE
;
844 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
849 /* Check for hardware events. */
850 if ((ProcessMask
& QS_MOUSE
) &&
851 co_MsqPeekMouseMove( ThreadQueue
,
861 if ((ProcessMask
& QS_INPUT
) &&
862 co_MsqPeekHardwareMessage( ThreadQueue
,
873 /* Check for sent messages again. */
874 while ( co_MsqDispatchOneSentMessage(ThreadQueue
) )
876 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
;
878 if (Hit
) return FALSE
;
880 /* Check for paint messages. */
881 if ((ProcessMask
& QS_PAINT
) &&
883 IntGetPaintMessage( Window
,
893 /* This is correct, check for the current threads timers waiting to be
894 posted to this threads message queue. If any we loop again.
896 if ((ProcessMask
& QS_TIMER
) &&
897 PostTimerMessages(Window
))
910 co_IntWaitMessage( PWND Window
,
915 PUSER_MESSAGE_QUEUE ThreadQueue
;
916 NTSTATUS Status
= STATUS_SUCCESS
;
919 pti
= PsGetCurrentThreadWin32Thread();
920 ThreadQueue
= pti
->MessageQueue
;
924 if ( co_IntPeekMessage( &Msg
, // Dont reenter!
928 MAKELONG( PM_NOREMOVE
, GetWakeMask( MsgFilterMin
, MsgFilterMax
)),
929 TRUE
) ) // act like GetMessage.
934 /* Nothing found. Wait for new messages. */
935 Status
= co_MsqWaitForNewMessages( ThreadQueue
,
939 if (!NT_SUCCESS(Status
))
941 SetLastNtError(Status
);
942 ERR("Exit co_IntWaitMessage on error!\n");
945 if (Status
== STATUS_USER_APC
|| Status
== STATUS_TIMEOUT
)
956 co_IntGetPeekMessage( PMSG pMsg
,
965 BOOL Present
= FALSE
;
968 if ( hWnd
== HWND_TOPMOST
|| hWnd
== HWND_BROADCAST
)
972 if (hWnd
&& hWnd
!= HWND_BOTTOM
)
974 if (!(Window
= UserGetWindowObject(hWnd
)))
987 if (MsgFilterMax
< MsgFilterMin
)
995 RemoveMsg
|= ((GetWakeMask( MsgFilterMin
, MsgFilterMax
))<< 16);
998 pti
= PsGetCurrentThreadWin32Thread();
999 pti
->pClientInfo
->cSpins
++; // Bump up the spin count.
1003 Present
= co_IntPeekMessage( pMsg
,
1011 /* GetMessage or PostMessage must never get messages that contain pointers */
1012 ASSERT(FindMsgMemory(pMsg
->message
) == NULL
);
1014 if (pMsg
->message
!= WM_PAINT
&& pMsg
->message
!= WM_QUIT
)
1016 pti
->timeLast
= pMsg
->time
;
1017 pti
->ptLast
= pMsg
->pt
;
1020 // The WH_GETMESSAGE hook enables an application to monitor messages about to
1021 // be returned by the GetMessage or PeekMessage function.
1023 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)pMsg
);
1030 Status
= co_MsqWaitForNewMessages( pti
->MessageQueue
,
1034 if ( !NT_SUCCESS(Status
) ||
1035 Status
== STATUS_USER_APC
||
1036 Status
== STATUS_TIMEOUT
)
1044 if (!(RemoveMsg
& PM_NOYIELD
))
1047 // Yield this thread!
1050 UserEnterExclusive();
1051 // Fall through to exit.
1057 while( bGMSG
&& !Present
);
1059 // Been spinning, time to swap vinyl...
1060 if (pti
->pClientInfo
->cSpins
>= 100)
1062 // Clear the spin cycle to fix the mix.
1063 pti
->pClientInfo
->cSpins
= 0;
1064 //if (!(pti->TIF_flags & TIF_SPINNING)) // FIXME: Need to swap vinyl...
1070 UserPostThreadMessage( DWORD idThread
,
1077 PTHREADINFO pThread
;
1078 LARGE_INTEGER LargeTickCount
;
1081 if (is_pointer_message(Msg
))
1083 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1087 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
1089 if( Status
== STATUS_SUCCESS
)
1091 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
1093 !pThread
->MessageQueue
||
1094 (pThread
->TIF_flags
& TIF_INCLEANUP
))
1096 ObDereferenceObject( peThread
);
1100 Message
.hwnd
= NULL
;
1101 Message
.message
= Msg
;
1102 Message
.wParam
= wParam
;
1103 Message
.lParam
= lParam
;
1104 Message
.pt
= gpsi
->ptCursor
;
1106 KeQueryTickCount(&LargeTickCount
);
1107 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1108 MsqPostMessage(pThread
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
, 0);
1109 ObDereferenceObject( peThread
);
1114 SetLastNtError( Status
);
1120 UserPostMessage( HWND Wnd
,
1126 MSG Message
, KernelModeMsg
;
1127 LARGE_INTEGER LargeTickCount
;
1130 Message
.message
= Msg
;
1131 Message
.wParam
= wParam
;
1132 Message
.lParam
= lParam
;
1133 Message
.pt
= gpsi
->ptCursor
;
1134 KeQueryTickCount(&LargeTickCount
);
1135 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1137 if (is_pointer_message(Message
.message
))
1139 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1143 if( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1146 PMSGMEMORY MsgMemoryEntry
;
1148 MsgMemoryEntry
= FindMsgMemory(Message
.message
);
1150 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &Message
, MsgMemoryEntry
);
1151 if (! NT_SUCCESS(Status
))
1153 EngSetLastError(ERROR_INVALID_PARAMETER
);
1156 co_IntSendMessageNoWait(KernelModeMsg
.hwnd
,
1157 KernelModeMsg
.message
,
1158 KernelModeMsg
.wParam
,
1159 KernelModeMsg
.lParam
);
1161 if (MsgMemoryEntry
&& KernelModeMsg
.lParam
)
1162 ExFreePool((PVOID
) KernelModeMsg
.lParam
);
1169 return UserPostThreadMessage( PtrToInt(PsGetCurrentThreadId()),
1174 if (Wnd
== HWND_BROADCAST
)
1180 DesktopWindow
= UserGetDesktopWindow();
1181 List
= IntWinListChildren(DesktopWindow
);
1185 UserPostMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1186 for (i
= 0; List
[i
]; i
++)
1188 PWND pwnd
= UserGetWindowObject(List
[i
]);
1189 if (!pwnd
) continue;
1191 if ( pwnd
->fnid
== FNID_MENU
|| // Also need pwnd->pcls->atomClassName == gaOleMainThreadWndClass
1192 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1195 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1197 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1204 Window
= UserGetWindowObject(Wnd
);
1207 ERR("UserPostMessage: Invalid handle 0x%p!\n",Wnd
);
1211 pti
= Window
->head
.pti
;
1212 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1214 ERR("Attempted to post message to window 0x%x when the thread is in cleanup!\n", Wnd
);
1218 if ( Window
->state
& WNDS_DESTROYED
)
1220 ERR("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd
);
1221 /* FIXME: Last error code? */
1227 MsqPostQuitMessage(Window
->head
.pti
->MessageQueue
, wParam
);
1231 MsqPostMessage(Window
->head
.pti
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
, 0);
1238 co_IntSendMessage( HWND hWnd
,
1243 ULONG_PTR Result
= 0;
1244 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1246 return (LRESULT
)Result
;
1251 static LRESULT FASTCALL
1252 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1258 ULONG_PTR
*uResult
)
1262 PMSGMEMORY MsgMemoryEntry
;
1263 INT lParamBufferSize
;
1264 LPARAM lParamPacked
;
1265 PTHREADINFO Win32Thread
;
1266 ULONG_PTR Hi
, Lo
, Result
= 0;
1267 DECLARE_RETURN(LRESULT
);
1268 USER_REFERENCE_ENTRY Ref
;
1269 BOOL DoCallBack
= TRUE
;
1271 if (!(Window
= UserGetWindowObject(hWnd
)))
1273 TRACE("SendMessageTimeoutSingle: Invalid handle 0x%p!\n",hWnd
);
1277 UserRefObjectCo(Window
, &Ref
);
1279 Win32Thread
= PsGetCurrentThreadWin32Thread();
1282 Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1284 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1286 /* Never send messages to exiting threads */
1290 if (Msg
& 0x80000000)
1292 TRACE("SMTS: Internal Message!\n");
1293 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1294 if (uResult
) *uResult
= Result
;
1298 // Only happens when calling the client!
1299 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1301 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1303 TRACE("SMT: Server Side Window Procedure\n");
1304 IoGetStackLimits(&Lo
, &Hi
);
1305 // Handle it here. Safeguard against excessive recursions.
1306 if (((ULONG_PTR
)&uResult
- Lo
) < 4096 )
1308 ERR("Server Callback Exceeded Stack!\n");
1311 /* Return after server side call, IntCallWndProcRet will not be called. */
1312 switch(Window
->fnid
)
1315 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1317 case FNID_MESSAGEWND
:
1318 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1323 if (uResult
) *uResult
= Result
;
1327 /* See if this message type is present in the table */
1328 MsgMemoryEntry
= FindMsgMemory(Msg
);
1329 if (NULL
== MsgMemoryEntry
)
1331 lParamBufferSize
= -1;
1335 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1338 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1340 ERR("Failed to pack message parameters\n");
1344 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1356 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1358 ERR("Failed to unpack message parameters\n");
1362 // Only happens when calling the client!
1363 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1368 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->head
.pti
->MessageQueue
))
1370 // FIXME: Set window hung and add to a list.
1371 /* FIXME: Set a LastError? */
1375 if (Window
->state
& WNDS_DESTROYED
)
1377 /* FIXME: Last error? */
1378 ERR("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1384 Status
= co_MsqSendMessage( Window
->head
.pti
->MessageQueue
,
1390 (uFlags
& SMTO_BLOCK
),
1394 while ((STATUS_TIMEOUT
== Status
) &&
1395 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1396 !MsqIsHung(Window
->head
.pti
->MessageQueue
)); // FIXME: Set window hung and add to a list.
1398 if (STATUS_TIMEOUT
== Status
)
1402 * Microsoft Windows 2000: If GetLastError returns zero, then the function
1404 * XP+ : If the function fails or times out, the return value is zero.
1405 * To get extended error information, call GetLastError. If GetLastError
1406 * returns ERROR_TIMEOUT, then the function timed out.
1408 EngSetLastError(ERROR_TIMEOUT
);
1411 else if (!NT_SUCCESS(Status
))
1413 SetLastNtError(Status
);
1420 if (Window
) UserDerefObjectCo(Window
);
1425 co_IntSendMessageTimeout( HWND hWnd
,
1431 ULONG_PTR
*uResult
)
1437 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1439 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1442 DesktopWindow
= UserGetDesktopWindow();
1443 if (NULL
== DesktopWindow
)
1445 EngSetLastError(ERROR_INTERNAL_ERROR
);
1449 if (hWnd
!= HWND_TOPMOST
)
1451 /* Send message to the desktop window too! */
1452 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1455 Children
= IntWinListChildren(DesktopWindow
);
1456 if (NULL
== Children
)
1461 for (Child
= Children
; NULL
!= *Child
; Child
++)
1463 if (hWnd
== HWND_TOPMOST
)
1465 DesktopWindow
= UserGetWindowObject(*Child
);
1466 if (DesktopWindow
&& DesktopWindow
->ExStyle
& WS_EX_TOPMOST
)
1468 ERR("HWND_TOPMOST Found\n");
1469 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1474 PWND pwnd
= UserGetWindowObject(*Child
);
1475 if (!pwnd
) continue;
1477 if ( pwnd
->fnid
== FNID_MENU
||
1478 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1481 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1485 ExFreePool(Children
);
1487 return (LRESULT
) TRUE
;
1491 co_IntSendMessageNoWait(HWND hWnd
,
1496 ULONG_PTR Result
= 0;
1497 return co_IntSendMessageWithCallBack( hWnd
,
1506 If you send a message in the range below WM_USER to the asynchronous message
1507 functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its
1508 message parameters cannot include pointers. Otherwise, the operation will fail.
1509 The functions will return before the receiving thread has had a chance to
1510 process the message and the sender will free the memory before it is used.
1513 co_IntSendMessageWithCallBack( HWND hWnd
,
1517 SENDASYNCPROC CompletionCallback
,
1518 ULONG_PTR CompletionCallbackContext
,
1523 PMSGMEMORY MsgMemoryEntry
;
1524 INT lParamBufferSize
;
1525 LPARAM lParamPacked
;
1526 PTHREADINFO Win32Thread
;
1527 DECLARE_RETURN(LRESULT
);
1528 USER_REFERENCE_ENTRY Ref
;
1529 PUSER_SENT_MESSAGE Message
;
1530 BOOL DoCallBack
= TRUE
;
1532 if (!(Window
= UserGetWindowObject(hWnd
)))
1534 TRACE("SendMessageWithCallBack: Invalid handle 0x%p!\n",hWnd
);
1538 UserRefObjectCo(Window
, &Ref
);
1540 if (Window
->state
& WNDS_DESTROYED
)
1542 /* FIXME: last error? */
1543 ERR("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1547 Win32Thread
= PsGetCurrentThreadWin32Thread();
1549 if (Win32Thread
== NULL
||
1550 Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1555 if (Msg
& 0x80000000 &&
1556 Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1558 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
) RETURN( FALSE
);
1560 TRACE("SMWCB: Internal Message!\n");
1561 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1562 if (uResult
) *uResult
= Result
;
1566 /* See if this message type is present in the table */
1567 MsgMemoryEntry
= FindMsgMemory(Msg
);
1568 if (NULL
== MsgMemoryEntry
)
1570 lParamBufferSize
= -1;
1574 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1577 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, Window
->head
.pti
->MessageQueue
!= Win32Thread
->MessageQueue
)))
1579 ERR("Failed to pack message parameters\n");
1583 /* If it can be sent now, then send it. */
1584 if (Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1586 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1588 UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
);
1589 /* Never send messages to exiting threads */
1593 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1595 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1597 TRACE("SMWCB: Server Side Window Procedure\n");
1598 switch(Window
->fnid
)
1601 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParamPacked
, (LRESULT
*)&Result
);
1603 case FNID_MESSAGEWND
:
1604 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1610 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1622 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1624 if (CompletionCallback
)
1626 co_IntCallSentMessageCallback(CompletionCallback
,
1629 CompletionCallbackContext
,
1634 if (Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1636 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1638 ERR("Failed to unpack message parameters\n");
1643 if(!(Message
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
1645 ERR("MsqSendMessage(): Not enough memory to allocate a message");
1649 IntReferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1650 /* Take reference on this MessageQueue if its a callback. It will be released
1651 when message is processed or removed from target hwnd MessageQueue */
1652 if (CompletionCallback
)
1653 IntReferenceMessageQueue(Win32Thread
->MessageQueue
);
1655 Message
->Msg
.hwnd
= hWnd
;
1656 Message
->Msg
.message
= Msg
;
1657 Message
->Msg
.wParam
= wParam
;
1658 Message
->Msg
.lParam
= lParamPacked
;
1659 Message
->CompletionEvent
= NULL
;
1660 Message
->Result
= 0;
1661 Message
->lResult
= 0;
1662 Message
->QS_Flags
= 0;
1663 Message
->SenderQueue
= NULL
; // mjmartin, you are right! This is null.
1664 Message
->CallBackSenderQueue
= Win32Thread
->MessageQueue
;
1665 Message
->DispatchingListEntry
.Flink
= NULL
;
1666 Message
->CompletionCallback
= CompletionCallback
;
1667 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1668 Message
->HookMessage
= MSQ_NORMAL
;
1669 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1670 Message
->QS_Flags
= QS_SENDMESSAGE
;
1672 InsertTailList(&Window
->head
.pti
->MessageQueue
->SentMessagesListHead
, &Message
->ListEntry
);
1673 MsqWakeQueue(Window
->head
.pti
->MessageQueue
, QS_SENDMESSAGE
, TRUE
);
1674 IntDereferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1679 if (Window
) UserDerefObjectCo(Window
);
1685 This HACK function posts a message if the destination's message queue belongs to
1686 another thread, otherwise it sends the message. It does not support broadcast
1690 co_IntPostOrSendMessage( HWND hWnd
,
1699 if ( hWnd
== HWND_BROADCAST
)
1704 if(!(Window
= UserGetWindowObject(hWnd
)))
1706 TRACE("PostOrSendMessage: Invalid handle 0x%p!\n",hWnd
);
1710 pti
= PsGetCurrentThreadWin32Thread();
1712 if ( Window
->head
.pti
->MessageQueue
!= pti
->MessageQueue
&&
1713 FindMsgMemory(Msg
) == 0 )
1715 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1719 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1725 return (LRESULT
)Result
;
1729 co_IntDoSendMessage( HWND hWnd
,
1736 LRESULT Result
= TRUE
;
1741 PMSGMEMORY MsgMemoryEntry
;
1743 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1745 Window
= UserGetWindowObject(hWnd
);
1752 /* Check for an exiting window. */
1753 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1755 ERR("co_IntDoSendMessage Window Exiting!\n");
1758 /* See if the current thread can handle the message */
1759 //pti = PsGetCurrentThreadWin32Thread();
1761 UserModeMsg
.hwnd
= hWnd
;
1762 UserModeMsg
.message
= Msg
;
1763 UserModeMsg
.wParam
= wParam
;
1764 UserModeMsg
.lParam
= lParam
;
1765 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1767 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1768 if (! NT_SUCCESS(Status
))
1770 EngSetLastError(ERROR_INVALID_PARAMETER
);
1771 return (dsm
? 0 : -1);
1776 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1777 KernelModeMsg
.message
,
1778 KernelModeMsg
.wParam
,
1779 KernelModeMsg
.lParam
);
1783 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1784 KernelModeMsg
.message
,
1785 KernelModeMsg
.wParam
,
1786 KernelModeMsg
.lParam
,
1792 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1793 if (! NT_SUCCESS(Status
))
1795 EngSetLastError(ERROR_INVALID_PARAMETER
);
1796 return(dsm
? 0 : -1);
1799 return (LRESULT
)Result
;
1803 UserSendNotifyMessage( HWND hWnd
,
1810 if (is_pointer_message(Msg
))
1812 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1816 // Basicly the same as IntPostOrSendMessage
1817 if (hWnd
== HWND_BROADCAST
) // Handle Broadcast
1823 DesktopWindow
= UserGetDesktopWindow();
1824 List
= IntWinListChildren(DesktopWindow
);
1828 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1829 for (i
= 0; List
[i
]; i
++)
1831 PWND pwnd
= UserGetWindowObject(List
[i
]);
1832 if (!pwnd
) continue;
1834 if ( pwnd
->fnid
== FNID_MENU
||
1835 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1838 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1845 Ret
= co_IntSendMessageNoWait( hWnd
, Msg
, wParam
, lParam
);
1852 IntGetQueueStatus(DWORD Changes
)
1857 pti
= PsGetCurrentThreadWin32Thread();
1859 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1861 /* High word, types of messages currently in the queue.
1862 Low word, types of messages that have been added to the queue and that
1863 are still in the queue
1865 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1867 pti
->pcti
->fsChangeBits
&= ~Changes
;
1873 IntInitMessagePumpHook()
1875 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1879 pti
->pcti
->dwcPumpHook
++;
1886 IntUninitMessagePumpHook()
1888 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1892 if (pti
->pcti
->dwcPumpHook
<= 0)
1896 pti
->pcti
->dwcPumpHook
--;
1902 /** Functions ******************************************************************/
1908 POINT pt
) // Just like the User call.
1912 ULONG wDragWidth
, wDragHeight
;
1913 DECLARE_RETURN(BOOL
);
1915 TRACE("Enter NtUserDragDetect(%x)\n", hWnd
);
1916 UserEnterExclusive();
1918 wDragWidth
= UserGetSystemMetrics(SM_CXDRAG
);
1919 wDragHeight
= UserGetSystemMetrics(SM_CYDRAG
);
1921 rect
.left
= pt
.x
- wDragWidth
;
1922 rect
.right
= pt
.x
+ wDragWidth
;
1924 rect
.top
= pt
.y
- wDragHeight
;
1925 rect
.bottom
= pt
.y
+ wDragHeight
;
1927 co_UserSetCapture(hWnd
);
1931 while (co_IntGetPeekMessage( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, FALSE
) ||
1932 co_IntGetPeekMessage( &msg
, 0, WM_QUEUESYNC
, WM_QUEUESYNC
, PM_REMOVE
, FALSE
) ||
1933 co_IntGetPeekMessage( &msg
, 0, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
, FALSE
) )
1935 if ( msg
.message
== WM_LBUTTONUP
)
1937 co_UserSetCapture(NULL
);
1940 if ( msg
.message
== WM_MOUSEMOVE
)
1943 tmp
.x
= (short)LOWORD(msg
.lParam
);
1944 tmp
.y
= (short)HIWORD(msg
.lParam
);
1945 if( !RECTL_bPointInRect( &rect
, tmp
.x
, tmp
.y
) )
1947 co_UserSetCapture(NULL
);
1951 if ( msg
.message
== WM_KEYDOWN
)
1953 if ( msg
.wParam
== VK_ESCAPE
)
1955 co_UserSetCapture(NULL
);
1959 if ( msg
.message
== WM_QUEUESYNC
)
1961 co_HOOK_CallHooks( WH_CBT
, HCBT_QS
, 0, 0 );
1964 co_IntWaitMessage(NULL
, 0, 0);
1969 TRACE("Leave NtUserDragDetect, ret=%i\n",_ret_
);
1975 NtUserPostMessage(HWND hWnd
,
1982 UserEnterExclusive();
1984 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1992 NtUserPostThreadMessage(DWORD idThread
,
1999 UserEnterExclusive();
2001 ret
= UserPostThreadMessage( idThread
, Msg
, wParam
, lParam
);
2009 NtUserWaitMessage(VOID
)
2013 UserEnterExclusive();
2014 TRACE("NtUserWaitMessage Enter\n");
2015 ret
= co_IntWaitMessage(NULL
, 0, 0);
2016 TRACE("NtUserWaitMessage Leave\n");
2023 NtUserGetMessage(PMSG pMsg
,
2031 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
2033 EngSetLastError(ERROR_INVALID_PARAMETER
);
2037 UserEnterExclusive();
2039 RtlZeroMemory(&Msg
, sizeof(MSG
));
2041 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
2049 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2050 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2052 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2054 SetLastNtError(_SEH2_GetExceptionCode());
2061 Ret
= Ret
? (WM_QUIT
!= pMsg
->message
) : FALSE
;
2067 NtUserPeekMessage( PMSG pMsg
,
2076 if ( RemoveMsg
& PM_BADMSGFLAGS
)
2078 EngSetLastError(ERROR_INVALID_FLAGS
);
2082 UserEnterExclusive();
2084 RtlZeroMemory(&Msg
, sizeof(MSG
));
2086 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
2094 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2095 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2097 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2099 SetLastNtError(_SEH2_GetExceptionCode());
2109 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
2116 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
2117 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
2119 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2121 _SEH2_YIELD(return FALSE
);
2125 UserEnterExclusive();
2127 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
2133 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
2140 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
2141 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
2143 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2153 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
2160 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
2161 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
2163 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2165 SetLastNtError(_SEH2_GetExceptionCode());
2166 _SEH2_YIELD(return FALSE
);
2170 UserEnterExclusive();
2172 Res
= IntDispatchMessage(&SafeMsg
);
2179 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
2187 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
2188 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
2190 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2192 SetLastNtError(_SEH2_GetExceptionCode());
2193 _SEH2_YIELD(return FALSE
);
2197 UserEnterExclusive();
2198 pWnd
= UserGetWindowObject(SafeMsg
.hwnd
);
2199 if (pWnd
) // Must have a window!
2201 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
2205 TRACE("No Window for Translate. hwnd 0x%p Msg %d\n",SafeMsg
.hwnd
,SafeMsg
.message
);
2213 LRESULT APIENTRY
ScrollBarWndProc(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
);
2216 NtUserMessageCall( HWND hWnd
,
2220 ULONG_PTR ResultInfo
,
2221 DWORD dwType
, // fnID?
2224 LRESULT lResult
= 0;
2227 USER_REFERENCE_ENTRY Ref
;
2229 UserEnterExclusive();
2233 case FNID_SCROLLBAR
:
2235 lResult
= ScrollBarWndProc(hWnd
, Msg
, wParam
, lParam
);
2240 Window
= UserGetWindowObject(hWnd
);
2243 //ERR("FNID_DESKTOP IN\n");
2244 Ret
= DesktopWindowProc(Window
, Msg
, wParam
, lParam
, &lResult
);
2245 //ERR("FNID_DESKTOP OUT\n");
2250 case FNID_MESSAGEWND
:
2252 Window
= UserGetWindowObject(hWnd
);
2255 Ret
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,&lResult
);
2259 case FNID_DEFWINDOWPROC
:
2260 /* Validate input */
2263 Window
= UserGetWindowObject(hWnd
);
2269 UserRefObjectCo(Window
, &Ref
);
2271 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2274 UserDerefObjectCo(Window
);
2276 case FNID_SENDNOTIFYMESSAGE
:
2277 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2279 case FNID_BROADCASTSYSTEMMESSAGE
:
2281 BROADCASTPARM parm
, *retparam
;
2282 DWORD_PTR RetVal
= 0;
2288 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2289 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2291 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2300 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2301 parm
.recipients
== BSM_ALLCOMPONENTS
)
2303 PLIST_ENTRY DesktopEntry
;
2305 HWND
*List
, hwndDenied
= NULL
;
2307 PWND pwnd
, pwndDesk
;
2311 for (DesktopEntry
= InputWindowStation
->DesktopListHead
.Flink
;
2312 DesktopEntry
!= &InputWindowStation
->DesktopListHead
;
2313 DesktopEntry
= DesktopEntry
->Flink
)
2315 rpdesk
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
2316 pwndDesk
= rpdesk
->pDeskInfo
->spwnd
;
2317 List
= IntWinListChildren(pwndDesk
);
2319 if (parm
.flags
& BSF_QUERY
)
2323 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2325 fuFlags
= SMTO_ABORTIFHUNG
;
2327 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2329 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2333 fuFlags
= SMTO_NORMAL
;
2335 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2343 for (i
= 0; List
[i
]; i
++)
2345 pwnd
= UserGetWindowObject(List
[i
]);
2346 if (!pwnd
) continue;
2348 if ( pwnd
->fnid
== FNID_MENU
||
2349 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2352 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2354 if ( pwnd
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
2357 co_IntSendMessageTimeout( List
[i
],
2365 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2367 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2370 if (RetVal
== BROADCAST_QUERY_DENY
)
2372 hwndDenied
= List
[i
];
2373 hDesk
= UserHMGetHandle(pwndDesk
);
2377 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2380 retparam
= (PBROADCASTPARM
) ResultInfo
;
2381 retparam
->hDesk
= hDesk
;
2382 retparam
->hWnd
= hwndDenied
;
2384 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2389 if (!Ret
) break; // Have a hit! Let everyone know!
2392 else if (parm
.flags
& BSF_POSTMESSAGE
)
2396 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2398 for (i
= 0; List
[i
]; i
++)
2400 pwnd
= UserGetWindowObject(List
[i
]);
2401 if (!pwnd
) continue;
2403 if ( pwnd
->fnid
== FNID_MENU
||
2404 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2407 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2409 if ( pwnd
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
2412 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2414 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2422 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2424 for (i
= 0; List
[i
]; i
++)
2426 pwnd
= UserGetWindowObject(List
[i
]);
2427 if (!pwnd
) continue;
2429 if ( pwnd
->fnid
== FNID_MENU
||
2430 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2433 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2435 if ( pwnd
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
2438 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2440 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2446 else if (parm
.recipients
& BSM_APPLICATIONS
)
2448 HWND
*List
, hwndDenied
= NULL
;
2450 PWND pwnd
, pwndDesk
;
2454 pwndDesk
= UserGetDesktopWindow();
2455 List
= IntWinListChildren(pwndDesk
);
2457 if (parm
.flags
& BSF_QUERY
)
2461 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2463 fuFlags
= SMTO_ABORTIFHUNG
;
2465 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2467 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2471 fuFlags
= SMTO_NORMAL
;
2473 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2481 for (i
= 0; List
[i
]; i
++)
2483 pwnd
= UserGetWindowObject(List
[i
]);
2484 if (!pwnd
) continue;
2486 if ( pwnd
->fnid
== FNID_MENU
||
2487 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2490 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2492 if ( pwnd
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
2495 co_IntSendMessageTimeout( List
[i
],
2503 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2505 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2508 if (RetVal
== BROADCAST_QUERY_DENY
)
2510 hwndDenied
= List
[i
];
2511 hDesk
= UserHMGetHandle(pwndDesk
);
2515 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2518 retparam
= (PBROADCASTPARM
) ResultInfo
;
2519 retparam
->hDesk
= hDesk
;
2520 retparam
->hWnd
= hwndDenied
;
2522 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2529 else if (parm
.flags
& BSF_POSTMESSAGE
)
2533 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2535 for (i
= 0; List
[i
]; i
++)
2537 pwnd
= UserGetWindowObject(List
[i
]);
2538 if (!pwnd
) continue;
2540 if ( pwnd
->fnid
== FNID_MENU
||
2541 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2544 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2546 if ( pwnd
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
2549 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2551 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2559 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2561 for (i
= 0; List
[i
]; i
++)
2563 pwnd
= UserGetWindowObject(List
[i
]);
2564 if (!pwnd
) continue;
2566 if ( pwnd
->fnid
== FNID_MENU
||
2567 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2570 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2572 if ( pwnd
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
2575 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2577 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2584 case FNID_SENDMESSAGECALLBACK
:
2586 CALL_BACK_INFO CallBackInfo
;
2591 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2592 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2594 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2600 if (is_pointer_message(Msg
))
2602 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
2606 if (!(Ret
= co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2607 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
)))
2609 ERR("Callback failure!\n");
2613 case FNID_SENDMESSAGE
:
2615 Ret
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2621 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2622 RtlCopyMemory((PVOID
)ResultInfo
, &Ret
, sizeof(ULONG_PTR
));
2624 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2633 case FNID_SENDMESSAGEFF
:
2634 case FNID_SENDMESSAGEWTOOPTION
:
2636 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2641 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2642 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2644 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2651 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, &dsm
);
2657 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2658 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2660 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2669 // CallNextHook bypass.
2670 case FNID_CALLWNDPROC
:
2671 case FNID_CALLWNDPROCRET
:
2674 PCLIENTINFO ClientInfo
;
2675 PHOOK NextObj
, Hook
;
2677 pti
= GetW32ThreadInfo();
2679 Hook
= pti
->sphkCurrent
;
2683 NextObj
= Hook
->phkNext
;
2684 ClientInfo
= pti
->pClientInfo
;
2687 ClientInfo
->phkCurrent
= NextObj
;
2689 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2695 if (!ClientInfo
|| !NextObj
) break;
2697 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2699 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2704 CWP
.wParam
= wParam
;
2705 CWP
.lParam
= lParam
;
2706 TRACE("WH_CALLWNDPROC: Hook %x NextHook %x\n", Hook
, NextObj
);
2708 lResult
= co_IntCallHookProc( Hook
->HookId
,
2710 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2721 CWPR
.wParam
= wParam
;
2722 CWPR
.lParam
= lParam
;
2723 CWPR
.lResult
= ClientInfo
->dwHookData
;
2725 lResult
= co_IntCallHookProc( Hook
->HookId
,
2727 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2739 case FNID_DEFWINDOWPROC
:
2740 case FNID_CALLWNDPROC
:
2741 case FNID_CALLWNDPROCRET
:
2742 case FNID_SCROLLBAR
:
2748 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2749 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2751 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2767 #define INFINITE 0xFFFFFFFF
2768 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2772 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2773 IN DWORD dwMilliseconds
,
2777 PPROCESSINFO W32Process
;
2781 LARGE_INTEGER Timeout
;
2783 UserEnterExclusive();
2785 Status
= ObReferenceObjectByHandle(hProcess
,
2786 PROCESS_QUERY_INFORMATION
,
2792 if (!NT_SUCCESS(Status
))
2795 SetLastNtError(Status
);
2799 pti
= PsGetCurrentThreadWin32Thread();
2801 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2803 if ( PsGetProcessExitProcessCalled(Process
) ||
2805 pti
->ppi
== W32Process
)
2807 ObDereferenceObject(Process
);
2809 EngSetLastError(ERROR_INVALID_PARAMETER
);
2813 Handles
[0] = Process
;
2814 Handles
[1] = W32Process
->InputIdleEvent
;
2815 Handles
[2] = pti
->MessageQueue
->NewMessages
; // pEventQueueServer; IntMsqSetWakeMask returns hEventQueueClient
2819 ObDereferenceObject(Process
);
2821 return STATUS_SUCCESS
; /* no event to wait on */
2824 if (dwMilliseconds
!= INFINITE
)
2825 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2827 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2828 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2830 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2831 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2834 TRACE("WFII: ppi 0x%x\n",W32Process
);
2835 TRACE("WFII: waiting for %p\n", Handles
[1] );
2839 Status
= KeWaitForMultipleObjects( 3,
2845 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2847 UserEnterExclusive();
2849 if (!NT_SUCCESS(Status
))
2851 SetLastNtError(Status
);
2852 Status
= WAIT_FAILED
;
2864 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2865 ERR("WFII: WAIT 2\n");
2869 case STATUS_TIMEOUT
:
2870 ERR("WFII: timeout\n");
2875 ERR("WFII: finished\n");
2876 Status
= STATUS_SUCCESS
;
2883 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2885 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
2886 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2888 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
2889 ObDereferenceObject(Process
);