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 pti
->timeLast
= pMsg
->time
;
1082 pti
->ptLast
= pMsg
->pt
;
1085 // The WH_GETMESSAGE hook enables an application to monitor messages about to
1086 // be returned by the GetMessage or PeekMessage function.
1088 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)pMsg
);
1090 if ( bGMSG
|| pMsg
->message
== WM_PAINT
) break;
1095 Status
= co_MsqWaitForNewMessages( pti
,
1099 if ( !NT_SUCCESS(Status
) ||
1100 Status
== STATUS_USER_APC
||
1101 Status
== STATUS_TIMEOUT
)
1109 if (!(RemoveMsg
& PM_NOYIELD
))
1112 // Yield this thread!
1115 UserEnterExclusive();
1116 // Fall through to exit.
1122 while( bGMSG
&& !Present
);
1124 // Been spinning, time to swap vinyl...
1125 if (pti
->pClientInfo
->cSpins
>= 100)
1127 // Clear the spin cycle to fix the mix.
1128 pti
->pClientInfo
->cSpins
= 0;
1129 //if (!(pti->TIF_flags & TIF_SPINNING)) // FIXME: Need to swap vinyl...
1135 UserPostThreadMessage( PTHREADINFO pti
,
1141 LARGE_INTEGER LargeTickCount
;
1143 if (is_pointer_message(Msg
))
1145 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1148 Message
.hwnd
= NULL
;
1149 Message
.message
= Msg
;
1150 Message
.wParam
= wParam
;
1151 Message
.lParam
= lParam
;
1152 Message
.pt
= gpsi
->ptCursor
;
1154 KeQueryTickCount(&LargeTickCount
);
1155 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1156 MsqPostMessage(pti
, &Message
, FALSE
, QS_POSTMESSAGE
, 0, 0);
1160 PTHREADINFO FASTCALL
1161 IntSendTo(PWND Window
, PTHREADINFO ptiCur
, UINT Msg
)
1166 Window
->head
.pti
== ptiCur
)
1171 return Window
? Window
->head
.pti
: NULL
;
1175 UserPostMessage( HWND Wnd
,
1182 LARGE_INTEGER LargeTickCount
;
1183 LONG_PTR ExtraInfo
= 0;
1186 Message
.message
= Msg
;
1187 Message
.wParam
= wParam
;
1188 Message
.lParam
= lParam
;
1189 Message
.pt
= gpsi
->ptCursor
;
1190 KeQueryTickCount(&LargeTickCount
);
1191 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1193 if (is_pointer_message(Message
.message
))
1195 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1199 if (Wnd
== HWND_BROADCAST
)
1205 DesktopWindow
= UserGetDesktopWindow();
1206 List
= IntWinListChildren(DesktopWindow
);
1210 UserPostMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1211 for (i
= 0; List
[i
]; i
++)
1213 PWND pwnd
= UserGetWindowObject(List
[i
]);
1214 if (!pwnd
) continue;
1216 if ( pwnd
->fnid
== FNID_MENU
|| // Also need pwnd->pcls->atomClassName == gaOleMainThreadWndClass
1217 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1220 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1222 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1231 return UserPostThreadMessage( gptiCurrent
,
1237 Window
= UserGetWindowObject(Wnd
);
1240 ERR("UserPostMessage: Invalid handle 0x%p Msg 0x%x!\n", Wnd
, Msg
);
1244 pti
= Window
->head
.pti
;
1246 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1248 ERR("Attempted to post message to window %p when the thread is in cleanup!\n", Wnd
);
1252 if ( Window
->state
& WNDS_DESTROYED
)
1254 ERR("Attempted to post message to window %p that is being destroyed!\n", Wnd
);
1255 /* FIXME: Last error code? */
1259 if ( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1261 if (!IntDdePostMessageHook(Window
, Msg
, wParam
, &lParam
, &ExtraInfo
))
1263 TRACE("Posting Exit DDE 0x%x\n",Msg
);
1266 Message
.lParam
= lParam
;
1269 MsqPostMessage(pti
, &Message
, FALSE
, QS_POSTMESSAGE
, 0, ExtraInfo
);
1275 co_IntSendMessage( HWND hWnd
,
1280 ULONG_PTR Result
= 0;
1281 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1283 return (LRESULT
)Result
;
1288 static LRESULT FASTCALL
1289 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1295 ULONG_PTR
*uResult
)
1297 NTSTATUS Status
= STATUS_SUCCESS
;
1299 PMSGMEMORY MsgMemoryEntry
;
1300 INT lParamBufferSize
;
1301 LPARAM lParamPacked
;
1302 PTHREADINFO Win32Thread
, ptiSendTo
= NULL
;
1303 ULONG_PTR Result
= 0;
1304 DECLARE_RETURN(LRESULT
);
1305 USER_REFERENCE_ENTRY Ref
;
1306 BOOL DoCallBack
= TRUE
;
1308 if (!(Window
= UserGetWindowObject(hWnd
)))
1310 TRACE("SendMessageTimeoutSingle: Invalid handle 0x%p!\n",hWnd
);
1314 UserRefObjectCo(Window
, &Ref
);
1316 Win32Thread
= PsGetCurrentThreadWin32Thread();
1318 ptiSendTo
= IntSendTo(Window
, Win32Thread
, Msg
);
1320 if ( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1322 if (!IntDdeSendMessageHook(Window
, Msg
, wParam
, lParam
))
1324 ERR("Sending Exit DDE 0x%x\n",Msg
);
1331 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1333 /* Never send messages to exiting threads */
1337 if (Msg
& 0x80000000)
1339 TRACE("SMTS: Internal Message!\n");
1340 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1341 if (uResult
) *uResult
= Result
;
1345 // Only happens when calling the client!
1346 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1348 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1350 TRACE("SMT: Server Side Window Procedure\n");
1351 // Handle it here. Safeguard against excessive recursions.
1352 if (IoGetRemainingStackSize() < PAGE_SIZE
)
1354 ERR("Server Callback Exceeded Stack!\n");
1357 /* Return after server side call, IntCallWndProcRet will not be called. */
1358 switch(Window
->fnid
)
1361 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1363 case FNID_MESSAGEWND
:
1364 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1367 DoCallBack
= !PopupMenuWndProc( Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1372 if (uResult
) *uResult
= Result
;
1376 /* See if this message type is present in the table */
1377 MsgMemoryEntry
= FindMsgMemory(Msg
);
1378 if (NULL
== MsgMemoryEntry
)
1380 lParamBufferSize
= -1;
1384 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1385 // If zero, do not allow callback on client side to allocate a buffer!!!!! See CORE-7695.
1386 if (!lParamBufferSize
) lParamBufferSize
= -1;
1389 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1391 ERR("Failed to pack message parameters\n");
1395 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1407 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1409 ERR("Failed to unpack message parameters\n");
1413 // Only happens when calling the client!
1414 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1419 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(ptiSendTo
))
1421 // FIXME: Set window hung and add to a list.
1422 /* FIXME: Set a LastError? */
1426 if (Window
->state
& WNDS_DESTROYED
)
1428 /* FIXME: Last error? */
1429 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1435 Status
= co_MsqSendMessage( ptiSendTo
,
1441 (uFlags
& SMTO_BLOCK
),
1445 while ((STATUS_TIMEOUT
== Status
) &&
1446 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1447 !MsqIsHung(ptiSendTo
)); // FIXME: Set window hung and add to a list.
1449 if (Status
== STATUS_TIMEOUT
)
1453 * Microsoft Windows 2000: If GetLastError returns zero, then the function
1455 * XP+ : If the function fails or times out, the return value is zero.
1456 * To get extended error information, call GetLastError. If GetLastError
1457 * returns ERROR_TIMEOUT, then the function timed out.
1459 EngSetLastError(ERROR_TIMEOUT
);
1462 else if (!NT_SUCCESS(Status
))
1464 SetLastNtError(Status
);
1471 if (Window
) UserDerefObjectCo(Window
);
1476 co_IntSendMessageTimeout( HWND hWnd
,
1482 ULONG_PTR
*uResult
)
1488 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1490 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1493 DesktopWindow
= UserGetDesktopWindow();
1494 if (NULL
== DesktopWindow
)
1496 EngSetLastError(ERROR_INTERNAL_ERROR
);
1500 if (hWnd
!= HWND_TOPMOST
)
1502 /* Send message to the desktop window too! */
1503 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1506 Children
= IntWinListChildren(DesktopWindow
);
1507 if (NULL
== Children
)
1512 for (Child
= Children
; NULL
!= *Child
; Child
++)
1514 if (hWnd
== HWND_TOPMOST
)
1516 DesktopWindow
= UserGetWindowObject(*Child
);
1517 if (DesktopWindow
&& DesktopWindow
->ExStyle
& WS_EX_TOPMOST
)
1519 ERR("HWND_TOPMOST Found\n");
1520 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1525 PWND pwnd
= UserGetWindowObject(*Child
);
1526 if (!pwnd
) continue;
1528 if ( pwnd
->fnid
== FNID_MENU
||
1529 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1532 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1536 ExFreePoolWithTag(Children
, USERTAG_WINDOWLIST
);
1538 return (LRESULT
) TRUE
;
1542 co_IntSendMessageNoWait(HWND hWnd
,
1547 ULONG_PTR Result
= 0;
1548 return co_IntSendMessageWithCallBack( hWnd
,
1557 If you send a message in the range below WM_USER to the asynchronous message
1558 functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its
1559 message parameters cannot include pointers. Otherwise, the operation will fail.
1560 The functions will return before the receiving thread has had a chance to
1561 process the message and the sender will free the memory before it is used.
1564 co_IntSendMessageWithCallBack( HWND hWnd
,
1568 SENDASYNCPROC CompletionCallback
,
1569 ULONG_PTR CompletionCallbackContext
,
1574 PMSGMEMORY MsgMemoryEntry
;
1575 INT lParamBufferSize
;
1576 LPARAM lParamPacked
;
1577 PTHREADINFO Win32Thread
, ptiSendTo
= NULL
;
1578 DECLARE_RETURN(LRESULT
);
1579 USER_REFERENCE_ENTRY Ref
;
1580 PUSER_SENT_MESSAGE Message
;
1581 BOOL DoCallBack
= TRUE
;
1583 if (!(Window
= UserGetWindowObject(hWnd
)))
1585 TRACE("SendMessageWithCallBack: Invalid handle 0x%p!\n",hWnd
);
1589 UserRefObjectCo(Window
, &Ref
);
1591 if (Window
->state
& WNDS_DESTROYED
)
1593 /* FIXME: last error? */
1594 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1598 Win32Thread
= PsGetCurrentThreadWin32Thread();
1600 if (Win32Thread
== NULL
||
1601 Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1606 ptiSendTo
= IntSendTo(Window
, Win32Thread
, Msg
);
1608 if (Msg
& 0x80000000 &&
1611 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
) RETURN( FALSE
);
1613 TRACE("SMWCB: Internal Message!\n");
1614 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1615 if (uResult
) *uResult
= Result
;
1619 /* See if this message type is present in the table */
1620 MsgMemoryEntry
= FindMsgMemory(Msg
);
1621 if (NULL
== MsgMemoryEntry
)
1623 lParamBufferSize
= -1;
1627 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1628 if (!lParamBufferSize
) lParamBufferSize
= -1;
1631 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, !!ptiSendTo
)))
1633 ERR("Failed to pack message parameters\n");
1637 /* If it can be sent now, then send it. */
1640 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1642 UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
);
1643 /* Never send messages to exiting threads */
1647 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1649 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1651 TRACE("SMWCB: Server Side Window Procedure\n");
1652 switch(Window
->fnid
)
1655 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParamPacked
, (LRESULT
*)&Result
);
1657 case FNID_MESSAGEWND
:
1658 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1661 DoCallBack
= !PopupMenuWndProc( Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1667 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1679 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1681 if (CompletionCallback
)
1683 co_IntCallSentMessageCallback(CompletionCallback
,
1686 CompletionCallbackContext
,
1693 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1695 ERR("Failed to unpack message parameters\n");
1700 if(!(Message
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
1702 ERR("MsqSendMessage(): Not enough memory to allocate a message");
1706 Message
->Msg
.hwnd
= hWnd
;
1707 Message
->Msg
.message
= Msg
;
1708 Message
->Msg
.wParam
= wParam
;
1709 Message
->Msg
.lParam
= lParamPacked
;
1710 Message
->CompletionEvent
= NULL
;
1711 Message
->Result
= 0;
1712 Message
->lResult
= 0;
1713 Message
->QS_Flags
= 0;
1714 Message
->ptiReceiver
= ptiSendTo
;
1715 Message
->ptiSender
= NULL
; // mjmartin, you are right! This is null.
1716 Message
->ptiCallBackSender
= Win32Thread
;
1717 InitializeListHead(&Message
->DispatchingListEntry
);
1718 Message
->CompletionCallback
= CompletionCallback
;
1719 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1720 Message
->HookMessage
= MSQ_NORMAL
;
1721 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1722 Message
->QS_Flags
= QS_SENDMESSAGE
;
1724 if (Msg
& 0x80000000) // Higher priority event message!
1725 InsertHeadList(&ptiSendTo
->SentMessagesListHead
, &Message
->ListEntry
);
1727 InsertTailList(&ptiSendTo
->SentMessagesListHead
, &Message
->ListEntry
);
1728 MsqWakeQueue(ptiSendTo
, QS_SENDMESSAGE
, TRUE
);
1733 if (Window
) UserDerefObjectCo(Window
);
1739 This HACK function posts a message if the destination's message queue belongs to
1740 another thread, otherwise it sends the message. It does not support broadcast
1744 co_IntPostOrSendMessage( HWND hWnd
,
1753 if ( hWnd
== HWND_BROADCAST
)
1758 if(!(Window
= UserGetWindowObject(hWnd
)))
1760 TRACE("PostOrSendMessage: Invalid handle 0x%p!\n",hWnd
);
1764 pti
= PsGetCurrentThreadWin32Thread();
1766 if ( IntSendTo(Window
, pti
, Msg
) &&
1767 FindMsgMemory(Msg
) == 0 )
1769 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1773 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1779 return (LRESULT
)Result
;
1783 static LRESULT FASTCALL
1784 co_IntDoSendMessage( HWND hWnd
,
1790 LRESULT Result
= TRUE
;
1793 MSG UserModeMsg
, KernelModeMsg
;
1794 PMSGMEMORY MsgMemoryEntry
;
1795 PTHREADINFO ptiSendTo
;
1797 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1799 Window
= UserGetWindowObject(hWnd
);
1806 /* Check for an exiting window. */
1807 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1809 ERR("co_IntDoSendMessage Window Exiting!\n");
1812 /* See if the current thread can handle this message */
1813 ptiSendTo
= IntSendTo(Window
, gptiCurrent
, Msg
);
1815 // If broadcasting or sending to another thread, save the users data.
1816 if (!Window
|| ptiSendTo
)
1818 UserModeMsg
.hwnd
= hWnd
;
1819 UserModeMsg
.message
= Msg
;
1820 UserModeMsg
.wParam
= wParam
;
1821 UserModeMsg
.lParam
= lParam
;
1822 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1823 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1824 if (!NT_SUCCESS(Status
))
1826 EngSetLastError(ERROR_INVALID_PARAMETER
);
1827 return (dsm
? 0 : -1);
1832 KernelModeMsg
.hwnd
= hWnd
;
1833 KernelModeMsg
.message
= Msg
;
1834 KernelModeMsg
.wParam
= wParam
;
1835 KernelModeMsg
.lParam
= lParam
;
1840 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1841 KernelModeMsg
.message
,
1842 KernelModeMsg
.wParam
,
1843 KernelModeMsg
.lParam
);
1847 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1848 KernelModeMsg
.message
,
1849 KernelModeMsg
.wParam
,
1850 KernelModeMsg
.lParam
,
1856 if (!Window
|| ptiSendTo
)
1858 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1859 if (!NT_SUCCESS(Status
))
1861 EngSetLastError(ERROR_INVALID_PARAMETER
);
1862 return(dsm
? 0 : -1);
1866 return (LRESULT
)Result
;
1870 UserSendNotifyMessage( HWND hWnd
,
1877 if (is_pointer_message(Msg
))
1879 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1883 // Basicly the same as IntPostOrSendMessage
1884 if (hWnd
== HWND_BROADCAST
) // Handle Broadcast
1890 DesktopWindow
= UserGetDesktopWindow();
1891 List
= IntWinListChildren(DesktopWindow
);
1895 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1896 for (i
= 0; List
[i
]; i
++)
1898 PWND pwnd
= UserGetWindowObject(List
[i
]);
1899 if (!pwnd
) continue;
1901 if ( pwnd
->fnid
== FNID_MENU
||
1902 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1905 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1907 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1912 Ret
= co_IntSendMessageNoWait( hWnd
, Msg
, wParam
, lParam
);
1919 IntGetQueueStatus(DWORD Changes
)
1924 pti
= PsGetCurrentThreadWin32Thread();
1926 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1928 /* High word, types of messages currently in the queue.
1929 Low word, types of messages that have been added to the queue and that
1930 are still in the queue
1932 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1934 pti
->pcti
->fsChangeBits
&= ~Changes
;
1940 IntInitMessagePumpHook(VOID
)
1942 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1946 pti
->pcti
->dwcPumpHook
++;
1953 IntUninitMessagePumpHook(VOID
)
1955 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1959 if (pti
->pcti
->dwcPumpHook
<= 0)
1963 pti
->pcti
->dwcPumpHook
--;
1970 IntCallMsgFilter( LPMSG lpmsg
, INT code
)
1974 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)lpmsg
))
1980 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)lpmsg
);
1985 /** Functions ******************************************************************/
1991 POINT pt
) // Just like the User call.
1995 ULONG wDragWidth
, wDragHeight
;
1996 DECLARE_RETURN(BOOL
);
1998 TRACE("Enter NtUserDragDetect(%p)\n", hWnd
);
1999 UserEnterExclusive();
2001 wDragWidth
= UserGetSystemMetrics(SM_CXDRAG
);
2002 wDragHeight
= UserGetSystemMetrics(SM_CYDRAG
);
2004 rect
.left
= pt
.x
- wDragWidth
;
2005 rect
.right
= pt
.x
+ wDragWidth
;
2007 rect
.top
= pt
.y
- wDragHeight
;
2008 rect
.bottom
= pt
.y
+ wDragHeight
;
2010 co_UserSetCapture(hWnd
);
2014 while (co_IntGetPeekMessage( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, FALSE
) ||
2015 co_IntGetPeekMessage( &msg
, 0, WM_QUEUESYNC
, WM_QUEUESYNC
, PM_REMOVE
, FALSE
) ||
2016 co_IntGetPeekMessage( &msg
, 0, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
, FALSE
) )
2018 if ( msg
.message
== WM_LBUTTONUP
)
2020 co_UserSetCapture(NULL
);
2023 if ( msg
.message
== WM_MOUSEMOVE
)
2026 tmp
.x
= (short)LOWORD(msg
.lParam
);
2027 tmp
.y
= (short)HIWORD(msg
.lParam
);
2028 if( !RECTL_bPointInRect( &rect
, tmp
.x
, tmp
.y
) )
2030 co_UserSetCapture(NULL
);
2034 if ( msg
.message
== WM_KEYDOWN
)
2036 if ( msg
.wParam
== VK_ESCAPE
)
2038 co_UserSetCapture(NULL
);
2042 if ( msg
.message
== WM_QUEUESYNC
)
2044 co_HOOK_CallHooks( WH_CBT
, HCBT_QS
, 0, 0 );
2047 co_IntWaitMessage(NULL
, 0, 0);
2052 TRACE("Leave NtUserDragDetect, ret=%i\n",_ret_
);
2058 NtUserPostMessage(HWND hWnd
,
2065 UserEnterExclusive();
2067 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
2075 NtUserPostThreadMessage(DWORD idThread
,
2082 PTHREADINFO pThread
;
2085 UserEnterExclusive();
2087 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
2089 if ( Status
== STATUS_SUCCESS
)
2091 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
2093 !pThread
->MessageQueue
||
2094 (pThread
->TIF_flags
& TIF_INCLEANUP
))
2096 ObDereferenceObject( peThread
);
2099 ret
= UserPostThreadMessage( pThread
, Msg
, wParam
, lParam
);
2100 ObDereferenceObject( peThread
);
2104 SetLastNtError( Status
);
2112 NtUserWaitMessage(VOID
)
2116 UserEnterExclusive();
2117 TRACE("NtUserWaitMessage Enter\n");
2118 ret
= co_IntWaitMessage(NULL
, 0, 0);
2119 TRACE("NtUserWaitMessage Leave\n");
2126 NtUserGetMessage(PMSG pMsg
,
2134 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
2136 EngSetLastError(ERROR_INVALID_PARAMETER
);
2140 UserEnterExclusive();
2142 RtlZeroMemory(&Msg
, sizeof(MSG
));
2144 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
2152 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2153 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2155 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2157 SetLastNtError(_SEH2_GetExceptionCode());
2164 Ret
= Ret
? (WM_QUIT
!= pMsg
->message
) : FALSE
;
2170 NtUserPeekMessage( PMSG pMsg
,
2179 if ( RemoveMsg
& PM_BADMSGFLAGS
)
2181 EngSetLastError(ERROR_INVALID_FLAGS
);
2185 UserEnterExclusive();
2187 RtlZeroMemory(&Msg
, sizeof(MSG
));
2189 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
2197 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2198 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2200 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2202 SetLastNtError(_SEH2_GetExceptionCode());
2212 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
2219 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
2220 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
2222 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2224 _SEH2_YIELD(return FALSE
);
2228 UserEnterExclusive();
2230 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
2236 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
2243 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
2244 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
2246 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2256 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
2263 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
2264 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
2266 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2268 SetLastNtError(_SEH2_GetExceptionCode());
2269 _SEH2_YIELD(return FALSE
);
2273 UserEnterExclusive();
2275 Res
= IntDispatchMessage(&SafeMsg
);
2282 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
2290 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
2291 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
2293 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2295 SetLastNtError(_SEH2_GetExceptionCode());
2296 _SEH2_YIELD(return FALSE
);
2300 UserEnterExclusive();
2301 pWnd
= UserGetWindowObject(SafeMsg
.hwnd
);
2302 if (pWnd
) // Must have a window!
2304 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
2308 TRACE("No Window for Translate. hwnd 0x%p Msg %u\n", SafeMsg
.hwnd
, SafeMsg
.message
);
2316 LRESULT APIENTRY
ScrollBarWndProc(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
);
2319 NtUserMessageCall( HWND hWnd
,
2323 ULONG_PTR ResultInfo
,
2324 DWORD dwType
, // fnID?
2327 LRESULT lResult
= 0;
2330 USER_REFERENCE_ENTRY Ref
;
2332 UserEnterExclusive();
2336 case FNID_SCROLLBAR
:
2338 lResult
= ScrollBarWndProc(hWnd
, Msg
, wParam
, lParam
);
2343 Window
= UserGetWindowObject(hWnd
);
2346 //ERR("FNID_DESKTOP IN\n");
2347 Ret
= DesktopWindowProc(Window
, Msg
, wParam
, lParam
, &lResult
);
2348 //ERR("FNID_DESKTOP OUT\n");
2354 Window
= UserGetWindowObject(hWnd
);
2357 Ret
= PopupMenuWndProc( Window
, Msg
, wParam
, lParam
, &lResult
);
2361 case FNID_MESSAGEWND
:
2363 Window
= UserGetWindowObject(hWnd
);
2366 Ret
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
, &lResult
);
2370 case FNID_DEFWINDOWPROC
:
2371 /* Validate input */
2374 Window
= UserGetWindowObject(hWnd
);
2380 UserRefObjectCo(Window
, &Ref
);
2382 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2385 UserDerefObjectCo(Window
);
2387 case FNID_SENDNOTIFYMESSAGE
:
2388 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2390 case FNID_BROADCASTSYSTEMMESSAGE
:
2392 BROADCASTPARM parm
, *retparam
;
2393 DWORD_PTR RetVal
= 0;
2399 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2400 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2402 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2411 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2412 parm
.recipients
== BSM_ALLCOMPONENTS
)
2414 PLIST_ENTRY DesktopEntry
;
2416 HWND
*List
, hwndDenied
= NULL
;
2418 PWND pwnd
, pwndDesk
;
2422 for (DesktopEntry
= InputWindowStation
->DesktopListHead
.Flink
;
2423 DesktopEntry
!= &InputWindowStation
->DesktopListHead
;
2424 DesktopEntry
= DesktopEntry
->Flink
)
2426 rpdesk
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
2427 pwndDesk
= rpdesk
->pDeskInfo
->spwnd
;
2428 List
= IntWinListChildren(pwndDesk
);
2430 if (parm
.flags
& BSF_QUERY
)
2434 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2436 fuFlags
= SMTO_ABORTIFHUNG
;
2438 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2440 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2444 fuFlags
= SMTO_NORMAL
;
2446 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2454 for (i
= 0; List
[i
]; i
++)
2456 pwnd
= UserGetWindowObject(List
[i
]);
2457 if (!pwnd
) continue;
2459 if ( pwnd
->fnid
== FNID_MENU
||
2460 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2463 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2465 if ( pwnd
->head
.pti
== gptiCurrent
)
2468 co_IntSendMessageTimeout( List
[i
],
2476 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2478 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2481 if (RetVal
== BROADCAST_QUERY_DENY
)
2483 hwndDenied
= List
[i
];
2484 hDesk
= UserHMGetHandle(pwndDesk
);
2488 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2491 retparam
= (PBROADCASTPARM
) ResultInfo
;
2492 retparam
->hDesk
= hDesk
;
2493 retparam
->hWnd
= hwndDenied
;
2495 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2500 if (!Ret
) break; // Have a hit! Let everyone know!
2503 else if (parm
.flags
& BSF_POSTMESSAGE
)
2507 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2509 for (i
= 0; List
[i
]; i
++)
2511 pwnd
= UserGetWindowObject(List
[i
]);
2512 if (!pwnd
) continue;
2514 if ( pwnd
->fnid
== FNID_MENU
||
2515 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2518 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2520 if ( pwnd
->head
.pti
== gptiCurrent
)
2523 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2525 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2533 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2535 for (i
= 0; List
[i
]; i
++)
2537 pwnd
= UserGetWindowObject(List
[i
]);
2538 if (!pwnd
) continue;
2540 if ( pwnd
->fnid
== FNID_MENU
||
2541 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2544 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2546 if ( pwnd
->head
.pti
== gptiCurrent
)
2549 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2551 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2557 else if (parm
.recipients
& BSM_APPLICATIONS
)
2559 HWND
*List
, hwndDenied
= NULL
;
2561 PWND pwnd
, pwndDesk
;
2565 pwndDesk
= UserGetDesktopWindow();
2566 List
= IntWinListChildren(pwndDesk
);
2568 if (parm
.flags
& BSF_QUERY
)
2572 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2574 fuFlags
= SMTO_ABORTIFHUNG
;
2576 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2578 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2582 fuFlags
= SMTO_NORMAL
;
2584 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2592 for (i
= 0; List
[i
]; i
++)
2594 pwnd
= UserGetWindowObject(List
[i
]);
2595 if (!pwnd
) continue;
2597 if ( pwnd
->fnid
== FNID_MENU
||
2598 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2601 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2603 if ( pwnd
->head
.pti
== gptiCurrent
)
2606 co_IntSendMessageTimeout( List
[i
],
2614 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2616 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2619 if (RetVal
== BROADCAST_QUERY_DENY
)
2621 hwndDenied
= List
[i
];
2622 hDesk
= UserHMGetHandle(pwndDesk
);
2626 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2629 retparam
= (PBROADCASTPARM
) ResultInfo
;
2630 retparam
->hDesk
= hDesk
;
2631 retparam
->hWnd
= hwndDenied
;
2633 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2640 else if (parm
.flags
& BSF_POSTMESSAGE
)
2644 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2646 for (i
= 0; List
[i
]; i
++)
2648 pwnd
= UserGetWindowObject(List
[i
]);
2649 if (!pwnd
) continue;
2651 if ( pwnd
->fnid
== FNID_MENU
||
2652 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2655 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2657 if ( pwnd
->head
.pti
== gptiCurrent
)
2660 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2662 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2670 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2672 for (i
= 0; List
[i
]; i
++)
2674 pwnd
= UserGetWindowObject(List
[i
]);
2675 if (!pwnd
) continue;
2677 if ( pwnd
->fnid
== FNID_MENU
||
2678 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2681 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2683 if ( pwnd
->head
.pti
== gptiCurrent
)
2686 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2688 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2695 case FNID_SENDMESSAGECALLBACK
:
2697 CALL_BACK_INFO CallBackInfo
;
2702 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2703 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2705 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2711 if (is_pointer_message(Msg
))
2713 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
2717 if (!(Ret
= co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2718 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
)))
2720 ERR("Callback failure!\n");
2724 case FNID_SENDMESSAGE
:
2726 Ret
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2732 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2733 RtlCopyMemory((PVOID
)ResultInfo
, &Ret
, sizeof(ULONG_PTR
));
2735 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2744 case FNID_SENDMESSAGEFF
:
2745 case FNID_SENDMESSAGEWTOOPTION
:
2747 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2752 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2753 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2755 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2762 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, pdsm
? &dsm
: NULL
);
2768 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2769 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2771 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2780 // CallNextHook bypass.
2781 case FNID_CALLWNDPROC
:
2782 case FNID_CALLWNDPROCRET
:
2785 PCLIENTINFO ClientInfo
;
2786 PHOOK NextObj
, Hook
;
2788 pti
= GetW32ThreadInfo();
2790 Hook
= pti
->sphkCurrent
;
2794 NextObj
= Hook
->phkNext
;
2795 ClientInfo
= pti
->pClientInfo
;
2798 ClientInfo
->phkCurrent
= NextObj
;
2800 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2806 if (!ClientInfo
|| !NextObj
) break;
2808 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2810 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2815 CWP
.wParam
= wParam
;
2816 CWP
.lParam
= lParam
;
2817 TRACE("WH_CALLWNDPROC: Hook %p NextHook %p\n", Hook
, NextObj
);
2819 lResult
= co_IntCallHookProc( Hook
->HookId
,
2821 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2834 CWPR
.wParam
= wParam
;
2835 CWPR
.lParam
= lParam
;
2836 CWPR
.lResult
= ClientInfo
->dwHookData
;
2838 lResult
= co_IntCallHookProc( Hook
->HookId
,
2840 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2854 case FNID_DEFWINDOWPROC
:
2855 case FNID_CALLWNDPROC
:
2856 case FNID_CALLWNDPROCRET
:
2857 case FNID_SCROLLBAR
:
2864 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2865 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2867 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2883 #define INFINITE 0xFFFFFFFF
2884 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2888 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2889 IN DWORD dwMilliseconds
,
2893 PPROCESSINFO W32Process
;
2897 LARGE_INTEGER Timeout
;
2898 KAPC_STATE ApcState
;
2900 UserEnterExclusive();
2902 Status
= ObReferenceObjectByHandle(hProcess
,
2903 PROCESS_QUERY_INFORMATION
,
2909 if (!NT_SUCCESS(Status
))
2912 SetLastNtError(Status
);
2916 pti
= PsGetCurrentThreadWin32Thread();
2918 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2920 if ( PsGetProcessExitProcessCalled(Process
) ||
2922 pti
->ppi
== W32Process
)
2924 ObDereferenceObject(Process
);
2926 EngSetLastError(ERROR_INVALID_PARAMETER
);
2930 Handles
[0] = Process
;
2931 Handles
[1] = W32Process
->InputIdleEvent
;
2932 Handles
[2] = pti
->pEventQueueServer
; // IntMsqSetWakeMask returns hEventQueueClient
2936 ObDereferenceObject(Process
);
2938 return STATUS_SUCCESS
; /* no event to wait on */
2941 if (dwMilliseconds
!= INFINITE
)
2942 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2944 KeStackAttachProcess(&Process
->Pcb
, &ApcState
);
2946 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2947 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2949 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2950 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2953 KeUnstackDetachProcess(&ApcState
);
2955 TRACE("WFII: ppi %p\n", W32Process
);
2956 TRACE("WFII: waiting for %p\n", Handles
[1] );
2959 * We must add a refcount to our current PROCESSINFO,
2960 * because anything could happen (including process death) we're leaving win32k
2962 IntReferenceProcessInfo(W32Process
);
2967 Status
= KeWaitForMultipleObjects( 3,
2973 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2975 UserEnterExclusive();
2977 if (!NT_SUCCESS(Status
))
2979 SetLastNtError(Status
);
2980 Status
= WAIT_FAILED
;
2992 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2993 ERR("WFII: WAIT 2\n");
2997 case STATUS_TIMEOUT
:
2998 ERR("WFII: timeout\n");
3003 ERR("WFII: finished\n");
3004 Status
= STATUS_SUCCESS
;
3011 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
3013 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
3014 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
3016 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
3017 IntDereferenceProcessInfo(W32Process
);
3018 ObDereferenceObject(Process
);