2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
5 * FILE: win32ss/user/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_GETMINMAXINFO
, sizeof(MINMAXINFO
), MMS_FLAG_READWRITE
},
126 { WM_GETTEXT
, MMS_SIZE_WPARAMWCHAR
, MMS_FLAG_WRITE
},
127 { WM_NCCALCSIZE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
128 { WM_NCCREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
129 { WM_SETTEXT
, MMS_SIZE_LPARAMSZ
, MMS_FLAG_READ
},
130 { WM_STYLECHANGED
, sizeof(STYLESTRUCT
), MMS_FLAG_READ
},
131 { WM_STYLECHANGING
, sizeof(STYLESTRUCT
), MMS_FLAG_READWRITE
},
132 { WM_SETTINGCHANGE
, MMS_SIZE_LPARAMSZ
, MMS_FLAG_READ
},
133 { WM_COPYDATA
, MMS_SIZE_SPECIAL
, MMS_FLAG_READ
},
134 { WM_COPYGLOBALDATA
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
135 { WM_WINDOWPOSCHANGED
, sizeof(WINDOWPOS
), MMS_FLAG_READWRITE
},
136 { WM_WINDOWPOSCHANGING
, sizeof(WINDOWPOS
), MMS_FLAG_READWRITE
},
137 { WM_SIZING
, sizeof(RECT
), MMS_FLAG_READWRITE
},
138 { WM_MOVING
, sizeof(RECT
), MMS_FLAG_READWRITE
},
139 { WM_MEASUREITEM
, sizeof(MEASUREITEMSTRUCT
), MMS_FLAG_READWRITE
},
140 { WM_DRAWITEM
, sizeof(DRAWITEMSTRUCT
), MMS_FLAG_READWRITE
},
141 { WM_HELP
, sizeof(HELPINFO
), MMS_FLAG_READWRITE
},
142 { WM_NEXTMENU
, sizeof(MDINEXTMENU
), MMS_FLAG_READWRITE
},
145 static PMSGMEMORY FASTCALL
146 FindMsgMemory(UINT Msg
)
148 PMSGMEMORY MsgMemoryEntry
;
150 /* See if this message type is present in the table */
151 for (MsgMemoryEntry
= g_MsgMemory
;
152 MsgMemoryEntry
< g_MsgMemory
+ sizeof(g_MsgMemory
) / sizeof(MSGMEMORY
);
155 if (Msg
== MsgMemoryEntry
->Message
)
157 return MsgMemoryEntry
;
165 MsgMemorySize(PMSGMEMORY MsgMemoryEntry
, WPARAM wParam
, LPARAM lParam
)
168 PUNICODE_STRING WindowName
;
169 PUNICODE_STRING ClassName
;
174 if (MMS_SIZE_WPARAM
== MsgMemoryEntry
->Size
)
178 else if (MMS_SIZE_WPARAMWCHAR
== MsgMemoryEntry
->Size
)
180 Size
= (UINT
) (wParam
* sizeof(WCHAR
));
182 else if (MMS_SIZE_LPARAMSZ
== MsgMemoryEntry
->Size
)
184 // WM_SETTEXT and WM_SETTINGCHANGE can be null!
187 TRACE("lParam is NULL!\n");
191 Size
= (UINT
) ((wcslen((PWSTR
) lParam
) + 1) * sizeof(WCHAR
));
193 else if (MMS_SIZE_SPECIAL
== MsgMemoryEntry
->Size
)
195 switch(MsgMemoryEntry
->Message
)
199 Cs
= (CREATESTRUCTW
*) lParam
;
200 WindowName
= (PUNICODE_STRING
) Cs
->lpszName
;
201 ClassName
= (PUNICODE_STRING
) Cs
->lpszClass
;
202 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
203 if (IS_ATOM(ClassName
->Buffer
))
205 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
209 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
214 Size
= wParam
? sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
) : sizeof(RECT
);
219 COPYDATASTRUCT
*cds
= (COPYDATASTRUCT
*)lParam
;
220 Size
= sizeof(COPYDATASTRUCT
) + cds
->cbData
;
232 Size
= MsgMemoryEntry
->Size
;
235 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
237 ERR("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH2_GetExceptionCode());
244 UINT
lParamMemorySize(UINT Msg
, WPARAM wParam
, LPARAM lParam
)
246 PMSGMEMORY MsgMemoryEntry
= FindMsgMemory(Msg
);
247 if(MsgMemoryEntry
== NULL
) return 0;
248 return MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
252 PackParam(LPARAM
*lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolNeeded
)
254 NCCALCSIZE_PARAMS
*UnpackedNcCalcsize
;
255 NCCALCSIZE_PARAMS
*PackedNcCalcsize
;
256 CREATESTRUCTW
*UnpackedCs
;
257 CREATESTRUCTW
*PackedCs
;
258 PLARGE_STRING WindowName
;
259 PUNICODE_STRING ClassName
;
264 *lParamPacked
= lParam
;
266 if (NonPagedPoolNeeded
)
267 PoolType
= NonPagedPool
;
269 PoolType
= PagedPool
;
271 if (WM_NCCALCSIZE
== Msg
&& wParam
)
274 UnpackedNcCalcsize
= (NCCALCSIZE_PARAMS
*) lParam
;
275 PackedNcCalcsize
= ExAllocatePoolWithTag(PoolType
,
276 sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
),
279 if (NULL
== PackedNcCalcsize
)
281 ERR("Not enough memory to pack lParam\n");
282 return STATUS_NO_MEMORY
;
284 RtlCopyMemory(PackedNcCalcsize
, UnpackedNcCalcsize
, sizeof(NCCALCSIZE_PARAMS
));
285 PackedNcCalcsize
->lppos
= (PWINDOWPOS
) (PackedNcCalcsize
+ 1);
286 RtlCopyMemory(PackedNcCalcsize
->lppos
, UnpackedNcCalcsize
->lppos
, sizeof(WINDOWPOS
));
287 *lParamPacked
= (LPARAM
) PackedNcCalcsize
;
289 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
291 UnpackedCs
= (CREATESTRUCTW
*) lParam
;
292 WindowName
= (PLARGE_STRING
) UnpackedCs
->lpszName
;
293 ClassName
= (PUNICODE_STRING
) UnpackedCs
->lpszClass
;
294 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
295 if (IS_ATOM(ClassName
->Buffer
))
297 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
301 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
303 PackedCs
= ExAllocatePoolWithTag(PoolType
, Size
, TAG_MSG
);
304 if (NULL
== PackedCs
)
306 ERR("Not enough memory to pack lParam\n");
307 return STATUS_NO_MEMORY
;
309 RtlCopyMemory(PackedCs
, UnpackedCs
, sizeof(CREATESTRUCTW
));
310 CsData
= (PCHAR
) (PackedCs
+ 1);
311 PackedCs
->lpszName
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
312 RtlCopyMemory(CsData
, WindowName
->Buffer
, WindowName
->Length
);
313 CsData
+= WindowName
->Length
;
314 *((WCHAR
*) CsData
) = L
'\0';
315 CsData
+= sizeof(WCHAR
);
316 PackedCs
->lpszClass
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
317 if (IS_ATOM(ClassName
->Buffer
))
319 *((WCHAR
*) CsData
) = L
'A';
320 CsData
+= sizeof(WCHAR
);
321 *((ATOM
*) CsData
) = (ATOM
)(DWORD_PTR
) ClassName
->Buffer
;
322 CsData
+= sizeof(ATOM
);
326 NT_ASSERT(ClassName
->Buffer
!= NULL
);
327 *((WCHAR
*) CsData
) = L
'S';
328 CsData
+= sizeof(WCHAR
);
329 RtlCopyMemory(CsData
, ClassName
->Buffer
, ClassName
->Length
);
330 CsData
+= ClassName
->Length
;
331 *((WCHAR
*) CsData
) = L
'\0';
332 CsData
+= sizeof(WCHAR
);
334 ASSERT(CsData
== (PCHAR
) PackedCs
+ Size
);
335 *lParamPacked
= (LPARAM
) PackedCs
;
337 else if (PoolType
== NonPagedPool
)
339 PMSGMEMORY MsgMemoryEntry
;
343 MsgMemoryEntry
= FindMsgMemory(Msg
);
347 /* Keep previous behavior */
348 return STATUS_SUCCESS
;
350 size
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
353 ERR("No size for lParamPacked\n");
354 return STATUS_SUCCESS
;
356 PackedData
= ExAllocatePoolWithTag(NonPagedPool
, size
, TAG_MSG
);
357 if (PackedData
== NULL
)
359 ERR("Not enough memory to pack lParam\n");
360 return STATUS_NO_MEMORY
;
362 RtlCopyMemory(PackedData
, (PVOID
)lParam
, MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
));
363 *lParamPacked
= (LPARAM
)PackedData
;
366 return STATUS_SUCCESS
;
370 UnpackParam(LPARAM lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolUsed
)
372 NCCALCSIZE_PARAMS
*UnpackedParams
;
373 NCCALCSIZE_PARAMS
*PackedParams
;
374 PWINDOWPOS UnpackedWindowPos
;
376 if (lParamPacked
== lParam
)
378 return STATUS_SUCCESS
;
381 if (WM_NCCALCSIZE
== Msg
&& wParam
)
383 PackedParams
= (NCCALCSIZE_PARAMS
*) lParamPacked
;
384 UnpackedParams
= (NCCALCSIZE_PARAMS
*) lParam
;
385 UnpackedWindowPos
= UnpackedParams
->lppos
;
386 RtlCopyMemory(UnpackedParams
, PackedParams
, sizeof(NCCALCSIZE_PARAMS
));
387 UnpackedParams
->lppos
= UnpackedWindowPos
;
388 RtlCopyMemory(UnpackedWindowPos
, PackedParams
+ 1, sizeof(WINDOWPOS
));
389 ExFreePool((PVOID
) lParamPacked
);
391 return STATUS_SUCCESS
;
393 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
395 ExFreePool((PVOID
) lParamPacked
);
397 return STATUS_SUCCESS
;
399 else if (NonPagedPoolUsed
)
401 PMSGMEMORY MsgMemoryEntry
;
402 MsgMemoryEntry
= FindMsgMemory(Msg
);
403 ASSERT(MsgMemoryEntry
);
405 if (MsgMemoryEntry
->Flags
== MMS_FLAG_READWRITE
)
407 //RtlCopyMemory((PVOID)lParam, (PVOID)lParamPacked, MsgMemoryEntry->Size);
409 ExFreePool((PVOID
) lParamPacked
);
410 return STATUS_SUCCESS
;
415 return STATUS_INVALID_PARAMETER
;
418 static NTSTATUS FASTCALL
419 CopyMsgToKernelMem(MSG
*KernelModeMsg
, MSG
*UserModeMsg
, PMSGMEMORY MsgMemoryEntry
)
426 *KernelModeMsg
= *UserModeMsg
;
428 /* See if this message type is present in the table */
429 if (NULL
== MsgMemoryEntry
)
431 /* Not present, no copying needed */
432 return STATUS_SUCCESS
;
435 /* Determine required size */
436 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
440 /* Allocate kernel mem */
441 KernelMem
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
442 if (NULL
== KernelMem
)
444 ERR("Not enough memory to copy message to kernel mem\n");
445 return STATUS_NO_MEMORY
;
447 KernelModeMsg
->lParam
= (LPARAM
) KernelMem
;
449 /* Copy data if required */
450 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_READ
))
452 TRACE("Copy Message %u from usermode buffer\n", KernelModeMsg
->message
);
453 Status
= MmCopyFromCaller(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
454 if (! NT_SUCCESS(Status
))
456 ERR("Failed to copy message to kernel: invalid usermode lParam buffer\n");
457 ExFreePoolWithTag(KernelMem
, TAG_MSG
);
463 /* Make sure we don't pass any secrets to usermode */
464 RtlZeroMemory(KernelMem
, Size
);
469 KernelModeMsg
->lParam
= 0;
472 return STATUS_SUCCESS
;
475 static NTSTATUS FASTCALL
476 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
479 PMSGMEMORY MsgMemoryEntry
;
482 /* See if this message type is present in the table */
483 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
484 if (NULL
== MsgMemoryEntry
)
486 /* Not present, no copying needed */
487 return STATUS_SUCCESS
;
490 /* Determine required size */
491 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
495 /* Copy data if required */
496 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
498 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
499 if (! NT_SUCCESS(Status
))
501 ERR("Failed to copy message from kernel: invalid usermode lParam buffer\n");
502 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
506 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
509 return STATUS_SUCCESS
;
513 // Wakeup any thread/process waiting on idle input.
518 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
521 pti
= PsGetCurrentThreadWin32Thread();
525 pti
->pClientInfo
->cSpins
= 0; // Reset spins.
527 if ( pti
->pDeskInfo
&& pti
== gptiForeground
)
529 if ( pti
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) ||
530 pti
->pDeskInfo
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) )
532 co_HOOK_CallHooks(WH_FOREGROUNDIDLE
,HC_ACTION
,0,0);
537 TRACE("IdlePing ppi %p\n", ppi
);
538 if ( ppi
&& ppi
->InputIdleEvent
)
540 TRACE("InputIdleEvent\n");
541 KeSetEvent( ppi
->InputIdleEvent
, IO_NO_INCREMENT
, FALSE
);
548 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
550 TRACE("IdlePong ppi %p\n", ppi
);
551 if ( ppi
&& ppi
->InputIdleEvent
)
553 KeClearEvent(ppi
->InputIdleEvent
);
558 GetWakeMask(UINT first
, UINT last
)
560 UINT mask
= QS_POSTMESSAGE
| QS_SENDMESSAGE
; /* Always selected */
564 if ((first
<= WM_KEYLAST
) && (last
>= WM_KEYFIRST
)) mask
|= QS_KEY
;
565 if ( ((first
<= WM_MOUSELAST
) && (last
>= WM_MOUSEFIRST
)) ||
566 ((first
<= WM_NCMOUSELAST
) && (last
>= WM_NCMOUSEFIRST
)) ) mask
|= QS_MOUSE
;
567 if ((first
<= WM_TIMER
) && (last
>= WM_TIMER
)) mask
|= QS_TIMER
;
568 if ((first
<= WM_SYSTIMER
) && (last
>= WM_SYSTIMER
)) mask
|= QS_TIMER
;
569 if ((first
<= WM_PAINT
) && (last
>= WM_PAINT
)) mask
|= QS_PAINT
;
571 else mask
= QS_ALLINPUT
;
577 IntCallWndProc( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
579 BOOL SameThread
= FALSE
;
582 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
589 co_HOOK_CallHooks( WH_CALLWNDPROC
, HC_ACTION
, SameThread
, (LPARAM
)&CWP
);
593 IntCallWndProcRet ( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*uResult
)
595 BOOL SameThread
= FALSE
;
598 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
603 CWPR
.wParam
= wParam
;
604 CWPR
.lParam
= lParam
;
605 CWPR
.lResult
= uResult
? (*uResult
) : 0;
606 co_HOOK_CallHooks( WH_CALLWNDPROCRET
, HC_ACTION
, SameThread
, (LPARAM
)&CWPR
);
609 static LRESULT
handle_internal_message( PWND pWnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
612 USER_REFERENCE_ENTRY Ref
;
613 // PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
616 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
617 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
620 TRACE("Internal Event Msg 0x%x hWnd 0x%p\n", msg
, pWnd
->head
.h
);
624 case WM_ASYNC_SHOWWINDOW
:
625 return co_WinPosShowWindow( pWnd
, wparam
);
626 case WM_ASYNC_SETWINDOWPOS
:
628 PWINDOWPOS winpos
= (PWINDOWPOS
)lparam
;
629 if (!winpos
) return 0;
630 lRes
= co_WinPosSetWindowPos( pWnd
,
631 winpos
->hwndInsertAfter
,
637 ExFreePoolWithTag(winpos
, USERTAG_SWP
);
640 case WM_ASYNC_SETACTIVEWINDOW
:
642 PWND Window
= (PWND
)wparam
;
643 if (wparam
) UserRefObjectCo(Window
, &Ref
);
644 lRes
= (LRESULT
)co_IntSetActiveWindow(Window
,(BOOL
)lparam
,TRUE
,TRUE
);
645 if (wparam
) UserDerefObjectCo(Window
);
648 case WM_ASYNC_DESTROYWINDOW
:
650 ERR("WM_ASYNC_DESTROYWINDOW\n");
651 if (pWnd
->style
& WS_CHILD
)
652 return co_UserFreeWindow(pWnd
, PsGetCurrentProcessWin32Process(), PsGetCurrentThreadWin32Thread(), TRUE
);
654 co_UserDestroyWindow(pWnd
);
660 static LRESULT
handle_internal_events( PTHREADINFO pti
, PWND pWnd
, LONG_PTR ExtraInfo
, PMSG pMsg
)
668 co_EVENT_CallEvents( pMsg
->message
, pMsg
->hwnd
, pMsg
->wParam
, ExtraInfo
);
675 IntDispatchMessage(PMSG pMsg
)
677 LARGE_INTEGER TickCount
;
682 BOOL DoCallBack
= TRUE
;
686 Window
= UserGetWindowObject(pMsg
->hwnd
);
687 if (!Window
) return 0;
690 pti
= PsGetCurrentThreadWin32Thread();
692 if ( Window
&& Window
->head
.pti
!= pti
)
694 EngSetLastError( ERROR_MESSAGE_SYNC_ONLY
);
698 if (((pMsg
->message
== WM_SYSTIMER
) ||
699 (pMsg
->message
== WM_TIMER
)) &&
702 if (pMsg
->message
== WM_TIMER
)
704 if (ValidateTimerCallback(pti
,pMsg
->lParam
))
706 KeQueryTickCount(&TickCount
);
707 Time
= MsqCalculateMessageTime(&TickCount
);
708 retval
= co_IntCallWindowProc((WNDPROC
)pMsg
->lParam
,
720 PTIMER pTimer
= FindSystemTimer(pMsg
);
721 if (pTimer
&& pTimer
->pfn
)
723 KeQueryTickCount(&TickCount
);
724 Time
= MsqCalculateMessageTime(&TickCount
);
725 pTimer
->pfn(pMsg
->hwnd
, WM_SYSTIMER
, (UINT
)pMsg
->wParam
, Time
);
731 if ( !Window
) return 0;
733 if (pMsg
->message
== WM_PAINT
) Window
->state
|= WNDS_PAINTNOTPROCESSED
;
735 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
737 TRACE("Dispatch: Server Side Window Procedure\n");
741 DoCallBack
= !DesktopWindowProc( Window
,
747 case FNID_MESSAGEWND
:
748 DoCallBack
= !UserMessageWindowProc( Window
,
755 DoCallBack
= !PopupMenuWndProc( Window
,
764 /* Since we are doing a callback on the same thread right away, there is
765 no need to copy the lparam to kernel mode and then back to usermode.
766 We just pretend it isn't a pointer */
769 retval
= co_IntCallWindowProc( Window
->lpfnWndProc
,
777 if ( pMsg
->message
== WM_PAINT
&&
779 Window
->state
& WNDS_PAINTNOTPROCESSED
) // <--- Cleared, paint was already processed!
781 Window
->state2
&= ~WNDS2_WMPAINTSENT
;
782 /* send a WM_ERASEBKGND if the non-client area is still invalid */
783 ERR("Message WM_PAINT\n");
784 co_IntPaintWindows( Window
, RDW_NOCHILDREN
, FALSE
);
791 * Internal version of PeekMessage() doing all the work
796 * Input (hardware) messages and system internal events
797 * Sent messages (again)
802 co_IntPeekMessage( PMSG Msg
,
811 LARGE_INTEGER LargeTickCount
;
816 pti
= PsGetCurrentThreadWin32Thread();
818 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
819 ProcessMask
= HIWORD(RemoveMsg
);
821 /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns
822 all available messages (that is, no range filtering is performed)". */
823 if (!ProcessMask
) ProcessMask
= (QS_ALLPOSTMESSAGE
|QS_ALLINPUT
);
829 KeQueryTickCount(&LargeTickCount
);
830 pti
->timeLast
= LargeTickCount
.u
.LowPart
;
831 pti
->pcti
->tickLastMsgChecked
= LargeTickCount
.u
.LowPart
;
833 // Post mouse moves while looping through peek messages.
834 if (pti
->MessageQueue
->QF_flags
& QF_MOUSEMOVED
)
836 IntCoalesceMouseMove(pti
);
839 /* Dispatch sent messages here. */
840 while ( co_MsqDispatchOneSentMessage(pti
) )
842 /* if some PM_QS* flags were specified, only handle sent messages from now on */
843 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
; // wine does this; ProcessMask = QS_SENDMESSAGE;
845 if (Hit
) return FALSE
;
847 /* Clear changed bits so we can wait on them if we don't find a message */
848 if (ProcessMask
& QS_POSTMESSAGE
)
850 pti
->pcti
->fsChangeBits
&= ~(QS_POSTMESSAGE
| QS_HOTKEY
| QS_TIMER
);
851 if (MsgFilterMin
== 0 && MsgFilterMax
== 0) // Wine hack does this; ~0U)
853 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
857 if (ProcessMask
& QS_INPUT
)
859 pti
->pcti
->fsChangeBits
&= ~QS_INPUT
;
862 /* Now check for normal messages. */
863 if (( (ProcessMask
& QS_POSTMESSAGE
) ||
864 (ProcessMask
& QS_HOTKEY
) ) &&
877 /* Only check for quit messages if not posted messages pending. */
878 if (ProcessMask
& QS_POSTMESSAGE
&& pti
->QuitPosted
)
880 /* According to the PSDK, WM_QUIT messages are always returned, regardless
881 of the filter specified */
883 Msg
->message
= WM_QUIT
;
884 Msg
->wParam
= pti
->exitCode
;
888 pti
->QuitPosted
= FALSE
;
889 ClearMsgBitsMask(pti
, QS_POSTMESSAGE
);
890 pti
->pcti
->fsWakeBits
&= ~QS_ALLPOSTMESSAGE
;
891 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
896 /* Check for hardware events. */
897 if ((ProcessMask
& QS_INPUT
) &&
898 co_MsqPeekHardwareMessage( pti
,
909 /* Now check for System Event messages. */
913 if (MsqPeekMessage( pti
,
922 handle_internal_events( pti
, Window
, eExtraInfo
, &eMsg
);
927 /* Check for sent messages again. */
928 while ( co_MsqDispatchOneSentMessage(pti
) )
930 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
;
932 if (Hit
) return FALSE
;
934 /* Check for paint messages. */
935 if ((ProcessMask
& QS_PAINT
) &&
937 IntGetPaintMessage( Window
,
947 /* This is correct, check for the current threads timers waiting to be
948 posted to this threads message queue. If any we loop again.
950 if ((ProcessMask
& QS_TIMER
) &&
951 PostTimerMessages(Window
))
964 co_IntWaitMessage( PWND Window
,
969 NTSTATUS Status
= STATUS_SUCCESS
;
971 LONG_PTR ExtraInfo
= 0;
973 pti
= PsGetCurrentThreadWin32Thread();
977 if ( co_IntPeekMessage( &Msg
, // Dont reenter!
981 MAKELONG( PM_NOREMOVE
, GetWakeMask( MsgFilterMin
, MsgFilterMax
)),
983 TRUE
) ) // act like GetMessage.
988 /* Nothing found. Wait for new messages. */
989 Status
= co_MsqWaitForNewMessages( pti
,
993 if (!NT_SUCCESS(Status
))
995 SetLastNtError(Status
);
996 ERR("Exit co_IntWaitMessage on error!\n");
999 if (Status
== STATUS_USER_APC
|| Status
== STATUS_TIMEOUT
)
1010 co_IntGetPeekMessage( PMSG pMsg
,
1019 BOOL Present
= FALSE
;
1021 LONG_PTR ExtraInfo
= 0;
1023 if ( hWnd
== HWND_TOPMOST
|| hWnd
== HWND_BROADCAST
)
1026 /* Validate input */
1027 if (hWnd
&& hWnd
!= HWND_BOTTOM
)
1029 if (!(Window
= UserGetWindowObject(hWnd
)))
1039 Window
= (PWND
)hWnd
;
1042 if (MsgFilterMax
< MsgFilterMin
)
1050 RemoveMsg
|= ((GetWakeMask( MsgFilterMin
, MsgFilterMax
))<< 16);
1053 pti
= PsGetCurrentThreadWin32Thread();
1054 pti
->pClientInfo
->cSpins
++; // Bump up the spin count.
1058 Present
= co_IntPeekMessage( pMsg
,
1067 /* GetMessage or PostMessage must never get messages that contain pointers */
1068 ASSERT(FindMsgMemory(pMsg
->message
) == NULL
);
1070 if ( pMsg
->message
>= WM_DDE_FIRST
&& pMsg
->message
<= WM_DDE_LAST
)
1072 if (!IntDdeGetMessageHook(pMsg
, ExtraInfo
))
1074 TRACE("DDE Get return ERROR\n");
1079 if (pMsg
->message
!= WM_PAINT
&& pMsg
->message
!= WM_QUIT
)
1081 if (!RtlEqualMemory(&pti
->ptLast
, &pMsg
->pt
, sizeof(POINT
)))
1083 pti
->TIF_flags
|= TIF_MSGPOSCHANGED
;
1085 pti
->timeLast
= pMsg
->time
;
1086 pti
->ptLast
= pMsg
->pt
;
1089 // The WH_GETMESSAGE hook enables an application to monitor messages about to
1090 // be returned by the GetMessage or PeekMessage function.
1092 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)pMsg
);
1094 if ( bGMSG
|| pMsg
->message
== WM_PAINT
) break;
1099 Status
= co_MsqWaitForNewMessages( pti
,
1103 if ( !NT_SUCCESS(Status
) ||
1104 Status
== STATUS_USER_APC
||
1105 Status
== STATUS_TIMEOUT
)
1113 if (!(RemoveMsg
& PM_NOYIELD
))
1116 // Yield this thread!
1119 UserEnterExclusive();
1120 // Fall through to exit.
1126 while( bGMSG
&& !Present
);
1128 // Been spinning, time to swap vinyl...
1129 if (pti
->pClientInfo
->cSpins
>= 100)
1131 // Clear the spin cycle to fix the mix.
1132 pti
->pClientInfo
->cSpins
= 0;
1133 //if (!(pti->TIF_flags & TIF_SPINNING)) // FIXME: Need to swap vinyl...
1139 UserPostThreadMessage( PTHREADINFO pti
,
1145 LARGE_INTEGER LargeTickCount
;
1147 if (is_pointer_message(Msg
))
1149 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1152 Message
.hwnd
= NULL
;
1153 Message
.message
= Msg
;
1154 Message
.wParam
= wParam
;
1155 Message
.lParam
= lParam
;
1156 Message
.pt
= gpsi
->ptCursor
;
1158 KeQueryTickCount(&LargeTickCount
);
1159 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1160 MsqPostMessage(pti
, &Message
, FALSE
, QS_POSTMESSAGE
, 0, 0);
1164 PTHREADINFO FASTCALL
1165 IntSendTo(PWND Window
, PTHREADINFO ptiCur
, UINT Msg
)
1170 Window
->head
.pti
== ptiCur
)
1175 return Window
? Window
->head
.pti
: NULL
;
1179 UserPostMessage( HWND Wnd
,
1186 LARGE_INTEGER LargeTickCount
;
1187 LONG_PTR ExtraInfo
= 0;
1190 Message
.message
= Msg
;
1191 Message
.wParam
= wParam
;
1192 Message
.lParam
= lParam
;
1193 Message
.pt
= gpsi
->ptCursor
;
1194 KeQueryTickCount(&LargeTickCount
);
1195 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1197 if (is_pointer_message(Message
.message
))
1199 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1203 if (Wnd
== HWND_BROADCAST
)
1209 DesktopWindow
= UserGetDesktopWindow();
1210 List
= IntWinListChildren(DesktopWindow
);
1214 UserPostMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1215 for (i
= 0; List
[i
]; i
++)
1217 PWND pwnd
= UserGetWindowObject(List
[i
]);
1218 if (!pwnd
) continue;
1220 if ( pwnd
->fnid
== FNID_MENU
|| // Also need pwnd->pcls->atomClassName == gaOleMainThreadWndClass
1221 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1224 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1226 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1235 return UserPostThreadMessage( gptiCurrent
,
1241 Window
= UserGetWindowObject(Wnd
);
1244 ERR("UserPostMessage: Invalid handle 0x%p Msg 0x%x!\n", Wnd
, Msg
);
1248 pti
= Window
->head
.pti
;
1250 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1252 ERR("Attempted to post message to window %p when the thread is in cleanup!\n", Wnd
);
1256 if ( Window
->state
& WNDS_DESTROYED
)
1258 ERR("Attempted to post message to window %p that is being destroyed!\n", Wnd
);
1259 /* FIXME: Last error code? */
1263 if ( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1265 if (!IntDdePostMessageHook(Window
, Msg
, wParam
, &lParam
, &ExtraInfo
))
1267 TRACE("Posting Exit DDE 0x%x\n",Msg
);
1270 Message
.lParam
= lParam
;
1273 MsqPostMessage(pti
, &Message
, FALSE
, QS_POSTMESSAGE
, 0, ExtraInfo
);
1279 co_IntSendMessage( HWND hWnd
,
1284 ULONG_PTR Result
= 0;
1286 if (co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1288 return (LRESULT
)Result
;
1293 static LRESULT FASTCALL
1294 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1300 ULONG_PTR
*uResult
)
1302 NTSTATUS Status
= STATUS_SUCCESS
;
1304 PMSGMEMORY MsgMemoryEntry
;
1305 INT lParamBufferSize
;
1306 LPARAM lParamPacked
;
1307 PTHREADINFO Win32Thread
, ptiSendTo
= NULL
;
1308 ULONG_PTR Result
= 0;
1309 DECLARE_RETURN(LRESULT
);
1310 USER_REFERENCE_ENTRY Ref
;
1311 BOOL DoCallBack
= TRUE
;
1313 if (!(Window
= UserGetWindowObject(hWnd
)))
1315 TRACE("SendMessageTimeoutSingle: Invalid handle 0x%p!\n",hWnd
);
1319 UserRefObjectCo(Window
, &Ref
);
1321 Win32Thread
= PsGetCurrentThreadWin32Thread();
1323 ptiSendTo
= IntSendTo(Window
, Win32Thread
, Msg
);
1325 if ( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1327 if (!IntDdeSendMessageHook(Window
, Msg
, wParam
, lParam
))
1329 ERR("Sending Exit DDE 0x%x\n",Msg
);
1336 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1338 /* Never send messages to exiting threads */
1342 if (Msg
& 0x80000000)
1344 TRACE("SMTS: Internal Message!\n");
1345 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1346 if (uResult
) *uResult
= Result
;
1350 // Only happens when calling the client!
1351 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1353 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1355 TRACE("SMT: Server Side Window Procedure\n");
1356 // Handle it here. Safeguard against excessive recursions.
1357 if (IoGetRemainingStackSize() < PAGE_SIZE
)
1359 ERR("Server Callback Exceeded Stack!\n");
1362 /* Return after server side call, IntCallWndProcRet will not be called. */
1363 switch(Window
->fnid
)
1366 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1368 case FNID_MESSAGEWND
:
1369 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1372 DoCallBack
= !PopupMenuWndProc( Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1377 if (uResult
) *uResult
= Result
;
1381 /* See if this message type is present in the table */
1382 MsgMemoryEntry
= FindMsgMemory(Msg
);
1383 if (NULL
== MsgMemoryEntry
)
1385 lParamBufferSize
= -1;
1389 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1390 // If zero, do not allow callback on client side to allocate a buffer!!!!! See CORE-7695.
1391 if (!lParamBufferSize
) lParamBufferSize
= -1;
1394 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1396 ERR("Failed to pack message parameters\n");
1400 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1412 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1414 ERR("Failed to unpack message parameters\n");
1418 // Only happens when calling the client!
1419 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1424 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(ptiSendTo
))
1426 // FIXME: Set window hung and add to a list.
1427 /* FIXME: Set a LastError? */
1431 if (Window
->state
& WNDS_DESTROYED
)
1433 /* FIXME: Last error? */
1434 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1440 Status
= co_MsqSendMessage( ptiSendTo
,
1446 (uFlags
& SMTO_BLOCK
),
1450 while ((STATUS_TIMEOUT
== Status
) &&
1451 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1452 !MsqIsHung(ptiSendTo
)); // FIXME: Set window hung and add to a list.
1454 if (Status
== STATUS_TIMEOUT
)
1458 * Microsoft Windows 2000: If GetLastError returns zero, then the function
1460 * XP+ : If the function fails or times out, the return value is zero.
1461 * To get extended error information, call GetLastError. If GetLastError
1462 * returns ERROR_TIMEOUT, then the function timed out.
1464 EngSetLastError(ERROR_TIMEOUT
);
1467 else if (!NT_SUCCESS(Status
))
1469 SetLastNtError(Status
);
1476 if (Window
) UserDerefObjectCo(Window
);
1481 co_IntSendMessageTimeout( HWND hWnd
,
1487 ULONG_PTR
*uResult
)
1493 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1495 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1498 DesktopWindow
= UserGetDesktopWindow();
1499 if (NULL
== DesktopWindow
)
1501 EngSetLastError(ERROR_INTERNAL_ERROR
);
1505 if (hWnd
!= HWND_TOPMOST
)
1507 /* Send message to the desktop window too! */
1508 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1511 Children
= IntWinListChildren(DesktopWindow
);
1512 if (NULL
== Children
)
1517 for (Child
= Children
; NULL
!= *Child
; Child
++)
1519 if (hWnd
== HWND_TOPMOST
)
1521 DesktopWindow
= UserGetWindowObject(*Child
);
1522 if (DesktopWindow
&& DesktopWindow
->ExStyle
& WS_EX_TOPMOST
)
1524 ERR("HWND_TOPMOST Found\n");
1525 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1530 PWND pwnd
= UserGetWindowObject(*Child
);
1531 if (!pwnd
) continue;
1533 if ( pwnd
->fnid
== FNID_MENU
||
1534 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1537 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1541 ExFreePoolWithTag(Children
, USERTAG_WINDOWLIST
);
1543 return (LRESULT
) TRUE
;
1547 co_IntSendMessageNoWait(HWND hWnd
,
1552 ULONG_PTR Result
= 0;
1553 return co_IntSendMessageWithCallBack( hWnd
,
1562 If you send a message in the range below WM_USER to the asynchronous message
1563 functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its
1564 message parameters cannot include pointers. Otherwise, the operation will fail.
1565 The functions will return before the receiving thread has had a chance to
1566 process the message and the sender will free the memory before it is used.
1569 co_IntSendMessageWithCallBack( HWND hWnd
,
1573 SENDASYNCPROC CompletionCallback
,
1574 ULONG_PTR CompletionCallbackContext
,
1579 PMSGMEMORY MsgMemoryEntry
;
1580 INT lParamBufferSize
;
1581 LPARAM lParamPacked
;
1582 PTHREADINFO Win32Thread
, ptiSendTo
= NULL
;
1583 DECLARE_RETURN(LRESULT
);
1584 USER_REFERENCE_ENTRY Ref
;
1585 PUSER_SENT_MESSAGE Message
;
1586 BOOL DoCallBack
= TRUE
;
1588 if (!(Window
= UserGetWindowObject(hWnd
)))
1590 TRACE("SendMessageWithCallBack: Invalid handle 0x%p!\n",hWnd
);
1594 UserRefObjectCo(Window
, &Ref
);
1596 if (Window
->state
& WNDS_DESTROYED
)
1598 /* FIXME: last error? */
1599 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1603 Win32Thread
= PsGetCurrentThreadWin32Thread();
1605 if (Win32Thread
== NULL
||
1606 Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1611 ptiSendTo
= IntSendTo(Window
, Win32Thread
, Msg
);
1613 if (Msg
& 0x80000000 &&
1616 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
) RETURN( FALSE
);
1618 TRACE("SMWCB: Internal Message!\n");
1619 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1620 if (uResult
) *uResult
= Result
;
1624 /* See if this message type is present in the table */
1625 MsgMemoryEntry
= FindMsgMemory(Msg
);
1626 if (NULL
== MsgMemoryEntry
)
1628 lParamBufferSize
= -1;
1632 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1633 if (!lParamBufferSize
) lParamBufferSize
= -1;
1636 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, !!ptiSendTo
)))
1638 ERR("Failed to pack message parameters\n");
1642 /* If it can be sent now, then send it. */
1645 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1647 UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
);
1648 /* Never send messages to exiting threads */
1652 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1654 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1656 TRACE("SMWCB: Server Side Window Procedure\n");
1657 switch(Window
->fnid
)
1660 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParamPacked
, (LRESULT
*)&Result
);
1662 case FNID_MESSAGEWND
:
1663 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1666 DoCallBack
= !PopupMenuWndProc( Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1672 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1684 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1686 if (CompletionCallback
)
1688 co_IntCallSentMessageCallback(CompletionCallback
,
1691 CompletionCallbackContext
,
1698 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1700 ERR("Failed to unpack message parameters\n");
1705 if(!(Message
= AllocateUserMessage(FALSE
)))
1707 ERR("MsqSendMessage(): Not enough memory to allocate a message");
1711 Message
->Msg
.hwnd
= hWnd
;
1712 Message
->Msg
.message
= Msg
;
1713 Message
->Msg
.wParam
= wParam
;
1714 Message
->Msg
.lParam
= lParamPacked
;
1715 Message
->pkCompletionEvent
= NULL
; // No event needed.
1716 Message
->lResult
= 0;
1717 Message
->QS_Flags
= 0;
1718 Message
->ptiReceiver
= ptiSendTo
;
1719 Message
->ptiSender
= NULL
; // mjmartin, you are right! This is null.
1720 Message
->ptiCallBackSender
= Win32Thread
;
1721 Message
->CompletionCallback
= CompletionCallback
;
1722 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1723 Message
->HookMessage
= MSQ_NORMAL
;
1724 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1725 Message
->QS_Flags
= QS_SENDMESSAGE
;
1726 Message
->flags
= SMF_RECEIVERFREE
;
1728 if (Msg
& 0x80000000) // Higher priority event message!
1729 InsertHeadList(&ptiSendTo
->SentMessagesListHead
, &Message
->ListEntry
);
1731 InsertTailList(&ptiSendTo
->SentMessagesListHead
, &Message
->ListEntry
);
1732 MsqWakeQueue(ptiSendTo
, QS_SENDMESSAGE
, TRUE
);
1737 if (Window
) UserDerefObjectCo(Window
);
1743 This HACK function posts a message if the destination's message queue belongs to
1744 another thread, otherwise it sends the message. It does not support broadcast
1748 co_IntPostOrSendMessage( HWND hWnd
,
1757 if ( hWnd
== HWND_BROADCAST
)
1762 if(!(Window
= UserGetWindowObject(hWnd
)))
1764 TRACE("PostOrSendMessage: Invalid handle 0x%p!\n",hWnd
);
1768 pti
= PsGetCurrentThreadWin32Thread();
1770 if ( IntSendTo(Window
, pti
, Msg
) &&
1771 FindMsgMemory(Msg
) == 0 )
1773 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1777 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1783 return (LRESULT
)Result
;
1787 static LRESULT FASTCALL
1788 co_IntDoSendMessage( HWND hWnd
,
1794 LRESULT Result
= TRUE
;
1797 MSG UserModeMsg
, KernelModeMsg
;
1798 PMSGMEMORY MsgMemoryEntry
;
1799 PTHREADINFO ptiSendTo
;
1801 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1803 Window
= UserGetWindowObject(hWnd
);
1810 /* Check for an exiting window. */
1811 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1813 ERR("co_IntDoSendMessage Window Exiting!\n");
1816 /* See if the current thread can handle this message */
1817 ptiSendTo
= IntSendTo(Window
, gptiCurrent
, Msg
);
1819 // If broadcasting or sending to another thread, save the users data.
1820 if (!Window
|| ptiSendTo
)
1822 UserModeMsg
.hwnd
= hWnd
;
1823 UserModeMsg
.message
= Msg
;
1824 UserModeMsg
.wParam
= wParam
;
1825 UserModeMsg
.lParam
= lParam
;
1826 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1827 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1828 if (!NT_SUCCESS(Status
))
1830 EngSetLastError(ERROR_INVALID_PARAMETER
);
1831 return (dsm
? 0 : -1);
1836 KernelModeMsg
.hwnd
= hWnd
;
1837 KernelModeMsg
.message
= Msg
;
1838 KernelModeMsg
.wParam
= wParam
;
1839 KernelModeMsg
.lParam
= lParam
;
1844 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1845 KernelModeMsg
.message
,
1846 KernelModeMsg
.wParam
,
1847 KernelModeMsg
.lParam
);
1851 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1852 KernelModeMsg
.message
,
1853 KernelModeMsg
.wParam
,
1854 KernelModeMsg
.lParam
,
1860 if (!Window
|| ptiSendTo
)
1862 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1863 if (!NT_SUCCESS(Status
))
1865 EngSetLastError(ERROR_INVALID_PARAMETER
);
1866 return(dsm
? 0 : -1);
1870 return (LRESULT
)Result
;
1874 UserSendNotifyMessage( HWND hWnd
,
1881 if (is_pointer_message(Msg
))
1883 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1887 // Basicly the same as IntPostOrSendMessage
1888 if (hWnd
== HWND_BROADCAST
) // Handle Broadcast
1894 DesktopWindow
= UserGetDesktopWindow();
1895 List
= IntWinListChildren(DesktopWindow
);
1899 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1900 for (i
= 0; List
[i
]; i
++)
1902 PWND pwnd
= UserGetWindowObject(List
[i
]);
1903 if (!pwnd
) continue;
1905 if ( pwnd
->fnid
== FNID_MENU
||
1906 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1909 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1911 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1916 Ret
= co_IntSendMessageNoWait( hWnd
, Msg
, wParam
, lParam
);
1923 IntGetQueueStatus(DWORD Changes
)
1928 pti
= PsGetCurrentThreadWin32Thread();
1930 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1932 /* High word, types of messages currently in the queue.
1933 Low word, types of messages that have been added to the queue and that
1934 are still in the queue
1936 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1938 pti
->pcti
->fsChangeBits
&= ~Changes
;
1944 IntInitMessagePumpHook(VOID
)
1946 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1950 pti
->pcti
->dwcPumpHook
++;
1957 IntUninitMessagePumpHook(VOID
)
1959 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1963 if (pti
->pcti
->dwcPumpHook
<= 0)
1967 pti
->pcti
->dwcPumpHook
--;
1974 IntCallMsgFilter( LPMSG lpmsg
, INT code
)
1978 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)lpmsg
))
1984 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)lpmsg
);
1989 /** Functions ******************************************************************/
1995 POINT pt
) // Just like the User call.
1999 ULONG wDragWidth
, wDragHeight
;
2000 DECLARE_RETURN(BOOL
);
2002 TRACE("Enter NtUserDragDetect(%p)\n", hWnd
);
2003 UserEnterExclusive();
2005 wDragWidth
= UserGetSystemMetrics(SM_CXDRAG
);
2006 wDragHeight
= UserGetSystemMetrics(SM_CYDRAG
);
2008 rect
.left
= pt
.x
- wDragWidth
;
2009 rect
.right
= pt
.x
+ wDragWidth
;
2011 rect
.top
= pt
.y
- wDragHeight
;
2012 rect
.bottom
= pt
.y
+ wDragHeight
;
2014 co_UserSetCapture(hWnd
);
2018 while (co_IntGetPeekMessage( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, FALSE
) ||
2019 co_IntGetPeekMessage( &msg
, 0, WM_QUEUESYNC
, WM_QUEUESYNC
, PM_REMOVE
, FALSE
) ||
2020 co_IntGetPeekMessage( &msg
, 0, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
, FALSE
) )
2022 if ( msg
.message
== WM_LBUTTONUP
)
2024 co_UserSetCapture(NULL
);
2027 if ( msg
.message
== WM_MOUSEMOVE
)
2030 tmp
.x
= (short)LOWORD(msg
.lParam
);
2031 tmp
.y
= (short)HIWORD(msg
.lParam
);
2032 if( !RECTL_bPointInRect( &rect
, tmp
.x
, tmp
.y
) )
2034 co_UserSetCapture(NULL
);
2038 if ( msg
.message
== WM_KEYDOWN
)
2040 if ( msg
.wParam
== VK_ESCAPE
)
2042 co_UserSetCapture(NULL
);
2046 if ( msg
.message
== WM_QUEUESYNC
)
2048 co_HOOK_CallHooks( WH_CBT
, HCBT_QS
, 0, 0 );
2051 co_IntWaitMessage(NULL
, 0, 0);
2056 TRACE("Leave NtUserDragDetect, ret=%i\n",_ret_
);
2062 NtUserPostMessage(HWND hWnd
,
2069 UserEnterExclusive();
2071 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
2079 NtUserPostThreadMessage(DWORD idThread
,
2086 PTHREADINFO pThread
;
2089 UserEnterExclusive();
2091 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
2093 if ( Status
== STATUS_SUCCESS
)
2095 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
2097 !pThread
->MessageQueue
||
2098 (pThread
->TIF_flags
& TIF_INCLEANUP
))
2100 ObDereferenceObject( peThread
);
2103 ret
= UserPostThreadMessage( pThread
, Msg
, wParam
, lParam
);
2104 ObDereferenceObject( peThread
);
2108 SetLastNtError( Status
);
2116 NtUserWaitMessage(VOID
)
2120 UserEnterExclusive();
2121 TRACE("NtUserWaitMessage Enter\n");
2122 ret
= co_IntWaitMessage(NULL
, 0, 0);
2123 TRACE("NtUserWaitMessage Leave\n");
2130 NtUserGetMessage(PMSG pMsg
,
2138 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
2140 EngSetLastError(ERROR_INVALID_PARAMETER
);
2144 UserEnterExclusive();
2146 RtlZeroMemory(&Msg
, sizeof(MSG
));
2148 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
2156 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2157 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2159 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2161 SetLastNtError(_SEH2_GetExceptionCode());
2168 Ret
= Ret
? (WM_QUIT
!= pMsg
->message
) : FALSE
;
2174 NtUserPeekMessage( PMSG pMsg
,
2183 if ( RemoveMsg
& PM_BADMSGFLAGS
)
2185 EngSetLastError(ERROR_INVALID_FLAGS
);
2189 UserEnterExclusive();
2191 RtlZeroMemory(&Msg
, sizeof(MSG
));
2193 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
2201 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2202 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2204 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2206 SetLastNtError(_SEH2_GetExceptionCode());
2216 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
2223 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
2224 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
2226 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2228 _SEH2_YIELD(return FALSE
);
2232 UserEnterExclusive();
2234 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
2240 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
2247 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
2248 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
2250 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2260 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
2267 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
2268 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
2270 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2272 SetLastNtError(_SEH2_GetExceptionCode());
2273 _SEH2_YIELD(return FALSE
);
2277 UserEnterExclusive();
2279 Res
= IntDispatchMessage(&SafeMsg
);
2286 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
2294 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
2295 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
2297 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2299 SetLastNtError(_SEH2_GetExceptionCode());
2300 _SEH2_YIELD(return FALSE
);
2304 UserEnterExclusive();
2305 pWnd
= UserGetWindowObject(SafeMsg
.hwnd
);
2306 if (pWnd
) // Must have a window!
2308 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
2312 TRACE("No Window for Translate. hwnd 0x%p Msg %u\n", SafeMsg
.hwnd
, SafeMsg
.message
);
2320 LRESULT APIENTRY
ScrollBarWndProc(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
);
2323 NtUserMessageCall( HWND hWnd
,
2327 ULONG_PTR ResultInfo
,
2328 DWORD dwType
, // fnID?
2331 LRESULT lResult
= 0;
2334 USER_REFERENCE_ENTRY Ref
;
2336 UserEnterExclusive();
2340 case FNID_SCROLLBAR
:
2342 lResult
= ScrollBarWndProc(hWnd
, Msg
, wParam
, lParam
);
2347 Window
= UserGetWindowObject(hWnd
);
2350 //ERR("FNID_DESKTOP IN\n");
2351 Ret
= DesktopWindowProc(Window
, Msg
, wParam
, lParam
, &lResult
);
2352 //ERR("FNID_DESKTOP OUT\n");
2358 Window
= UserGetWindowObject(hWnd
);
2361 Ret
= PopupMenuWndProc( Window
, Msg
, wParam
, lParam
, &lResult
);
2365 case FNID_MESSAGEWND
:
2367 Window
= UserGetWindowObject(hWnd
);
2370 Ret
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
, &lResult
);
2374 case FNID_DEFWINDOWPROC
:
2375 /* Validate input */
2378 Window
= UserGetWindowObject(hWnd
);
2384 UserRefObjectCo(Window
, &Ref
);
2386 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2389 UserDerefObjectCo(Window
);
2391 case FNID_SENDNOTIFYMESSAGE
:
2392 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2394 case FNID_BROADCASTSYSTEMMESSAGE
:
2396 BROADCASTPARM parm
, *retparam
;
2397 DWORD_PTR RetVal
= 0;
2403 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2404 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2406 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2415 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2416 parm
.recipients
== BSM_ALLCOMPONENTS
)
2418 PLIST_ENTRY DesktopEntry
;
2420 HWND
*List
, hwndDenied
= NULL
;
2422 PWND pwnd
, pwndDesk
;
2426 for (DesktopEntry
= InputWindowStation
->DesktopListHead
.Flink
;
2427 DesktopEntry
!= &InputWindowStation
->DesktopListHead
;
2428 DesktopEntry
= DesktopEntry
->Flink
)
2430 rpdesk
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
2431 pwndDesk
= rpdesk
->pDeskInfo
->spwnd
;
2432 List
= IntWinListChildren(pwndDesk
);
2434 if (parm
.flags
& BSF_QUERY
)
2438 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2440 fuFlags
= SMTO_ABORTIFHUNG
;
2442 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2444 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2448 fuFlags
= SMTO_NORMAL
;
2450 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2458 for (i
= 0; List
[i
]; i
++)
2460 pwnd
= UserGetWindowObject(List
[i
]);
2461 if (!pwnd
) continue;
2463 if ( pwnd
->fnid
== FNID_MENU
||
2464 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2467 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2469 if ( pwnd
->head
.pti
== gptiCurrent
)
2472 co_IntSendMessageTimeout( List
[i
],
2480 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2482 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2485 if (RetVal
== BROADCAST_QUERY_DENY
)
2487 hwndDenied
= List
[i
];
2488 hDesk
= UserHMGetHandle(pwndDesk
);
2492 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2495 retparam
= (PBROADCASTPARM
) ResultInfo
;
2496 retparam
->hDesk
= hDesk
;
2497 retparam
->hWnd
= hwndDenied
;
2499 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2504 if (!Ret
) break; // Have a hit! Let everyone know!
2507 else if (parm
.flags
& BSF_POSTMESSAGE
)
2511 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2513 for (i
= 0; List
[i
]; i
++)
2515 pwnd
= UserGetWindowObject(List
[i
]);
2516 if (!pwnd
) continue;
2518 if ( pwnd
->fnid
== FNID_MENU
||
2519 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2522 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2524 if ( pwnd
->head
.pti
== gptiCurrent
)
2527 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2529 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2537 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2539 for (i
= 0; List
[i
]; i
++)
2541 pwnd
= UserGetWindowObject(List
[i
]);
2542 if (!pwnd
) continue;
2544 if ( pwnd
->fnid
== FNID_MENU
||
2545 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2548 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2550 if ( pwnd
->head
.pti
== gptiCurrent
)
2553 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2555 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2561 else if (parm
.recipients
& BSM_APPLICATIONS
)
2563 HWND
*List
, hwndDenied
= NULL
;
2565 PWND pwnd
, pwndDesk
;
2569 pwndDesk
= UserGetDesktopWindow();
2570 List
= IntWinListChildren(pwndDesk
);
2572 if (parm
.flags
& BSF_QUERY
)
2576 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2578 fuFlags
= SMTO_ABORTIFHUNG
;
2580 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2582 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2586 fuFlags
= SMTO_NORMAL
;
2588 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2596 for (i
= 0; List
[i
]; i
++)
2598 pwnd
= UserGetWindowObject(List
[i
]);
2599 if (!pwnd
) continue;
2601 if ( pwnd
->fnid
== FNID_MENU
||
2602 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2605 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2607 if ( pwnd
->head
.pti
== gptiCurrent
)
2610 co_IntSendMessageTimeout( List
[i
],
2618 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2620 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2623 if (RetVal
== BROADCAST_QUERY_DENY
)
2625 hwndDenied
= List
[i
];
2626 hDesk
= UserHMGetHandle(pwndDesk
);
2630 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2633 retparam
= (PBROADCASTPARM
) ResultInfo
;
2634 retparam
->hDesk
= hDesk
;
2635 retparam
->hWnd
= hwndDenied
;
2637 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2644 else if (parm
.flags
& BSF_POSTMESSAGE
)
2648 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2650 for (i
= 0; List
[i
]; i
++)
2652 pwnd
= UserGetWindowObject(List
[i
]);
2653 if (!pwnd
) continue;
2655 if ( pwnd
->fnid
== FNID_MENU
||
2656 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2659 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2661 if ( pwnd
->head
.pti
== gptiCurrent
)
2664 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2666 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2674 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2676 for (i
= 0; List
[i
]; i
++)
2678 pwnd
= UserGetWindowObject(List
[i
]);
2679 if (!pwnd
) continue;
2681 if ( pwnd
->fnid
== FNID_MENU
||
2682 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2685 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2687 if ( pwnd
->head
.pti
== gptiCurrent
)
2690 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2692 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2699 case FNID_SENDMESSAGECALLBACK
:
2701 CALL_BACK_INFO CallBackInfo
;
2706 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2707 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2709 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2715 if (is_pointer_message(Msg
))
2717 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
2721 if (!(Ret
= co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2722 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
)))
2724 ERR("Callback failure!\n");
2728 case FNID_SENDMESSAGE
:
2730 lResult
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2737 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2738 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(ULONG_PTR
));
2740 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2749 case FNID_SENDMESSAGEFF
:
2750 case FNID_SENDMESSAGEWTOOPTION
:
2752 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2757 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2758 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2760 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2767 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, pdsm
? &dsm
: NULL
);
2773 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2774 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2776 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2785 // CallNextHook bypass.
2786 case FNID_CALLWNDPROC
:
2787 case FNID_CALLWNDPROCRET
:
2790 PCLIENTINFO ClientInfo
;
2791 PHOOK NextObj
, Hook
;
2793 pti
= GetW32ThreadInfo();
2795 Hook
= pti
->sphkCurrent
;
2799 NextObj
= Hook
->phkNext
;
2800 ClientInfo
= pti
->pClientInfo
;
2803 ClientInfo
->phkCurrent
= NextObj
;
2805 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2811 if (!ClientInfo
|| !NextObj
) break;
2813 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2815 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2820 CWP
.wParam
= wParam
;
2821 CWP
.lParam
= lParam
;
2822 TRACE("WH_CALLWNDPROC: Hook %p NextHook %p\n", Hook
, NextObj
);
2824 lResult
= co_IntCallHookProc( Hook
->HookId
,
2826 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2839 CWPR
.wParam
= wParam
;
2840 CWPR
.lParam
= lParam
;
2841 CWPR
.lResult
= ClientInfo
->dwHookData
;
2843 lResult
= co_IntCallHookProc( Hook
->HookId
,
2845 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2859 case FNID_DEFWINDOWPROC
:
2860 case FNID_CALLWNDPROC
:
2861 case FNID_CALLWNDPROCRET
:
2862 case FNID_SCROLLBAR
:
2869 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2870 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2872 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2888 #define INFINITE 0xFFFFFFFF
2889 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2893 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2894 IN DWORD dwMilliseconds
,
2898 PPROCESSINFO W32Process
;
2902 LARGE_INTEGER Timeout
;
2903 KAPC_STATE ApcState
;
2905 UserEnterExclusive();
2907 Status
= ObReferenceObjectByHandle(hProcess
,
2908 PROCESS_QUERY_INFORMATION
,
2914 if (!NT_SUCCESS(Status
))
2917 SetLastNtError(Status
);
2921 pti
= PsGetCurrentThreadWin32Thread();
2923 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2925 if ( PsGetProcessExitProcessCalled(Process
) ||
2927 pti
->ppi
== W32Process
)
2929 ObDereferenceObject(Process
);
2931 EngSetLastError(ERROR_INVALID_PARAMETER
);
2935 Handles
[0] = Process
;
2936 Handles
[1] = W32Process
->InputIdleEvent
;
2937 Handles
[2] = pti
->pEventQueueServer
; // IntMsqSetWakeMask returns hEventQueueClient
2941 ObDereferenceObject(Process
);
2943 return STATUS_SUCCESS
; /* no event to wait on */
2946 if (dwMilliseconds
!= INFINITE
)
2947 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2949 KeStackAttachProcess(&Process
->Pcb
, &ApcState
);
2951 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2952 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2954 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2955 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2958 KeUnstackDetachProcess(&ApcState
);
2960 TRACE("WFII: ppi %p\n", W32Process
);
2961 TRACE("WFII: waiting for %p\n", Handles
[1] );
2964 * We must add a refcount to our current PROCESSINFO,
2965 * because anything could happen (including process death) we're leaving win32k
2967 IntReferenceProcessInfo(W32Process
);
2972 Status
= KeWaitForMultipleObjects( 3,
2978 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2980 UserEnterExclusive();
2982 if (!NT_SUCCESS(Status
))
2984 SetLastNtError(Status
);
2985 Status
= WAIT_FAILED
;
2997 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2998 ERR("WFII: WAIT 2\n");
3002 case STATUS_TIMEOUT
:
3003 ERR("WFII: timeout\n");
3008 ERR("WFII: finished\n");
3009 Status
= STATUS_SUCCESS
;
3016 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
3018 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
3019 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
3021 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
3022 IntDereferenceProcessInfo(W32Process
);
3023 ObDereferenceObject(Process
);