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_READWRITE
},
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 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 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
)
1103 if ( Window
->head
.pti
->MessageQueue
== ptiCur
->MessageQueue
)
1108 return Window
->head
.pti
;
1112 UserPostMessage( HWND Wnd
,
1118 MSG Message
, KernelModeMsg
;
1119 LARGE_INTEGER LargeTickCount
;
1122 Message
.message
= Msg
;
1123 Message
.wParam
= wParam
;
1124 Message
.lParam
= lParam
;
1125 Message
.pt
= gpsi
->ptCursor
;
1126 KeQueryTickCount(&LargeTickCount
);
1127 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1129 if (is_pointer_message(Message
.message
))
1131 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1135 if( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1138 PMSGMEMORY MsgMemoryEntry
;
1140 MsgMemoryEntry
= FindMsgMemory(Message
.message
);
1142 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &Message
, MsgMemoryEntry
);
1143 if (! NT_SUCCESS(Status
))
1145 EngSetLastError(ERROR_INVALID_PARAMETER
);
1148 co_IntSendMessageNoWait(KernelModeMsg
.hwnd
,
1149 KernelModeMsg
.message
,
1150 KernelModeMsg
.wParam
,
1151 KernelModeMsg
.lParam
);
1153 if (MsgMemoryEntry
&& KernelModeMsg
.lParam
)
1154 ExFreePool((PVOID
) KernelModeMsg
.lParam
);
1161 pti
= PsGetCurrentThreadWin32Thread();
1162 return UserPostThreadMessage( pti
,
1167 if (Wnd
== HWND_BROADCAST
)
1173 DesktopWindow
= UserGetDesktopWindow();
1174 List
= IntWinListChildren(DesktopWindow
);
1178 UserPostMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1179 for (i
= 0; List
[i
]; i
++)
1181 PWND pwnd
= UserGetWindowObject(List
[i
]);
1182 if (!pwnd
) continue;
1184 if ( pwnd
->fnid
== FNID_MENU
|| // Also need pwnd->pcls->atomClassName == gaOleMainThreadWndClass
1185 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1188 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1190 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1197 Window
= UserGetWindowObject(Wnd
);
1200 ERR("UserPostMessage: Invalid handle 0x%p!\n",Wnd
);
1204 pti
= Window
->head
.pti
;
1205 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1207 ERR("Attempted to post message to window %p when the thread is in cleanup!\n", Wnd
);
1211 if ( Window
->state
& WNDS_DESTROYED
)
1213 ERR("Attempted to post message to window %p that is being destroyed!\n", Wnd
);
1214 /* FIXME: Last error code? */
1220 MsqPostQuitMessage(pti
, wParam
);
1224 MsqPostMessage(pti
, &Message
, FALSE
, QS_POSTMESSAGE
, 0);
1231 co_IntSendMessage( HWND hWnd
,
1236 ULONG_PTR Result
= 0;
1237 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1239 return (LRESULT
)Result
;
1244 static LRESULT FASTCALL
1245 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1251 ULONG_PTR
*uResult
)
1255 PMSGMEMORY MsgMemoryEntry
;
1256 INT lParamBufferSize
;
1257 LPARAM lParamPacked
;
1258 PTHREADINFO Win32Thread
, ptiSendTo
= NULL
;
1259 ULONG_PTR Hi
, Lo
, Result
= 0;
1260 DECLARE_RETURN(LRESULT
);
1261 USER_REFERENCE_ENTRY Ref
;
1262 BOOL DoCallBack
= TRUE
;
1264 if (!(Window
= UserGetWindowObject(hWnd
)))
1266 TRACE("SendMessageTimeoutSingle: Invalid handle 0x%p!\n",hWnd
);
1270 UserRefObjectCo(Window
, &Ref
);
1272 Win32Thread
= PsGetCurrentThreadWin32Thread();
1274 ptiSendTo
= IntSendTo(Window
, Win32Thread
, Msg
);
1278 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1280 /* Never send messages to exiting threads */
1284 if (Msg
& 0x80000000)
1286 TRACE("SMTS: Internal Message!\n");
1287 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1288 if (uResult
) *uResult
= Result
;
1292 // Only happens when calling the client!
1293 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1295 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1297 TRACE("SMT: Server Side Window Procedure\n");
1298 IoGetStackLimits(&Lo
, &Hi
);
1299 // Handle it here. Safeguard against excessive recursions.
1300 if (((ULONG_PTR
)&uResult
- Lo
) < 4096 )
1302 ERR("Server Callback Exceeded Stack!\n");
1305 /* Return after server side call, IntCallWndProcRet will not be called. */
1306 switch(Window
->fnid
)
1309 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1311 case FNID_MESSAGEWND
:
1312 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1317 if (uResult
) *uResult
= Result
;
1321 /* See if this message type is present in the table */
1322 MsgMemoryEntry
= FindMsgMemory(Msg
);
1323 if (NULL
== MsgMemoryEntry
)
1325 lParamBufferSize
= -1;
1329 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1332 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1334 ERR("Failed to pack message parameters\n");
1338 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1350 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1352 ERR("Failed to unpack message parameters\n");
1356 // Only happens when calling the client!
1357 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1362 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(ptiSendTo
/*Window->head.pti*/))
1364 // FIXME: Set window hung and add to a list.
1365 /* FIXME: Set a LastError? */
1369 if (Window
->state
& WNDS_DESTROYED
)
1371 /* FIXME: Last error? */
1372 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1378 Status
= co_MsqSendMessage( ptiSendTo
, //Window->head.pti,
1384 (uFlags
& SMTO_BLOCK
),
1388 while ((STATUS_TIMEOUT
== Status
) &&
1389 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1390 !MsqIsHung(ptiSendTo
/*Window->head.pti*/)); // FIXME: Set window hung and add to a list.
1392 if (STATUS_TIMEOUT
== Status
)
1396 * Microsoft Windows 2000: If GetLastError returns zero, then the function
1398 * XP+ : If the function fails or times out, the return value is zero.
1399 * To get extended error information, call GetLastError. If GetLastError
1400 * returns ERROR_TIMEOUT, then the function timed out.
1402 EngSetLastError(ERROR_TIMEOUT
);
1405 else if (!NT_SUCCESS(Status
))
1407 SetLastNtError(Status
);
1414 if (Window
) UserDerefObjectCo(Window
);
1419 co_IntSendMessageTimeout( HWND hWnd
,
1425 ULONG_PTR
*uResult
)
1431 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1433 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1436 DesktopWindow
= UserGetDesktopWindow();
1437 if (NULL
== DesktopWindow
)
1439 EngSetLastError(ERROR_INTERNAL_ERROR
);
1443 if (hWnd
!= HWND_TOPMOST
)
1445 /* Send message to the desktop window too! */
1446 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1449 Children
= IntWinListChildren(DesktopWindow
);
1450 if (NULL
== Children
)
1455 for (Child
= Children
; NULL
!= *Child
; Child
++)
1457 if (hWnd
== HWND_TOPMOST
)
1459 DesktopWindow
= UserGetWindowObject(*Child
);
1460 if (DesktopWindow
&& DesktopWindow
->ExStyle
& WS_EX_TOPMOST
)
1462 ERR("HWND_TOPMOST Found\n");
1463 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1468 PWND pwnd
= UserGetWindowObject(*Child
);
1469 if (!pwnd
) continue;
1471 if ( pwnd
->fnid
== FNID_MENU
||
1472 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1475 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1479 ExFreePool(Children
);
1481 return (LRESULT
) TRUE
;
1485 co_IntSendMessageNoWait(HWND hWnd
,
1490 ULONG_PTR Result
= 0;
1491 return co_IntSendMessageWithCallBack( hWnd
,
1500 If you send a message in the range below WM_USER to the asynchronous message
1501 functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its
1502 message parameters cannot include pointers. Otherwise, the operation will fail.
1503 The functions will return before the receiving thread has had a chance to
1504 process the message and the sender will free the memory before it is used.
1507 co_IntSendMessageWithCallBack( HWND hWnd
,
1511 SENDASYNCPROC CompletionCallback
,
1512 ULONG_PTR CompletionCallbackContext
,
1517 PMSGMEMORY MsgMemoryEntry
;
1518 INT lParamBufferSize
;
1519 LPARAM lParamPacked
;
1520 PTHREADINFO Win32Thread
, ptiSendTo
= NULL
;
1521 DECLARE_RETURN(LRESULT
);
1522 USER_REFERENCE_ENTRY Ref
;
1523 PUSER_SENT_MESSAGE Message
;
1524 BOOL DoCallBack
= TRUE
;
1526 if (!(Window
= UserGetWindowObject(hWnd
)))
1528 TRACE("SendMessageWithCallBack: Invalid handle 0x%p!\n",hWnd
);
1532 UserRefObjectCo(Window
, &Ref
);
1534 if (Window
->state
& WNDS_DESTROYED
)
1536 /* FIXME: last error? */
1537 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1541 Win32Thread
= PsGetCurrentThreadWin32Thread();
1543 if (Win32Thread
== NULL
||
1544 Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1549 ptiSendTo
= IntSendTo(Window
, Win32Thread
, Msg
);
1551 if (Msg
& 0x80000000 &&
1554 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
) RETURN( FALSE
);
1556 TRACE("SMWCB: Internal Message!\n");
1557 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1558 if (uResult
) *uResult
= Result
;
1562 /* See if this message type is present in the table */
1563 MsgMemoryEntry
= FindMsgMemory(Msg
);
1564 if (NULL
== MsgMemoryEntry
)
1566 lParamBufferSize
= -1;
1570 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1573 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, !!ptiSendTo
)))
1575 ERR("Failed to pack message parameters\n");
1579 /* If it can be sent now, then send it. */
1582 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1584 UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
);
1585 /* Never send messages to exiting threads */
1589 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1591 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1593 TRACE("SMWCB: Server Side Window Procedure\n");
1594 switch(Window
->fnid
)
1597 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParamPacked
, (LRESULT
*)&Result
);
1599 case FNID_MESSAGEWND
:
1600 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1606 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1618 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1620 if (CompletionCallback
)
1622 co_IntCallSentMessageCallback(CompletionCallback
,
1625 CompletionCallbackContext
,
1632 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1634 ERR("Failed to unpack message parameters\n");
1639 if(!(Message
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
1641 ERR("MsqSendMessage(): Not enough memory to allocate a message");
1645 Message
->Msg
.hwnd
= hWnd
;
1646 Message
->Msg
.message
= Msg
;
1647 Message
->Msg
.wParam
= wParam
;
1648 Message
->Msg
.lParam
= lParamPacked
;
1649 Message
->CompletionEvent
= NULL
;
1650 Message
->Result
= 0;
1651 Message
->lResult
= 0;
1652 Message
->QS_Flags
= 0;
1653 Message
->ptiReceiver
= ptiSendTo
; //Window->head.pti;
1654 Message
->ptiSender
= NULL
; // mjmartin, you are right! This is null.
1655 Message
->ptiCallBackSender
= Win32Thread
;
1656 Message
->DispatchingListEntry
.Flink
= NULL
;
1657 Message
->CompletionCallback
= CompletionCallback
;
1658 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1659 Message
->HookMessage
= MSQ_NORMAL
;
1660 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1661 Message
->QS_Flags
= QS_SENDMESSAGE
;
1663 if (Msg
& 0x80000000) // Higher priority event message!
1664 InsertHeadList(&ptiSendTo
->SentMessagesListHead
/*&Window->head.pti->SentMessagesListHead*/, &Message
->ListEntry
);
1666 InsertTailList(&ptiSendTo
->SentMessagesListHead
/*&Window->head.pti->SentMessagesListHead*/, &Message
->ListEntry
);
1667 MsqWakeQueue(ptiSendTo
/*Window->head.pti*/, QS_SENDMESSAGE
, TRUE
);
1672 if (Window
) UserDerefObjectCo(Window
);
1678 This HACK function posts a message if the destination's message queue belongs to
1679 another thread, otherwise it sends the message. It does not support broadcast
1683 co_IntPostOrSendMessage( HWND hWnd
,
1692 if ( hWnd
== HWND_BROADCAST
)
1697 if(!(Window
= UserGetWindowObject(hWnd
)))
1699 TRACE("PostOrSendMessage: Invalid handle 0x%p!\n",hWnd
);
1703 pti
= PsGetCurrentThreadWin32Thread();
1705 if ( IntSendTo(Window
, pti
, Msg
) &&
1706 FindMsgMemory(Msg
) == 0 )
1708 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1712 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1718 return (LRESULT
)Result
;
1722 co_IntDoSendMessage( HWND hWnd
,
1729 LRESULT Result
= TRUE
;
1734 PMSGMEMORY MsgMemoryEntry
;
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 the message */
1752 //pti = PsGetCurrentThreadWin32Thread();
1754 UserModeMsg
.hwnd
= hWnd
;
1755 UserModeMsg
.message
= Msg
;
1756 UserModeMsg
.wParam
= wParam
;
1757 UserModeMsg
.lParam
= lParam
;
1758 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1760 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1761 if (! NT_SUCCESS(Status
))
1763 EngSetLastError(ERROR_INVALID_PARAMETER
);
1764 return (dsm
? 0 : -1);
1769 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1770 KernelModeMsg
.message
,
1771 KernelModeMsg
.wParam
,
1772 KernelModeMsg
.lParam
);
1776 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1777 KernelModeMsg
.message
,
1778 KernelModeMsg
.wParam
,
1779 KernelModeMsg
.lParam
,
1785 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1786 if (! NT_SUCCESS(Status
))
1788 EngSetLastError(ERROR_INVALID_PARAMETER
);
1789 return(dsm
? 0 : -1);
1792 return (LRESULT
)Result
;
1796 UserSendNotifyMessage( HWND hWnd
,
1803 if (is_pointer_message(Msg
))
1805 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1809 // Basicly the same as IntPostOrSendMessage
1810 if (hWnd
== HWND_BROADCAST
) // Handle Broadcast
1816 DesktopWindow
= UserGetDesktopWindow();
1817 List
= IntWinListChildren(DesktopWindow
);
1821 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1822 for (i
= 0; List
[i
]; i
++)
1824 PWND pwnd
= UserGetWindowObject(List
[i
]);
1825 if (!pwnd
) continue;
1827 if ( pwnd
->fnid
== FNID_MENU
||
1828 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1831 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1838 Ret
= co_IntSendMessageNoWait( hWnd
, Msg
, wParam
, lParam
);
1845 IntGetQueueStatus(DWORD Changes
)
1850 pti
= PsGetCurrentThreadWin32Thread();
1852 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1854 /* High word, types of messages currently in the queue.
1855 Low word, types of messages that have been added to the queue and that
1856 are still in the queue
1858 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1860 pti
->pcti
->fsChangeBits
&= ~Changes
;
1866 IntInitMessagePumpHook()
1868 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1872 pti
->pcti
->dwcPumpHook
++;
1879 IntUninitMessagePumpHook()
1881 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1885 if (pti
->pcti
->dwcPumpHook
<= 0)
1889 pti
->pcti
->dwcPumpHook
--;
1895 /** Functions ******************************************************************/
1901 POINT pt
) // Just like the User call.
1905 ULONG wDragWidth
, wDragHeight
;
1906 DECLARE_RETURN(BOOL
);
1908 TRACE("Enter NtUserDragDetect(%p)\n", hWnd
);
1909 UserEnterExclusive();
1911 wDragWidth
= UserGetSystemMetrics(SM_CXDRAG
);
1912 wDragHeight
= UserGetSystemMetrics(SM_CYDRAG
);
1914 rect
.left
= pt
.x
- wDragWidth
;
1915 rect
.right
= pt
.x
+ wDragWidth
;
1917 rect
.top
= pt
.y
- wDragHeight
;
1918 rect
.bottom
= pt
.y
+ wDragHeight
;
1920 co_UserSetCapture(hWnd
);
1924 while (co_IntGetPeekMessage( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, FALSE
) ||
1925 co_IntGetPeekMessage( &msg
, 0, WM_QUEUESYNC
, WM_QUEUESYNC
, PM_REMOVE
, FALSE
) ||
1926 co_IntGetPeekMessage( &msg
, 0, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
, FALSE
) )
1928 if ( msg
.message
== WM_LBUTTONUP
)
1930 co_UserSetCapture(NULL
);
1933 if ( msg
.message
== WM_MOUSEMOVE
)
1936 tmp
.x
= (short)LOWORD(msg
.lParam
);
1937 tmp
.y
= (short)HIWORD(msg
.lParam
);
1938 if( !RECTL_bPointInRect( &rect
, tmp
.x
, tmp
.y
) )
1940 co_UserSetCapture(NULL
);
1944 if ( msg
.message
== WM_KEYDOWN
)
1946 if ( msg
.wParam
== VK_ESCAPE
)
1948 co_UserSetCapture(NULL
);
1952 if ( msg
.message
== WM_QUEUESYNC
)
1954 co_HOOK_CallHooks( WH_CBT
, HCBT_QS
, 0, 0 );
1957 co_IntWaitMessage(NULL
, 0, 0);
1962 TRACE("Leave NtUserDragDetect, ret=%i\n",_ret_
);
1968 NtUserPostMessage(HWND hWnd
,
1975 UserEnterExclusive();
1977 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1985 NtUserPostThreadMessage(DWORD idThread
,
1992 PTHREADINFO pThread
;
1995 UserEnterExclusive();
1997 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
1999 if ( Status
== STATUS_SUCCESS
)
2001 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
2003 !pThread
->MessageQueue
||
2004 (pThread
->TIF_flags
& TIF_INCLEANUP
))
2006 ObDereferenceObject( peThread
);
2009 ret
= UserPostThreadMessage( pThread
, Msg
, wParam
, lParam
);
2010 ObDereferenceObject( peThread
);
2014 SetLastNtError( Status
);
2022 NtUserWaitMessage(VOID
)
2026 UserEnterExclusive();
2027 TRACE("NtUserWaitMessage Enter\n");
2028 ret
= co_IntWaitMessage(NULL
, 0, 0);
2029 TRACE("NtUserWaitMessage Leave\n");
2036 NtUserGetMessage(PMSG pMsg
,
2044 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
2046 EngSetLastError(ERROR_INVALID_PARAMETER
);
2050 UserEnterExclusive();
2052 RtlZeroMemory(&Msg
, sizeof(MSG
));
2054 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
2062 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2063 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2065 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2067 SetLastNtError(_SEH2_GetExceptionCode());
2074 Ret
= Ret
? (WM_QUIT
!= pMsg
->message
) : FALSE
;
2080 NtUserPeekMessage( PMSG pMsg
,
2089 if ( RemoveMsg
& PM_BADMSGFLAGS
)
2091 EngSetLastError(ERROR_INVALID_FLAGS
);
2095 UserEnterExclusive();
2097 RtlZeroMemory(&Msg
, sizeof(MSG
));
2099 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
2107 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2108 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2110 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2112 SetLastNtError(_SEH2_GetExceptionCode());
2122 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
2129 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
2130 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
2132 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2134 _SEH2_YIELD(return FALSE
);
2138 UserEnterExclusive();
2140 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
2146 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
2153 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
2154 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
2156 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2166 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
2173 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
2174 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
2176 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2178 SetLastNtError(_SEH2_GetExceptionCode());
2179 _SEH2_YIELD(return FALSE
);
2183 UserEnterExclusive();
2185 Res
= IntDispatchMessage(&SafeMsg
);
2192 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
2200 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
2201 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
2203 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2205 SetLastNtError(_SEH2_GetExceptionCode());
2206 _SEH2_YIELD(return FALSE
);
2210 UserEnterExclusive();
2211 pWnd
= UserGetWindowObject(SafeMsg
.hwnd
);
2212 if (pWnd
) // Must have a window!
2214 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
2218 TRACE("No Window for Translate. hwnd 0x%p Msg %u\n", SafeMsg
.hwnd
, SafeMsg
.message
);
2226 LRESULT APIENTRY
ScrollBarWndProc(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
);
2229 NtUserMessageCall( HWND hWnd
,
2233 ULONG_PTR ResultInfo
,
2234 DWORD dwType
, // fnID?
2237 LRESULT lResult
= 0;
2240 USER_REFERENCE_ENTRY Ref
;
2242 UserEnterExclusive();
2246 case FNID_SCROLLBAR
:
2248 lResult
= ScrollBarWndProc(hWnd
, Msg
, wParam
, lParam
);
2253 Window
= UserGetWindowObject(hWnd
);
2256 //ERR("FNID_DESKTOP IN\n");
2257 Ret
= DesktopWindowProc(Window
, Msg
, wParam
, lParam
, &lResult
);
2258 //ERR("FNID_DESKTOP OUT\n");
2263 case FNID_MESSAGEWND
:
2265 Window
= UserGetWindowObject(hWnd
);
2268 Ret
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,&lResult
);
2272 case FNID_DEFWINDOWPROC
:
2273 /* Validate input */
2276 Window
= UserGetWindowObject(hWnd
);
2282 UserRefObjectCo(Window
, &Ref
);
2284 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2287 UserDerefObjectCo(Window
);
2289 case FNID_SENDNOTIFYMESSAGE
:
2290 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2292 case FNID_BROADCASTSYSTEMMESSAGE
:
2294 BROADCASTPARM parm
, *retparam
;
2295 DWORD_PTR RetVal
= 0;
2301 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2302 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2304 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2313 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2314 parm
.recipients
== BSM_ALLCOMPONENTS
)
2316 PLIST_ENTRY DesktopEntry
;
2318 HWND
*List
, hwndDenied
= NULL
;
2320 PWND pwnd
, pwndDesk
;
2324 for (DesktopEntry
= InputWindowStation
->DesktopListHead
.Flink
;
2325 DesktopEntry
!= &InputWindowStation
->DesktopListHead
;
2326 DesktopEntry
= DesktopEntry
->Flink
)
2328 rpdesk
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
2329 pwndDesk
= rpdesk
->pDeskInfo
->spwnd
;
2330 List
= IntWinListChildren(pwndDesk
);
2332 if (parm
.flags
& BSF_QUERY
)
2336 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2338 fuFlags
= SMTO_ABORTIFHUNG
;
2340 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2342 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2346 fuFlags
= SMTO_NORMAL
;
2348 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2356 for (i
= 0; List
[i
]; i
++)
2358 pwnd
= UserGetWindowObject(List
[i
]);
2359 if (!pwnd
) continue;
2361 if ( pwnd
->fnid
== FNID_MENU
||
2362 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2365 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2367 if ( pwnd
->head
.pti
== gptiCurrent
)
2370 co_IntSendMessageTimeout( List
[i
],
2378 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2380 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2383 if (RetVal
== BROADCAST_QUERY_DENY
)
2385 hwndDenied
= List
[i
];
2386 hDesk
= UserHMGetHandle(pwndDesk
);
2390 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2393 retparam
= (PBROADCASTPARM
) ResultInfo
;
2394 retparam
->hDesk
= hDesk
;
2395 retparam
->hWnd
= hwndDenied
;
2397 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2402 if (!Ret
) break; // Have a hit! Let everyone know!
2405 else if (parm
.flags
& BSF_POSTMESSAGE
)
2409 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2411 for (i
= 0; List
[i
]; i
++)
2413 pwnd
= UserGetWindowObject(List
[i
]);
2414 if (!pwnd
) continue;
2416 if ( pwnd
->fnid
== FNID_MENU
||
2417 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2420 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2422 if ( pwnd
->head
.pti
== gptiCurrent
)
2425 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2427 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2435 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2437 for (i
= 0; List
[i
]; i
++)
2439 pwnd
= UserGetWindowObject(List
[i
]);
2440 if (!pwnd
) continue;
2442 if ( pwnd
->fnid
== FNID_MENU
||
2443 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2446 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2448 if ( pwnd
->head
.pti
== gptiCurrent
)
2451 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2453 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2459 else if (parm
.recipients
& BSM_APPLICATIONS
)
2461 HWND
*List
, hwndDenied
= NULL
;
2463 PWND pwnd
, pwndDesk
;
2467 pwndDesk
= UserGetDesktopWindow();
2468 List
= IntWinListChildren(pwndDesk
);
2470 if (parm
.flags
& BSF_QUERY
)
2474 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2476 fuFlags
= SMTO_ABORTIFHUNG
;
2478 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2480 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2484 fuFlags
= SMTO_NORMAL
;
2486 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2494 for (i
= 0; List
[i
]; i
++)
2496 pwnd
= UserGetWindowObject(List
[i
]);
2497 if (!pwnd
) continue;
2499 if ( pwnd
->fnid
== FNID_MENU
||
2500 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2503 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2505 if ( pwnd
->head
.pti
== gptiCurrent
)
2508 co_IntSendMessageTimeout( List
[i
],
2516 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2518 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2521 if (RetVal
== BROADCAST_QUERY_DENY
)
2523 hwndDenied
= List
[i
];
2524 hDesk
= UserHMGetHandle(pwndDesk
);
2528 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2531 retparam
= (PBROADCASTPARM
) ResultInfo
;
2532 retparam
->hDesk
= hDesk
;
2533 retparam
->hWnd
= hwndDenied
;
2535 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2542 else if (parm
.flags
& BSF_POSTMESSAGE
)
2546 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2548 for (i
= 0; List
[i
]; i
++)
2550 pwnd
= UserGetWindowObject(List
[i
]);
2551 if (!pwnd
) continue;
2553 if ( pwnd
->fnid
== FNID_MENU
||
2554 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2557 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2559 if ( pwnd
->head
.pti
== gptiCurrent
)
2562 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2564 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2572 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2574 for (i
= 0; List
[i
]; i
++)
2576 pwnd
= UserGetWindowObject(List
[i
]);
2577 if (!pwnd
) continue;
2579 if ( pwnd
->fnid
== FNID_MENU
||
2580 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2583 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2585 if ( pwnd
->head
.pti
== gptiCurrent
)
2588 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2590 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2597 case FNID_SENDMESSAGECALLBACK
:
2599 CALL_BACK_INFO CallBackInfo
;
2604 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2605 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2607 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2613 if (is_pointer_message(Msg
))
2615 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
2619 if (!(Ret
= co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2620 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
)))
2622 ERR("Callback failure!\n");
2626 case FNID_SENDMESSAGE
:
2628 Ret
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2634 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2635 RtlCopyMemory((PVOID
)ResultInfo
, &Ret
, sizeof(ULONG_PTR
));
2637 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2646 case FNID_SENDMESSAGEFF
:
2647 case FNID_SENDMESSAGEWTOOPTION
:
2649 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2654 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2655 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2657 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2664 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, &dsm
);
2670 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2671 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2673 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2682 // CallNextHook bypass.
2683 case FNID_CALLWNDPROC
:
2684 case FNID_CALLWNDPROCRET
:
2687 PCLIENTINFO ClientInfo
;
2688 PHOOK NextObj
, Hook
;
2690 pti
= GetW32ThreadInfo();
2692 Hook
= pti
->sphkCurrent
;
2696 NextObj
= Hook
->phkNext
;
2697 ClientInfo
= pti
->pClientInfo
;
2700 ClientInfo
->phkCurrent
= NextObj
;
2702 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2708 if (!ClientInfo
|| !NextObj
) break;
2710 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2712 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2717 CWP
.wParam
= wParam
;
2718 CWP
.lParam
= lParam
;
2719 TRACE("WH_CALLWNDPROC: Hook %p NextHook %p\n", Hook
, NextObj
);
2721 lResult
= co_IntCallHookProc( Hook
->HookId
,
2723 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2736 CWPR
.wParam
= wParam
;
2737 CWPR
.lParam
= lParam
;
2738 CWPR
.lResult
= ClientInfo
->dwHookData
;
2740 lResult
= co_IntCallHookProc( Hook
->HookId
,
2742 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2756 case FNID_DEFWINDOWPROC
:
2757 case FNID_CALLWNDPROC
:
2758 case FNID_CALLWNDPROCRET
:
2759 case FNID_SCROLLBAR
:
2765 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2766 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2768 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2784 #define INFINITE 0xFFFFFFFF
2785 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2789 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2790 IN DWORD dwMilliseconds
,
2794 PPROCESSINFO W32Process
;
2798 LARGE_INTEGER Timeout
;
2800 UserEnterExclusive();
2802 Status
= ObReferenceObjectByHandle(hProcess
,
2803 PROCESS_QUERY_INFORMATION
,
2809 if (!NT_SUCCESS(Status
))
2812 SetLastNtError(Status
);
2816 pti
= PsGetCurrentThreadWin32Thread();
2818 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2820 if ( PsGetProcessExitProcessCalled(Process
) ||
2822 pti
->ppi
== W32Process
)
2824 ObDereferenceObject(Process
);
2826 EngSetLastError(ERROR_INVALID_PARAMETER
);
2830 Handles
[0] = Process
;
2831 Handles
[1] = W32Process
->InputIdleEvent
;
2832 Handles
[2] = pti
->pEventQueueServer
; // IntMsqSetWakeMask returns hEventQueueClient
2836 ObDereferenceObject(Process
);
2838 return STATUS_SUCCESS
; /* no event to wait on */
2841 if (dwMilliseconds
!= INFINITE
)
2842 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2844 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2845 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2847 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2848 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2851 TRACE("WFII: ppi %p\n", W32Process
);
2852 TRACE("WFII: waiting for %p\n", Handles
[1] );
2856 Status
= KeWaitForMultipleObjects( 3,
2862 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2864 UserEnterExclusive();
2866 if (!NT_SUCCESS(Status
))
2868 SetLastNtError(Status
);
2869 Status
= WAIT_FAILED
;
2881 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2882 ERR("WFII: WAIT 2\n");
2886 case STATUS_TIMEOUT
:
2887 ERR("WFII: timeout\n");
2892 ERR("WFII: finished\n");
2893 Status
= STATUS_SUCCESS
;
2900 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2902 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
2903 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2905 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
2906 ObDereferenceObject(Process
);