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
);
1333 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1335 ERR("Failed to pack message parameters\n");
1339 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1351 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1353 ERR("Failed to unpack message parameters\n");
1357 // Only happens when calling the client!
1358 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1363 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(ptiSendTo
))
1365 // FIXME: Set window hung and add to a list.
1366 /* FIXME: Set a LastError? */
1370 if (Window
->state
& WNDS_DESTROYED
)
1372 /* FIXME: Last error? */
1373 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1379 Status
= co_MsqSendMessage( ptiSendTo
,
1385 (uFlags
& SMTO_BLOCK
),
1389 while ((STATUS_TIMEOUT
== Status
) &&
1390 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1391 !MsqIsHung(ptiSendTo
)); // FIXME: Set window hung and add to a list.
1393 if (STATUS_TIMEOUT
== Status
)
1397 * Microsoft Windows 2000: If GetLastError returns zero, then the function
1399 * XP+ : If the function fails or times out, the return value is zero.
1400 * To get extended error information, call GetLastError. If GetLastError
1401 * returns ERROR_TIMEOUT, then the function timed out.
1403 EngSetLastError(ERROR_TIMEOUT
);
1406 else if (!NT_SUCCESS(Status
))
1408 SetLastNtError(Status
);
1415 if (Window
) UserDerefObjectCo(Window
);
1420 co_IntSendMessageTimeout( HWND hWnd
,
1426 ULONG_PTR
*uResult
)
1432 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1434 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1437 DesktopWindow
= UserGetDesktopWindow();
1438 if (NULL
== DesktopWindow
)
1440 EngSetLastError(ERROR_INTERNAL_ERROR
);
1444 if (hWnd
!= HWND_TOPMOST
)
1446 /* Send message to the desktop window too! */
1447 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1450 Children
= IntWinListChildren(DesktopWindow
);
1451 if (NULL
== Children
)
1456 for (Child
= Children
; NULL
!= *Child
; Child
++)
1458 if (hWnd
== HWND_TOPMOST
)
1460 DesktopWindow
= UserGetWindowObject(*Child
);
1461 if (DesktopWindow
&& DesktopWindow
->ExStyle
& WS_EX_TOPMOST
)
1463 ERR("HWND_TOPMOST Found\n");
1464 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1469 PWND pwnd
= UserGetWindowObject(*Child
);
1470 if (!pwnd
) continue;
1472 if ( pwnd
->fnid
== FNID_MENU
||
1473 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1476 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1480 ExFreePool(Children
);
1482 return (LRESULT
) TRUE
;
1486 co_IntSendMessageNoWait(HWND hWnd
,
1491 ULONG_PTR Result
= 0;
1492 return co_IntSendMessageWithCallBack( hWnd
,
1501 If you send a message in the range below WM_USER to the asynchronous message
1502 functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its
1503 message parameters cannot include pointers. Otherwise, the operation will fail.
1504 The functions will return before the receiving thread has had a chance to
1505 process the message and the sender will free the memory before it is used.
1508 co_IntSendMessageWithCallBack( HWND hWnd
,
1512 SENDASYNCPROC CompletionCallback
,
1513 ULONG_PTR CompletionCallbackContext
,
1518 PMSGMEMORY MsgMemoryEntry
;
1519 INT lParamBufferSize
;
1520 LPARAM lParamPacked
;
1521 PTHREADINFO Win32Thread
, ptiSendTo
= NULL
;
1522 DECLARE_RETURN(LRESULT
);
1523 USER_REFERENCE_ENTRY Ref
;
1524 PUSER_SENT_MESSAGE Message
;
1525 BOOL DoCallBack
= TRUE
;
1527 if (!(Window
= UserGetWindowObject(hWnd
)))
1529 TRACE("SendMessageWithCallBack: Invalid handle 0x%p!\n",hWnd
);
1533 UserRefObjectCo(Window
, &Ref
);
1535 if (Window
->state
& WNDS_DESTROYED
)
1537 /* FIXME: last error? */
1538 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1542 Win32Thread
= PsGetCurrentThreadWin32Thread();
1544 if (Win32Thread
== NULL
||
1545 Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1550 ptiSendTo
= IntSendTo(Window
, Win32Thread
, Msg
);
1552 if (Msg
& 0x80000000 &&
1555 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
) RETURN( FALSE
);
1557 TRACE("SMWCB: Internal Message!\n");
1558 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1559 if (uResult
) *uResult
= Result
;
1563 /* See if this message type is present in the table */
1564 MsgMemoryEntry
= FindMsgMemory(Msg
);
1565 if (NULL
== MsgMemoryEntry
)
1567 lParamBufferSize
= -1;
1571 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1574 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, !!ptiSendTo
)))
1576 ERR("Failed to pack message parameters\n");
1580 /* If it can be sent now, then send it. */
1583 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1585 UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
);
1586 /* Never send messages to exiting threads */
1590 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1592 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1594 TRACE("SMWCB: Server Side Window Procedure\n");
1595 switch(Window
->fnid
)
1598 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParamPacked
, (LRESULT
*)&Result
);
1600 case FNID_MESSAGEWND
:
1601 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1607 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1619 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1621 if (CompletionCallback
)
1623 co_IntCallSentMessageCallback(CompletionCallback
,
1626 CompletionCallbackContext
,
1633 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1635 ERR("Failed to unpack message parameters\n");
1640 if(!(Message
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
1642 ERR("MsqSendMessage(): Not enough memory to allocate a message");
1646 Message
->Msg
.hwnd
= hWnd
;
1647 Message
->Msg
.message
= Msg
;
1648 Message
->Msg
.wParam
= wParam
;
1649 Message
->Msg
.lParam
= lParamPacked
;
1650 Message
->CompletionEvent
= NULL
;
1651 Message
->Result
= 0;
1652 Message
->lResult
= 0;
1653 Message
->QS_Flags
= 0;
1654 Message
->ptiReceiver
= ptiSendTo
;
1655 Message
->ptiSender
= NULL
; // mjmartin, you are right! This is null.
1656 Message
->ptiCallBackSender
= Win32Thread
;
1657 Message
->DispatchingListEntry
.Flink
= NULL
;
1658 Message
->CompletionCallback
= CompletionCallback
;
1659 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1660 Message
->HookMessage
= MSQ_NORMAL
;
1661 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1662 Message
->QS_Flags
= QS_SENDMESSAGE
;
1664 if (Msg
& 0x80000000) // Higher priority event message!
1665 InsertHeadList(&ptiSendTo
->SentMessagesListHead
, &Message
->ListEntry
);
1667 InsertTailList(&ptiSendTo
->SentMessagesListHead
, &Message
->ListEntry
);
1668 MsqWakeQueue(ptiSendTo
, QS_SENDMESSAGE
, TRUE
);
1673 if (Window
) UserDerefObjectCo(Window
);
1679 This HACK function posts a message if the destination's message queue belongs to
1680 another thread, otherwise it sends the message. It does not support broadcast
1684 co_IntPostOrSendMessage( HWND hWnd
,
1693 if ( hWnd
== HWND_BROADCAST
)
1698 if(!(Window
= UserGetWindowObject(hWnd
)))
1700 TRACE("PostOrSendMessage: Invalid handle 0x%p!\n",hWnd
);
1704 pti
= PsGetCurrentThreadWin32Thread();
1706 if ( IntSendTo(Window
, pti
, Msg
) &&
1707 FindMsgMemory(Msg
) == 0 )
1709 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1713 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1719 return (LRESULT
)Result
;
1722 static LRESULT FASTCALL
1723 co_IntDoSendMessage( HWND hWnd
,
1729 LRESULT Result
= TRUE
;
1732 MSG UserModeMsg
, KernelModeMsg
;
1733 PMSGMEMORY MsgMemoryEntry
;
1734 PTHREADINFO ptiSendTo
;
1736 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1738 Window
= UserGetWindowObject(hWnd
);
1745 /* Check for an exiting window. */
1746 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1748 ERR("co_IntDoSendMessage Window Exiting!\n");
1751 /* See if the current thread can handle this message */
1752 ptiSendTo
= IntSendTo(Window
, gptiCurrent
, Msg
);
1754 // If broadcasting or sending to another thread, save the users data.
1755 if (!Window
|| ptiSendTo
)
1757 UserModeMsg
.hwnd
= hWnd
;
1758 UserModeMsg
.message
= Msg
;
1759 UserModeMsg
.wParam
= wParam
;
1760 UserModeMsg
.lParam
= lParam
;
1761 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1762 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1763 if (!NT_SUCCESS(Status
))
1765 EngSetLastError(ERROR_INVALID_PARAMETER
);
1766 return (dsm
? 0 : -1);
1771 KernelModeMsg
.hwnd
= hWnd
;
1772 KernelModeMsg
.message
= Msg
;
1773 KernelModeMsg
.wParam
= wParam
;
1774 KernelModeMsg
.lParam
= lParam
;
1779 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1780 KernelModeMsg
.message
,
1781 KernelModeMsg
.wParam
,
1782 KernelModeMsg
.lParam
);
1786 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1787 KernelModeMsg
.message
,
1788 KernelModeMsg
.wParam
,
1789 KernelModeMsg
.lParam
,
1795 if (!Window
|| ptiSendTo
)
1797 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1798 if (!NT_SUCCESS(Status
))
1800 EngSetLastError(ERROR_INVALID_PARAMETER
);
1801 return(dsm
? 0 : -1);
1805 return (LRESULT
)Result
;
1809 UserSendNotifyMessage( HWND hWnd
,
1816 if (is_pointer_message(Msg
))
1818 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1822 // Basicly the same as IntPostOrSendMessage
1823 if (hWnd
== HWND_BROADCAST
) // Handle Broadcast
1829 DesktopWindow
= UserGetDesktopWindow();
1830 List
= IntWinListChildren(DesktopWindow
);
1834 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1835 for (i
= 0; List
[i
]; i
++)
1837 PWND pwnd
= UserGetWindowObject(List
[i
]);
1838 if (!pwnd
) continue;
1840 if ( pwnd
->fnid
== FNID_MENU
||
1841 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1844 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1851 Ret
= co_IntSendMessageNoWait( hWnd
, Msg
, wParam
, lParam
);
1858 IntGetQueueStatus(DWORD Changes
)
1863 pti
= PsGetCurrentThreadWin32Thread();
1865 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1867 /* High word, types of messages currently in the queue.
1868 Low word, types of messages that have been added to the queue and that
1869 are still in the queue
1871 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1873 pti
->pcti
->fsChangeBits
&= ~Changes
;
1879 IntInitMessagePumpHook()
1881 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1885 pti
->pcti
->dwcPumpHook
++;
1892 IntUninitMessagePumpHook()
1894 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1898 if (pti
->pcti
->dwcPumpHook
<= 0)
1902 pti
->pcti
->dwcPumpHook
--;
1908 /** Functions ******************************************************************/
1914 POINT pt
) // Just like the User call.
1918 ULONG wDragWidth
, wDragHeight
;
1919 DECLARE_RETURN(BOOL
);
1921 TRACE("Enter NtUserDragDetect(%p)\n", hWnd
);
1922 UserEnterExclusive();
1924 wDragWidth
= UserGetSystemMetrics(SM_CXDRAG
);
1925 wDragHeight
= UserGetSystemMetrics(SM_CYDRAG
);
1927 rect
.left
= pt
.x
- wDragWidth
;
1928 rect
.right
= pt
.x
+ wDragWidth
;
1930 rect
.top
= pt
.y
- wDragHeight
;
1931 rect
.bottom
= pt
.y
+ wDragHeight
;
1933 co_UserSetCapture(hWnd
);
1937 while (co_IntGetPeekMessage( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, FALSE
) ||
1938 co_IntGetPeekMessage( &msg
, 0, WM_QUEUESYNC
, WM_QUEUESYNC
, PM_REMOVE
, FALSE
) ||
1939 co_IntGetPeekMessage( &msg
, 0, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
, FALSE
) )
1941 if ( msg
.message
== WM_LBUTTONUP
)
1943 co_UserSetCapture(NULL
);
1946 if ( msg
.message
== WM_MOUSEMOVE
)
1949 tmp
.x
= (short)LOWORD(msg
.lParam
);
1950 tmp
.y
= (short)HIWORD(msg
.lParam
);
1951 if( !RECTL_bPointInRect( &rect
, tmp
.x
, tmp
.y
) )
1953 co_UserSetCapture(NULL
);
1957 if ( msg
.message
== WM_KEYDOWN
)
1959 if ( msg
.wParam
== VK_ESCAPE
)
1961 co_UserSetCapture(NULL
);
1965 if ( msg
.message
== WM_QUEUESYNC
)
1967 co_HOOK_CallHooks( WH_CBT
, HCBT_QS
, 0, 0 );
1970 co_IntWaitMessage(NULL
, 0, 0);
1975 TRACE("Leave NtUserDragDetect, ret=%i\n",_ret_
);
1981 NtUserPostMessage(HWND hWnd
,
1988 UserEnterExclusive();
1990 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1998 NtUserPostThreadMessage(DWORD idThread
,
2005 PTHREADINFO pThread
;
2008 UserEnterExclusive();
2010 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
2012 if ( Status
== STATUS_SUCCESS
)
2014 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
2016 !pThread
->MessageQueue
||
2017 (pThread
->TIF_flags
& TIF_INCLEANUP
))
2019 ObDereferenceObject( peThread
);
2022 ret
= UserPostThreadMessage( pThread
, Msg
, wParam
, lParam
);
2023 ObDereferenceObject( peThread
);
2027 SetLastNtError( Status
);
2035 NtUserWaitMessage(VOID
)
2039 UserEnterExclusive();
2040 TRACE("NtUserWaitMessage Enter\n");
2041 ret
= co_IntWaitMessage(NULL
, 0, 0);
2042 TRACE("NtUserWaitMessage Leave\n");
2049 NtUserGetMessage(PMSG pMsg
,
2057 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
2059 EngSetLastError(ERROR_INVALID_PARAMETER
);
2063 UserEnterExclusive();
2065 RtlZeroMemory(&Msg
, sizeof(MSG
));
2067 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
2075 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2076 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2078 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2080 SetLastNtError(_SEH2_GetExceptionCode());
2087 Ret
= Ret
? (WM_QUIT
!= pMsg
->message
) : FALSE
;
2093 NtUserPeekMessage( PMSG pMsg
,
2102 if ( RemoveMsg
& PM_BADMSGFLAGS
)
2104 EngSetLastError(ERROR_INVALID_FLAGS
);
2108 UserEnterExclusive();
2110 RtlZeroMemory(&Msg
, sizeof(MSG
));
2112 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
2120 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2121 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2123 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2125 SetLastNtError(_SEH2_GetExceptionCode());
2135 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
2142 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
2143 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
2145 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2147 _SEH2_YIELD(return FALSE
);
2151 UserEnterExclusive();
2153 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
2159 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
2166 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
2167 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
2169 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2179 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
2186 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
2187 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
2189 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2191 SetLastNtError(_SEH2_GetExceptionCode());
2192 _SEH2_YIELD(return FALSE
);
2196 UserEnterExclusive();
2198 Res
= IntDispatchMessage(&SafeMsg
);
2205 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
2213 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
2214 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
2216 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2218 SetLastNtError(_SEH2_GetExceptionCode());
2219 _SEH2_YIELD(return FALSE
);
2223 UserEnterExclusive();
2224 pWnd
= UserGetWindowObject(SafeMsg
.hwnd
);
2225 if (pWnd
) // Must have a window!
2227 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
2231 TRACE("No Window for Translate. hwnd 0x%p Msg %u\n", SafeMsg
.hwnd
, SafeMsg
.message
);
2239 LRESULT APIENTRY
ScrollBarWndProc(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
);
2242 NtUserMessageCall( HWND hWnd
,
2246 ULONG_PTR ResultInfo
,
2247 DWORD dwType
, // fnID?
2250 LRESULT lResult
= 0;
2253 USER_REFERENCE_ENTRY Ref
;
2255 UserEnterExclusive();
2259 case FNID_SCROLLBAR
:
2261 lResult
= ScrollBarWndProc(hWnd
, Msg
, wParam
, lParam
);
2266 Window
= UserGetWindowObject(hWnd
);
2269 //ERR("FNID_DESKTOP IN\n");
2270 Ret
= DesktopWindowProc(Window
, Msg
, wParam
, lParam
, &lResult
);
2271 //ERR("FNID_DESKTOP OUT\n");
2276 case FNID_MESSAGEWND
:
2278 Window
= UserGetWindowObject(hWnd
);
2281 Ret
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,&lResult
);
2285 case FNID_DEFWINDOWPROC
:
2286 /* Validate input */
2289 Window
= UserGetWindowObject(hWnd
);
2295 UserRefObjectCo(Window
, &Ref
);
2297 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2300 UserDerefObjectCo(Window
);
2302 case FNID_SENDNOTIFYMESSAGE
:
2303 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2305 case FNID_BROADCASTSYSTEMMESSAGE
:
2307 BROADCASTPARM parm
, *retparam
;
2308 DWORD_PTR RetVal
= 0;
2314 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2315 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2317 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2326 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2327 parm
.recipients
== BSM_ALLCOMPONENTS
)
2329 PLIST_ENTRY DesktopEntry
;
2331 HWND
*List
, hwndDenied
= NULL
;
2333 PWND pwnd
, pwndDesk
;
2337 for (DesktopEntry
= InputWindowStation
->DesktopListHead
.Flink
;
2338 DesktopEntry
!= &InputWindowStation
->DesktopListHead
;
2339 DesktopEntry
= DesktopEntry
->Flink
)
2341 rpdesk
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
2342 pwndDesk
= rpdesk
->pDeskInfo
->spwnd
;
2343 List
= IntWinListChildren(pwndDesk
);
2345 if (parm
.flags
& BSF_QUERY
)
2349 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2351 fuFlags
= SMTO_ABORTIFHUNG
;
2353 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2355 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2359 fuFlags
= SMTO_NORMAL
;
2361 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2369 for (i
= 0; List
[i
]; i
++)
2371 pwnd
= UserGetWindowObject(List
[i
]);
2372 if (!pwnd
) continue;
2374 if ( pwnd
->fnid
== FNID_MENU
||
2375 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2378 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2380 if ( pwnd
->head
.pti
== gptiCurrent
)
2383 co_IntSendMessageTimeout( List
[i
],
2391 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2393 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2396 if (RetVal
== BROADCAST_QUERY_DENY
)
2398 hwndDenied
= List
[i
];
2399 hDesk
= UserHMGetHandle(pwndDesk
);
2403 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2406 retparam
= (PBROADCASTPARM
) ResultInfo
;
2407 retparam
->hDesk
= hDesk
;
2408 retparam
->hWnd
= hwndDenied
;
2410 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2415 if (!Ret
) break; // Have a hit! Let everyone know!
2418 else if (parm
.flags
& BSF_POSTMESSAGE
)
2422 UserPostMessage(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
== gptiCurrent
)
2438 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2440 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2448 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2450 for (i
= 0; List
[i
]; i
++)
2452 pwnd
= UserGetWindowObject(List
[i
]);
2453 if (!pwnd
) continue;
2455 if ( pwnd
->fnid
== FNID_MENU
||
2456 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2459 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2461 if ( pwnd
->head
.pti
== gptiCurrent
)
2464 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2466 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2472 else if (parm
.recipients
& BSM_APPLICATIONS
)
2474 HWND
*List
, hwndDenied
= NULL
;
2476 PWND pwnd
, pwndDesk
;
2480 pwndDesk
= UserGetDesktopWindow();
2481 List
= IntWinListChildren(pwndDesk
);
2483 if (parm
.flags
& BSF_QUERY
)
2487 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2489 fuFlags
= SMTO_ABORTIFHUNG
;
2491 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2493 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2497 fuFlags
= SMTO_NORMAL
;
2499 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2507 for (i
= 0; List
[i
]; i
++)
2509 pwnd
= UserGetWindowObject(List
[i
]);
2510 if (!pwnd
) continue;
2512 if ( pwnd
->fnid
== FNID_MENU
||
2513 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2516 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2518 if ( pwnd
->head
.pti
== gptiCurrent
)
2521 co_IntSendMessageTimeout( List
[i
],
2529 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2531 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2534 if (RetVal
== BROADCAST_QUERY_DENY
)
2536 hwndDenied
= List
[i
];
2537 hDesk
= UserHMGetHandle(pwndDesk
);
2541 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2544 retparam
= (PBROADCASTPARM
) ResultInfo
;
2545 retparam
->hDesk
= hDesk
;
2546 retparam
->hWnd
= hwndDenied
;
2548 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2555 else if (parm
.flags
& BSF_POSTMESSAGE
)
2559 UserPostMessage(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
== gptiCurrent
)
2575 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2577 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2585 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2587 for (i
= 0; List
[i
]; i
++)
2589 pwnd
= UserGetWindowObject(List
[i
]);
2590 if (!pwnd
) continue;
2592 if ( pwnd
->fnid
== FNID_MENU
||
2593 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2596 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2598 if ( pwnd
->head
.pti
== gptiCurrent
)
2601 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2603 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2610 case FNID_SENDMESSAGECALLBACK
:
2612 CALL_BACK_INFO CallBackInfo
;
2617 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2618 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2620 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2626 if (is_pointer_message(Msg
))
2628 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
2632 if (!(Ret
= co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2633 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
)))
2635 ERR("Callback failure!\n");
2639 case FNID_SENDMESSAGE
:
2641 Ret
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2647 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2648 RtlCopyMemory((PVOID
)ResultInfo
, &Ret
, sizeof(ULONG_PTR
));
2650 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2659 case FNID_SENDMESSAGEFF
:
2660 case FNID_SENDMESSAGEWTOOPTION
:
2662 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2667 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2668 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2670 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2677 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, &dsm
);
2683 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2684 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2686 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2695 // CallNextHook bypass.
2696 case FNID_CALLWNDPROC
:
2697 case FNID_CALLWNDPROCRET
:
2700 PCLIENTINFO ClientInfo
;
2701 PHOOK NextObj
, Hook
;
2703 pti
= GetW32ThreadInfo();
2705 Hook
= pti
->sphkCurrent
;
2709 NextObj
= Hook
->phkNext
;
2710 ClientInfo
= pti
->pClientInfo
;
2713 ClientInfo
->phkCurrent
= NextObj
;
2715 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2721 if (!ClientInfo
|| !NextObj
) break;
2723 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2725 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2730 CWP
.wParam
= wParam
;
2731 CWP
.lParam
= lParam
;
2732 TRACE("WH_CALLWNDPROC: Hook %p NextHook %p\n", Hook
, NextObj
);
2734 lResult
= co_IntCallHookProc( Hook
->HookId
,
2736 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2749 CWPR
.wParam
= wParam
;
2750 CWPR
.lParam
= lParam
;
2751 CWPR
.lResult
= ClientInfo
->dwHookData
;
2753 lResult
= co_IntCallHookProc( Hook
->HookId
,
2755 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2769 case FNID_DEFWINDOWPROC
:
2770 case FNID_CALLWNDPROC
:
2771 case FNID_CALLWNDPROCRET
:
2772 case FNID_SCROLLBAR
:
2778 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2779 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2781 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2797 #define INFINITE 0xFFFFFFFF
2798 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2802 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2803 IN DWORD dwMilliseconds
,
2807 PPROCESSINFO W32Process
;
2811 LARGE_INTEGER Timeout
;
2813 UserEnterExclusive();
2815 Status
= ObReferenceObjectByHandle(hProcess
,
2816 PROCESS_QUERY_INFORMATION
,
2822 if (!NT_SUCCESS(Status
))
2825 SetLastNtError(Status
);
2829 pti
= PsGetCurrentThreadWin32Thread();
2831 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2833 if ( PsGetProcessExitProcessCalled(Process
) ||
2835 pti
->ppi
== W32Process
)
2837 ObDereferenceObject(Process
);
2839 EngSetLastError(ERROR_INVALID_PARAMETER
);
2843 Handles
[0] = Process
;
2844 Handles
[1] = W32Process
->InputIdleEvent
;
2845 Handles
[2] = pti
->pEventQueueServer
; // IntMsqSetWakeMask returns hEventQueueClient
2849 ObDereferenceObject(Process
);
2851 return STATUS_SUCCESS
; /* no event to wait on */
2854 if (dwMilliseconds
!= INFINITE
)
2855 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2857 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2858 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2860 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2861 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2864 TRACE("WFII: ppi %p\n", W32Process
);
2865 TRACE("WFII: waiting for %p\n", Handles
[1] );
2869 Status
= KeWaitForMultipleObjects( 3,
2875 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2877 UserEnterExclusive();
2879 if (!NT_SUCCESS(Status
))
2881 SetLastNtError(Status
);
2882 Status
= WAIT_FAILED
;
2894 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2895 ERR("WFII: WAIT 2\n");
2899 case STATUS_TIMEOUT
:
2900 ERR("WFII: timeout\n");
2905 ERR("WFII: finished\n");
2906 Status
= STATUS_SUCCESS
;
2913 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2915 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
2916 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2918 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
2919 ObDereferenceObject(Process
);