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)
13 DBG_DEFAULT_CHANNEL(UserMsg
);
15 #define PM_BADMSGFLAGS ~((QS_RAWINPUT << 16)|PM_QS_SENDMESSAGE|PM_QS_PAINT|PM_QS_POSTMESSAGE|PM_QS_INPUT|PM_NOYIELD|PM_REMOVE)
17 /* FUNCTIONS *****************************************************************/
20 IntInitMessageImpl(VOID
)
22 return STATUS_SUCCESS
;
26 IntCleanupMessageImpl(VOID
)
28 return STATUS_SUCCESS
;
32 /* flag for messages that contain pointers */
33 /* 32 messages per entry, messages 0..31 map to bits 0..31 */
35 #define SET(msg) (1 << ((msg) & 31))
37 static const unsigned int message_pointer_flags
[] =
40 SET(WM_CREATE
) | SET(WM_SETTEXT
) | SET(WM_GETTEXT
) |
41 SET(WM_WININICHANGE
) | SET(WM_DEVMODECHANGE
),
43 SET(WM_GETMINMAXINFO
) | SET(WM_DRAWITEM
) | SET(WM_MEASUREITEM
) | SET(WM_DELETEITEM
) |
46 SET(WM_WINDOWPOSCHANGING
) | SET(WM_WINDOWPOSCHANGED
) | SET(WM_COPYDATA
) |
47 SET(WM_COPYGLOBALDATA
) | SET(WM_NOTIFY
) | SET(WM_HELP
),
49 SET(WM_STYLECHANGING
) | SET(WM_STYLECHANGED
),
51 SET(WM_NCCREATE
) | SET(WM_NCCALCSIZE
) | SET(WM_GETDLGCODE
),
53 SET(EM_GETSEL
) | SET(EM_GETRECT
) | SET(EM_SETRECT
) | SET(EM_SETRECTNP
),
55 SET(EM_REPLACESEL
) | SET(EM_GETLINE
) | SET(EM_SETTABSTOPS
),
57 SET(SBM_GETRANGE
) | SET(SBM_SETSCROLLINFO
) | SET(SBM_GETSCROLLINFO
) | SET(SBM_GETSCROLLBARINFO
),
63 SET(CB_GETEDITSEL
) | SET(CB_ADDSTRING
) | SET(CB_DIR
) | SET(CB_GETLBTEXT
) |
64 SET(CB_INSERTSTRING
) | SET(CB_FINDSTRING
) | SET(CB_SELECTSTRING
) |
65 SET(CB_GETDROPPEDCONTROLRECT
) | SET(CB_FINDSTRINGEXACT
),
69 SET(LB_ADDSTRING
) | SET(LB_INSERTSTRING
) | SET(LB_GETTEXT
) | SET(LB_SELECTSTRING
) |
70 SET(LB_DIR
) | SET(LB_FINDSTRING
) |
71 SET(LB_GETSELITEMS
) | SET(LB_SETTABSTOPS
) | SET(LB_ADDFILE
) | SET(LB_GETITEMRECT
),
73 SET(LB_FINDSTRINGEXACT
),
79 SET(WM_NEXTMENU
) | SET(WM_SIZING
) | SET(WM_MOVING
) | SET(WM_DEVICECHANGE
),
81 SET(WM_MDICREATE
) | SET(WM_MDIGETACTIVE
) | SET(WM_DROPOBJECT
) |
82 SET(WM_QUERYDROPOBJECT
) | SET(WM_DRAGLOOP
) | SET(WM_DRAGSELECT
) | SET(WM_DRAGMOVE
),
96 SET(WM_ASKCBFORMATNAME
)
99 /* check whether a given message type includes pointers */
100 static inline int is_pointer_message( UINT message
)
102 if (message
>= 8*sizeof(message_pointer_flags
)) return FALSE
;
103 return (message_pointer_flags
[message
/ 32] & SET(message
)) != 0;
107 #define MMS_SIZE_WPARAM -1
108 #define MMS_SIZE_WPARAMWCHAR -2
109 #define MMS_SIZE_LPARAMSZ -3
110 #define MMS_SIZE_SPECIAL -4
111 #define MMS_FLAG_READ 0x01
112 #define MMS_FLAG_WRITE 0x02
113 #define MMS_FLAG_READWRITE (MMS_FLAG_READ | MMS_FLAG_WRITE)
114 typedef struct tagMSGMEMORY
120 MSGMEMORY
, *PMSGMEMORY
;
122 static MSGMEMORY g_MsgMemory
[] =
124 { WM_CREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
125 { WM_DDE_ACK
, sizeof(KMDDELPARAM
), MMS_FLAG_READ
},
126 { WM_DDE_EXECUTE
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
127 { WM_GETMINMAXINFO
, sizeof(MINMAXINFO
), MMS_FLAG_READWRITE
},
128 { WM_GETTEXT
, MMS_SIZE_WPARAMWCHAR
, MMS_FLAG_WRITE
},
129 { WM_NCCALCSIZE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
130 { WM_NCCREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
131 { WM_SETTEXT
, MMS_SIZE_LPARAMSZ
, MMS_FLAG_READ
},
132 { WM_STYLECHANGED
, sizeof(STYLESTRUCT
), MMS_FLAG_READ
},
133 { WM_STYLECHANGING
, sizeof(STYLESTRUCT
), MMS_FLAG_READWRITE
},
134 { WM_SETTINGCHANGE
, MMS_SIZE_LPARAMSZ
, MMS_FLAG_READ
},
135 { WM_COPYDATA
, MMS_SIZE_SPECIAL
, MMS_FLAG_READ
},
136 { WM_COPYGLOBALDATA
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
137 { WM_WINDOWPOSCHANGED
, sizeof(WINDOWPOS
), MMS_FLAG_READWRITE
},
138 { WM_WINDOWPOSCHANGING
, sizeof(WINDOWPOS
), MMS_FLAG_READWRITE
},
139 { WM_SIZING
, sizeof(RECT
), MMS_FLAG_READWRITE
},
140 { WM_MOVING
, sizeof(RECT
), MMS_FLAG_READWRITE
},
143 static PMSGMEMORY FASTCALL
144 FindMsgMemory(UINT Msg
)
146 PMSGMEMORY MsgMemoryEntry
;
148 /* See if this message type is present in the table */
149 for (MsgMemoryEntry
= g_MsgMemory
;
150 MsgMemoryEntry
< g_MsgMemory
+ sizeof(g_MsgMemory
) / sizeof(MSGMEMORY
);
153 if (Msg
== MsgMemoryEntry
->Message
)
155 return MsgMemoryEntry
;
163 MsgMemorySize(PMSGMEMORY MsgMemoryEntry
, WPARAM wParam
, LPARAM lParam
)
166 PUNICODE_STRING WindowName
;
167 PUNICODE_STRING ClassName
;
172 if (MMS_SIZE_WPARAM
== MsgMemoryEntry
->Size
)
176 else if (MMS_SIZE_WPARAMWCHAR
== MsgMemoryEntry
->Size
)
178 Size
= (UINT
) (wParam
* sizeof(WCHAR
));
180 else if (MMS_SIZE_LPARAMSZ
== MsgMemoryEntry
->Size
)
182 // WM_SETTEXT and WM_SETTINGCHANGE can be null!
185 TRACE("lParam is NULL!\n");
189 Size
= (UINT
) ((wcslen((PWSTR
) lParam
) + 1) * sizeof(WCHAR
));
191 else if (MMS_SIZE_SPECIAL
== MsgMemoryEntry
->Size
)
193 switch(MsgMemoryEntry
->Message
)
197 Cs
= (CREATESTRUCTW
*) lParam
;
198 WindowName
= (PUNICODE_STRING
) Cs
->lpszName
;
199 ClassName
= (PUNICODE_STRING
) Cs
->lpszClass
;
200 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
201 if (IS_ATOM(ClassName
->Buffer
))
203 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
207 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
212 Size
= wParam
? sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
) : sizeof(RECT
);
216 Size
= sizeof(COPYDATASTRUCT
) + ((PCOPYDATASTRUCT
)lParam
)->cbData
;
227 Size
= MsgMemoryEntry
->Size
;
230 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
232 ERR("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH2_GetExceptionCode());
239 UINT
lParamMemorySize(UINT Msg
, WPARAM wParam
, LPARAM lParam
)
241 PMSGMEMORY MsgMemoryEntry
= FindMsgMemory(Msg
);
242 if(MsgMemoryEntry
== NULL
) return 0;
243 return MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
247 PackParam(LPARAM
*lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolNeeded
)
249 NCCALCSIZE_PARAMS
*UnpackedNcCalcsize
;
250 NCCALCSIZE_PARAMS
*PackedNcCalcsize
;
251 CREATESTRUCTW
*UnpackedCs
;
252 CREATESTRUCTW
*PackedCs
;
253 PLARGE_STRING WindowName
;
254 PUNICODE_STRING ClassName
;
259 *lParamPacked
= lParam
;
261 if (NonPagedPoolNeeded
)
262 PoolType
= NonPagedPool
;
264 PoolType
= PagedPool
;
266 if (WM_NCCALCSIZE
== Msg
&& wParam
)
269 UnpackedNcCalcsize
= (NCCALCSIZE_PARAMS
*) lParam
;
270 PackedNcCalcsize
= ExAllocatePoolWithTag(PoolType
,
271 sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
),
274 if (NULL
== PackedNcCalcsize
)
276 ERR("Not enough memory to pack lParam\n");
277 return STATUS_NO_MEMORY
;
279 RtlCopyMemory(PackedNcCalcsize
, UnpackedNcCalcsize
, sizeof(NCCALCSIZE_PARAMS
));
280 PackedNcCalcsize
->lppos
= (PWINDOWPOS
) (PackedNcCalcsize
+ 1);
281 RtlCopyMemory(PackedNcCalcsize
->lppos
, UnpackedNcCalcsize
->lppos
, sizeof(WINDOWPOS
));
282 *lParamPacked
= (LPARAM
) PackedNcCalcsize
;
284 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
286 UnpackedCs
= (CREATESTRUCTW
*) lParam
;
287 WindowName
= (PLARGE_STRING
) UnpackedCs
->lpszName
;
288 ClassName
= (PUNICODE_STRING
) UnpackedCs
->lpszClass
;
289 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
290 if (IS_ATOM(ClassName
->Buffer
))
292 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
296 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
298 PackedCs
= ExAllocatePoolWithTag(PoolType
, Size
, TAG_MSG
);
299 if (NULL
== PackedCs
)
301 ERR("Not enough memory to pack lParam\n");
302 return STATUS_NO_MEMORY
;
304 RtlCopyMemory(PackedCs
, UnpackedCs
, sizeof(CREATESTRUCTW
));
305 CsData
= (PCHAR
) (PackedCs
+ 1);
306 PackedCs
->lpszName
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
307 RtlCopyMemory(CsData
, WindowName
->Buffer
, WindowName
->Length
);
308 CsData
+= WindowName
->Length
;
309 *((WCHAR
*) CsData
) = L
'\0';
310 CsData
+= sizeof(WCHAR
);
311 PackedCs
->lpszClass
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
312 if (IS_ATOM(ClassName
->Buffer
))
314 *((WCHAR
*) CsData
) = L
'A';
315 CsData
+= sizeof(WCHAR
);
316 *((ATOM
*) CsData
) = (ATOM
)(DWORD_PTR
) ClassName
->Buffer
;
317 CsData
+= sizeof(ATOM
);
321 *((WCHAR
*) CsData
) = L
'S';
322 CsData
+= sizeof(WCHAR
);
323 RtlCopyMemory(CsData
, ClassName
->Buffer
, ClassName
->Length
);
324 CsData
+= ClassName
->Length
;
325 *((WCHAR
*) CsData
) = L
'\0';
326 CsData
+= sizeof(WCHAR
);
328 ASSERT(CsData
== (PCHAR
) PackedCs
+ Size
);
329 *lParamPacked
= (LPARAM
) PackedCs
;
331 else if (PoolType
== NonPagedPool
)
333 PMSGMEMORY MsgMemoryEntry
;
337 MsgMemoryEntry
= FindMsgMemory(Msg
);
341 /* Keep previous behavior */
342 return STATUS_SUCCESS
;
344 size
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
347 ERR("No size for lParamPacked\n");
348 return STATUS_SUCCESS
;
350 PackedData
= ExAllocatePoolWithTag(NonPagedPool
, size
, TAG_MSG
);
351 if (PackedData
== NULL
)
353 ERR("Not enough memory to pack lParam\n");
354 return STATUS_NO_MEMORY
;
356 RtlCopyMemory(PackedData
, (PVOID
)lParam
, MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
));
357 *lParamPacked
= (LPARAM
)PackedData
;
360 return STATUS_SUCCESS
;
364 UnpackParam(LPARAM lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolUsed
)
366 NCCALCSIZE_PARAMS
*UnpackedParams
;
367 NCCALCSIZE_PARAMS
*PackedParams
;
368 PWINDOWPOS UnpackedWindowPos
;
370 if (lParamPacked
== lParam
)
372 return STATUS_SUCCESS
;
375 if (WM_NCCALCSIZE
== Msg
&& wParam
)
377 PackedParams
= (NCCALCSIZE_PARAMS
*) lParamPacked
;
378 UnpackedParams
= (NCCALCSIZE_PARAMS
*) lParam
;
379 UnpackedWindowPos
= UnpackedParams
->lppos
;
380 RtlCopyMemory(UnpackedParams
, PackedParams
, sizeof(NCCALCSIZE_PARAMS
));
381 UnpackedParams
->lppos
= UnpackedWindowPos
;
382 RtlCopyMemory(UnpackedWindowPos
, PackedParams
+ 1, sizeof(WINDOWPOS
));
383 ExFreePool((PVOID
) lParamPacked
);
385 return STATUS_SUCCESS
;
387 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
389 ExFreePool((PVOID
) lParamPacked
);
391 return STATUS_SUCCESS
;
393 else if (NonPagedPoolUsed
)
395 PMSGMEMORY MsgMemoryEntry
;
396 MsgMemoryEntry
= FindMsgMemory(Msg
);
397 ASSERT(MsgMemoryEntry
);
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
;
655 BOOL DoCallBack
= TRUE
;
659 Window
= UserGetWindowObject(pMsg
->hwnd
);
660 if (!Window
) return 0;
663 pti
= PsGetCurrentThreadWin32Thread();
665 if ( Window
&& Window
->head
.pti
!= pti
)
667 EngSetLastError( ERROR_MESSAGE_SYNC_ONLY
);
671 if (((pMsg
->message
== WM_SYSTIMER
) ||
672 (pMsg
->message
== WM_TIMER
)) &&
675 if (pMsg
->message
== WM_TIMER
)
677 if (ValidateTimerCallback(pti
,pMsg
->lParam
))
679 KeQueryTickCount(&TickCount
);
680 Time
= MsqCalculateMessageTime(&TickCount
);
681 retval
= co_IntCallWindowProc((WNDPROC
)pMsg
->lParam
,
693 PTIMER pTimer
= FindSystemTimer(pMsg
);
694 if (pTimer
&& pTimer
->pfn
)
696 KeQueryTickCount(&TickCount
);
697 Time
= MsqCalculateMessageTime(&TickCount
);
698 pTimer
->pfn(pMsg
->hwnd
, WM_SYSTIMER
, (UINT
)pMsg
->wParam
, Time
);
704 if ( !Window
) return 0;
706 if (pMsg
->message
== WM_PAINT
) Window
->state
|= WNDS_PAINTNOTPROCESSED
;
708 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
710 TRACE("Dispatch: Server Side Window Procedure\n");
714 DoCallBack
= !DesktopWindowProc( Window
,
720 case FNID_MESSAGEWND
:
721 DoCallBack
= !UserMessageWindowProc( Window
,
730 /* Since we are doing a callback on the same thread right away, there is
731 no need to copy the lparam to kernel mode and then back to usermode.
732 We just pretend it isn't a pointer */
735 retval
= co_IntCallWindowProc( Window
->lpfnWndProc
,
743 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 Rgn
= IntSysCreateRectpRgn( 0, 0, 0, 0 );
749 co_UserGetUpdateRgn( Window
, Rgn
, TRUE
);
757 * Internal version of PeekMessage() doing all the work
762 * Input (hardware) messages and system internal events
763 * Sent messages (again)
768 co_IntPeekMessage( PMSG Msg
,
776 LARGE_INTEGER LargeTickCount
;
781 pti
= PsGetCurrentThreadWin32Thread();
783 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
784 ProcessMask
= HIWORD(RemoveMsg
);
786 /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns
787 all available messages (that is, no range filtering is performed)". */
788 if (!ProcessMask
) ProcessMask
= (QS_ALLPOSTMESSAGE
|QS_ALLINPUT
);
794 KeQueryTickCount(&LargeTickCount
);
795 pti
->timeLast
= LargeTickCount
.u
.LowPart
;
796 pti
->pcti
->tickLastMsgChecked
= LargeTickCount
.u
.LowPart
;
798 /* Dispatch sent messages here. */
799 while ( co_MsqDispatchOneSentMessage(pti
) )
801 /* if some PM_QS* flags were specified, only handle sent messages from now on */
802 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
; // wine does this; ProcessMask = QS_SENDMESSAGE;
804 if (Hit
) return FALSE
;
806 /* Clear changed bits so we can wait on them if we don't find a message */
807 if (ProcessMask
& QS_POSTMESSAGE
)
809 pti
->pcti
->fsChangeBits
&= ~(QS_POSTMESSAGE
| QS_HOTKEY
| QS_TIMER
);
810 if (MsgFilterMin
== 0 && MsgFilterMax
== 0) // Wine hack does this; ~0U)
812 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
816 if (ProcessMask
& QS_INPUT
)
818 pti
->pcti
->fsChangeBits
&= ~QS_INPUT
;
821 /* Now check for normal messages. */
822 if (( (ProcessMask
& QS_POSTMESSAGE
) ||
823 (ProcessMask
& QS_HOTKEY
) ) &&
835 /* Now look for a quit message. */
838 /* According to the PSDK, WM_QUIT messages are always returned, regardless
839 of the filter specified */
841 Msg
->message
= WM_QUIT
;
842 Msg
->wParam
= pti
->exitCode
;
846 pti
->QuitPosted
= FALSE
;
847 ClearMsgBitsMask(pti
, QS_POSTMESSAGE
);
848 pti
->pcti
->fsWakeBits
&= ~QS_ALLPOSTMESSAGE
;
849 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
854 /* Check for hardware events. */
855 if ((ProcessMask
& QS_MOUSE
) &&
856 co_MsqPeekMouseMove( pti
,
866 if ((ProcessMask
& QS_INPUT
) &&
867 co_MsqPeekHardwareMessage( pti
,
878 /* Check for sent messages again. */
879 while ( co_MsqDispatchOneSentMessage(pti
) )
881 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
;
883 if (Hit
) return FALSE
;
885 /* Check for paint messages. */
886 if ((ProcessMask
& QS_PAINT
) &&
888 IntGetPaintMessage( Window
,
898 /* This is correct, check for the current threads timers waiting to be
899 posted to this threads message queue. If any we loop again.
901 if ((ProcessMask
& QS_TIMER
) &&
902 PostTimerMessages(Window
))
915 co_IntWaitMessage( PWND Window
,
920 NTSTATUS Status
= STATUS_SUCCESS
;
923 pti
= PsGetCurrentThreadWin32Thread();
927 if ( co_IntPeekMessage( &Msg
, // Dont reenter!
931 MAKELONG( PM_NOREMOVE
, GetWakeMask( MsgFilterMin
, MsgFilterMax
)),
932 TRUE
) ) // act like GetMessage.
937 /* Nothing found. Wait for new messages. */
938 Status
= co_MsqWaitForNewMessages( pti
,
942 if (!NT_SUCCESS(Status
))
944 SetLastNtError(Status
);
945 ERR("Exit co_IntWaitMessage on error!\n");
948 if (Status
== STATUS_USER_APC
|| Status
== STATUS_TIMEOUT
)
959 co_IntGetPeekMessage( PMSG pMsg
,
968 BOOL Present
= FALSE
;
971 if ( hWnd
== HWND_TOPMOST
|| hWnd
== HWND_BROADCAST
)
975 if (hWnd
&& hWnd
!= HWND_BOTTOM
)
977 if (!(Window
= UserGetWindowObject(hWnd
)))
990 if (MsgFilterMax
< MsgFilterMin
)
998 RemoveMsg
|= ((GetWakeMask( MsgFilterMin
, MsgFilterMax
))<< 16);
1001 pti
= PsGetCurrentThreadWin32Thread();
1002 pti
->pClientInfo
->cSpins
++; // Bump up the spin count.
1006 Present
= co_IntPeekMessage( pMsg
,
1014 /* GetMessage or PostMessage must never get messages that contain pointers */
1015 ASSERT(FindMsgMemory(pMsg
->message
) == NULL
);
1017 if (pMsg
->message
!= WM_PAINT
&& pMsg
->message
!= WM_QUIT
)
1019 pti
->timeLast
= pMsg
->time
;
1020 pti
->ptLast
= pMsg
->pt
;
1023 // The WH_GETMESSAGE hook enables an application to monitor messages about to
1024 // be returned by the GetMessage or PeekMessage function.
1026 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)pMsg
);
1033 Status
= co_MsqWaitForNewMessages( pti
,
1037 if ( !NT_SUCCESS(Status
) ||
1038 Status
== STATUS_USER_APC
||
1039 Status
== STATUS_TIMEOUT
)
1047 if (!(RemoveMsg
& PM_NOYIELD
))
1050 // Yield this thread!
1053 UserEnterExclusive();
1054 // Fall through to exit.
1060 while( bGMSG
&& !Present
);
1062 // Been spinning, time to swap vinyl...
1063 if (pti
->pClientInfo
->cSpins
>= 100)
1065 // Clear the spin cycle to fix the mix.
1066 pti
->pClientInfo
->cSpins
= 0;
1067 //if (!(pti->TIF_flags & TIF_SPINNING)) // FIXME: Need to swap vinyl...
1073 UserPostThreadMessage( PTHREADINFO pti
,
1079 LARGE_INTEGER LargeTickCount
;
1081 if (is_pointer_message(Msg
))
1083 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1086 Message
.hwnd
= NULL
;
1087 Message
.message
= Msg
;
1088 Message
.wParam
= wParam
;
1089 Message
.lParam
= lParam
;
1090 Message
.pt
= gpsi
->ptCursor
;
1092 KeQueryTickCount(&LargeTickCount
);
1093 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1094 MsqPostMessage(pti
, &Message
, FALSE
, QS_POSTMESSAGE
, 0);
1098 PTHREADINFO FASTCALL
1099 IntSendTo(PWND Window
, PTHREADINFO ptiCur
, UINT Msg
)
1104 Window
->head
.pti
->MessageQueue
== ptiCur
->MessageQueue
)
1109 return Window
? Window
->head
.pti
: NULL
;
1113 UserPostMessage( HWND Wnd
,
1119 MSG Message
, KernelModeMsg
;
1120 LARGE_INTEGER LargeTickCount
;
1123 Message
.message
= Msg
;
1124 Message
.wParam
= wParam
;
1125 Message
.lParam
= lParam
;
1126 Message
.pt
= gpsi
->ptCursor
;
1127 KeQueryTickCount(&LargeTickCount
);
1128 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1130 if (is_pointer_message(Message
.message
))
1132 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1136 if( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1139 PMSGMEMORY MsgMemoryEntry
;
1141 MsgMemoryEntry
= FindMsgMemory(Message
.message
);
1143 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &Message
, MsgMemoryEntry
);
1144 if (! NT_SUCCESS(Status
))
1146 EngSetLastError(ERROR_INVALID_PARAMETER
);
1149 co_IntSendMessageNoWait(KernelModeMsg
.hwnd
,
1150 KernelModeMsg
.message
,
1151 KernelModeMsg
.wParam
,
1152 KernelModeMsg
.lParam
);
1154 if (MsgMemoryEntry
&& KernelModeMsg
.lParam
)
1155 ExFreePool((PVOID
) KernelModeMsg
.lParam
);
1162 pti
= PsGetCurrentThreadWin32Thread();
1163 return UserPostThreadMessage( pti
,
1168 if (Wnd
== HWND_BROADCAST
)
1174 DesktopWindow
= UserGetDesktopWindow();
1175 List
= IntWinListChildren(DesktopWindow
);
1179 UserPostMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1180 for (i
= 0; List
[i
]; i
++)
1182 PWND pwnd
= UserGetWindowObject(List
[i
]);
1183 if (!pwnd
) continue;
1185 if ( pwnd
->fnid
== FNID_MENU
|| // Also need pwnd->pcls->atomClassName == gaOleMainThreadWndClass
1186 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1189 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1191 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1198 Window
= UserGetWindowObject(Wnd
);
1201 ERR("UserPostMessage: Invalid handle 0x%p!\n",Wnd
);
1205 pti
= Window
->head
.pti
;
1206 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1208 ERR("Attempted to post message to window %p when the thread is in cleanup!\n", Wnd
);
1212 if ( Window
->state
& WNDS_DESTROYED
)
1214 ERR("Attempted to post message to window %p that is being destroyed!\n", Wnd
);
1215 /* FIXME: Last error code? */
1221 MsqPostQuitMessage(pti
, wParam
);
1225 MsqPostMessage(pti
, &Message
, FALSE
, QS_POSTMESSAGE
, 0);
1232 co_IntSendMessage( HWND hWnd
,
1237 ULONG_PTR Result
= 0;
1238 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1240 return (LRESULT
)Result
;
1245 static LRESULT FASTCALL
1246 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1252 ULONG_PTR
*uResult
)
1256 PMSGMEMORY MsgMemoryEntry
;
1257 INT lParamBufferSize
;
1258 LPARAM lParamPacked
;
1259 PTHREADINFO Win32Thread
, ptiSendTo
= NULL
;
1260 ULONG_PTR Hi
, Lo
, Result
= 0;
1261 DECLARE_RETURN(LRESULT
);
1262 USER_REFERENCE_ENTRY Ref
;
1263 BOOL DoCallBack
= TRUE
;
1265 if (!(Window
= UserGetWindowObject(hWnd
)))
1267 TRACE("SendMessageTimeoutSingle: Invalid handle 0x%p!\n",hWnd
);
1271 UserRefObjectCo(Window
, &Ref
);
1273 Win32Thread
= PsGetCurrentThreadWin32Thread();
1275 ptiSendTo
= IntSendTo(Window
, Win32Thread
, Msg
);
1279 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1281 /* Never send messages to exiting threads */
1285 if (Msg
& 0x80000000)
1287 TRACE("SMTS: Internal Message!\n");
1288 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1289 if (uResult
) *uResult
= Result
;
1293 // Only happens when calling the client!
1294 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1296 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1298 TRACE("SMT: Server Side Window Procedure\n");
1299 IoGetStackLimits(&Lo
, &Hi
);
1300 // Handle it here. Safeguard against excessive recursions.
1301 if (((ULONG_PTR
)&uResult
- Lo
) < 4096 )
1303 ERR("Server Callback Exceeded Stack!\n");
1306 /* Return after server side call, IntCallWndProcRet will not be called. */
1307 switch(Window
->fnid
)
1310 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1312 case FNID_MESSAGEWND
:
1313 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1318 if (uResult
) *uResult
= Result
;
1322 /* See if this message type is present in the table */
1323 MsgMemoryEntry
= FindMsgMemory(Msg
);
1324 if (NULL
== MsgMemoryEntry
)
1326 lParamBufferSize
= -1;
1330 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1331 // If zero, do not allow callback on client side to allocate a buffer!!!!! See CORE-7695.
1332 if (!lParamBufferSize
) lParamBufferSize
= -1;
1335 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1337 ERR("Failed to pack message parameters\n");
1341 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1353 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1355 ERR("Failed to unpack message parameters\n");
1359 // Only happens when calling the client!
1360 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1365 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(ptiSendTo
))
1367 // FIXME: Set window hung and add to a list.
1368 /* FIXME: Set a LastError? */
1372 if (Window
->state
& WNDS_DESTROYED
)
1374 /* FIXME: Last error? */
1375 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1381 Status
= co_MsqSendMessage( ptiSendTo
,
1387 (uFlags
& SMTO_BLOCK
),
1391 while ((STATUS_TIMEOUT
== Status
) &&
1392 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1393 !MsqIsHung(ptiSendTo
)); // FIXME: Set window hung and add to a list.
1395 if (STATUS_TIMEOUT
== Status
)
1399 * Microsoft Windows 2000: If GetLastError returns zero, then the function
1401 * XP+ : If the function fails or times out, the return value is zero.
1402 * To get extended error information, call GetLastError. If GetLastError
1403 * returns ERROR_TIMEOUT, then the function timed out.
1405 EngSetLastError(ERROR_TIMEOUT
);
1408 else if (!NT_SUCCESS(Status
))
1410 SetLastNtError(Status
);
1417 if (Window
) UserDerefObjectCo(Window
);
1422 co_IntSendMessageTimeout( HWND hWnd
,
1428 ULONG_PTR
*uResult
)
1434 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1436 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1439 DesktopWindow
= UserGetDesktopWindow();
1440 if (NULL
== DesktopWindow
)
1442 EngSetLastError(ERROR_INTERNAL_ERROR
);
1446 if (hWnd
!= HWND_TOPMOST
)
1448 /* Send message to the desktop window too! */
1449 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1452 Children
= IntWinListChildren(DesktopWindow
);
1453 if (NULL
== Children
)
1458 for (Child
= Children
; NULL
!= *Child
; Child
++)
1460 if (hWnd
== HWND_TOPMOST
)
1462 DesktopWindow
= UserGetWindowObject(*Child
);
1463 if (DesktopWindow
&& DesktopWindow
->ExStyle
& WS_EX_TOPMOST
)
1465 ERR("HWND_TOPMOST Found\n");
1466 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1471 PWND pwnd
= UserGetWindowObject(*Child
);
1472 if (!pwnd
) continue;
1474 if ( pwnd
->fnid
== FNID_MENU
||
1475 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1478 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1482 ExFreePool(Children
);
1484 return (LRESULT
) TRUE
;
1488 co_IntSendMessageNoWait(HWND hWnd
,
1493 ULONG_PTR Result
= 0;
1494 return co_IntSendMessageWithCallBack( hWnd
,
1503 If you send a message in the range below WM_USER to the asynchronous message
1504 functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its
1505 message parameters cannot include pointers. Otherwise, the operation will fail.
1506 The functions will return before the receiving thread has had a chance to
1507 process the message and the sender will free the memory before it is used.
1510 co_IntSendMessageWithCallBack( HWND hWnd
,
1514 SENDASYNCPROC CompletionCallback
,
1515 ULONG_PTR CompletionCallbackContext
,
1520 PMSGMEMORY MsgMemoryEntry
;
1521 INT lParamBufferSize
;
1522 LPARAM lParamPacked
;
1523 PTHREADINFO Win32Thread
, ptiSendTo
= NULL
;
1524 DECLARE_RETURN(LRESULT
);
1525 USER_REFERENCE_ENTRY Ref
;
1526 PUSER_SENT_MESSAGE Message
;
1527 BOOL DoCallBack
= TRUE
;
1529 if (!(Window
= UserGetWindowObject(hWnd
)))
1531 TRACE("SendMessageWithCallBack: Invalid handle 0x%p!\n",hWnd
);
1535 UserRefObjectCo(Window
, &Ref
);
1537 if (Window
->state
& WNDS_DESTROYED
)
1539 /* FIXME: last error? */
1540 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1544 Win32Thread
= PsGetCurrentThreadWin32Thread();
1546 if (Win32Thread
== NULL
||
1547 Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1552 ptiSendTo
= IntSendTo(Window
, Win32Thread
, Msg
);
1554 if (Msg
& 0x80000000 &&
1557 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
) RETURN( FALSE
);
1559 TRACE("SMWCB: Internal Message!\n");
1560 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1561 if (uResult
) *uResult
= Result
;
1565 /* See if this message type is present in the table */
1566 MsgMemoryEntry
= FindMsgMemory(Msg
);
1567 if (NULL
== MsgMemoryEntry
)
1569 lParamBufferSize
= -1;
1573 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1574 if (!lParamBufferSize
) lParamBufferSize
= -1;
1577 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, !!ptiSendTo
)))
1579 ERR("Failed to pack message parameters\n");
1583 /* If it can be sent now, then send it. */
1586 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1588 UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
);
1589 /* Never send messages to exiting threads */
1593 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1595 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1597 TRACE("SMWCB: Server Side Window Procedure\n");
1598 switch(Window
->fnid
)
1601 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParamPacked
, (LRESULT
*)&Result
);
1603 case FNID_MESSAGEWND
:
1604 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1610 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1622 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1624 if (CompletionCallback
)
1626 co_IntCallSentMessageCallback(CompletionCallback
,
1629 CompletionCallbackContext
,
1636 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1638 ERR("Failed to unpack message parameters\n");
1643 if(!(Message
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
1645 ERR("MsqSendMessage(): Not enough memory to allocate a message");
1649 Message
->Msg
.hwnd
= hWnd
;
1650 Message
->Msg
.message
= Msg
;
1651 Message
->Msg
.wParam
= wParam
;
1652 Message
->Msg
.lParam
= lParamPacked
;
1653 Message
->CompletionEvent
= NULL
;
1654 Message
->Result
= 0;
1655 Message
->lResult
= 0;
1656 Message
->QS_Flags
= 0;
1657 Message
->ptiReceiver
= ptiSendTo
;
1658 Message
->ptiSender
= NULL
; // mjmartin, you are right! This is null.
1659 Message
->ptiCallBackSender
= Win32Thread
;
1660 Message
->DispatchingListEntry
.Flink
= NULL
;
1661 Message
->CompletionCallback
= CompletionCallback
;
1662 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1663 Message
->HookMessage
= MSQ_NORMAL
;
1664 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1665 Message
->QS_Flags
= QS_SENDMESSAGE
;
1667 if (Msg
& 0x80000000) // Higher priority event message!
1668 InsertHeadList(&ptiSendTo
->SentMessagesListHead
, &Message
->ListEntry
);
1670 InsertTailList(&ptiSendTo
->SentMessagesListHead
, &Message
->ListEntry
);
1671 MsqWakeQueue(ptiSendTo
, QS_SENDMESSAGE
, TRUE
);
1676 if (Window
) UserDerefObjectCo(Window
);
1682 This HACK function posts a message if the destination's message queue belongs to
1683 another thread, otherwise it sends the message. It does not support broadcast
1687 co_IntPostOrSendMessage( HWND hWnd
,
1696 if ( hWnd
== HWND_BROADCAST
)
1701 if(!(Window
= UserGetWindowObject(hWnd
)))
1703 TRACE("PostOrSendMessage: Invalid handle 0x%p!\n",hWnd
);
1707 pti
= PsGetCurrentThreadWin32Thread();
1709 if ( IntSendTo(Window
, pti
, Msg
) &&
1710 FindMsgMemory(Msg
) == 0 )
1712 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1716 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1722 return (LRESULT
)Result
;
1725 static LRESULT FASTCALL
1726 co_IntDoSendMessage( HWND hWnd
,
1732 LRESULT Result
= TRUE
;
1735 MSG UserModeMsg
, KernelModeMsg
;
1736 PMSGMEMORY MsgMemoryEntry
;
1737 PTHREADINFO ptiSendTo
;
1739 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1741 Window
= UserGetWindowObject(hWnd
);
1748 /* Check for an exiting window. */
1749 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1751 ERR("co_IntDoSendMessage Window Exiting!\n");
1754 /* See if the current thread can handle this message */
1755 ptiSendTo
= IntSendTo(Window
, gptiCurrent
, Msg
);
1757 // If broadcasting or sending to another thread, save the users data.
1758 if (!Window
|| ptiSendTo
)
1760 UserModeMsg
.hwnd
= hWnd
;
1761 UserModeMsg
.message
= Msg
;
1762 UserModeMsg
.wParam
= wParam
;
1763 UserModeMsg
.lParam
= lParam
;
1764 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1765 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1766 if (!NT_SUCCESS(Status
))
1768 EngSetLastError(ERROR_INVALID_PARAMETER
);
1769 return (dsm
? 0 : -1);
1774 KernelModeMsg
.hwnd
= hWnd
;
1775 KernelModeMsg
.message
= Msg
;
1776 KernelModeMsg
.wParam
= wParam
;
1777 KernelModeMsg
.lParam
= lParam
;
1782 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1783 KernelModeMsg
.message
,
1784 KernelModeMsg
.wParam
,
1785 KernelModeMsg
.lParam
);
1789 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1790 KernelModeMsg
.message
,
1791 KernelModeMsg
.wParam
,
1792 KernelModeMsg
.lParam
,
1798 if (!Window
|| ptiSendTo
)
1800 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1801 if (!NT_SUCCESS(Status
))
1803 EngSetLastError(ERROR_INVALID_PARAMETER
);
1804 return(dsm
? 0 : -1);
1808 return (LRESULT
)Result
;
1812 UserSendNotifyMessage( HWND hWnd
,
1819 if (is_pointer_message(Msg
))
1821 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1825 // Basicly the same as IntPostOrSendMessage
1826 if (hWnd
== HWND_BROADCAST
) // Handle Broadcast
1832 DesktopWindow
= UserGetDesktopWindow();
1833 List
= IntWinListChildren(DesktopWindow
);
1837 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1838 for (i
= 0; List
[i
]; i
++)
1840 PWND pwnd
= UserGetWindowObject(List
[i
]);
1841 if (!pwnd
) continue;
1843 if ( pwnd
->fnid
== FNID_MENU
||
1844 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1847 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1854 Ret
= co_IntSendMessageNoWait( hWnd
, Msg
, wParam
, lParam
);
1861 IntGetQueueStatus(DWORD Changes
)
1866 pti
= PsGetCurrentThreadWin32Thread();
1868 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1870 /* High word, types of messages currently in the queue.
1871 Low word, types of messages that have been added to the queue and that
1872 are still in the queue
1874 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1876 pti
->pcti
->fsChangeBits
&= ~Changes
;
1882 IntInitMessagePumpHook()
1884 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1888 pti
->pcti
->dwcPumpHook
++;
1895 IntUninitMessagePumpHook()
1897 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1901 if (pti
->pcti
->dwcPumpHook
<= 0)
1905 pti
->pcti
->dwcPumpHook
--;
1912 IntCallMsgFilter( LPMSG lpmsg
, INT code
)
1916 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)lpmsg
))
1922 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)lpmsg
);
1927 /** Functions ******************************************************************/
1933 POINT pt
) // Just like the User call.
1937 ULONG wDragWidth
, wDragHeight
;
1938 DECLARE_RETURN(BOOL
);
1940 TRACE("Enter NtUserDragDetect(%p)\n", hWnd
);
1941 UserEnterExclusive();
1943 wDragWidth
= UserGetSystemMetrics(SM_CXDRAG
);
1944 wDragHeight
= UserGetSystemMetrics(SM_CYDRAG
);
1946 rect
.left
= pt
.x
- wDragWidth
;
1947 rect
.right
= pt
.x
+ wDragWidth
;
1949 rect
.top
= pt
.y
- wDragHeight
;
1950 rect
.bottom
= pt
.y
+ wDragHeight
;
1952 co_UserSetCapture(hWnd
);
1956 while (co_IntGetPeekMessage( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, FALSE
) ||
1957 co_IntGetPeekMessage( &msg
, 0, WM_QUEUESYNC
, WM_QUEUESYNC
, PM_REMOVE
, FALSE
) ||
1958 co_IntGetPeekMessage( &msg
, 0, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
, FALSE
) )
1960 if ( msg
.message
== WM_LBUTTONUP
)
1962 co_UserSetCapture(NULL
);
1965 if ( msg
.message
== WM_MOUSEMOVE
)
1968 tmp
.x
= (short)LOWORD(msg
.lParam
);
1969 tmp
.y
= (short)HIWORD(msg
.lParam
);
1970 if( !RECTL_bPointInRect( &rect
, tmp
.x
, tmp
.y
) )
1972 co_UserSetCapture(NULL
);
1976 if ( msg
.message
== WM_KEYDOWN
)
1978 if ( msg
.wParam
== VK_ESCAPE
)
1980 co_UserSetCapture(NULL
);
1984 if ( msg
.message
== WM_QUEUESYNC
)
1986 co_HOOK_CallHooks( WH_CBT
, HCBT_QS
, 0, 0 );
1989 co_IntWaitMessage(NULL
, 0, 0);
1994 TRACE("Leave NtUserDragDetect, ret=%i\n",_ret_
);
2000 NtUserPostMessage(HWND hWnd
,
2007 UserEnterExclusive();
2009 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
2017 NtUserPostThreadMessage(DWORD idThread
,
2024 PTHREADINFO pThread
;
2027 UserEnterExclusive();
2029 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
2031 if ( Status
== STATUS_SUCCESS
)
2033 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
2035 !pThread
->MessageQueue
||
2036 (pThread
->TIF_flags
& TIF_INCLEANUP
))
2038 ObDereferenceObject( peThread
);
2041 ret
= UserPostThreadMessage( pThread
, Msg
, wParam
, lParam
);
2042 ObDereferenceObject( peThread
);
2046 SetLastNtError( Status
);
2054 NtUserWaitMessage(VOID
)
2058 UserEnterExclusive();
2059 TRACE("NtUserWaitMessage Enter\n");
2060 ret
= co_IntWaitMessage(NULL
, 0, 0);
2061 TRACE("NtUserWaitMessage Leave\n");
2068 NtUserGetMessage(PMSG pMsg
,
2076 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
2078 EngSetLastError(ERROR_INVALID_PARAMETER
);
2082 UserEnterExclusive();
2084 RtlZeroMemory(&Msg
, sizeof(MSG
));
2086 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
2094 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2095 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2097 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2099 SetLastNtError(_SEH2_GetExceptionCode());
2106 Ret
= Ret
? (WM_QUIT
!= pMsg
->message
) : FALSE
;
2112 NtUserPeekMessage( PMSG pMsg
,
2121 if ( RemoveMsg
& PM_BADMSGFLAGS
)
2123 EngSetLastError(ERROR_INVALID_FLAGS
);
2127 UserEnterExclusive();
2129 RtlZeroMemory(&Msg
, sizeof(MSG
));
2131 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
2139 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2140 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2142 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2144 SetLastNtError(_SEH2_GetExceptionCode());
2154 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
2161 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
2162 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
2164 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2166 _SEH2_YIELD(return FALSE
);
2170 UserEnterExclusive();
2172 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
2178 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
2185 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
2186 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
2188 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2198 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
2205 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
2206 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
2208 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2210 SetLastNtError(_SEH2_GetExceptionCode());
2211 _SEH2_YIELD(return FALSE
);
2215 UserEnterExclusive();
2217 Res
= IntDispatchMessage(&SafeMsg
);
2224 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
2232 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
2233 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
2235 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2237 SetLastNtError(_SEH2_GetExceptionCode());
2238 _SEH2_YIELD(return FALSE
);
2242 UserEnterExclusive();
2243 pWnd
= UserGetWindowObject(SafeMsg
.hwnd
);
2244 if (pWnd
) // Must have a window!
2246 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
2250 TRACE("No Window for Translate. hwnd 0x%p Msg %u\n", SafeMsg
.hwnd
, SafeMsg
.message
);
2258 LRESULT APIENTRY
ScrollBarWndProc(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
);
2261 NtUserMessageCall( HWND hWnd
,
2265 ULONG_PTR ResultInfo
,
2266 DWORD dwType
, // fnID?
2269 LRESULT lResult
= 0;
2272 USER_REFERENCE_ENTRY Ref
;
2274 UserEnterExclusive();
2278 case FNID_SCROLLBAR
:
2280 lResult
= ScrollBarWndProc(hWnd
, Msg
, wParam
, lParam
);
2285 Window
= UserGetWindowObject(hWnd
);
2288 //ERR("FNID_DESKTOP IN\n");
2289 Ret
= DesktopWindowProc(Window
, Msg
, wParam
, lParam
, &lResult
);
2290 //ERR("FNID_DESKTOP OUT\n");
2295 case FNID_MESSAGEWND
:
2297 Window
= UserGetWindowObject(hWnd
);
2300 Ret
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,&lResult
);
2304 case FNID_DEFWINDOWPROC
:
2305 /* Validate input */
2308 Window
= UserGetWindowObject(hWnd
);
2314 UserRefObjectCo(Window
, &Ref
);
2316 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2319 UserDerefObjectCo(Window
);
2321 case FNID_SENDNOTIFYMESSAGE
:
2322 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2324 case FNID_BROADCASTSYSTEMMESSAGE
:
2326 BROADCASTPARM parm
, *retparam
;
2327 DWORD_PTR RetVal
= 0;
2333 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2334 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2336 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2345 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2346 parm
.recipients
== BSM_ALLCOMPONENTS
)
2348 PLIST_ENTRY DesktopEntry
;
2350 HWND
*List
, hwndDenied
= NULL
;
2352 PWND pwnd
, pwndDesk
;
2356 for (DesktopEntry
= InputWindowStation
->DesktopListHead
.Flink
;
2357 DesktopEntry
!= &InputWindowStation
->DesktopListHead
;
2358 DesktopEntry
= DesktopEntry
->Flink
)
2360 rpdesk
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
2361 pwndDesk
= rpdesk
->pDeskInfo
->spwnd
;
2362 List
= IntWinListChildren(pwndDesk
);
2364 if (parm
.flags
& BSF_QUERY
)
2368 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2370 fuFlags
= SMTO_ABORTIFHUNG
;
2372 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2374 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2378 fuFlags
= SMTO_NORMAL
;
2380 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2388 for (i
= 0; List
[i
]; i
++)
2390 pwnd
= UserGetWindowObject(List
[i
]);
2391 if (!pwnd
) continue;
2393 if ( pwnd
->fnid
== FNID_MENU
||
2394 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2397 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2399 if ( pwnd
->head
.pti
== gptiCurrent
)
2402 co_IntSendMessageTimeout( List
[i
],
2410 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2412 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2415 if (RetVal
== BROADCAST_QUERY_DENY
)
2417 hwndDenied
= List
[i
];
2418 hDesk
= UserHMGetHandle(pwndDesk
);
2422 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2425 retparam
= (PBROADCASTPARM
) ResultInfo
;
2426 retparam
->hDesk
= hDesk
;
2427 retparam
->hWnd
= hwndDenied
;
2429 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2434 if (!Ret
) break; // Have a hit! Let everyone know!
2437 else if (parm
.flags
& BSF_POSTMESSAGE
)
2441 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2443 for (i
= 0; List
[i
]; i
++)
2445 pwnd
= UserGetWindowObject(List
[i
]);
2446 if (!pwnd
) continue;
2448 if ( pwnd
->fnid
== FNID_MENU
||
2449 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2452 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2454 if ( pwnd
->head
.pti
== gptiCurrent
)
2457 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2459 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2467 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2469 for (i
= 0; List
[i
]; i
++)
2471 pwnd
= UserGetWindowObject(List
[i
]);
2472 if (!pwnd
) continue;
2474 if ( pwnd
->fnid
== FNID_MENU
||
2475 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2478 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2480 if ( pwnd
->head
.pti
== gptiCurrent
)
2483 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2485 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2491 else if (parm
.recipients
& BSM_APPLICATIONS
)
2493 HWND
*List
, hwndDenied
= NULL
;
2495 PWND pwnd
, pwndDesk
;
2499 pwndDesk
= UserGetDesktopWindow();
2500 List
= IntWinListChildren(pwndDesk
);
2502 if (parm
.flags
& BSF_QUERY
)
2506 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2508 fuFlags
= SMTO_ABORTIFHUNG
;
2510 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2512 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2516 fuFlags
= SMTO_NORMAL
;
2518 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2526 for (i
= 0; List
[i
]; i
++)
2528 pwnd
= UserGetWindowObject(List
[i
]);
2529 if (!pwnd
) continue;
2531 if ( pwnd
->fnid
== FNID_MENU
||
2532 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2535 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2537 if ( pwnd
->head
.pti
== gptiCurrent
)
2540 co_IntSendMessageTimeout( List
[i
],
2548 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2550 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2553 if (RetVal
== BROADCAST_QUERY_DENY
)
2555 hwndDenied
= List
[i
];
2556 hDesk
= UserHMGetHandle(pwndDesk
);
2560 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2563 retparam
= (PBROADCASTPARM
) ResultInfo
;
2564 retparam
->hDesk
= hDesk
;
2565 retparam
->hWnd
= hwndDenied
;
2567 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2574 else if (parm
.flags
& BSF_POSTMESSAGE
)
2578 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2580 for (i
= 0; List
[i
]; i
++)
2582 pwnd
= UserGetWindowObject(List
[i
]);
2583 if (!pwnd
) continue;
2585 if ( pwnd
->fnid
== FNID_MENU
||
2586 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2589 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2591 if ( pwnd
->head
.pti
== gptiCurrent
)
2594 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2596 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2604 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2606 for (i
= 0; List
[i
]; i
++)
2608 pwnd
= UserGetWindowObject(List
[i
]);
2609 if (!pwnd
) continue;
2611 if ( pwnd
->fnid
== FNID_MENU
||
2612 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2615 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2617 if ( pwnd
->head
.pti
== gptiCurrent
)
2620 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2622 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2629 case FNID_SENDMESSAGECALLBACK
:
2631 CALL_BACK_INFO CallBackInfo
;
2636 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2637 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2639 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2645 if (is_pointer_message(Msg
))
2647 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
2651 if (!(Ret
= co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2652 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
)))
2654 ERR("Callback failure!\n");
2658 case FNID_SENDMESSAGE
:
2660 Ret
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2666 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2667 RtlCopyMemory((PVOID
)ResultInfo
, &Ret
, sizeof(ULONG_PTR
));
2669 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2678 case FNID_SENDMESSAGEFF
:
2679 case FNID_SENDMESSAGEWTOOPTION
:
2681 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2686 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2687 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2689 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2696 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, &dsm
);
2702 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2703 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2705 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2714 // CallNextHook bypass.
2715 case FNID_CALLWNDPROC
:
2716 case FNID_CALLWNDPROCRET
:
2719 PCLIENTINFO ClientInfo
;
2720 PHOOK NextObj
, Hook
;
2722 pti
= GetW32ThreadInfo();
2724 Hook
= pti
->sphkCurrent
;
2728 NextObj
= Hook
->phkNext
;
2729 ClientInfo
= pti
->pClientInfo
;
2732 ClientInfo
->phkCurrent
= NextObj
;
2734 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2740 if (!ClientInfo
|| !NextObj
) break;
2742 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2744 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2749 CWP
.wParam
= wParam
;
2750 CWP
.lParam
= lParam
;
2751 TRACE("WH_CALLWNDPROC: Hook %p NextHook %p\n", Hook
, NextObj
);
2753 lResult
= co_IntCallHookProc( Hook
->HookId
,
2755 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2768 CWPR
.wParam
= wParam
;
2769 CWPR
.lParam
= lParam
;
2770 CWPR
.lResult
= ClientInfo
->dwHookData
;
2772 lResult
= co_IntCallHookProc( Hook
->HookId
,
2774 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2788 case FNID_DEFWINDOWPROC
:
2789 case FNID_CALLWNDPROC
:
2790 case FNID_CALLWNDPROCRET
:
2791 case FNID_SCROLLBAR
:
2797 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2798 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2800 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2816 #define INFINITE 0xFFFFFFFF
2817 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2821 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2822 IN DWORD dwMilliseconds
,
2826 PPROCESSINFO W32Process
;
2830 LARGE_INTEGER Timeout
;
2832 UserEnterExclusive();
2834 Status
= ObReferenceObjectByHandle(hProcess
,
2835 PROCESS_QUERY_INFORMATION
,
2841 if (!NT_SUCCESS(Status
))
2844 SetLastNtError(Status
);
2848 pti
= PsGetCurrentThreadWin32Thread();
2850 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2852 if ( PsGetProcessExitProcessCalled(Process
) ||
2854 pti
->ppi
== W32Process
)
2856 ObDereferenceObject(Process
);
2858 EngSetLastError(ERROR_INVALID_PARAMETER
);
2862 Handles
[0] = Process
;
2863 Handles
[1] = W32Process
->InputIdleEvent
;
2864 Handles
[2] = pti
->pEventQueueServer
; // IntMsqSetWakeMask returns hEventQueueClient
2868 ObDereferenceObject(Process
);
2870 return STATUS_SUCCESS
; /* no event to wait on */
2873 if (dwMilliseconds
!= INFINITE
)
2874 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2876 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2877 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2879 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2880 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2883 TRACE("WFII: ppi %p\n", W32Process
);
2884 TRACE("WFII: waiting for %p\n", Handles
[1] );
2888 Status
= KeWaitForMultipleObjects( 3,
2894 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2896 UserEnterExclusive();
2898 if (!NT_SUCCESS(Status
))
2900 SetLastNtError(Status
);
2901 Status
= WAIT_FAILED
;
2913 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2914 ERR("WFII: WAIT 2\n");
2918 case STATUS_TIMEOUT
:
2919 ERR("WFII: timeout\n");
2924 ERR("WFII: finished\n");
2925 Status
= STATUS_SUCCESS
;
2932 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2934 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
2935 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2937 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
2938 ObDereferenceObject(Process
);