2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
5 * FILE: subsystems/win32/win32k/ntuser/message.c
6 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
10 DBG_DEFAULT_CHANNEL(UserMsg
);
12 #define PM_BADMSGFLAGS ~((QS_RAWINPUT << 16)|PM_QS_SENDMESSAGE|PM_QS_PAINT|PM_QS_POSTMESSAGE|PM_QS_INPUT|PM_NOYIELD|PM_REMOVE)
14 /* FUNCTIONS *****************************************************************/
17 IntInitMessageImpl(VOID
)
19 return STATUS_SUCCESS
;
23 IntCleanupMessageImpl(VOID
)
25 return STATUS_SUCCESS
;
29 /* flag for messages that contain pointers */
30 /* 32 messages per entry, messages 0..31 map to bits 0..31 */
32 #define SET(msg) (1 << ((msg) & 31))
34 static const unsigned int message_pointer_flags
[] =
37 SET(WM_CREATE
) | SET(WM_SETTEXT
) | SET(WM_GETTEXT
) |
38 SET(WM_WININICHANGE
) | SET(WM_DEVMODECHANGE
),
40 SET(WM_GETMINMAXINFO
) | SET(WM_DRAWITEM
) | SET(WM_MEASUREITEM
) | SET(WM_DELETEITEM
) |
43 SET(WM_WINDOWPOSCHANGING
) | SET(WM_WINDOWPOSCHANGED
) | SET(WM_COPYDATA
) |
44 SET(WM_COPYGLOBALDATA
) | SET(WM_NOTIFY
) | SET(WM_HELP
),
46 SET(WM_STYLECHANGING
) | SET(WM_STYLECHANGED
),
48 SET(WM_NCCREATE
) | SET(WM_NCCALCSIZE
) | SET(WM_GETDLGCODE
),
50 SET(EM_GETSEL
) | SET(EM_GETRECT
) | SET(EM_SETRECT
) | SET(EM_SETRECTNP
),
52 SET(EM_REPLACESEL
) | SET(EM_GETLINE
) | SET(EM_SETTABSTOPS
),
54 SET(SBM_GETRANGE
) | SET(SBM_SETSCROLLINFO
) | SET(SBM_GETSCROLLINFO
) | SET(SBM_GETSCROLLBARINFO
),
60 SET(CB_GETEDITSEL
) | SET(CB_ADDSTRING
) | SET(CB_DIR
) | SET(CB_GETLBTEXT
) |
61 SET(CB_INSERTSTRING
) | SET(CB_FINDSTRING
) | SET(CB_SELECTSTRING
) |
62 SET(CB_GETDROPPEDCONTROLRECT
) | SET(CB_FINDSTRINGEXACT
),
66 SET(LB_ADDSTRING
) | SET(LB_INSERTSTRING
) | SET(LB_GETTEXT
) | SET(LB_SELECTSTRING
) |
67 SET(LB_DIR
) | SET(LB_FINDSTRING
) |
68 SET(LB_GETSELITEMS
) | SET(LB_SETTABSTOPS
) | SET(LB_ADDFILE
) | SET(LB_GETITEMRECT
),
70 SET(LB_FINDSTRINGEXACT
),
76 SET(WM_NEXTMENU
) | SET(WM_SIZING
) | SET(WM_MOVING
) | SET(WM_DEVICECHANGE
),
78 SET(WM_MDICREATE
) | SET(WM_MDIGETACTIVE
) | SET(WM_DROPOBJECT
) |
79 SET(WM_QUERYDROPOBJECT
) | SET(WM_DRAGLOOP
) | SET(WM_DRAGSELECT
) | SET(WM_DRAGMOVE
),
93 SET(WM_ASKCBFORMATNAME
)
96 /* check whether a given message type includes pointers */
97 static inline int is_pointer_message( UINT message
)
99 if (message
>= 8*sizeof(message_pointer_flags
)) return FALSE
;
100 return (message_pointer_flags
[message
/ 32] & SET(message
)) != 0;
104 #define MMS_SIZE_WPARAM -1
105 #define MMS_SIZE_WPARAMWCHAR -2
106 #define MMS_SIZE_LPARAMSZ -3
107 #define MMS_SIZE_SPECIAL -4
108 #define MMS_FLAG_READ 0x01
109 #define MMS_FLAG_WRITE 0x02
110 #define MMS_FLAG_READWRITE (MMS_FLAG_READ | MMS_FLAG_WRITE)
111 typedef struct tagMSGMEMORY
117 MSGMEMORY
, *PMSGMEMORY
;
119 static MSGMEMORY g_MsgMemory
[] =
121 { WM_CREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
122 { WM_DDE_ACK
, sizeof(KMDDELPARAM
), MMS_FLAG_READ
},
123 { WM_DDE_EXECUTE
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
124 { WM_GETMINMAXINFO
, sizeof(MINMAXINFO
), MMS_FLAG_READWRITE
},
125 { WM_GETTEXT
, MMS_SIZE_WPARAMWCHAR
, MMS_FLAG_WRITE
},
126 { WM_NCCALCSIZE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
127 { WM_NCCREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
128 { WM_SETTEXT
, MMS_SIZE_LPARAMSZ
, MMS_FLAG_READ
},
129 { WM_STYLECHANGED
, sizeof(STYLESTRUCT
), MMS_FLAG_READ
},
130 { WM_STYLECHANGING
, sizeof(STYLESTRUCT
), MMS_FLAG_READWRITE
},
131 { WM_SETTINGCHANGE
, MMS_SIZE_LPARAMSZ
, MMS_FLAG_READ
},
132 { WM_COPYDATA
, MMS_SIZE_SPECIAL
, MMS_FLAG_READ
},
133 { WM_COPYGLOBALDATA
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
134 { WM_WINDOWPOSCHANGED
, sizeof(WINDOWPOS
), MMS_FLAG_READ
},
135 { WM_WINDOWPOSCHANGING
, sizeof(WINDOWPOS
), MMS_FLAG_READWRITE
},
138 static PMSGMEMORY FASTCALL
139 FindMsgMemory(UINT Msg
)
141 PMSGMEMORY MsgMemoryEntry
;
143 /* See if this message type is present in the table */
144 for (MsgMemoryEntry
= g_MsgMemory
;
145 MsgMemoryEntry
< g_MsgMemory
+ sizeof(g_MsgMemory
) / sizeof(MSGMEMORY
);
148 if (Msg
== MsgMemoryEntry
->Message
)
150 return MsgMemoryEntry
;
158 MsgMemorySize(PMSGMEMORY MsgMemoryEntry
, WPARAM wParam
, LPARAM lParam
)
161 PUNICODE_STRING WindowName
;
162 PUNICODE_STRING ClassName
;
167 if (MMS_SIZE_WPARAM
== MsgMemoryEntry
->Size
)
171 else if (MMS_SIZE_WPARAMWCHAR
== MsgMemoryEntry
->Size
)
173 Size
= (UINT
) (wParam
* sizeof(WCHAR
));
175 else if (MMS_SIZE_LPARAMSZ
== MsgMemoryEntry
->Size
)
177 // WM_SETTEXT and WM_SETTINGCHANGE can be null!
180 TRACE("lParam is NULL!\n");
184 Size
= (UINT
) ((wcslen((PWSTR
) lParam
) + 1) * sizeof(WCHAR
));
186 else if (MMS_SIZE_SPECIAL
== MsgMemoryEntry
->Size
)
188 switch(MsgMemoryEntry
->Message
)
192 Cs
= (CREATESTRUCTW
*) lParam
;
193 WindowName
= (PUNICODE_STRING
) Cs
->lpszName
;
194 ClassName
= (PUNICODE_STRING
) Cs
->lpszClass
;
195 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
196 if (IS_ATOM(ClassName
->Buffer
))
198 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
202 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
207 Size
= wParam
? sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
) : sizeof(RECT
);
211 Size
= sizeof(COPYDATASTRUCT
) + ((PCOPYDATASTRUCT
)lParam
)->cbData
;
222 Size
= MsgMemoryEntry
->Size
;
225 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
227 ERR("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH2_GetExceptionCode());
234 UINT
lParamMemorySize(UINT Msg
, WPARAM wParam
, LPARAM lParam
)
236 PMSGMEMORY MsgMemoryEntry
= FindMsgMemory(Msg
);
237 if(MsgMemoryEntry
== NULL
) return 0;
238 return MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
242 PackParam(LPARAM
*lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolNeeded
)
244 NCCALCSIZE_PARAMS
*UnpackedNcCalcsize
;
245 NCCALCSIZE_PARAMS
*PackedNcCalcsize
;
246 CREATESTRUCTW
*UnpackedCs
;
247 CREATESTRUCTW
*PackedCs
;
248 PLARGE_STRING WindowName
;
249 PUNICODE_STRING ClassName
;
254 *lParamPacked
= lParam
;
256 if (NonPagedPoolNeeded
)
257 PoolType
= NonPagedPool
;
259 PoolType
= PagedPool
;
261 if (WM_NCCALCSIZE
== Msg
&& wParam
)
264 UnpackedNcCalcsize
= (NCCALCSIZE_PARAMS
*) lParam
;
265 PackedNcCalcsize
= ExAllocatePoolWithTag(PoolType
,
266 sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
),
269 if (NULL
== PackedNcCalcsize
)
271 ERR("Not enough memory to pack lParam\n");
272 return STATUS_NO_MEMORY
;
274 RtlCopyMemory(PackedNcCalcsize
, UnpackedNcCalcsize
, sizeof(NCCALCSIZE_PARAMS
));
275 PackedNcCalcsize
->lppos
= (PWINDOWPOS
) (PackedNcCalcsize
+ 1);
276 RtlCopyMemory(PackedNcCalcsize
->lppos
, UnpackedNcCalcsize
->lppos
, sizeof(WINDOWPOS
));
277 *lParamPacked
= (LPARAM
) PackedNcCalcsize
;
279 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
281 UnpackedCs
= (CREATESTRUCTW
*) lParam
;
282 WindowName
= (PLARGE_STRING
) UnpackedCs
->lpszName
;
283 ClassName
= (PUNICODE_STRING
) UnpackedCs
->lpszClass
;
284 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
285 if (IS_ATOM(ClassName
->Buffer
))
287 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
291 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
293 PackedCs
= ExAllocatePoolWithTag(PoolType
, Size
, TAG_MSG
);
294 if (NULL
== PackedCs
)
296 ERR("Not enough memory to pack lParam\n");
297 return STATUS_NO_MEMORY
;
299 RtlCopyMemory(PackedCs
, UnpackedCs
, sizeof(CREATESTRUCTW
));
300 CsData
= (PCHAR
) (PackedCs
+ 1);
301 PackedCs
->lpszName
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
302 RtlCopyMemory(CsData
, WindowName
->Buffer
, WindowName
->Length
);
303 CsData
+= WindowName
->Length
;
304 *((WCHAR
*) CsData
) = L
'\0';
305 CsData
+= sizeof(WCHAR
);
306 PackedCs
->lpszClass
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
307 if (IS_ATOM(ClassName
->Buffer
))
309 *((WCHAR
*) CsData
) = L
'A';
310 CsData
+= sizeof(WCHAR
);
311 *((ATOM
*) CsData
) = (ATOM
)(DWORD_PTR
) ClassName
->Buffer
;
312 CsData
+= sizeof(ATOM
);
316 *((WCHAR
*) CsData
) = L
'S';
317 CsData
+= sizeof(WCHAR
);
318 RtlCopyMemory(CsData
, ClassName
->Buffer
, ClassName
->Length
);
319 CsData
+= ClassName
->Length
;
320 *((WCHAR
*) CsData
) = L
'\0';
321 CsData
+= sizeof(WCHAR
);
323 ASSERT(CsData
== (PCHAR
) PackedCs
+ Size
);
324 *lParamPacked
= (LPARAM
) PackedCs
;
326 else if (PoolType
== NonPagedPool
)
328 PMSGMEMORY MsgMemoryEntry
;
332 MsgMemoryEntry
= FindMsgMemory(Msg
);
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
);
394 if (MsgMemoryEntry
->Flags
== MMS_FLAG_READWRITE
)
396 //RtlCopyMemory((PVOID)lParam, (PVOID)lParamPacked, MsgMemoryEntry->Size);
398 ExFreePool((PVOID
) lParamPacked
);
399 return STATUS_SUCCESS
;
404 return STATUS_INVALID_PARAMETER
;
407 static NTSTATUS FASTCALL
408 CopyMsgToKernelMem(MSG
*KernelModeMsg
, MSG
*UserModeMsg
, PMSGMEMORY MsgMemoryEntry
)
415 *KernelModeMsg
= *UserModeMsg
;
417 /* See if this message type is present in the table */
418 if (NULL
== MsgMemoryEntry
)
420 /* Not present, no copying needed */
421 return STATUS_SUCCESS
;
424 /* Determine required size */
425 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
429 /* Allocate kernel mem */
430 KernelMem
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
431 if (NULL
== KernelMem
)
433 ERR("Not enough memory to copy message to kernel mem\n");
434 return STATUS_NO_MEMORY
;
436 KernelModeMsg
->lParam
= (LPARAM
) KernelMem
;
438 /* Copy data if required */
439 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_READ
))
441 TRACE("Copy Message %d from usermode buffer\n", KernelModeMsg
->message
);
442 Status
= MmCopyFromCaller(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
443 if (! NT_SUCCESS(Status
))
445 ERR("Failed to copy message to kernel: invalid usermode lParam buffer\n");
446 ExFreePoolWithTag(KernelMem
, TAG_MSG
);
452 /* Make sure we don't pass any secrets to usermode */
453 RtlZeroMemory(KernelMem
, Size
);
458 KernelModeMsg
->lParam
= 0;
461 return STATUS_SUCCESS
;
464 static NTSTATUS FASTCALL
465 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
468 PMSGMEMORY MsgMemoryEntry
;
471 /* See if this message type is present in the table */
472 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
473 if (NULL
== MsgMemoryEntry
)
475 /* Not present, no copying needed */
476 return STATUS_SUCCESS
;
479 /* Determine required size */
480 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
484 /* Copy data if required */
485 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
487 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
488 if (! NT_SUCCESS(Status
))
490 ERR("Failed to copy message from kernel: invalid usermode lParam buffer\n");
491 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
496 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
499 return STATUS_SUCCESS
;
503 // Wakeup any thread/process waiting on idle input.
508 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
511 pti
= PsGetCurrentThreadWin32Thread();
515 pti
->pClientInfo
->cSpins
= 0; // Reset spins.
517 if ( pti
->pDeskInfo
&& pti
== gptiForeground
)
519 if ( pti
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) ||
520 pti
->pDeskInfo
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) )
522 co_HOOK_CallHooks(WH_FOREGROUNDIDLE
,HC_ACTION
,0,0);
527 TRACE("IdlePing ppi %p\n", ppi
);
528 if ( ppi
&& ppi
->InputIdleEvent
)
530 TRACE("InputIdleEvent\n");
531 KeSetEvent( ppi
->InputIdleEvent
, IO_NO_INCREMENT
, FALSE
);
538 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
540 TRACE("IdlePong ppi %p\n", ppi
);
541 if ( ppi
&& ppi
->InputIdleEvent
)
543 KeClearEvent(ppi
->InputIdleEvent
);
548 GetWakeMask(UINT first
, UINT last
)
550 UINT mask
= QS_POSTMESSAGE
| QS_SENDMESSAGE
; /* Always selected */
554 if ((first
<= WM_KEYLAST
) && (last
>= WM_KEYFIRST
)) mask
|= QS_KEY
;
555 if ( ((first
<= WM_MOUSELAST
) && (last
>= WM_MOUSEFIRST
)) ||
556 ((first
<= WM_NCMOUSELAST
) && (last
>= WM_NCMOUSEFIRST
)) ) mask
|= QS_MOUSE
;
557 if ((first
<= WM_TIMER
) && (last
>= WM_TIMER
)) mask
|= QS_TIMER
;
558 if ((first
<= WM_SYSTIMER
) && (last
>= WM_SYSTIMER
)) mask
|= QS_TIMER
;
559 if ((first
<= WM_PAINT
) && (last
>= WM_PAINT
)) mask
|= QS_PAINT
;
561 else mask
= QS_ALLINPUT
;
567 IntCallWndProc( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
569 BOOL SameThread
= FALSE
;
572 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
579 co_HOOK_CallHooks( WH_CALLWNDPROC
, HC_ACTION
, SameThread
, (LPARAM
)&CWP
);
583 IntCallWndProcRet ( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*uResult
)
585 BOOL SameThread
= FALSE
;
588 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
593 CWPR
.wParam
= wParam
;
594 CWPR
.lParam
= lParam
;
595 CWPR
.lResult
= uResult
? (*uResult
) : 0;
596 co_HOOK_CallHooks( WH_CALLWNDPROCRET
, HC_ACTION
, SameThread
, (LPARAM
)&CWPR
);
599 static LRESULT
handle_internal_message( PWND pWnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
602 USER_REFERENCE_ENTRY Ref
;
603 // PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
606 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
607 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
610 TRACE("Internal Event Msg %p hWnd 0x%x\n",msg
,pWnd
->head
.h
);
614 case WM_ASYNC_SHOWWINDOW
:
615 return co_WinPosShowWindow( pWnd
, wparam
);
616 case WM_ASYNC_SETWINDOWPOS
:
618 PWINDOWPOS winpos
= (PWINDOWPOS
)lparam
;
619 if (!winpos
) return 0;
620 lRes
= co_WinPosSetWindowPos( pWnd
,
621 winpos
->hwndInsertAfter
,
627 ExFreePoolWithTag(winpos
, USERTAG_SWP
);
630 case WM_ASYNC_SETACTIVEWINDOW
:
632 PWND Window
= (PWND
)wparam
;
633 if (wparam
) UserRefObjectCo(Window
, &Ref
);
634 lRes
= (LRESULT
)co_IntSetActiveWindow(Window
,(BOOL
)lparam
,TRUE
,TRUE
);
635 if (wparam
) UserDerefObjectCo(Window
);
643 IntDispatchMessage(PMSG pMsg
)
645 LARGE_INTEGER TickCount
;
651 BOOL DoCallBack
= TRUE
;
655 Window
= UserGetWindowObject(pMsg
->hwnd
);
656 if (!Window
) return 0;
659 pti
= PsGetCurrentThreadWin32Thread();
661 if ( Window
&& Window
->head
.pti
!= pti
)
663 EngSetLastError( ERROR_MESSAGE_SYNC_ONLY
);
667 if (((pMsg
->message
== WM_SYSTIMER
) ||
668 (pMsg
->message
== WM_TIMER
)) &&
671 if (pMsg
->message
== WM_TIMER
)
673 if (ValidateTimerCallback(pti
,pMsg
->lParam
))
675 KeQueryTickCount(&TickCount
);
676 Time
= MsqCalculateMessageTime(&TickCount
);
677 retval
= co_IntCallWindowProc((WNDPROC
)pMsg
->lParam
,
689 PTIMER pTimer
= FindSystemTimer(pMsg
);
690 if (pTimer
&& pTimer
->pfn
)
692 KeQueryTickCount(&TickCount
);
693 Time
= MsqCalculateMessageTime(&TickCount
);
694 pTimer
->pfn(pMsg
->hwnd
, WM_SYSTIMER
, (UINT
)pMsg
->wParam
, Time
);
700 if ( !Window
) return 0;
702 if (pMsg
->message
== WM_PAINT
) Window
->state
|= WNDS_PAINTNOTPROCESSED
;
704 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
706 TRACE("Dispatch: Server Side Window Procedure\n");
710 DoCallBack
= !DesktopWindowProc( Window
,
716 case FNID_MESSAGEWND
:
717 DoCallBack
= !UserMessageWindowProc( Window
,
726 /* Since we are doing a callback on the same thread right away, there is
727 no need to copy the lparam to kernel mode and then back to usermode.
728 We just pretend it isn't a pointer */
731 retval
= co_IntCallWindowProc( Window
->lpfnWndProc
,
739 if (pMsg
->message
== WM_PAINT
)
741 Window
->state2
&= ~WNDS2_WMPAINTSENT
;
742 /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
743 hrgn
= IntSysCreateRectRgn( 0, 0, 0, 0 );
744 co_UserGetUpdateRgn( Window
, hrgn
, TRUE
);
745 GreDeleteObject(hrgn
);
752 * Internal version of PeekMessage() doing all the work
757 * Input (hardware) messages and system internal events
758 * Sent messages (again)
763 co_IntPeekMessage( PMSG Msg
,
771 LARGE_INTEGER LargeTickCount
;
776 pti
= PsGetCurrentThreadWin32Thread();
778 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
779 ProcessMask
= HIWORD(RemoveMsg
);
781 /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns
782 all available messages (that is, no range filtering is performed)". */
783 if (!ProcessMask
) ProcessMask
= (QS_ALLPOSTMESSAGE
|QS_ALLINPUT
);
789 KeQueryTickCount(&LargeTickCount
);
790 pti
->timeLast
= LargeTickCount
.u
.LowPart
;
791 pti
->pcti
->tickLastMsgChecked
= LargeTickCount
.u
.LowPart
;
793 /* Dispatch sent messages here. */
794 while ( co_MsqDispatchOneSentMessage(pti
) )
796 /* if some PM_QS* flags were specified, only handle sent messages from now on */
797 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
; // wine does this; ProcessMask = QS_SENDMESSAGE;
799 if (Hit
) return FALSE
;
801 /* Clear changed bits so we can wait on them if we don't find a message */
802 if (ProcessMask
& QS_POSTMESSAGE
)
804 pti
->pcti
->fsChangeBits
&= ~(QS_POSTMESSAGE
| QS_HOTKEY
| QS_TIMER
);
805 if (MsgFilterMin
== 0 && MsgFilterMax
== 0) // Wine hack does this; ~0U)
807 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
811 if (ProcessMask
& QS_INPUT
)
813 pti
->pcti
->fsChangeBits
&= ~QS_INPUT
;
816 /* Now check for normal messages. */
817 if (( (ProcessMask
& QS_POSTMESSAGE
) ||
818 (ProcessMask
& QS_HOTKEY
) ) &&
830 /* Now look for a quit message. */
833 /* According to the PSDK, WM_QUIT messages are always returned, regardless
834 of the filter specified */
836 Msg
->message
= WM_QUIT
;
837 Msg
->wParam
= pti
->exitCode
;
841 pti
->QuitPosted
= FALSE
;
842 ClearMsgBitsMask(pti
, QS_POSTMESSAGE
);
843 pti
->pcti
->fsWakeBits
&= ~QS_ALLPOSTMESSAGE
;
844 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
849 /* Check for hardware events. */
850 if ((ProcessMask
& QS_MOUSE
) &&
851 co_MsqPeekMouseMove( pti
,
861 if ((ProcessMask
& QS_INPUT
) &&
862 co_MsqPeekHardwareMessage( pti
,
873 /* Check for sent messages again. */
874 while ( co_MsqDispatchOneSentMessage(pti
) )
876 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
;
878 if (Hit
) return FALSE
;
880 /* Check for paint messages. */
881 if ((ProcessMask
& QS_PAINT
) &&
883 IntGetPaintMessage( Window
,
893 /* This is correct, check for the current threads timers waiting to be
894 posted to this threads message queue. If any we loop again.
896 if ((ProcessMask
& QS_TIMER
) &&
897 PostTimerMessages(Window
))
910 co_IntWaitMessage( PWND Window
,
915 NTSTATUS Status
= STATUS_SUCCESS
;
918 pti
= PsGetCurrentThreadWin32Thread();
922 if ( co_IntPeekMessage( &Msg
, // Dont reenter!
926 MAKELONG( PM_NOREMOVE
, GetWakeMask( MsgFilterMin
, MsgFilterMax
)),
927 TRUE
) ) // act like GetMessage.
932 /* Nothing found. Wait for new messages. */
933 Status
= co_MsqWaitForNewMessages( pti
,
937 if (!NT_SUCCESS(Status
))
939 SetLastNtError(Status
);
940 ERR("Exit co_IntWaitMessage on error!\n");
943 if (Status
== STATUS_USER_APC
|| Status
== STATUS_TIMEOUT
)
954 co_IntGetPeekMessage( PMSG pMsg
,
963 BOOL Present
= FALSE
;
966 if ( hWnd
== HWND_TOPMOST
|| hWnd
== HWND_BROADCAST
)
970 if (hWnd
&& hWnd
!= HWND_BOTTOM
)
972 if (!(Window
= UserGetWindowObject(hWnd
)))
985 if (MsgFilterMax
< MsgFilterMin
)
993 RemoveMsg
|= ((GetWakeMask( MsgFilterMin
, MsgFilterMax
))<< 16);
996 pti
= PsGetCurrentThreadWin32Thread();
997 pti
->pClientInfo
->cSpins
++; // Bump up the spin count.
1001 Present
= co_IntPeekMessage( pMsg
,
1009 /* GetMessage or PostMessage must never get messages that contain pointers */
1010 ASSERT(FindMsgMemory(pMsg
->message
) == NULL
);
1012 if (pMsg
->message
!= WM_PAINT
&& pMsg
->message
!= WM_QUIT
)
1014 pti
->timeLast
= pMsg
->time
;
1015 pti
->ptLast
= pMsg
->pt
;
1018 // The WH_GETMESSAGE hook enables an application to monitor messages about to
1019 // be returned by the GetMessage or PeekMessage function.
1021 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)pMsg
);
1028 Status
= co_MsqWaitForNewMessages( pti
,
1032 if ( !NT_SUCCESS(Status
) ||
1033 Status
== STATUS_USER_APC
||
1034 Status
== STATUS_TIMEOUT
)
1042 if (!(RemoveMsg
& PM_NOYIELD
))
1045 // Yield this thread!
1048 UserEnterExclusive();
1049 // Fall through to exit.
1055 while( bGMSG
&& !Present
);
1057 // Been spinning, time to swap vinyl...
1058 if (pti
->pClientInfo
->cSpins
>= 100)
1060 // Clear the spin cycle to fix the mix.
1061 pti
->pClientInfo
->cSpins
= 0;
1062 //if (!(pti->TIF_flags & TIF_SPINNING)) // FIXME: Need to swap vinyl...
1068 UserPostThreadMessage( PTHREADINFO pti
,
1074 LARGE_INTEGER LargeTickCount
;
1076 if (is_pointer_message(Msg
))
1078 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1081 Message
.hwnd
= NULL
;
1082 Message
.message
= Msg
;
1083 Message
.wParam
= wParam
;
1084 Message
.lParam
= lParam
;
1085 Message
.pt
= gpsi
->ptCursor
;
1087 KeQueryTickCount(&LargeTickCount
);
1088 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1089 MsqPostMessage(pti
, &Message
, FALSE
, QS_POSTMESSAGE
, 0);
1093 PTHREADINFO FASTCALL
1094 IntSendTo(PWND Window
, PTHREADINFO ptiCur
, UINT Msg
)
1099 Window
->head
.pti
->MessageQueue
== ptiCur
->MessageQueue
)
1104 return Window
? Window
->head
.pti
: NULL
;
1108 UserPostMessage( HWND Wnd
,
1114 MSG Message
, KernelModeMsg
;
1115 LARGE_INTEGER LargeTickCount
;
1118 Message
.message
= Msg
;
1119 Message
.wParam
= wParam
;
1120 Message
.lParam
= lParam
;
1121 Message
.pt
= gpsi
->ptCursor
;
1122 KeQueryTickCount(&LargeTickCount
);
1123 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1125 if (is_pointer_message(Message
.message
))
1127 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1131 if( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1134 PMSGMEMORY MsgMemoryEntry
;
1136 MsgMemoryEntry
= FindMsgMemory(Message
.message
);
1138 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &Message
, MsgMemoryEntry
);
1139 if (! NT_SUCCESS(Status
))
1141 EngSetLastError(ERROR_INVALID_PARAMETER
);
1144 co_IntSendMessageNoWait(KernelModeMsg
.hwnd
,
1145 KernelModeMsg
.message
,
1146 KernelModeMsg
.wParam
,
1147 KernelModeMsg
.lParam
);
1149 if (MsgMemoryEntry
&& KernelModeMsg
.lParam
)
1150 ExFreePool((PVOID
) KernelModeMsg
.lParam
);
1157 pti
= PsGetCurrentThreadWin32Thread();
1158 return UserPostThreadMessage( pti
,
1163 if (Wnd
== HWND_BROADCAST
)
1169 DesktopWindow
= UserGetDesktopWindow();
1170 List
= IntWinListChildren(DesktopWindow
);
1174 UserPostMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1175 for (i
= 0; List
[i
]; i
++)
1177 PWND pwnd
= UserGetWindowObject(List
[i
]);
1178 if (!pwnd
) continue;
1180 if ( pwnd
->fnid
== FNID_MENU
|| // Also need pwnd->pcls->atomClassName == gaOleMainThreadWndClass
1181 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1184 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1186 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1193 Window
= UserGetWindowObject(Wnd
);
1196 ERR("UserPostMessage: Invalid handle 0x%p!\n",Wnd
);
1200 pti
= Window
->head
.pti
;
1201 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1203 ERR("Attempted to post message to window %p when the thread is in cleanup!\n", Wnd
);
1207 if ( Window
->state
& WNDS_DESTROYED
)
1209 ERR("Attempted to post message to window %p that is being destroyed!\n", Wnd
);
1210 /* FIXME: Last error code? */
1216 MsqPostQuitMessage(pti
, wParam
);
1220 MsqPostMessage(pti
, &Message
, FALSE
, QS_POSTMESSAGE
, 0);
1227 co_IntSendMessage( HWND hWnd
,
1232 ULONG_PTR Result
= 0;
1233 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1235 return (LRESULT
)Result
;
1240 static LRESULT FASTCALL
1241 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1247 ULONG_PTR
*uResult
)
1251 PMSGMEMORY MsgMemoryEntry
;
1252 INT lParamBufferSize
;
1253 LPARAM lParamPacked
;
1254 PTHREADINFO Win32Thread
, ptiSendTo
= NULL
;
1255 ULONG_PTR Hi
, Lo
, Result
= 0;
1256 DECLARE_RETURN(LRESULT
);
1257 USER_REFERENCE_ENTRY Ref
;
1258 BOOL DoCallBack
= TRUE
;
1260 if (!(Window
= UserGetWindowObject(hWnd
)))
1262 TRACE("SendMessageTimeoutSingle: Invalid handle 0x%p!\n",hWnd
);
1266 UserRefObjectCo(Window
, &Ref
);
1268 Win32Thread
= PsGetCurrentThreadWin32Thread();
1270 ptiSendTo
= IntSendTo(Window
, Win32Thread
, Msg
);
1274 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1276 /* Never send messages to exiting threads */
1280 if (Msg
& 0x80000000)
1282 TRACE("SMTS: Internal Message!\n");
1283 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1284 if (uResult
) *uResult
= Result
;
1288 // Only happens when calling the client!
1289 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1291 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1293 TRACE("SMT: Server Side Window Procedure\n");
1294 IoGetStackLimits(&Lo
, &Hi
);
1295 // Handle it here. Safeguard against excessive recursions.
1296 if (((ULONG_PTR
)&uResult
- Lo
) < 4096 )
1298 ERR("Server Callback Exceeded Stack!\n");
1301 /* Return after server side call, IntCallWndProcRet will not be called. */
1302 switch(Window
->fnid
)
1305 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1307 case FNID_MESSAGEWND
:
1308 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1313 if (uResult
) *uResult
= Result
;
1317 /* See if this message type is present in the table */
1318 MsgMemoryEntry
= FindMsgMemory(Msg
);
1319 if (NULL
== MsgMemoryEntry
)
1321 lParamBufferSize
= -1;
1325 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1326 // If zero, do not allow callback on client side to allocate a buffer!!!!! See CORE-7695.
1327 if (!lParamBufferSize
) lParamBufferSize
= -1;
1330 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1332 ERR("Failed to pack message parameters\n");
1336 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1348 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1350 ERR("Failed to unpack message parameters\n");
1354 // Only happens when calling the client!
1355 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1360 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(ptiSendTo
))
1362 // FIXME: Set window hung and add to a list.
1363 /* FIXME: Set a LastError? */
1367 if (Window
->state
& WNDS_DESTROYED
)
1369 /* FIXME: Last error? */
1370 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1376 Status
= co_MsqSendMessage( ptiSendTo
,
1382 (uFlags
& SMTO_BLOCK
),
1386 while ((STATUS_TIMEOUT
== Status
) &&
1387 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1388 !MsqIsHung(ptiSendTo
)); // FIXME: Set window hung and add to a list.
1390 if (STATUS_TIMEOUT
== Status
)
1394 * Microsoft Windows 2000: If GetLastError returns zero, then the function
1396 * XP+ : If the function fails or times out, the return value is zero.
1397 * To get extended error information, call GetLastError. If GetLastError
1398 * returns ERROR_TIMEOUT, then the function timed out.
1400 EngSetLastError(ERROR_TIMEOUT
);
1403 else if (!NT_SUCCESS(Status
))
1405 SetLastNtError(Status
);
1412 if (Window
) UserDerefObjectCo(Window
);
1417 co_IntSendMessageTimeout( HWND hWnd
,
1423 ULONG_PTR
*uResult
)
1429 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1431 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1434 DesktopWindow
= UserGetDesktopWindow();
1435 if (NULL
== DesktopWindow
)
1437 EngSetLastError(ERROR_INTERNAL_ERROR
);
1441 if (hWnd
!= HWND_TOPMOST
)
1443 /* Send message to the desktop window too! */
1444 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1447 Children
= IntWinListChildren(DesktopWindow
);
1448 if (NULL
== Children
)
1453 for (Child
= Children
; NULL
!= *Child
; Child
++)
1455 if (hWnd
== HWND_TOPMOST
)
1457 DesktopWindow
= UserGetWindowObject(*Child
);
1458 if (DesktopWindow
&& DesktopWindow
->ExStyle
& WS_EX_TOPMOST
)
1460 ERR("HWND_TOPMOST Found\n");
1461 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1466 PWND pwnd
= UserGetWindowObject(*Child
);
1467 if (!pwnd
) continue;
1469 if ( pwnd
->fnid
== FNID_MENU
||
1470 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1473 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1477 ExFreePool(Children
);
1479 return (LRESULT
) TRUE
;
1483 co_IntSendMessageNoWait(HWND hWnd
,
1488 ULONG_PTR Result
= 0;
1489 return co_IntSendMessageWithCallBack( hWnd
,
1498 If you send a message in the range below WM_USER to the asynchronous message
1499 functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its
1500 message parameters cannot include pointers. Otherwise, the operation will fail.
1501 The functions will return before the receiving thread has had a chance to
1502 process the message and the sender will free the memory before it is used.
1505 co_IntSendMessageWithCallBack( HWND hWnd
,
1509 SENDASYNCPROC CompletionCallback
,
1510 ULONG_PTR CompletionCallbackContext
,
1515 PMSGMEMORY MsgMemoryEntry
;
1516 INT lParamBufferSize
;
1517 LPARAM lParamPacked
;
1518 PTHREADINFO Win32Thread
, ptiSendTo
= NULL
;
1519 DECLARE_RETURN(LRESULT
);
1520 USER_REFERENCE_ENTRY Ref
;
1521 PUSER_SENT_MESSAGE Message
;
1522 BOOL DoCallBack
= TRUE
;
1524 if (!(Window
= UserGetWindowObject(hWnd
)))
1526 TRACE("SendMessageWithCallBack: Invalid handle 0x%p!\n",hWnd
);
1530 UserRefObjectCo(Window
, &Ref
);
1532 if (Window
->state
& WNDS_DESTROYED
)
1534 /* FIXME: last error? */
1535 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1539 Win32Thread
= PsGetCurrentThreadWin32Thread();
1541 if (Win32Thread
== NULL
||
1542 Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1547 ptiSendTo
= IntSendTo(Window
, Win32Thread
, Msg
);
1549 if (Msg
& 0x80000000 &&
1552 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
) RETURN( FALSE
);
1554 TRACE("SMWCB: Internal Message!\n");
1555 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1556 if (uResult
) *uResult
= Result
;
1560 /* See if this message type is present in the table */
1561 MsgMemoryEntry
= FindMsgMemory(Msg
);
1562 if (NULL
== MsgMemoryEntry
)
1564 lParamBufferSize
= -1;
1568 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1569 if (!lParamBufferSize
) lParamBufferSize
= -1;
1572 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, !!ptiSendTo
)))
1574 ERR("Failed to pack message parameters\n");
1578 /* If it can be sent now, then send it. */
1581 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1583 UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
);
1584 /* Never send messages to exiting threads */
1588 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1590 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1592 TRACE("SMWCB: Server Side Window Procedure\n");
1593 switch(Window
->fnid
)
1596 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParamPacked
, (LRESULT
*)&Result
);
1598 case FNID_MESSAGEWND
:
1599 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1605 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1617 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1619 if (CompletionCallback
)
1621 co_IntCallSentMessageCallback(CompletionCallback
,
1624 CompletionCallbackContext
,
1631 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1633 ERR("Failed to unpack message parameters\n");
1638 if(!(Message
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
1640 ERR("MsqSendMessage(): Not enough memory to allocate a message");
1644 Message
->Msg
.hwnd
= hWnd
;
1645 Message
->Msg
.message
= Msg
;
1646 Message
->Msg
.wParam
= wParam
;
1647 Message
->Msg
.lParam
= lParamPacked
;
1648 Message
->CompletionEvent
= NULL
;
1649 Message
->Result
= 0;
1650 Message
->lResult
= 0;
1651 Message
->QS_Flags
= 0;
1652 Message
->ptiReceiver
= ptiSendTo
;
1653 Message
->ptiSender
= NULL
; // mjmartin, you are right! This is null.
1654 Message
->ptiCallBackSender
= Win32Thread
;
1655 Message
->DispatchingListEntry
.Flink
= NULL
;
1656 Message
->CompletionCallback
= CompletionCallback
;
1657 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1658 Message
->HookMessage
= MSQ_NORMAL
;
1659 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1660 Message
->QS_Flags
= QS_SENDMESSAGE
;
1662 if (Msg
& 0x80000000) // Higher priority event message!
1663 InsertHeadList(&ptiSendTo
->SentMessagesListHead
, &Message
->ListEntry
);
1665 InsertTailList(&ptiSendTo
->SentMessagesListHead
, &Message
->ListEntry
);
1666 MsqWakeQueue(ptiSendTo
, QS_SENDMESSAGE
, TRUE
);
1671 if (Window
) UserDerefObjectCo(Window
);
1677 This HACK function posts a message if the destination's message queue belongs to
1678 another thread, otherwise it sends the message. It does not support broadcast
1682 co_IntPostOrSendMessage( HWND hWnd
,
1691 if ( hWnd
== HWND_BROADCAST
)
1696 if(!(Window
= UserGetWindowObject(hWnd
)))
1698 TRACE("PostOrSendMessage: Invalid handle 0x%p!\n",hWnd
);
1702 pti
= PsGetCurrentThreadWin32Thread();
1704 if ( IntSendTo(Window
, pti
, Msg
) &&
1705 FindMsgMemory(Msg
) == 0 )
1707 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1711 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1717 return (LRESULT
)Result
;
1720 static LRESULT FASTCALL
1721 co_IntDoSendMessage( HWND hWnd
,
1727 LRESULT Result
= TRUE
;
1730 MSG UserModeMsg
, KernelModeMsg
;
1731 PMSGMEMORY MsgMemoryEntry
;
1732 PTHREADINFO ptiSendTo
;
1734 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1736 Window
= UserGetWindowObject(hWnd
);
1743 /* Check for an exiting window. */
1744 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1746 ERR("co_IntDoSendMessage Window Exiting!\n");
1749 /* See if the current thread can handle this message */
1750 ptiSendTo
= IntSendTo(Window
, gptiCurrent
, Msg
);
1752 // If broadcasting or sending to another thread, save the users data.
1753 if (!Window
|| ptiSendTo
)
1755 UserModeMsg
.hwnd
= hWnd
;
1756 UserModeMsg
.message
= Msg
;
1757 UserModeMsg
.wParam
= wParam
;
1758 UserModeMsg
.lParam
= lParam
;
1759 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 KernelModeMsg
.hwnd
= hWnd
;
1770 KernelModeMsg
.message
= Msg
;
1771 KernelModeMsg
.wParam
= wParam
;
1772 KernelModeMsg
.lParam
= lParam
;
1777 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1778 KernelModeMsg
.message
,
1779 KernelModeMsg
.wParam
,
1780 KernelModeMsg
.lParam
);
1784 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1785 KernelModeMsg
.message
,
1786 KernelModeMsg
.wParam
,
1787 KernelModeMsg
.lParam
,
1793 if (!Window
|| ptiSendTo
)
1795 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1796 if (!NT_SUCCESS(Status
))
1798 EngSetLastError(ERROR_INVALID_PARAMETER
);
1799 return(dsm
? 0 : -1);
1803 return (LRESULT
)Result
;
1807 UserSendNotifyMessage( HWND hWnd
,
1814 if (is_pointer_message(Msg
))
1816 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1820 // Basicly the same as IntPostOrSendMessage
1821 if (hWnd
== HWND_BROADCAST
) // Handle Broadcast
1827 DesktopWindow
= UserGetDesktopWindow();
1828 List
= IntWinListChildren(DesktopWindow
);
1832 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1833 for (i
= 0; List
[i
]; i
++)
1835 PWND pwnd
= UserGetWindowObject(List
[i
]);
1836 if (!pwnd
) continue;
1838 if ( pwnd
->fnid
== FNID_MENU
||
1839 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1842 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1849 Ret
= co_IntSendMessageNoWait( hWnd
, Msg
, wParam
, lParam
);
1856 IntGetQueueStatus(DWORD Changes
)
1861 pti
= PsGetCurrentThreadWin32Thread();
1863 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1865 /* High word, types of messages currently in the queue.
1866 Low word, types of messages that have been added to the queue and that
1867 are still in the queue
1869 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1871 pti
->pcti
->fsChangeBits
&= ~Changes
;
1877 IntInitMessagePumpHook()
1879 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1883 pti
->pcti
->dwcPumpHook
++;
1890 IntUninitMessagePumpHook()
1892 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1896 if (pti
->pcti
->dwcPumpHook
<= 0)
1900 pti
->pcti
->dwcPumpHook
--;
1906 /** Functions ******************************************************************/
1912 POINT pt
) // Just like the User call.
1916 ULONG wDragWidth
, wDragHeight
;
1917 DECLARE_RETURN(BOOL
);
1919 TRACE("Enter NtUserDragDetect(%p)\n", hWnd
);
1920 UserEnterExclusive();
1922 wDragWidth
= UserGetSystemMetrics(SM_CXDRAG
);
1923 wDragHeight
= UserGetSystemMetrics(SM_CYDRAG
);
1925 rect
.left
= pt
.x
- wDragWidth
;
1926 rect
.right
= pt
.x
+ wDragWidth
;
1928 rect
.top
= pt
.y
- wDragHeight
;
1929 rect
.bottom
= pt
.y
+ wDragHeight
;
1931 co_UserSetCapture(hWnd
);
1935 while (co_IntGetPeekMessage( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, FALSE
) ||
1936 co_IntGetPeekMessage( &msg
, 0, WM_QUEUESYNC
, WM_QUEUESYNC
, PM_REMOVE
, FALSE
) ||
1937 co_IntGetPeekMessage( &msg
, 0, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
, FALSE
) )
1939 if ( msg
.message
== WM_LBUTTONUP
)
1941 co_UserSetCapture(NULL
);
1944 if ( msg
.message
== WM_MOUSEMOVE
)
1947 tmp
.x
= (short)LOWORD(msg
.lParam
);
1948 tmp
.y
= (short)HIWORD(msg
.lParam
);
1949 if( !RECTL_bPointInRect( &rect
, tmp
.x
, tmp
.y
) )
1951 co_UserSetCapture(NULL
);
1955 if ( msg
.message
== WM_KEYDOWN
)
1957 if ( msg
.wParam
== VK_ESCAPE
)
1959 co_UserSetCapture(NULL
);
1963 if ( msg
.message
== WM_QUEUESYNC
)
1965 co_HOOK_CallHooks( WH_CBT
, HCBT_QS
, 0, 0 );
1968 co_IntWaitMessage(NULL
, 0, 0);
1973 TRACE("Leave NtUserDragDetect, ret=%i\n",_ret_
);
1979 NtUserPostMessage(HWND hWnd
,
1986 UserEnterExclusive();
1988 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1996 NtUserPostThreadMessage(DWORD idThread
,
2003 PTHREADINFO pThread
;
2006 UserEnterExclusive();
2008 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
2010 if ( Status
== STATUS_SUCCESS
)
2012 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
2014 !pThread
->MessageQueue
||
2015 (pThread
->TIF_flags
& TIF_INCLEANUP
))
2017 ObDereferenceObject( peThread
);
2020 ret
= UserPostThreadMessage( pThread
, Msg
, wParam
, lParam
);
2021 ObDereferenceObject( peThread
);
2025 SetLastNtError( Status
);
2033 NtUserWaitMessage(VOID
)
2037 UserEnterExclusive();
2038 TRACE("NtUserWaitMessage Enter\n");
2039 ret
= co_IntWaitMessage(NULL
, 0, 0);
2040 TRACE("NtUserWaitMessage Leave\n");
2047 NtUserGetMessage(PMSG pMsg
,
2055 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
2057 EngSetLastError(ERROR_INVALID_PARAMETER
);
2061 UserEnterExclusive();
2063 RtlZeroMemory(&Msg
, sizeof(MSG
));
2065 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
2073 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2074 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2076 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2078 SetLastNtError(_SEH2_GetExceptionCode());
2085 Ret
= Ret
? (WM_QUIT
!= pMsg
->message
) : FALSE
;
2091 NtUserPeekMessage( PMSG pMsg
,
2100 if ( RemoveMsg
& PM_BADMSGFLAGS
)
2102 EngSetLastError(ERROR_INVALID_FLAGS
);
2106 UserEnterExclusive();
2108 RtlZeroMemory(&Msg
, sizeof(MSG
));
2110 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
2118 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2119 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2121 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2123 SetLastNtError(_SEH2_GetExceptionCode());
2133 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
2140 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
2141 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
2143 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2145 _SEH2_YIELD(return FALSE
);
2149 UserEnterExclusive();
2151 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
2157 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
2164 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
2165 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
2167 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2177 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
2184 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
2185 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
2187 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2189 SetLastNtError(_SEH2_GetExceptionCode());
2190 _SEH2_YIELD(return FALSE
);
2194 UserEnterExclusive();
2196 Res
= IntDispatchMessage(&SafeMsg
);
2203 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
2211 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
2212 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
2214 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2216 SetLastNtError(_SEH2_GetExceptionCode());
2217 _SEH2_YIELD(return FALSE
);
2221 UserEnterExclusive();
2222 pWnd
= UserGetWindowObject(SafeMsg
.hwnd
);
2223 if (pWnd
) // Must have a window!
2225 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
2229 TRACE("No Window for Translate. hwnd 0x%p Msg %u\n", SafeMsg
.hwnd
, SafeMsg
.message
);
2237 LRESULT APIENTRY
ScrollBarWndProc(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
);
2240 NtUserMessageCall( HWND hWnd
,
2244 ULONG_PTR ResultInfo
,
2245 DWORD dwType
, // fnID?
2248 LRESULT lResult
= 0;
2251 USER_REFERENCE_ENTRY Ref
;
2253 UserEnterExclusive();
2257 case FNID_SCROLLBAR
:
2259 lResult
= ScrollBarWndProc(hWnd
, Msg
, wParam
, lParam
);
2264 Window
= UserGetWindowObject(hWnd
);
2267 //ERR("FNID_DESKTOP IN\n");
2268 Ret
= DesktopWindowProc(Window
, Msg
, wParam
, lParam
, &lResult
);
2269 //ERR("FNID_DESKTOP OUT\n");
2274 case FNID_MESSAGEWND
:
2276 Window
= UserGetWindowObject(hWnd
);
2279 Ret
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,&lResult
);
2283 case FNID_DEFWINDOWPROC
:
2284 /* Validate input */
2287 Window
= UserGetWindowObject(hWnd
);
2293 UserRefObjectCo(Window
, &Ref
);
2295 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2298 UserDerefObjectCo(Window
);
2300 case FNID_SENDNOTIFYMESSAGE
:
2301 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2303 case FNID_BROADCASTSYSTEMMESSAGE
:
2305 BROADCASTPARM parm
, *retparam
;
2306 DWORD_PTR RetVal
= 0;
2312 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2313 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2315 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2324 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2325 parm
.recipients
== BSM_ALLCOMPONENTS
)
2327 PLIST_ENTRY DesktopEntry
;
2329 HWND
*List
, hwndDenied
= NULL
;
2331 PWND pwnd
, pwndDesk
;
2335 for (DesktopEntry
= InputWindowStation
->DesktopListHead
.Flink
;
2336 DesktopEntry
!= &InputWindowStation
->DesktopListHead
;
2337 DesktopEntry
= DesktopEntry
->Flink
)
2339 rpdesk
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
2340 pwndDesk
= rpdesk
->pDeskInfo
->spwnd
;
2341 List
= IntWinListChildren(pwndDesk
);
2343 if (parm
.flags
& BSF_QUERY
)
2347 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2349 fuFlags
= SMTO_ABORTIFHUNG
;
2351 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2353 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2357 fuFlags
= SMTO_NORMAL
;
2359 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2367 for (i
= 0; List
[i
]; i
++)
2369 pwnd
= UserGetWindowObject(List
[i
]);
2370 if (!pwnd
) continue;
2372 if ( pwnd
->fnid
== FNID_MENU
||
2373 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2376 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2378 if ( pwnd
->head
.pti
== gptiCurrent
)
2381 co_IntSendMessageTimeout( List
[i
],
2389 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2391 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2394 if (RetVal
== BROADCAST_QUERY_DENY
)
2396 hwndDenied
= List
[i
];
2397 hDesk
= UserHMGetHandle(pwndDesk
);
2401 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2404 retparam
= (PBROADCASTPARM
) ResultInfo
;
2405 retparam
->hDesk
= hDesk
;
2406 retparam
->hWnd
= hwndDenied
;
2408 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2413 if (!Ret
) break; // Have a hit! Let everyone know!
2416 else if (parm
.flags
& BSF_POSTMESSAGE
)
2420 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2422 for (i
= 0; List
[i
]; i
++)
2424 pwnd
= UserGetWindowObject(List
[i
]);
2425 if (!pwnd
) continue;
2427 if ( pwnd
->fnid
== FNID_MENU
||
2428 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2431 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2433 if ( pwnd
->head
.pti
== gptiCurrent
)
2436 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2438 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2446 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2448 for (i
= 0; List
[i
]; i
++)
2450 pwnd
= UserGetWindowObject(List
[i
]);
2451 if (!pwnd
) continue;
2453 if ( pwnd
->fnid
== FNID_MENU
||
2454 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2457 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2459 if ( pwnd
->head
.pti
== gptiCurrent
)
2462 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2464 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2470 else if (parm
.recipients
& BSM_APPLICATIONS
)
2472 HWND
*List
, hwndDenied
= NULL
;
2474 PWND pwnd
, pwndDesk
;
2478 pwndDesk
= UserGetDesktopWindow();
2479 List
= IntWinListChildren(pwndDesk
);
2481 if (parm
.flags
& BSF_QUERY
)
2485 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2487 fuFlags
= SMTO_ABORTIFHUNG
;
2489 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2491 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2495 fuFlags
= SMTO_NORMAL
;
2497 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2505 for (i
= 0; List
[i
]; i
++)
2507 pwnd
= UserGetWindowObject(List
[i
]);
2508 if (!pwnd
) continue;
2510 if ( pwnd
->fnid
== FNID_MENU
||
2511 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2514 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2516 if ( pwnd
->head
.pti
== gptiCurrent
)
2519 co_IntSendMessageTimeout( List
[i
],
2527 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2529 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2532 if (RetVal
== BROADCAST_QUERY_DENY
)
2534 hwndDenied
= List
[i
];
2535 hDesk
= UserHMGetHandle(pwndDesk
);
2539 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2542 retparam
= (PBROADCASTPARM
) ResultInfo
;
2543 retparam
->hDesk
= hDesk
;
2544 retparam
->hWnd
= hwndDenied
;
2546 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2553 else if (parm
.flags
& BSF_POSTMESSAGE
)
2557 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2559 for (i
= 0; List
[i
]; i
++)
2561 pwnd
= UserGetWindowObject(List
[i
]);
2562 if (!pwnd
) continue;
2564 if ( pwnd
->fnid
== FNID_MENU
||
2565 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2568 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2570 if ( pwnd
->head
.pti
== gptiCurrent
)
2573 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2575 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2583 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2585 for (i
= 0; List
[i
]; i
++)
2587 pwnd
= UserGetWindowObject(List
[i
]);
2588 if (!pwnd
) continue;
2590 if ( pwnd
->fnid
== FNID_MENU
||
2591 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2594 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2596 if ( pwnd
->head
.pti
== gptiCurrent
)
2599 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2601 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2608 case FNID_SENDMESSAGECALLBACK
:
2610 CALL_BACK_INFO CallBackInfo
;
2615 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2616 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2618 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2624 if (is_pointer_message(Msg
))
2626 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
2630 if (!(Ret
= co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2631 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
)))
2633 ERR("Callback failure!\n");
2637 case FNID_SENDMESSAGE
:
2639 Ret
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2645 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2646 RtlCopyMemory((PVOID
)ResultInfo
, &Ret
, sizeof(ULONG_PTR
));
2648 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2657 case FNID_SENDMESSAGEFF
:
2658 case FNID_SENDMESSAGEWTOOPTION
:
2660 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2665 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2666 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2668 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2675 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, &dsm
);
2681 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2682 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2684 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2693 // CallNextHook bypass.
2694 case FNID_CALLWNDPROC
:
2695 case FNID_CALLWNDPROCRET
:
2698 PCLIENTINFO ClientInfo
;
2699 PHOOK NextObj
, Hook
;
2701 pti
= GetW32ThreadInfo();
2703 Hook
= pti
->sphkCurrent
;
2707 NextObj
= Hook
->phkNext
;
2708 ClientInfo
= pti
->pClientInfo
;
2711 ClientInfo
->phkCurrent
= NextObj
;
2713 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2719 if (!ClientInfo
|| !NextObj
) break;
2721 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2723 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2728 CWP
.wParam
= wParam
;
2729 CWP
.lParam
= lParam
;
2730 TRACE("WH_CALLWNDPROC: Hook %p NextHook %p\n", Hook
, NextObj
);
2732 lResult
= co_IntCallHookProc( Hook
->HookId
,
2734 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2747 CWPR
.wParam
= wParam
;
2748 CWPR
.lParam
= lParam
;
2749 CWPR
.lResult
= ClientInfo
->dwHookData
;
2751 lResult
= co_IntCallHookProc( Hook
->HookId
,
2753 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2767 case FNID_DEFWINDOWPROC
:
2768 case FNID_CALLWNDPROC
:
2769 case FNID_CALLWNDPROCRET
:
2770 case FNID_SCROLLBAR
:
2776 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2777 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2779 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2795 #define INFINITE 0xFFFFFFFF
2796 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2800 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2801 IN DWORD dwMilliseconds
,
2805 PPROCESSINFO W32Process
;
2809 LARGE_INTEGER Timeout
;
2811 UserEnterExclusive();
2813 Status
= ObReferenceObjectByHandle(hProcess
,
2814 PROCESS_QUERY_INFORMATION
,
2820 if (!NT_SUCCESS(Status
))
2823 SetLastNtError(Status
);
2827 pti
= PsGetCurrentThreadWin32Thread();
2829 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2831 if ( PsGetProcessExitProcessCalled(Process
) ||
2833 pti
->ppi
== W32Process
)
2835 ObDereferenceObject(Process
);
2837 EngSetLastError(ERROR_INVALID_PARAMETER
);
2841 Handles
[0] = Process
;
2842 Handles
[1] = W32Process
->InputIdleEvent
;
2843 Handles
[2] = pti
->pEventQueueServer
; // IntMsqSetWakeMask returns hEventQueueClient
2847 ObDereferenceObject(Process
);
2849 return STATUS_SUCCESS
; /* no event to wait on */
2852 if (dwMilliseconds
!= INFINITE
)
2853 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2855 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2856 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2858 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2859 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2862 TRACE("WFII: ppi %p\n", W32Process
);
2863 TRACE("WFII: waiting for %p\n", Handles
[1] );
2867 Status
= KeWaitForMultipleObjects( 3,
2873 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2875 UserEnterExclusive();
2877 if (!NT_SUCCESS(Status
))
2879 SetLastNtError(Status
);
2880 Status
= WAIT_FAILED
;
2892 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2893 ERR("WFII: WAIT 2\n");
2897 case STATUS_TIMEOUT
:
2898 ERR("WFII: timeout\n");
2903 ERR("WFII: finished\n");
2904 Status
= STATUS_SUCCESS
;
2911 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2913 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
2914 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2916 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
2917 ObDereferenceObject(Process
);