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_SETTINGCHANGE
, MMS_SIZE_LPARAMSZ
, MMS_FLAG_READ
},
132 { WM_COPYDATA
, MMS_SIZE_SPECIAL
, MMS_FLAG_READ
},
133 { WM_COPYGLOBALDATA
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
134 { WM_WINDOWPOSCHANGED
, sizeof(WINDOWPOS
), MMS_FLAG_READ
},
135 { WM_WINDOWPOSCHANGING
, sizeof(WINDOWPOS
), MMS_FLAG_READWRITE
},
138 static PMSGMEMORY FASTCALL
139 FindMsgMemory(UINT Msg
)
141 PMSGMEMORY MsgMemoryEntry
;
143 /* See if this message type is present in the table */
144 for (MsgMemoryEntry
= g_MsgMemory
;
145 MsgMemoryEntry
< g_MsgMemory
+ sizeof(g_MsgMemory
) / sizeof(MSGMEMORY
);
148 if (Msg
== MsgMemoryEntry
->Message
)
150 return MsgMemoryEntry
;
158 MsgMemorySize(PMSGMEMORY MsgMemoryEntry
, WPARAM wParam
, LPARAM lParam
)
161 PUNICODE_STRING WindowName
;
162 PUNICODE_STRING ClassName
;
167 if (MMS_SIZE_WPARAM
== MsgMemoryEntry
->Size
)
171 else if (MMS_SIZE_WPARAMWCHAR
== MsgMemoryEntry
->Size
)
173 Size
= (UINT
) (wParam
* sizeof(WCHAR
));
175 else if (MMS_SIZE_LPARAMSZ
== MsgMemoryEntry
->Size
)
177 // WM_SETTEXT and WM_SETTINGCHANGE can be null!
180 TRACE("lParam is NULL!\n");
184 Size
= (UINT
) ((wcslen((PWSTR
) lParam
) + 1) * sizeof(WCHAR
));
186 else if (MMS_SIZE_SPECIAL
== MsgMemoryEntry
->Size
)
188 switch(MsgMemoryEntry
->Message
)
192 Cs
= (CREATESTRUCTW
*) lParam
;
193 WindowName
= (PUNICODE_STRING
) Cs
->lpszName
;
194 ClassName
= (PUNICODE_STRING
) Cs
->lpszClass
;
195 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
196 if (IS_ATOM(ClassName
->Buffer
))
198 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
202 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
207 Size
= wParam
? sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
) : sizeof(RECT
);
211 Size
= sizeof(COPYDATASTRUCT
) + ((PCOPYDATASTRUCT
)lParam
)->cbData
;
222 Size
= MsgMemoryEntry
->Size
;
225 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
227 ERR("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH2_GetExceptionCode());
234 UINT
lParamMemorySize(UINT Msg
, WPARAM wParam
, LPARAM lParam
)
236 PMSGMEMORY MsgMemoryEntry
= FindMsgMemory(Msg
);
237 if(MsgMemoryEntry
== NULL
) return 0;
238 return MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
242 PackParam(LPARAM
*lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolNeeded
)
244 NCCALCSIZE_PARAMS
*UnpackedNcCalcsize
;
245 NCCALCSIZE_PARAMS
*PackedNcCalcsize
;
246 CREATESTRUCTW
*UnpackedCs
;
247 CREATESTRUCTW
*PackedCs
;
248 PLARGE_STRING WindowName
;
249 PUNICODE_STRING ClassName
;
254 *lParamPacked
= lParam
;
256 if (NonPagedPoolNeeded
)
257 PoolType
= NonPagedPool
;
259 PoolType
= PagedPool
;
261 if (WM_NCCALCSIZE
== Msg
&& wParam
)
264 UnpackedNcCalcsize
= (NCCALCSIZE_PARAMS
*) lParam
;
265 PackedNcCalcsize
= ExAllocatePoolWithTag(PoolType
,
266 sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
),
269 if (NULL
== PackedNcCalcsize
)
271 ERR("Not enough memory to pack lParam\n");
272 return STATUS_NO_MEMORY
;
274 RtlCopyMemory(PackedNcCalcsize
, UnpackedNcCalcsize
, sizeof(NCCALCSIZE_PARAMS
));
275 PackedNcCalcsize
->lppos
= (PWINDOWPOS
) (PackedNcCalcsize
+ 1);
276 RtlCopyMemory(PackedNcCalcsize
->lppos
, UnpackedNcCalcsize
->lppos
, sizeof(WINDOWPOS
));
277 *lParamPacked
= (LPARAM
) PackedNcCalcsize
;
279 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
281 UnpackedCs
= (CREATESTRUCTW
*) lParam
;
282 WindowName
= (PLARGE_STRING
) UnpackedCs
->lpszName
;
283 ClassName
= (PUNICODE_STRING
) UnpackedCs
->lpszClass
;
284 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
285 if (IS_ATOM(ClassName
->Buffer
))
287 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
291 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
293 PackedCs
= ExAllocatePoolWithTag(PoolType
, Size
, TAG_MSG
);
294 if (NULL
== PackedCs
)
296 ERR("Not enough memory to pack lParam\n");
297 return STATUS_NO_MEMORY
;
299 RtlCopyMemory(PackedCs
, UnpackedCs
, sizeof(CREATESTRUCTW
));
300 CsData
= (PCHAR
) (PackedCs
+ 1);
301 PackedCs
->lpszName
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
302 RtlCopyMemory(CsData
, WindowName
->Buffer
, WindowName
->Length
);
303 CsData
+= WindowName
->Length
;
304 *((WCHAR
*) CsData
) = L
'\0';
305 CsData
+= sizeof(WCHAR
);
306 PackedCs
->lpszClass
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
307 if (IS_ATOM(ClassName
->Buffer
))
309 *((WCHAR
*) CsData
) = L
'A';
310 CsData
+= sizeof(WCHAR
);
311 *((ATOM
*) CsData
) = (ATOM
)(DWORD_PTR
) ClassName
->Buffer
;
312 CsData
+= sizeof(ATOM
);
316 *((WCHAR
*) CsData
) = L
'S';
317 CsData
+= sizeof(WCHAR
);
318 RtlCopyMemory(CsData
, ClassName
->Buffer
, ClassName
->Length
);
319 CsData
+= ClassName
->Length
;
320 *((WCHAR
*) CsData
) = L
'\0';
321 CsData
+= sizeof(WCHAR
);
323 ASSERT(CsData
== (PCHAR
) PackedCs
+ Size
);
324 *lParamPacked
= (LPARAM
) PackedCs
;
326 else if (PoolType
== NonPagedPool
)
328 PMSGMEMORY MsgMemoryEntry
;
332 MsgMemoryEntry
= FindMsgMemory(Msg
);
334 if ((!MsgMemoryEntry
) || (MsgMemoryEntry
->Size
< 0))
336 /* Keep previous behavior */
337 return STATUS_SUCCESS
;
339 size
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
342 ERR("No size for lParamPacked\n");
343 return STATUS_SUCCESS
;
345 PackedData
= ExAllocatePoolWithTag(NonPagedPool
, size
, TAG_MSG
);
346 if (PackedData
== NULL
)
348 ERR("Not enough memory to pack lParam\n");
349 return STATUS_NO_MEMORY
;
351 RtlCopyMemory(PackedData
, (PVOID
)lParam
, MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
));
352 *lParamPacked
= (LPARAM
)PackedData
;
355 return STATUS_SUCCESS
;
359 UnpackParam(LPARAM lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolUsed
)
361 NCCALCSIZE_PARAMS
*UnpackedParams
;
362 NCCALCSIZE_PARAMS
*PackedParams
;
363 PWINDOWPOS UnpackedWindowPos
;
365 if (lParamPacked
== lParam
)
367 return STATUS_SUCCESS
;
370 if (WM_NCCALCSIZE
== Msg
&& wParam
)
372 PackedParams
= (NCCALCSIZE_PARAMS
*) lParamPacked
;
373 UnpackedParams
= (NCCALCSIZE_PARAMS
*) lParam
;
374 UnpackedWindowPos
= UnpackedParams
->lppos
;
375 RtlCopyMemory(UnpackedParams
, PackedParams
, sizeof(NCCALCSIZE_PARAMS
));
376 UnpackedParams
->lppos
= UnpackedWindowPos
;
377 RtlCopyMemory(UnpackedWindowPos
, PackedParams
+ 1, sizeof(WINDOWPOS
));
378 ExFreePool((PVOID
) lParamPacked
);
380 return STATUS_SUCCESS
;
382 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
384 ExFreePool((PVOID
) lParamPacked
);
386 return STATUS_SUCCESS
;
388 else if (NonPagedPoolUsed
)
390 PMSGMEMORY MsgMemoryEntry
;
391 MsgMemoryEntry
= FindMsgMemory(Msg
);
392 ASSERT(MsgMemoryEntry
);
393 if (MsgMemoryEntry
->Size
< 0)
395 /* Keep previous behavior */
396 return STATUS_INVALID_PARAMETER
;
399 if (MsgMemoryEntry
->Flags
== MMS_FLAG_READWRITE
)
401 //RtlCopyMemory((PVOID)lParam, (PVOID)lParamPacked, MsgMemoryEntry->Size);
403 ExFreePool((PVOID
) lParamPacked
);
404 return STATUS_SUCCESS
;
409 return STATUS_INVALID_PARAMETER
;
412 static NTSTATUS FASTCALL
413 CopyMsgToKernelMem(MSG
*KernelModeMsg
, MSG
*UserModeMsg
, PMSGMEMORY MsgMemoryEntry
)
420 *KernelModeMsg
= *UserModeMsg
;
422 /* See if this message type is present in the table */
423 if (NULL
== MsgMemoryEntry
)
425 /* Not present, no copying needed */
426 return STATUS_SUCCESS
;
429 /* Determine required size */
430 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
434 /* Allocate kernel mem */
435 KernelMem
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
436 if (NULL
== KernelMem
)
438 ERR("Not enough memory to copy message to kernel mem\n");
439 return STATUS_NO_MEMORY
;
441 KernelModeMsg
->lParam
= (LPARAM
) KernelMem
;
443 /* Copy data if required */
444 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_READ
))
446 TRACE("Copy Message %d from usermode buffer\n", KernelModeMsg
->message
);
447 Status
= MmCopyFromCaller(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
448 if (! NT_SUCCESS(Status
))
450 ERR("Failed to copy message to kernel: invalid usermode lParam buffer\n");
451 ExFreePoolWithTag(KernelMem
, TAG_MSG
);
457 /* Make sure we don't pass any secrets to usermode */
458 RtlZeroMemory(KernelMem
, Size
);
463 KernelModeMsg
->lParam
= 0;
466 return STATUS_SUCCESS
;
469 static NTSTATUS FASTCALL
470 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
473 PMSGMEMORY MsgMemoryEntry
;
476 /* See if this message type is present in the table */
477 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
478 if (NULL
== MsgMemoryEntry
)
480 /* Not present, no copying needed */
481 return STATUS_SUCCESS
;
484 /* Determine required size */
485 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
489 /* Copy data if required */
490 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
492 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
493 if (! NT_SUCCESS(Status
))
495 ERR("Failed to copy message from kernel: invalid usermode lParam buffer\n");
496 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
501 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
504 return STATUS_SUCCESS
;
508 // Wakeup any thread/process waiting on idle input.
513 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
516 pti
= PsGetCurrentThreadWin32Thread();
520 pti
->pClientInfo
->cSpins
= 0; // Reset spins.
522 if ( pti
->pDeskInfo
&& pti
== gptiForeground
)
524 if ( pti
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) ||
525 pti
->pDeskInfo
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) )
527 co_HOOK_CallHooks(WH_FOREGROUNDIDLE
,HC_ACTION
,0,0);
532 TRACE("IdlePing ppi %p\n", ppi
);
533 if ( ppi
&& ppi
->InputIdleEvent
)
535 TRACE("InputIdleEvent\n");
536 KeSetEvent( ppi
->InputIdleEvent
, IO_NO_INCREMENT
, FALSE
);
543 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
545 TRACE("IdlePong ppi %p\n", ppi
);
546 if ( ppi
&& ppi
->InputIdleEvent
)
548 KeClearEvent(ppi
->InputIdleEvent
);
553 GetWakeMask(UINT first
, UINT last
)
555 UINT mask
= QS_POSTMESSAGE
| QS_SENDMESSAGE
; /* Always selected */
559 if ((first
<= WM_KEYLAST
) && (last
>= WM_KEYFIRST
)) mask
|= QS_KEY
;
560 if ( ((first
<= WM_MOUSELAST
) && (last
>= WM_MOUSEFIRST
)) ||
561 ((first
<= WM_NCMOUSELAST
) && (last
>= WM_NCMOUSEFIRST
)) ) mask
|= QS_MOUSE
;
562 if ((first
<= WM_TIMER
) && (last
>= WM_TIMER
)) mask
|= QS_TIMER
;
563 if ((first
<= WM_SYSTIMER
) && (last
>= WM_SYSTIMER
)) mask
|= QS_TIMER
;
564 if ((first
<= WM_PAINT
) && (last
>= WM_PAINT
)) mask
|= QS_PAINT
;
566 else mask
= QS_ALLINPUT
;
572 IntCallWndProc( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
574 BOOL SameThread
= FALSE
;
577 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
584 co_HOOK_CallHooks( WH_CALLWNDPROC
, HC_ACTION
, SameThread
, (LPARAM
)&CWP
);
588 IntCallWndProcRet ( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*uResult
)
590 BOOL SameThread
= FALSE
;
593 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
598 CWPR
.wParam
= wParam
;
599 CWPR
.lParam
= lParam
;
600 CWPR
.lResult
= uResult
? (*uResult
) : 0;
601 co_HOOK_CallHooks( WH_CALLWNDPROCRET
, HC_ACTION
, SameThread
, (LPARAM
)&CWPR
);
604 static LRESULT
handle_internal_message( PWND pWnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
607 USER_REFERENCE_ENTRY Ref
;
608 // PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
611 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
612 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
615 TRACE("Internal Event Msg %p hWnd 0x%x\n",msg
,pWnd
->head
.h
);
619 case WM_ASYNC_SHOWWINDOW
:
620 return co_WinPosShowWindow( pWnd
, wparam
);
621 case WM_ASYNC_SETWINDOWPOS
:
623 PWINDOWPOS winpos
= (PWINDOWPOS
)lparam
;
624 if (!winpos
) return 0;
625 lRes
= co_WinPosSetWindowPos( pWnd
,
626 winpos
->hwndInsertAfter
,
632 ExFreePoolWithTag(winpos
, USERTAG_SWP
);
635 case WM_ASYNC_SETACTIVEWINDOW
:
637 PWND Window
= (PWND
)wparam
;
638 if (wparam
) UserRefObjectCo(Window
, &Ref
);
639 lRes
= (LRESULT
)co_IntSetActiveWindow(Window
,(BOOL
)lparam
,TRUE
,TRUE
);
640 if (wparam
) UserDerefObjectCo(Window
);
648 IntDispatchMessage(PMSG pMsg
)
650 LARGE_INTEGER TickCount
;
656 BOOL DoCallBack
= TRUE
;
660 Window
= UserGetWindowObject(pMsg
->hwnd
);
661 if (!Window
) return 0;
664 pti
= PsGetCurrentThreadWin32Thread();
666 if ( Window
&& Window
->head
.pti
!= pti
)
668 EngSetLastError( ERROR_MESSAGE_SYNC_ONLY
);
672 if (((pMsg
->message
== WM_SYSTIMER
) ||
673 (pMsg
->message
== WM_TIMER
)) &&
676 if (pMsg
->message
== WM_TIMER
)
678 if (ValidateTimerCallback(pti
,pMsg
->lParam
))
680 KeQueryTickCount(&TickCount
);
681 Time
= MsqCalculateMessageTime(&TickCount
);
682 retval
= co_IntCallWindowProc((WNDPROC
)pMsg
->lParam
,
694 PTIMER pTimer
= FindSystemTimer(pMsg
);
695 if (pTimer
&& pTimer
->pfn
)
697 KeQueryTickCount(&TickCount
);
698 Time
= MsqCalculateMessageTime(&TickCount
);
699 pTimer
->pfn(pMsg
->hwnd
, WM_SYSTIMER
, (UINT
)pMsg
->wParam
, Time
);
705 if ( !Window
) return 0;
707 if (pMsg
->message
== WM_PAINT
) Window
->state
|= WNDS_PAINTNOTPROCESSED
;
709 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
711 TRACE("Dispatch: Server Side Window Procedure\n");
715 DoCallBack
= !DesktopWindowProc( Window
,
721 case FNID_MESSAGEWND
:
722 DoCallBack
= !UserMessageWindowProc( Window
,
731 /* Since we are doing a callback on the same thread right away, there is
732 no need to copy the lparam to kernel mode and then back to usermode.
733 We just pretend it isn't a pointer */
736 retval
= co_IntCallWindowProc( Window
->lpfnWndProc
,
744 if (pMsg
->message
== WM_PAINT
)
746 Window
->state2
&= ~WNDS2_WMPAINTSENT
;
747 /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
748 hrgn
= IntSysCreateRectRgn( 0, 0, 0, 0 );
749 co_UserGetUpdateRgn( Window
, hrgn
, TRUE
);
750 GreDeleteObject(hrgn
);
757 * Internal version of PeekMessage() doing all the work
762 * Input (hardware) messages and system internal events
763 * Sent messages (again)
768 co_IntPeekMessage( PMSG Msg
,
776 LARGE_INTEGER LargeTickCount
;
781 pti
= PsGetCurrentThreadWin32Thread();
783 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
784 ProcessMask
= HIWORD(RemoveMsg
);
786 /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns
787 all available messages (that is, no range filtering is performed)". */
788 if (!ProcessMask
) ProcessMask
= (QS_ALLPOSTMESSAGE
|QS_ALLINPUT
);
794 KeQueryTickCount(&LargeTickCount
);
795 pti
->timeLast
= LargeTickCount
.u
.LowPart
;
796 pti
->pcti
->tickLastMsgChecked
= LargeTickCount
.u
.LowPart
;
798 /* Dispatch sent messages here. */
799 while ( co_MsqDispatchOneSentMessage(pti
) )
801 /* if some PM_QS* flags were specified, only handle sent messages from now on */
802 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
; // wine does this; ProcessMask = QS_SENDMESSAGE;
804 if (Hit
) return FALSE
;
806 /* Clear changed bits so we can wait on them if we don't find a message */
807 if (ProcessMask
& QS_POSTMESSAGE
)
809 pti
->pcti
->fsChangeBits
&= ~(QS_POSTMESSAGE
| QS_HOTKEY
| QS_TIMER
);
810 if (MsgFilterMin
== 0 && MsgFilterMax
== 0) // Wine hack does this; ~0U)
812 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
816 if (ProcessMask
& QS_INPUT
)
818 pti
->pcti
->fsChangeBits
&= ~QS_INPUT
;
821 /* Now check for normal messages. */
822 if (( (ProcessMask
& QS_POSTMESSAGE
) ||
823 (ProcessMask
& QS_HOTKEY
) ) &&
835 /* Now look for a quit message. */
838 /* According to the PSDK, WM_QUIT messages are always returned, regardless
839 of the filter specified */
841 Msg
->message
= WM_QUIT
;
842 Msg
->wParam
= pti
->exitCode
;
846 pti
->QuitPosted
= FALSE
;
847 ClearMsgBitsMask(pti
, QS_POSTMESSAGE
);
848 pti
->pcti
->fsWakeBits
&= ~QS_ALLPOSTMESSAGE
;
849 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
854 /* Check for hardware events. */
855 if ((ProcessMask
& QS_MOUSE
) &&
856 co_MsqPeekMouseMove( pti
,
866 if ((ProcessMask
& QS_INPUT
) &&
867 co_MsqPeekHardwareMessage( pti
,
878 /* Check for sent messages again. */
879 while ( co_MsqDispatchOneSentMessage(pti
) )
881 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
;
883 if (Hit
) return FALSE
;
885 /* Check for paint messages. */
886 if ((ProcessMask
& QS_PAINT
) &&
888 IntGetPaintMessage( Window
,
898 /* This is correct, check for the current threads timers waiting to be
899 posted to this threads message queue. If any we loop again.
901 if ((ProcessMask
& QS_TIMER
) &&
902 PostTimerMessages(Window
))
915 co_IntWaitMessage( PWND Window
,
920 NTSTATUS Status
= STATUS_SUCCESS
;
923 pti
= PsGetCurrentThreadWin32Thread();
927 if ( co_IntPeekMessage( &Msg
, // Dont reenter!
931 MAKELONG( PM_NOREMOVE
, GetWakeMask( MsgFilterMin
, MsgFilterMax
)),
932 TRUE
) ) // act like GetMessage.
937 /* Nothing found. Wait for new messages. */
938 Status
= co_MsqWaitForNewMessages( pti
,
942 if (!NT_SUCCESS(Status
))
944 SetLastNtError(Status
);
945 ERR("Exit co_IntWaitMessage on error!\n");
948 if (Status
== STATUS_USER_APC
|| Status
== STATUS_TIMEOUT
)
959 co_IntGetPeekMessage( PMSG pMsg
,
968 BOOL Present
= FALSE
;
971 if ( hWnd
== HWND_TOPMOST
|| hWnd
== HWND_BROADCAST
)
975 if (hWnd
&& hWnd
!= HWND_BOTTOM
)
977 if (!(Window
= UserGetWindowObject(hWnd
)))
990 if (MsgFilterMax
< MsgFilterMin
)
998 RemoveMsg
|= ((GetWakeMask( MsgFilterMin
, MsgFilterMax
))<< 16);
1001 pti
= PsGetCurrentThreadWin32Thread();
1002 pti
->pClientInfo
->cSpins
++; // Bump up the spin count.
1006 Present
= co_IntPeekMessage( pMsg
,
1014 /* GetMessage or PostMessage must never get messages that contain pointers */
1015 ASSERT(FindMsgMemory(pMsg
->message
) == NULL
);
1017 if (pMsg
->message
!= WM_PAINT
&& pMsg
->message
!= WM_QUIT
)
1019 pti
->timeLast
= pMsg
->time
;
1020 pti
->ptLast
= pMsg
->pt
;
1023 // The WH_GETMESSAGE hook enables an application to monitor messages about to
1024 // be returned by the GetMessage or PeekMessage function.
1026 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)pMsg
);
1033 Status
= co_MsqWaitForNewMessages( pti
,
1037 if ( !NT_SUCCESS(Status
) ||
1038 Status
== STATUS_USER_APC
||
1039 Status
== STATUS_TIMEOUT
)
1047 if (!(RemoveMsg
& PM_NOYIELD
))
1050 // Yield this thread!
1053 UserEnterExclusive();
1054 // Fall through to exit.
1060 while( bGMSG
&& !Present
);
1062 // Been spinning, time to swap vinyl...
1063 if (pti
->pClientInfo
->cSpins
>= 100)
1065 // Clear the spin cycle to fix the mix.
1066 pti
->pClientInfo
->cSpins
= 0;
1067 //if (!(pti->TIF_flags & TIF_SPINNING)) // FIXME: Need to swap vinyl...
1073 UserPostThreadMessage( PTHREADINFO pti
,
1079 LARGE_INTEGER LargeTickCount
;
1081 if (is_pointer_message(Msg
))
1083 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1086 Message
.hwnd
= NULL
;
1087 Message
.message
= Msg
;
1088 Message
.wParam
= wParam
;
1089 Message
.lParam
= lParam
;
1090 Message
.pt
= gpsi
->ptCursor
;
1092 KeQueryTickCount(&LargeTickCount
);
1093 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1094 MsqPostMessage(pti
, &Message
, FALSE
, QS_POSTMESSAGE
, 0);
1098 PTHREADINFO FASTCALL
1099 IntSendTo(PWND Window
, PTHREADINFO ptiCur
, UINT Msg
)
1104 Window
->head
.pti
->MessageQueue
== ptiCur
->MessageQueue
)
1109 return Window
? Window
->head
.pti
: NULL
;
1113 UserPostMessage( HWND Wnd
,
1119 MSG Message
, KernelModeMsg
;
1120 LARGE_INTEGER LargeTickCount
;
1123 Message
.message
= Msg
;
1124 Message
.wParam
= wParam
;
1125 Message
.lParam
= lParam
;
1126 Message
.pt
= gpsi
->ptCursor
;
1127 KeQueryTickCount(&LargeTickCount
);
1128 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1130 if (is_pointer_message(Message
.message
))
1132 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1136 if( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1139 PMSGMEMORY MsgMemoryEntry
;
1141 MsgMemoryEntry
= FindMsgMemory(Message
.message
);
1143 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &Message
, MsgMemoryEntry
);
1144 if (! NT_SUCCESS(Status
))
1146 EngSetLastError(ERROR_INVALID_PARAMETER
);
1149 co_IntSendMessageNoWait(KernelModeMsg
.hwnd
,
1150 KernelModeMsg
.message
,
1151 KernelModeMsg
.wParam
,
1152 KernelModeMsg
.lParam
);
1154 if (MsgMemoryEntry
&& KernelModeMsg
.lParam
)
1155 ExFreePool((PVOID
) KernelModeMsg
.lParam
);
1162 pti
= PsGetCurrentThreadWin32Thread();
1163 return UserPostThreadMessage( pti
,
1168 if (Wnd
== HWND_BROADCAST
)
1174 DesktopWindow
= UserGetDesktopWindow();
1175 List
= IntWinListChildren(DesktopWindow
);
1179 UserPostMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1180 for (i
= 0; List
[i
]; i
++)
1182 PWND pwnd
= UserGetWindowObject(List
[i
]);
1183 if (!pwnd
) continue;
1185 if ( pwnd
->fnid
== FNID_MENU
|| // Also need pwnd->pcls->atomClassName == gaOleMainThreadWndClass
1186 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1189 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1191 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1198 Window
= UserGetWindowObject(Wnd
);
1201 ERR("UserPostMessage: Invalid handle 0x%p!\n",Wnd
);
1205 pti
= Window
->head
.pti
;
1206 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1208 ERR("Attempted to post message to window %p when the thread is in cleanup!\n", Wnd
);
1212 if ( Window
->state
& WNDS_DESTROYED
)
1214 ERR("Attempted to post message to window %p that is being destroyed!\n", Wnd
);
1215 /* FIXME: Last error code? */
1221 MsqPostQuitMessage(pti
, wParam
);
1225 MsqPostMessage(pti
, &Message
, FALSE
, QS_POSTMESSAGE
, 0);
1232 co_IntSendMessage( HWND hWnd
,
1237 ULONG_PTR Result
= 0;
1238 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1240 return (LRESULT
)Result
;
1245 static LRESULT FASTCALL
1246 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1252 ULONG_PTR
*uResult
)
1256 PMSGMEMORY MsgMemoryEntry
;
1257 INT lParamBufferSize
;
1258 LPARAM lParamPacked
;
1259 PTHREADINFO Win32Thread
, ptiSendTo
= NULL
;
1260 ULONG_PTR Hi
, Lo
, Result
= 0;
1261 DECLARE_RETURN(LRESULT
);
1262 USER_REFERENCE_ENTRY Ref
;
1263 BOOL DoCallBack
= TRUE
;
1265 if (!(Window
= UserGetWindowObject(hWnd
)))
1267 TRACE("SendMessageTimeoutSingle: Invalid handle 0x%p!\n",hWnd
);
1271 UserRefObjectCo(Window
, &Ref
);
1273 Win32Thread
= PsGetCurrentThreadWin32Thread();
1275 ptiSendTo
= IntSendTo(Window
, Win32Thread
, Msg
);
1279 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1281 /* Never send messages to exiting threads */
1285 if (Msg
& 0x80000000)
1287 TRACE("SMTS: Internal Message!\n");
1288 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1289 if (uResult
) *uResult
= Result
;
1293 // Only happens when calling the client!
1294 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1296 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1298 TRACE("SMT: Server Side Window Procedure\n");
1299 IoGetStackLimits(&Lo
, &Hi
);
1300 // Handle it here. Safeguard against excessive recursions.
1301 if (((ULONG_PTR
)&uResult
- Lo
) < 4096 )
1303 ERR("Server Callback Exceeded Stack!\n");
1306 /* Return after server side call, IntCallWndProcRet will not be called. */
1307 switch(Window
->fnid
)
1310 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1312 case FNID_MESSAGEWND
:
1313 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1318 if (uResult
) *uResult
= Result
;
1322 /* See if this message type is present in the table */
1323 MsgMemoryEntry
= FindMsgMemory(Msg
);
1324 if (NULL
== MsgMemoryEntry
)
1326 lParamBufferSize
= -1;
1330 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1331 // If zero, do not allow callback on client side to allocate a buffer!!!!! See CORE-7695.
1332 if (!lParamBufferSize
) lParamBufferSize
= -1;
1335 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1337 ERR("Failed to pack message parameters\n");
1341 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1353 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1355 ERR("Failed to unpack message parameters\n");
1359 // Only happens when calling the client!
1360 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1365 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(ptiSendTo
))
1367 // FIXME: Set window hung and add to a list.
1368 /* FIXME: Set a LastError? */
1372 if (Window
->state
& WNDS_DESTROYED
)
1374 /* FIXME: Last error? */
1375 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1381 Status
= co_MsqSendMessage( ptiSendTo
,
1387 (uFlags
& SMTO_BLOCK
),
1391 while ((STATUS_TIMEOUT
== Status
) &&
1392 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1393 !MsqIsHung(ptiSendTo
)); // FIXME: Set window hung and add to a list.
1395 if (STATUS_TIMEOUT
== Status
)
1399 * Microsoft Windows 2000: If GetLastError returns zero, then the function
1401 * XP+ : If the function fails or times out, the return value is zero.
1402 * To get extended error information, call GetLastError. If GetLastError
1403 * returns ERROR_TIMEOUT, then the function timed out.
1405 EngSetLastError(ERROR_TIMEOUT
);
1408 else if (!NT_SUCCESS(Status
))
1410 SetLastNtError(Status
);
1417 if (Window
) UserDerefObjectCo(Window
);
1422 co_IntSendMessageTimeout( HWND hWnd
,
1428 ULONG_PTR
*uResult
)
1434 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1436 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1439 DesktopWindow
= UserGetDesktopWindow();
1440 if (NULL
== DesktopWindow
)
1442 EngSetLastError(ERROR_INTERNAL_ERROR
);
1446 if (hWnd
!= HWND_TOPMOST
)
1448 /* Send message to the desktop window too! */
1449 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1452 Children
= IntWinListChildren(DesktopWindow
);
1453 if (NULL
== Children
)
1458 for (Child
= Children
; NULL
!= *Child
; Child
++)
1460 if (hWnd
== HWND_TOPMOST
)
1462 DesktopWindow
= UserGetWindowObject(*Child
);
1463 if (DesktopWindow
&& DesktopWindow
->ExStyle
& WS_EX_TOPMOST
)
1465 ERR("HWND_TOPMOST Found\n");
1466 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1471 PWND pwnd
= UserGetWindowObject(*Child
);
1472 if (!pwnd
) continue;
1474 if ( pwnd
->fnid
== FNID_MENU
||
1475 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1478 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1482 ExFreePool(Children
);
1484 return (LRESULT
) TRUE
;
1488 co_IntSendMessageNoWait(HWND hWnd
,
1493 ULONG_PTR Result
= 0;
1494 return co_IntSendMessageWithCallBack( hWnd
,
1503 If you send a message in the range below WM_USER to the asynchronous message
1504 functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its
1505 message parameters cannot include pointers. Otherwise, the operation will fail.
1506 The functions will return before the receiving thread has had a chance to
1507 process the message and the sender will free the memory before it is used.
1510 co_IntSendMessageWithCallBack( HWND hWnd
,
1514 SENDASYNCPROC CompletionCallback
,
1515 ULONG_PTR CompletionCallbackContext
,
1520 PMSGMEMORY MsgMemoryEntry
;
1521 INT lParamBufferSize
;
1522 LPARAM lParamPacked
;
1523 PTHREADINFO Win32Thread
, ptiSendTo
= NULL
;
1524 DECLARE_RETURN(LRESULT
);
1525 USER_REFERENCE_ENTRY Ref
;
1526 PUSER_SENT_MESSAGE Message
;
1527 BOOL DoCallBack
= TRUE
;
1529 if (!(Window
= UserGetWindowObject(hWnd
)))
1531 TRACE("SendMessageWithCallBack: Invalid handle 0x%p!\n",hWnd
);
1535 UserRefObjectCo(Window
, &Ref
);
1537 if (Window
->state
& WNDS_DESTROYED
)
1539 /* FIXME: last error? */
1540 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1544 Win32Thread
= PsGetCurrentThreadWin32Thread();
1546 if (Win32Thread
== NULL
||
1547 Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1552 ptiSendTo
= IntSendTo(Window
, Win32Thread
, Msg
);
1554 if (Msg
& 0x80000000 &&
1557 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
) RETURN( FALSE
);
1559 TRACE("SMWCB: Internal Message!\n");
1560 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1561 if (uResult
) *uResult
= Result
;
1565 /* See if this message type is present in the table */
1566 MsgMemoryEntry
= FindMsgMemory(Msg
);
1567 if (NULL
== MsgMemoryEntry
)
1569 lParamBufferSize
= -1;
1573 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1574 if (!lParamBufferSize
) lParamBufferSize
= -1;
1577 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, !!ptiSendTo
)))
1579 ERR("Failed to pack message parameters\n");
1583 /* If it can be sent now, then send it. */
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
,
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 Message
->Msg
.hwnd
= hWnd
;
1650 Message
->Msg
.message
= Msg
;
1651 Message
->Msg
.wParam
= wParam
;
1652 Message
->Msg
.lParam
= lParamPacked
;
1653 Message
->CompletionEvent
= NULL
;
1654 Message
->Result
= 0;
1655 Message
->lResult
= 0;
1656 Message
->QS_Flags
= 0;
1657 Message
->ptiReceiver
= ptiSendTo
;
1658 Message
->ptiSender
= NULL
; // mjmartin, you are right! This is null.
1659 Message
->ptiCallBackSender
= Win32Thread
;
1660 Message
->DispatchingListEntry
.Flink
= NULL
;
1661 Message
->CompletionCallback
= CompletionCallback
;
1662 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1663 Message
->HookMessage
= MSQ_NORMAL
;
1664 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1665 Message
->QS_Flags
= QS_SENDMESSAGE
;
1667 if (Msg
& 0x80000000) // Higher priority event message!
1668 InsertHeadList(&ptiSendTo
->SentMessagesListHead
, &Message
->ListEntry
);
1670 InsertTailList(&ptiSendTo
->SentMessagesListHead
, &Message
->ListEntry
);
1671 MsqWakeQueue(ptiSendTo
, QS_SENDMESSAGE
, TRUE
);
1676 if (Window
) UserDerefObjectCo(Window
);
1682 This HACK function posts a message if the destination's message queue belongs to
1683 another thread, otherwise it sends the message. It does not support broadcast
1687 co_IntPostOrSendMessage( HWND hWnd
,
1696 if ( hWnd
== HWND_BROADCAST
)
1701 if(!(Window
= UserGetWindowObject(hWnd
)))
1703 TRACE("PostOrSendMessage: Invalid handle 0x%p!\n",hWnd
);
1707 pti
= PsGetCurrentThreadWin32Thread();
1709 if ( IntSendTo(Window
, pti
, Msg
) &&
1710 FindMsgMemory(Msg
) == 0 )
1712 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1716 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1722 return (LRESULT
)Result
;
1725 static LRESULT FASTCALL
1726 co_IntDoSendMessage( HWND hWnd
,
1732 LRESULT Result
= TRUE
;
1735 MSG UserModeMsg
, KernelModeMsg
;
1736 PMSGMEMORY MsgMemoryEntry
;
1737 PTHREADINFO ptiSendTo
;
1739 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1741 Window
= UserGetWindowObject(hWnd
);
1748 /* Check for an exiting window. */
1749 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1751 ERR("co_IntDoSendMessage Window Exiting!\n");
1754 /* See if the current thread can handle this message */
1755 ptiSendTo
= IntSendTo(Window
, gptiCurrent
, Msg
);
1757 // If broadcasting or sending to another thread, save the users data.
1758 if (!Window
|| ptiSendTo
)
1760 UserModeMsg
.hwnd
= hWnd
;
1761 UserModeMsg
.message
= Msg
;
1762 UserModeMsg
.wParam
= wParam
;
1763 UserModeMsg
.lParam
= lParam
;
1764 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1765 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1766 if (!NT_SUCCESS(Status
))
1768 EngSetLastError(ERROR_INVALID_PARAMETER
);
1769 return (dsm
? 0 : -1);
1774 KernelModeMsg
.hwnd
= hWnd
;
1775 KernelModeMsg
.message
= Msg
;
1776 KernelModeMsg
.wParam
= wParam
;
1777 KernelModeMsg
.lParam
= lParam
;
1782 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1783 KernelModeMsg
.message
,
1784 KernelModeMsg
.wParam
,
1785 KernelModeMsg
.lParam
);
1789 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1790 KernelModeMsg
.message
,
1791 KernelModeMsg
.wParam
,
1792 KernelModeMsg
.lParam
,
1798 if (!Window
|| ptiSendTo
)
1800 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1801 if (!NT_SUCCESS(Status
))
1803 EngSetLastError(ERROR_INVALID_PARAMETER
);
1804 return(dsm
? 0 : -1);
1808 return (LRESULT
)Result
;
1812 UserSendNotifyMessage( HWND hWnd
,
1819 if (is_pointer_message(Msg
))
1821 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1825 // Basicly the same as IntPostOrSendMessage
1826 if (hWnd
== HWND_BROADCAST
) // Handle Broadcast
1832 DesktopWindow
= UserGetDesktopWindow();
1833 List
= IntWinListChildren(DesktopWindow
);
1837 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1838 for (i
= 0; List
[i
]; i
++)
1840 PWND pwnd
= UserGetWindowObject(List
[i
]);
1841 if (!pwnd
) continue;
1843 if ( pwnd
->fnid
== FNID_MENU
||
1844 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1847 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1854 Ret
= co_IntSendMessageNoWait( hWnd
, Msg
, wParam
, lParam
);
1861 IntGetQueueStatus(DWORD Changes
)
1866 pti
= PsGetCurrentThreadWin32Thread();
1868 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1870 /* High word, types of messages currently in the queue.
1871 Low word, types of messages that have been added to the queue and that
1872 are still in the queue
1874 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1876 pti
->pcti
->fsChangeBits
&= ~Changes
;
1882 IntInitMessagePumpHook()
1884 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1888 pti
->pcti
->dwcPumpHook
++;
1895 IntUninitMessagePumpHook()
1897 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1901 if (pti
->pcti
->dwcPumpHook
<= 0)
1905 pti
->pcti
->dwcPumpHook
--;
1911 /** Functions ******************************************************************/
1917 POINT pt
) // Just like the User call.
1921 ULONG wDragWidth
, wDragHeight
;
1922 DECLARE_RETURN(BOOL
);
1924 TRACE("Enter NtUserDragDetect(%p)\n", hWnd
);
1925 UserEnterExclusive();
1927 wDragWidth
= UserGetSystemMetrics(SM_CXDRAG
);
1928 wDragHeight
= UserGetSystemMetrics(SM_CYDRAG
);
1930 rect
.left
= pt
.x
- wDragWidth
;
1931 rect
.right
= pt
.x
+ wDragWidth
;
1933 rect
.top
= pt
.y
- wDragHeight
;
1934 rect
.bottom
= pt
.y
+ wDragHeight
;
1936 co_UserSetCapture(hWnd
);
1940 while (co_IntGetPeekMessage( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, FALSE
) ||
1941 co_IntGetPeekMessage( &msg
, 0, WM_QUEUESYNC
, WM_QUEUESYNC
, PM_REMOVE
, FALSE
) ||
1942 co_IntGetPeekMessage( &msg
, 0, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
, FALSE
) )
1944 if ( msg
.message
== WM_LBUTTONUP
)
1946 co_UserSetCapture(NULL
);
1949 if ( msg
.message
== WM_MOUSEMOVE
)
1952 tmp
.x
= (short)LOWORD(msg
.lParam
);
1953 tmp
.y
= (short)HIWORD(msg
.lParam
);
1954 if( !RECTL_bPointInRect( &rect
, tmp
.x
, tmp
.y
) )
1956 co_UserSetCapture(NULL
);
1960 if ( msg
.message
== WM_KEYDOWN
)
1962 if ( msg
.wParam
== VK_ESCAPE
)
1964 co_UserSetCapture(NULL
);
1968 if ( msg
.message
== WM_QUEUESYNC
)
1970 co_HOOK_CallHooks( WH_CBT
, HCBT_QS
, 0, 0 );
1973 co_IntWaitMessage(NULL
, 0, 0);
1978 TRACE("Leave NtUserDragDetect, ret=%i\n",_ret_
);
1984 NtUserPostMessage(HWND hWnd
,
1991 UserEnterExclusive();
1993 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
2001 NtUserPostThreadMessage(DWORD idThread
,
2008 PTHREADINFO pThread
;
2011 UserEnterExclusive();
2013 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
2015 if ( Status
== STATUS_SUCCESS
)
2017 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
2019 !pThread
->MessageQueue
||
2020 (pThread
->TIF_flags
& TIF_INCLEANUP
))
2022 ObDereferenceObject( peThread
);
2025 ret
= UserPostThreadMessage( pThread
, Msg
, wParam
, lParam
);
2026 ObDereferenceObject( peThread
);
2030 SetLastNtError( Status
);
2038 NtUserWaitMessage(VOID
)
2042 UserEnterExclusive();
2043 TRACE("NtUserWaitMessage Enter\n");
2044 ret
= co_IntWaitMessage(NULL
, 0, 0);
2045 TRACE("NtUserWaitMessage Leave\n");
2052 NtUserGetMessage(PMSG pMsg
,
2060 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
2062 EngSetLastError(ERROR_INVALID_PARAMETER
);
2066 UserEnterExclusive();
2068 RtlZeroMemory(&Msg
, sizeof(MSG
));
2070 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
2078 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2079 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2081 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2083 SetLastNtError(_SEH2_GetExceptionCode());
2090 Ret
= Ret
? (WM_QUIT
!= pMsg
->message
) : FALSE
;
2096 NtUserPeekMessage( PMSG pMsg
,
2105 if ( RemoveMsg
& PM_BADMSGFLAGS
)
2107 EngSetLastError(ERROR_INVALID_FLAGS
);
2111 UserEnterExclusive();
2113 RtlZeroMemory(&Msg
, sizeof(MSG
));
2115 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
2123 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2124 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2126 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2128 SetLastNtError(_SEH2_GetExceptionCode());
2138 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
2145 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
2146 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
2148 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2150 _SEH2_YIELD(return FALSE
);
2154 UserEnterExclusive();
2156 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
2162 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
2169 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
2170 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
2172 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2182 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
2189 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
2190 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
2192 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2194 SetLastNtError(_SEH2_GetExceptionCode());
2195 _SEH2_YIELD(return FALSE
);
2199 UserEnterExclusive();
2201 Res
= IntDispatchMessage(&SafeMsg
);
2208 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
2216 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
2217 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
2219 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2221 SetLastNtError(_SEH2_GetExceptionCode());
2222 _SEH2_YIELD(return FALSE
);
2226 UserEnterExclusive();
2227 pWnd
= UserGetWindowObject(SafeMsg
.hwnd
);
2228 if (pWnd
) // Must have a window!
2230 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
2234 TRACE("No Window for Translate. hwnd 0x%p Msg %u\n", SafeMsg
.hwnd
, SafeMsg
.message
);
2242 LRESULT APIENTRY
ScrollBarWndProc(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
);
2245 NtUserMessageCall( HWND hWnd
,
2249 ULONG_PTR ResultInfo
,
2250 DWORD dwType
, // fnID?
2253 LRESULT lResult
= 0;
2256 USER_REFERENCE_ENTRY Ref
;
2258 UserEnterExclusive();
2262 case FNID_SCROLLBAR
:
2264 lResult
= ScrollBarWndProc(hWnd
, Msg
, wParam
, lParam
);
2269 Window
= UserGetWindowObject(hWnd
);
2272 //ERR("FNID_DESKTOP IN\n");
2273 Ret
= DesktopWindowProc(Window
, Msg
, wParam
, lParam
, &lResult
);
2274 //ERR("FNID_DESKTOP OUT\n");
2279 case FNID_MESSAGEWND
:
2281 Window
= UserGetWindowObject(hWnd
);
2284 Ret
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,&lResult
);
2288 case FNID_DEFWINDOWPROC
:
2289 /* Validate input */
2292 Window
= UserGetWindowObject(hWnd
);
2298 UserRefObjectCo(Window
, &Ref
);
2300 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2303 UserDerefObjectCo(Window
);
2305 case FNID_SENDNOTIFYMESSAGE
:
2306 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2308 case FNID_BROADCASTSYSTEMMESSAGE
:
2310 BROADCASTPARM parm
, *retparam
;
2311 DWORD_PTR RetVal
= 0;
2317 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2318 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2320 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2329 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2330 parm
.recipients
== BSM_ALLCOMPONENTS
)
2332 PLIST_ENTRY DesktopEntry
;
2334 HWND
*List
, hwndDenied
= NULL
;
2336 PWND pwnd
, pwndDesk
;
2340 for (DesktopEntry
= InputWindowStation
->DesktopListHead
.Flink
;
2341 DesktopEntry
!= &InputWindowStation
->DesktopListHead
;
2342 DesktopEntry
= DesktopEntry
->Flink
)
2344 rpdesk
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
2345 pwndDesk
= rpdesk
->pDeskInfo
->spwnd
;
2346 List
= IntWinListChildren(pwndDesk
);
2348 if (parm
.flags
& BSF_QUERY
)
2352 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2354 fuFlags
= SMTO_ABORTIFHUNG
;
2356 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2358 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2362 fuFlags
= SMTO_NORMAL
;
2364 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2372 for (i
= 0; List
[i
]; i
++)
2374 pwnd
= UserGetWindowObject(List
[i
]);
2375 if (!pwnd
) continue;
2377 if ( pwnd
->fnid
== FNID_MENU
||
2378 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2381 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2383 if ( pwnd
->head
.pti
== gptiCurrent
)
2386 co_IntSendMessageTimeout( List
[i
],
2394 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2396 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2399 if (RetVal
== BROADCAST_QUERY_DENY
)
2401 hwndDenied
= List
[i
];
2402 hDesk
= UserHMGetHandle(pwndDesk
);
2406 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2409 retparam
= (PBROADCASTPARM
) ResultInfo
;
2410 retparam
->hDesk
= hDesk
;
2411 retparam
->hWnd
= hwndDenied
;
2413 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2418 if (!Ret
) break; // Have a hit! Let everyone know!
2421 else if (parm
.flags
& BSF_POSTMESSAGE
)
2425 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2427 for (i
= 0; List
[i
]; i
++)
2429 pwnd
= UserGetWindowObject(List
[i
]);
2430 if (!pwnd
) continue;
2432 if ( pwnd
->fnid
== FNID_MENU
||
2433 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2436 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2438 if ( pwnd
->head
.pti
== gptiCurrent
)
2441 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2443 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2451 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2453 for (i
= 0; List
[i
]; i
++)
2455 pwnd
= UserGetWindowObject(List
[i
]);
2456 if (!pwnd
) continue;
2458 if ( pwnd
->fnid
== FNID_MENU
||
2459 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2462 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2464 if ( pwnd
->head
.pti
== gptiCurrent
)
2467 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2469 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2475 else if (parm
.recipients
& BSM_APPLICATIONS
)
2477 HWND
*List
, hwndDenied
= NULL
;
2479 PWND pwnd
, pwndDesk
;
2483 pwndDesk
= UserGetDesktopWindow();
2484 List
= IntWinListChildren(pwndDesk
);
2486 if (parm
.flags
& BSF_QUERY
)
2490 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2492 fuFlags
= SMTO_ABORTIFHUNG
;
2494 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2496 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2500 fuFlags
= SMTO_NORMAL
;
2502 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2510 for (i
= 0; List
[i
]; i
++)
2512 pwnd
= UserGetWindowObject(List
[i
]);
2513 if (!pwnd
) continue;
2515 if ( pwnd
->fnid
== FNID_MENU
||
2516 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2519 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2521 if ( pwnd
->head
.pti
== gptiCurrent
)
2524 co_IntSendMessageTimeout( List
[i
],
2532 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2534 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2537 if (RetVal
== BROADCAST_QUERY_DENY
)
2539 hwndDenied
= List
[i
];
2540 hDesk
= UserHMGetHandle(pwndDesk
);
2544 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2547 retparam
= (PBROADCASTPARM
) ResultInfo
;
2548 retparam
->hDesk
= hDesk
;
2549 retparam
->hWnd
= hwndDenied
;
2551 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2558 else if (parm
.flags
& BSF_POSTMESSAGE
)
2562 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2564 for (i
= 0; List
[i
]; i
++)
2566 pwnd
= UserGetWindowObject(List
[i
]);
2567 if (!pwnd
) continue;
2569 if ( pwnd
->fnid
== FNID_MENU
||
2570 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2573 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2575 if ( pwnd
->head
.pti
== gptiCurrent
)
2578 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2580 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2588 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2590 for (i
= 0; List
[i
]; i
++)
2592 pwnd
= UserGetWindowObject(List
[i
]);
2593 if (!pwnd
) continue;
2595 if ( pwnd
->fnid
== FNID_MENU
||
2596 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2599 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2601 if ( pwnd
->head
.pti
== gptiCurrent
)
2604 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2606 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2613 case FNID_SENDMESSAGECALLBACK
:
2615 CALL_BACK_INFO CallBackInfo
;
2620 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2621 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2623 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2629 if (is_pointer_message(Msg
))
2631 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
2635 if (!(Ret
= co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2636 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
)))
2638 ERR("Callback failure!\n");
2642 case FNID_SENDMESSAGE
:
2644 Ret
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2650 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2651 RtlCopyMemory((PVOID
)ResultInfo
, &Ret
, sizeof(ULONG_PTR
));
2653 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2662 case FNID_SENDMESSAGEFF
:
2663 case FNID_SENDMESSAGEWTOOPTION
:
2665 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2670 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2671 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2673 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2680 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, &dsm
);
2686 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2687 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2689 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2698 // CallNextHook bypass.
2699 case FNID_CALLWNDPROC
:
2700 case FNID_CALLWNDPROCRET
:
2703 PCLIENTINFO ClientInfo
;
2704 PHOOK NextObj
, Hook
;
2706 pti
= GetW32ThreadInfo();
2708 Hook
= pti
->sphkCurrent
;
2712 NextObj
= Hook
->phkNext
;
2713 ClientInfo
= pti
->pClientInfo
;
2716 ClientInfo
->phkCurrent
= NextObj
;
2718 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2724 if (!ClientInfo
|| !NextObj
) break;
2726 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2728 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2733 CWP
.wParam
= wParam
;
2734 CWP
.lParam
= lParam
;
2735 TRACE("WH_CALLWNDPROC: Hook %p NextHook %p\n", Hook
, NextObj
);
2737 lResult
= co_IntCallHookProc( Hook
->HookId
,
2739 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2752 CWPR
.wParam
= wParam
;
2753 CWPR
.lParam
= lParam
;
2754 CWPR
.lResult
= ClientInfo
->dwHookData
;
2756 lResult
= co_IntCallHookProc( Hook
->HookId
,
2758 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2772 case FNID_DEFWINDOWPROC
:
2773 case FNID_CALLWNDPROC
:
2774 case FNID_CALLWNDPROCRET
:
2775 case FNID_SCROLLBAR
:
2781 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2782 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2784 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2800 #define INFINITE 0xFFFFFFFF
2801 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2805 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2806 IN DWORD dwMilliseconds
,
2810 PPROCESSINFO W32Process
;
2814 LARGE_INTEGER Timeout
;
2816 UserEnterExclusive();
2818 Status
= ObReferenceObjectByHandle(hProcess
,
2819 PROCESS_QUERY_INFORMATION
,
2825 if (!NT_SUCCESS(Status
))
2828 SetLastNtError(Status
);
2832 pti
= PsGetCurrentThreadWin32Thread();
2834 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2836 if ( PsGetProcessExitProcessCalled(Process
) ||
2838 pti
->ppi
== W32Process
)
2840 ObDereferenceObject(Process
);
2842 EngSetLastError(ERROR_INVALID_PARAMETER
);
2846 Handles
[0] = Process
;
2847 Handles
[1] = W32Process
->InputIdleEvent
;
2848 Handles
[2] = pti
->pEventQueueServer
; // IntMsqSetWakeMask returns hEventQueueClient
2852 ObDereferenceObject(Process
);
2854 return STATUS_SUCCESS
; /* no event to wait on */
2857 if (dwMilliseconds
!= INFINITE
)
2858 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2860 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2861 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2863 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2864 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2867 TRACE("WFII: ppi %p\n", W32Process
);
2868 TRACE("WFII: waiting for %p\n", Handles
[1] );
2872 Status
= KeWaitForMultipleObjects( 3,
2878 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2880 UserEnterExclusive();
2882 if (!NT_SUCCESS(Status
))
2884 SetLastNtError(Status
);
2885 Status
= WAIT_FAILED
;
2897 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2898 ERR("WFII: WAIT 2\n");
2902 case STATUS_TIMEOUT
:
2903 ERR("WFII: timeout\n");
2908 ERR("WFII: finished\n");
2909 Status
= STATUS_SUCCESS
;
2916 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2918 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
2919 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2921 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
2922 ObDereferenceObject(Process
);