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
) | SET(WM_COPYGLOBALDATA
) | SET(WM_HELP
),
48 SET(WM_STYLECHANGING
) | SET(WM_STYLECHANGED
),
50 SET(WM_NCCREATE
) | SET(WM_NCCALCSIZE
) | SET(WM_GETDLGCODE
),
52 SET(EM_GETSEL
) | SET(EM_GETRECT
) | SET(EM_SETRECT
) | SET(EM_SETRECTNP
),
54 SET(EM_REPLACESEL
) | SET(EM_GETLINE
) | SET(EM_SETTABSTOPS
),
56 SET(SBM_GETRANGE
) | SET(SBM_SETSCROLLINFO
) | SET(SBM_GETSCROLLINFO
) | SET(SBM_GETSCROLLBARINFO
),
62 SET(CB_GETEDITSEL
) | SET(CB_ADDSTRING
) | SET(CB_DIR
) | SET(CB_GETLBTEXT
) |
63 SET(CB_INSERTSTRING
) | SET(CB_FINDSTRING
) | SET(CB_SELECTSTRING
) |
64 SET(CB_GETDROPPEDCONTROLRECT
) | SET(CB_FINDSTRINGEXACT
),
68 SET(LB_ADDSTRING
) | SET(LB_INSERTSTRING
) | SET(LB_GETTEXT
) | SET(LB_SELECTSTRING
) |
69 SET(LB_DIR
) | SET(LB_FINDSTRING
) |
70 SET(LB_GETSELITEMS
) | SET(LB_SETTABSTOPS
) | SET(LB_ADDFILE
) | SET(LB_GETITEMRECT
),
72 SET(LB_FINDSTRINGEXACT
),
78 SET(WM_NEXTMENU
) | SET(WM_SIZING
) | SET(WM_MOVING
) | SET(WM_DEVICECHANGE
),
80 SET(WM_MDICREATE
) | SET(WM_MDIGETACTIVE
) | SET(WM_DROPOBJECT
) |
81 SET(WM_QUERYDROPOBJECT
) | SET(WM_DRAGLOOP
) | SET(WM_DRAGSELECT
) | SET(WM_DRAGMOVE
),
95 SET(WM_ASKCBFORMATNAME
)
98 /* check whether a given message type includes pointers */
99 static inline int is_pointer_message( UINT message
)
101 if (message
>= 8*sizeof(message_pointer_flags
)) return FALSE
;
102 return (message_pointer_flags
[message
/ 32] & SET(message
)) != 0;
106 #define MMS_SIZE_WPARAM -1
107 #define MMS_SIZE_WPARAMWCHAR -2
108 #define MMS_SIZE_LPARAMSZ -3
109 #define MMS_SIZE_SPECIAL -4
110 #define MMS_FLAG_READ 0x01
111 #define MMS_FLAG_WRITE 0x02
112 #define MMS_FLAG_READWRITE (MMS_FLAG_READ | MMS_FLAG_WRITE)
113 typedef struct tagMSGMEMORY
119 MSGMEMORY
, *PMSGMEMORY
;
121 static MSGMEMORY g_MsgMemory
[] =
123 { WM_CREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
124 { WM_GETMINMAXINFO
, sizeof(MINMAXINFO
), MMS_FLAG_READWRITE
},
125 { WM_GETTEXT
, MMS_SIZE_WPARAMWCHAR
, MMS_FLAG_WRITE
},
126 { WM_NCCALCSIZE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
127 { WM_NCCREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
128 { WM_SETTEXT
, MMS_SIZE_LPARAMSZ
, MMS_FLAG_READ
},
129 { WM_STYLECHANGED
, sizeof(STYLESTRUCT
), MMS_FLAG_READ
},
130 { WM_STYLECHANGING
, sizeof(STYLESTRUCT
), MMS_FLAG_READWRITE
},
131 { WM_SETTINGCHANGE
, MMS_SIZE_LPARAMSZ
, MMS_FLAG_READ
},
132 { WM_COPYDATA
, MMS_SIZE_SPECIAL
, MMS_FLAG_READ
},
133 { WM_COPYGLOBALDATA
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
134 { WM_WINDOWPOSCHANGED
, sizeof(WINDOWPOS
), MMS_FLAG_READWRITE
},
135 { WM_WINDOWPOSCHANGING
, sizeof(WINDOWPOS
), MMS_FLAG_READWRITE
},
136 { WM_SIZING
, sizeof(RECT
), MMS_FLAG_READWRITE
},
137 { WM_MOVING
, sizeof(RECT
), MMS_FLAG_READWRITE
},
138 { WM_MEASUREITEM
, sizeof(MEASUREITEMSTRUCT
), MMS_FLAG_READWRITE
},
139 { WM_DRAWITEM
, sizeof(DRAWITEMSTRUCT
), MMS_FLAG_READWRITE
},
140 { WM_HELP
, sizeof(HELPINFO
), MMS_FLAG_READWRITE
},
141 { WM_NEXTMENU
, sizeof(MDINEXTMENU
), MMS_FLAG_READWRITE
},
144 static PMSGMEMORY FASTCALL
145 FindMsgMemory(UINT Msg
)
147 PMSGMEMORY MsgMemoryEntry
;
149 /* See if this message type is present in the table */
150 for (MsgMemoryEntry
= g_MsgMemory
;
151 MsgMemoryEntry
< g_MsgMemory
+ sizeof(g_MsgMemory
) / sizeof(MSGMEMORY
);
154 if (Msg
== MsgMemoryEntry
->Message
)
156 return MsgMemoryEntry
;
164 MsgMemorySize(PMSGMEMORY MsgMemoryEntry
, WPARAM wParam
, LPARAM lParam
)
167 PUNICODE_STRING WindowName
;
168 PUNICODE_STRING ClassName
;
173 if (MMS_SIZE_WPARAM
== MsgMemoryEntry
->Size
)
177 else if (MMS_SIZE_WPARAMWCHAR
== MsgMemoryEntry
->Size
)
179 Size
= (UINT
) (wParam
* sizeof(WCHAR
));
181 else if (MMS_SIZE_LPARAMSZ
== MsgMemoryEntry
->Size
)
183 // WM_SETTEXT and WM_SETTINGCHANGE can be null!
186 TRACE("lParam is NULL!\n");
190 Size
= (UINT
) ((wcslen((PWSTR
) lParam
) + 1) * sizeof(WCHAR
));
192 else if (MMS_SIZE_SPECIAL
== MsgMemoryEntry
->Size
)
194 switch(MsgMemoryEntry
->Message
)
198 Cs
= (CREATESTRUCTW
*) lParam
;
199 WindowName
= (PUNICODE_STRING
) Cs
->lpszName
;
200 ClassName
= (PUNICODE_STRING
) Cs
->lpszClass
;
201 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
202 if (IS_ATOM(ClassName
->Buffer
))
204 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
208 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
213 Size
= wParam
? sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
) : sizeof(RECT
);
218 COPYDATASTRUCT
*cds
= (COPYDATASTRUCT
*)lParam
;
219 Size
= sizeof(COPYDATASTRUCT
) + cds
->cbData
;
231 Size
= MsgMemoryEntry
->Size
;
234 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
236 ERR("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH2_GetExceptionCode());
243 UINT
lParamMemorySize(UINT Msg
, WPARAM wParam
, LPARAM lParam
)
245 PMSGMEMORY MsgMemoryEntry
= FindMsgMemory(Msg
);
246 if(MsgMemoryEntry
== NULL
) return 0;
247 return MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
251 PackParam(LPARAM
*lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolNeeded
)
253 NCCALCSIZE_PARAMS
*UnpackedNcCalcsize
;
254 NCCALCSIZE_PARAMS
*PackedNcCalcsize
;
255 CREATESTRUCTW
*UnpackedCs
;
256 CREATESTRUCTW
*PackedCs
;
257 PLARGE_STRING WindowName
;
258 PUNICODE_STRING ClassName
;
263 *lParamPacked
= lParam
;
265 if (NonPagedPoolNeeded
)
266 PoolType
= NonPagedPool
;
268 PoolType
= PagedPool
;
270 if (WM_NCCALCSIZE
== Msg
&& wParam
)
273 UnpackedNcCalcsize
= (NCCALCSIZE_PARAMS
*) lParam
;
274 PackedNcCalcsize
= ExAllocatePoolWithTag(PoolType
,
275 sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
),
278 if (NULL
== PackedNcCalcsize
)
280 ERR("Not enough memory to pack lParam\n");
281 return STATUS_NO_MEMORY
;
283 RtlCopyMemory(PackedNcCalcsize
, UnpackedNcCalcsize
, sizeof(NCCALCSIZE_PARAMS
));
284 PackedNcCalcsize
->lppos
= (PWINDOWPOS
) (PackedNcCalcsize
+ 1);
285 RtlCopyMemory(PackedNcCalcsize
->lppos
, UnpackedNcCalcsize
->lppos
, sizeof(WINDOWPOS
));
286 *lParamPacked
= (LPARAM
) PackedNcCalcsize
;
288 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
290 UnpackedCs
= (CREATESTRUCTW
*) lParam
;
291 WindowName
= (PLARGE_STRING
) UnpackedCs
->lpszName
;
292 ClassName
= (PUNICODE_STRING
) UnpackedCs
->lpszClass
;
293 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
294 if (IS_ATOM(ClassName
->Buffer
))
296 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
300 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
302 PackedCs
= ExAllocatePoolWithTag(PoolType
, Size
, TAG_MSG
);
303 if (NULL
== PackedCs
)
305 ERR("Not enough memory to pack lParam\n");
306 return STATUS_NO_MEMORY
;
308 RtlCopyMemory(PackedCs
, UnpackedCs
, sizeof(CREATESTRUCTW
));
309 CsData
= (PCHAR
) (PackedCs
+ 1);
310 PackedCs
->lpszName
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
311 RtlCopyMemory(CsData
, WindowName
->Buffer
, WindowName
->Length
);
312 CsData
+= WindowName
->Length
;
313 *((WCHAR
*) CsData
) = L
'\0';
314 CsData
+= sizeof(WCHAR
);
315 PackedCs
->lpszClass
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
316 if (IS_ATOM(ClassName
->Buffer
))
318 *((WCHAR
*) CsData
) = L
'A';
319 CsData
+= sizeof(WCHAR
);
320 *((ATOM
*) CsData
) = (ATOM
)(DWORD_PTR
) ClassName
->Buffer
;
321 CsData
+= sizeof(ATOM
);
325 NT_ASSERT(ClassName
->Buffer
!= NULL
);
326 *((WCHAR
*) CsData
) = L
'S';
327 CsData
+= sizeof(WCHAR
);
328 RtlCopyMemory(CsData
, ClassName
->Buffer
, ClassName
->Length
);
329 CsData
+= ClassName
->Length
;
330 *((WCHAR
*) CsData
) = L
'\0';
331 CsData
+= sizeof(WCHAR
);
333 ASSERT(CsData
== (PCHAR
) PackedCs
+ Size
);
334 *lParamPacked
= (LPARAM
) PackedCs
;
336 else if (PoolType
== NonPagedPool
)
338 PMSGMEMORY MsgMemoryEntry
;
342 MsgMemoryEntry
= FindMsgMemory(Msg
);
346 /* Keep previous behavior */
347 return STATUS_SUCCESS
;
349 size
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
352 ERR("No size for lParamPacked\n");
353 return STATUS_SUCCESS
;
355 PackedData
= ExAllocatePoolWithTag(NonPagedPool
, size
, TAG_MSG
);
356 if (PackedData
== NULL
)
358 ERR("Not enough memory to pack lParam\n");
359 return STATUS_NO_MEMORY
;
361 RtlCopyMemory(PackedData
, (PVOID
)lParam
, MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
));
362 *lParamPacked
= (LPARAM
)PackedData
;
365 return STATUS_SUCCESS
;
369 UnpackParam(LPARAM lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolUsed
)
371 NCCALCSIZE_PARAMS
*UnpackedParams
;
372 NCCALCSIZE_PARAMS
*PackedParams
;
373 PWINDOWPOS UnpackedWindowPos
;
375 if (lParamPacked
== lParam
)
377 return STATUS_SUCCESS
;
380 if (WM_NCCALCSIZE
== Msg
&& wParam
)
382 PackedParams
= (NCCALCSIZE_PARAMS
*) lParamPacked
;
383 UnpackedParams
= (NCCALCSIZE_PARAMS
*) lParam
;
384 UnpackedWindowPos
= UnpackedParams
->lppos
;
385 RtlCopyMemory(UnpackedParams
, PackedParams
, sizeof(NCCALCSIZE_PARAMS
));
386 UnpackedParams
->lppos
= UnpackedWindowPos
;
387 RtlCopyMemory(UnpackedWindowPos
, PackedParams
+ 1, sizeof(WINDOWPOS
));
388 ExFreePool((PVOID
) lParamPacked
);
390 return STATUS_SUCCESS
;
392 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
394 ExFreePool((PVOID
) lParamPacked
);
396 return STATUS_SUCCESS
;
398 else if (NonPagedPoolUsed
)
400 PMSGMEMORY MsgMemoryEntry
;
401 MsgMemoryEntry
= FindMsgMemory(Msg
);
402 ASSERT(MsgMemoryEntry
);
404 if (MsgMemoryEntry
->Flags
== MMS_FLAG_READWRITE
)
406 //RtlCopyMemory((PVOID)lParam, (PVOID)lParamPacked, MsgMemoryEntry->Size);
408 ExFreePool((PVOID
) lParamPacked
);
409 return STATUS_SUCCESS
;
414 return STATUS_INVALID_PARAMETER
;
417 static NTSTATUS FASTCALL
418 CopyMsgToKernelMem(MSG
*KernelModeMsg
, MSG
*UserModeMsg
, PMSGMEMORY MsgMemoryEntry
)
425 *KernelModeMsg
= *UserModeMsg
;
427 /* See if this message type is present in the table */
428 if (NULL
== MsgMemoryEntry
)
430 /* Not present, no copying needed */
431 return STATUS_SUCCESS
;
434 /* Determine required size */
435 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
439 /* Allocate kernel mem */
440 KernelMem
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
441 if (NULL
== KernelMem
)
443 ERR("Not enough memory to copy message to kernel mem\n");
444 return STATUS_NO_MEMORY
;
446 KernelModeMsg
->lParam
= (LPARAM
) KernelMem
;
448 /* Copy data if required */
449 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_READ
))
451 TRACE("Copy Message %u from usermode buffer\n", KernelModeMsg
->message
);
452 Status
= MmCopyFromCaller(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
453 if (! NT_SUCCESS(Status
))
455 ERR("Failed to copy message to kernel: invalid usermode lParam buffer\n");
456 ExFreePoolWithTag(KernelMem
, TAG_MSG
);
462 /* Make sure we don't pass any secrets to usermode */
463 RtlZeroMemory(KernelMem
, Size
);
468 KernelModeMsg
->lParam
= 0;
471 return STATUS_SUCCESS
;
474 static NTSTATUS FASTCALL
475 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
478 PMSGMEMORY MsgMemoryEntry
;
481 /* See if this message type is present in the table */
482 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
483 if (NULL
== MsgMemoryEntry
)
485 /* Not present, no copying needed */
486 return STATUS_SUCCESS
;
489 /* Determine required size */
490 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
494 /* Copy data if required */
495 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
497 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
498 if (! NT_SUCCESS(Status
))
500 ERR("Failed to copy message from kernel: invalid usermode lParam buffer\n");
501 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
505 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
508 return STATUS_SUCCESS
;
512 // Wakeup any thread/process waiting on idle input.
517 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
520 pti
= PsGetCurrentThreadWin32Thread();
524 pti
->pClientInfo
->cSpins
= 0; // Reset spins.
526 if ( pti
->pDeskInfo
&& pti
== gptiForeground
)
528 if ( pti
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) ||
529 pti
->pDeskInfo
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) )
531 co_HOOK_CallHooks(WH_FOREGROUNDIDLE
,HC_ACTION
,0,0);
536 TRACE("IdlePing ppi %p\n", ppi
);
537 if ( ppi
&& ppi
->InputIdleEvent
)
539 TRACE("InputIdleEvent\n");
540 KeSetEvent( ppi
->InputIdleEvent
, IO_NO_INCREMENT
, FALSE
);
547 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
549 TRACE("IdlePong ppi %p\n", ppi
);
550 if ( ppi
&& ppi
->InputIdleEvent
)
552 KeClearEvent(ppi
->InputIdleEvent
);
556 static BOOL
is_message_broadcastable(UINT msg
)
558 return msg
< WM_USER
|| msg
>= 0xc000;
562 GetWakeMask(UINT first
, UINT last
)
564 UINT mask
= QS_POSTMESSAGE
| QS_SENDMESSAGE
; /* Always selected */
568 if ((first
<= WM_KEYLAST
) && (last
>= WM_KEYFIRST
)) mask
|= QS_KEY
;
569 if ( ((first
<= WM_MOUSELAST
) && (last
>= WM_MOUSEFIRST
)) ||
570 ((first
<= WM_NCMOUSELAST
) && (last
>= WM_NCMOUSEFIRST
)) ) mask
|= QS_MOUSE
;
571 if ((first
<= WM_TIMER
) && (last
>= WM_TIMER
)) mask
|= QS_TIMER
;
572 if ((first
<= WM_SYSTIMER
) && (last
>= WM_SYSTIMER
)) mask
|= QS_TIMER
;
573 if ((first
<= WM_PAINT
) && (last
>= WM_PAINT
)) mask
|= QS_PAINT
;
575 else mask
= QS_ALLINPUT
;
581 IntCallWndProc( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
583 BOOL SameThread
= FALSE
;
586 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
593 co_HOOK_CallHooks( WH_CALLWNDPROC
, HC_ACTION
, SameThread
, (LPARAM
)&CWP
);
597 IntCallWndProcRet ( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*uResult
)
599 BOOL SameThread
= FALSE
;
602 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
607 CWPR
.wParam
= wParam
;
608 CWPR
.lParam
= lParam
;
609 CWPR
.lResult
= uResult
? (*uResult
) : 0;
610 co_HOOK_CallHooks( WH_CALLWNDPROCRET
, HC_ACTION
, SameThread
, (LPARAM
)&CWPR
);
613 static LRESULT
handle_internal_message( PWND pWnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
616 // USER_REFERENCE_ENTRY Ref;
617 // PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
619 if (!pWnd
|| UserIsDesktopWindow(pWnd
) || UserIsMessageWindow(pWnd
))
622 TRACE("Internal Event Msg 0x%x hWnd 0x%p\n", msg
, pWnd
->head
.h
);
626 case WM_ASYNC_SHOWWINDOW
:
627 return co_WinPosShowWindow( pWnd
, wparam
);
628 case WM_ASYNC_SETWINDOWPOS
:
630 PWINDOWPOS winpos
= (PWINDOWPOS
)lparam
;
631 if (!winpos
) return 0;
632 lRes
= co_WinPosSetWindowPos( pWnd
,
633 winpos
->hwndInsertAfter
,
639 ExFreePoolWithTag(winpos
, USERTAG_SWP
);
642 case WM_ASYNC_DESTROYWINDOW
:
644 ERR("WM_ASYNC_DESTROYWINDOW\n");
645 if (pWnd
->style
& WS_CHILD
)
646 return co_UserFreeWindow(pWnd
, PsGetCurrentProcessWin32Process(), PsGetCurrentThreadWin32Thread(), TRUE
);
648 co_UserDestroyWindow(pWnd
);
654 static LRESULT
handle_internal_events( PTHREADINFO pti
, PWND pWnd
, DWORD dwQEvent
, LONG_PTR ExtraInfo
, PMSG pMsg
)
662 co_EVENT_CallEvents( pMsg
->message
, pMsg
->hwnd
, pMsg
->wParam
, ExtraInfo
);
667 //ERR("HIE : SAW : pti 0x%p hWnd 0x%p\n",pti,pMsg->hwnd);
668 IntActivateWindow((PWND
)pMsg
->wParam
, pti
, (HANDLE
)pMsg
->lParam
, (DWORD
)ExtraInfo
);
673 //ERR("HIE : DAW : pti 0x%p tid 0x%p hWndPrev 0x%p\n",pti,ExtraInfo,pMsg->hwnd);
674 IntDeactivateWindow(pti
, (HANDLE
)ExtraInfo
);
682 IntDispatchMessage(PMSG pMsg
)
684 LARGE_INTEGER TickCount
;
689 BOOL DoCallBack
= TRUE
;
693 Window
= UserGetWindowObject(pMsg
->hwnd
);
694 if (!Window
) return 0;
697 pti
= PsGetCurrentThreadWin32Thread();
699 if ( Window
&& Window
->head
.pti
!= pti
)
701 EngSetLastError( ERROR_MESSAGE_SYNC_ONLY
);
705 if (((pMsg
->message
== WM_SYSTIMER
) ||
706 (pMsg
->message
== WM_TIMER
)) &&
709 if (pMsg
->message
== WM_TIMER
)
711 if (ValidateTimerCallback(pti
,pMsg
->lParam
))
713 KeQueryTickCount(&TickCount
);
714 Time
= MsqCalculateMessageTime(&TickCount
);
715 retval
= co_IntCallWindowProc((WNDPROC
)pMsg
->lParam
,
727 PTIMER pTimer
= FindSystemTimer(pMsg
);
728 if (pTimer
&& pTimer
->pfn
)
730 KeQueryTickCount(&TickCount
);
731 Time
= MsqCalculateMessageTime(&TickCount
);
732 pTimer
->pfn(pMsg
->hwnd
, WM_SYSTIMER
, (UINT
)pMsg
->wParam
, Time
);
738 if ( !Window
) return 0;
740 if (pMsg
->message
== WM_PAINT
) Window
->state
|= WNDS_PAINTNOTPROCESSED
;
742 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
744 TRACE("Dispatch: Server Side Window Procedure\n");
748 DoCallBack
= !DesktopWindowProc( Window
,
754 case FNID_MESSAGEWND
:
755 DoCallBack
= !UserMessageWindowProc( Window
,
762 DoCallBack
= !PopupMenuWndProc( Window
,
771 /* Since we are doing a callback on the same thread right away, there is
772 no need to copy the lparam to kernel mode and then back to usermode.
773 We just pretend it isn't a pointer */
776 retval
= co_IntCallWindowProc( Window
->lpfnWndProc
,
784 if ( pMsg
->message
== WM_PAINT
&&
786 Window
->state
& WNDS_PAINTNOTPROCESSED
) // <--- Cleared, paint was already processed!
788 Window
->state2
&= ~WNDS2_WMPAINTSENT
;
789 /* send a WM_ERASEBKGND if the non-client area is still invalid */
790 ERR("Message WM_PAINT count %d Internal Paint Set? %s\n",Window
->head
.pti
->cPaintsReady
, Window
->state
& WNDS_INTERNALPAINT
? "TRUE" : "FALSE");
791 IntPaintWindow( Window
);
798 * Internal version of PeekMessage() doing all the work
803 * Input (hardware) messages and system internal events
804 * Sent messages (again)
809 co_IntPeekMessage( PMSG Msg
,
818 LARGE_INTEGER LargeTickCount
;
823 pti
= PsGetCurrentThreadWin32Thread();
825 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
826 ProcessMask
= HIWORD(RemoveMsg
);
828 /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns
829 all available messages (that is, no range filtering is performed)". */
830 if (!ProcessMask
) ProcessMask
= (QS_ALLPOSTMESSAGE
|QS_ALLINPUT
);
836 KeQueryTickCount(&LargeTickCount
);
837 pti
->timeLast
= LargeTickCount
.u
.LowPart
;
838 pti
->pcti
->tickLastMsgChecked
= LargeTickCount
.u
.LowPart
;
840 // Post mouse moves while looping through peek messages.
841 if (pti
->MessageQueue
->QF_flags
& QF_MOUSEMOVED
)
843 IntCoalesceMouseMove(pti
);
846 /* Dispatch sent messages here. */
847 while ( co_MsqDispatchOneSentMessage(pti
) )
849 /* if some PM_QS* flags were specified, only handle sent messages from now on */
850 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
; // wine does this; ProcessMask = QS_SENDMESSAGE;
852 if (Hit
) return FALSE
;
854 /* Clear changed bits so we can wait on them if we don't find a message */
855 if (ProcessMask
& QS_POSTMESSAGE
)
857 pti
->pcti
->fsChangeBits
&= ~(QS_POSTMESSAGE
| QS_HOTKEY
| QS_TIMER
);
858 if (MsgFilterMin
== 0 && MsgFilterMax
== 0) // Wine hack does this; ~0U)
860 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
864 if (ProcessMask
& QS_INPUT
)
866 pti
->pcti
->fsChangeBits
&= ~QS_INPUT
;
869 /* Now check for normal messages. */
870 if (( (ProcessMask
& QS_POSTMESSAGE
) ||
871 (ProcessMask
& QS_HOTKEY
) ) &&
885 /* Only check for quit messages if not posted messages pending. */
886 if (ProcessMask
& QS_POSTMESSAGE
&& pti
->QuitPosted
)
888 /* According to the PSDK, WM_QUIT messages are always returned, regardless
889 of the filter specified */
891 Msg
->message
= WM_QUIT
;
892 Msg
->wParam
= pti
->exitCode
;
896 pti
->QuitPosted
= FALSE
;
897 ClearMsgBitsMask(pti
, QS_POSTMESSAGE
);
898 pti
->pcti
->fsWakeBits
&= ~QS_ALLPOSTMESSAGE
;
899 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
904 /* Check for hardware events. */
905 if ((ProcessMask
& QS_INPUT
) &&
906 co_MsqPeekHardwareMessage( pti
,
917 /* Now check for System Event messages. */
922 if (MsqPeekMessage( pti
,
932 handle_internal_events( pti
, Window
, dwQEvent
, eExtraInfo
, &eMsg
);
937 /* Check for sent messages again. */
938 while ( co_MsqDispatchOneSentMessage(pti
) )
940 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
;
942 if (Hit
) return FALSE
;
944 /* Check for paint messages. */
945 if ((ProcessMask
& QS_PAINT
) &&
947 IntGetPaintMessage( Window
,
957 /* This is correct, check for the current threads timers waiting to be
958 posted to this threads message queue. If any we loop again.
960 if ((ProcessMask
& QS_TIMER
) &&
961 PostTimerMessages(Window
))
974 co_IntWaitMessage( PWND Window
,
979 NTSTATUS Status
= STATUS_SUCCESS
;
981 LONG_PTR ExtraInfo
= 0;
983 pti
= PsGetCurrentThreadWin32Thread();
987 if ( co_IntPeekMessage( &Msg
, // Dont reenter!
991 MAKELONG( PM_NOREMOVE
, GetWakeMask( MsgFilterMin
, MsgFilterMax
)),
993 TRUE
) ) // act like GetMessage.
998 /* Nothing found. Wait for new messages. */
999 Status
= co_MsqWaitForNewMessages( pti
,
1003 if (!NT_SUCCESS(Status
))
1005 SetLastNtError(Status
);
1006 ERR("Exit co_IntWaitMessage on error!\n");
1009 if (Status
== STATUS_USER_APC
|| Status
== STATUS_TIMEOUT
)
1020 co_IntGetPeekMessage( PMSG pMsg
,
1029 BOOL Present
= FALSE
;
1031 LONG_PTR ExtraInfo
= 0;
1033 if ( hWnd
== HWND_TOPMOST
|| hWnd
== HWND_BROADCAST
)
1036 /* Validate input */
1037 if (hWnd
&& hWnd
!= HWND_BOTTOM
)
1039 if (!(Window
= UserGetWindowObject(hWnd
)))
1049 Window
= (PWND
)hWnd
;
1052 if (MsgFilterMax
< MsgFilterMin
)
1060 RemoveMsg
|= ((GetWakeMask( MsgFilterMin
, MsgFilterMax
))<< 16);
1063 pti
= PsGetCurrentThreadWin32Thread();
1064 pti
->pClientInfo
->cSpins
++; // Bump up the spin count.
1068 Present
= co_IntPeekMessage( pMsg
,
1077 /* GetMessage or PostMessage must never get messages that contain pointers */
1078 ASSERT(FindMsgMemory(pMsg
->message
) == NULL
);
1080 if ( pMsg
->message
>= WM_DDE_FIRST
&& pMsg
->message
<= WM_DDE_LAST
)
1082 if (!IntDdeGetMessageHook(pMsg
, ExtraInfo
))
1084 TRACE("DDE Get return ERROR\n");
1089 if (pMsg
->message
!= WM_PAINT
&& pMsg
->message
!= WM_QUIT
)
1091 if (!RtlEqualMemory(&pti
->ptLast
, &pMsg
->pt
, sizeof(POINT
)))
1093 pti
->TIF_flags
|= TIF_MSGPOSCHANGED
;
1095 pti
->timeLast
= pMsg
->time
;
1096 pti
->ptLast
= pMsg
->pt
;
1099 // The WH_GETMESSAGE hook enables an application to monitor messages about to
1100 // be returned by the GetMessage or PeekMessage function.
1102 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)pMsg
);
1104 if ( bGMSG
|| pMsg
->message
== WM_PAINT
) break;
1109 Status
= co_MsqWaitForNewMessages( pti
,
1113 if ( !NT_SUCCESS(Status
) ||
1114 Status
== STATUS_USER_APC
||
1115 Status
== STATUS_TIMEOUT
)
1123 if (!(RemoveMsg
& PM_NOYIELD
))
1126 // Yield this thread!
1129 UserEnterExclusive();
1130 // Fall through to exit.
1136 while( bGMSG
&& !Present
);
1138 // Been spinning, time to swap vinyl...
1139 if (pti
->pClientInfo
->cSpins
>= 100)
1141 // Clear the spin cycle to fix the mix.
1142 pti
->pClientInfo
->cSpins
= 0;
1143 //if (!(pti->TIF_flags & TIF_SPINNING)) // FIXME: Need to swap vinyl...
1149 UserPostThreadMessage( PTHREADINFO pti
,
1155 LARGE_INTEGER LargeTickCount
;
1157 if (is_pointer_message(Msg
))
1159 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1162 Message
.hwnd
= NULL
;
1163 Message
.message
= Msg
;
1164 Message
.wParam
= wParam
;
1165 Message
.lParam
= lParam
;
1166 Message
.pt
= gpsi
->ptCursor
;
1168 KeQueryTickCount(&LargeTickCount
);
1169 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1170 MsqPostMessage(pti
, &Message
, FALSE
, QS_POSTMESSAGE
, 0, 0);
1174 PTHREADINFO FASTCALL
1175 IntSendTo(PWND Window
, PTHREADINFO ptiCur
, UINT Msg
)
1180 Window
->head
.pti
== ptiCur
)
1185 return Window
? Window
->head
.pti
: NULL
;
1189 UserPostMessage( HWND Wnd
,
1196 LARGE_INTEGER LargeTickCount
;
1197 LONG_PTR ExtraInfo
= 0;
1200 Message
.message
= Msg
;
1201 Message
.wParam
= wParam
;
1202 Message
.lParam
= lParam
;
1203 Message
.pt
= gpsi
->ptCursor
;
1204 KeQueryTickCount(&LargeTickCount
);
1205 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1207 if (is_pointer_message(Message
.message
))
1209 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1213 if (Wnd
== HWND_BROADCAST
|| Wnd
== HWND_TOPMOST
)
1219 if (!is_message_broadcastable(Msg
)) return TRUE
;
1221 DesktopWindow
= UserGetDesktopWindow();
1222 List
= IntWinListChildren(DesktopWindow
);
1226 UserPostMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1227 for (i
= 0; List
[i
]; i
++)
1229 PWND pwnd
= UserGetWindowObject(List
[i
]);
1230 if (!pwnd
) continue;
1232 if ( pwnd
->fnid
== FNID_MENU
|| // Also need pwnd->pcls->atomClassName == gaOleMainThreadWndClass
1233 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1236 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1238 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1247 return UserPostThreadMessage( gptiCurrent
,
1253 Window
= UserGetWindowObject(Wnd
);
1256 ERR("UserPostMessage: Invalid handle 0x%p Msg 0x%x!\n", Wnd
, Msg
);
1260 pti
= Window
->head
.pti
;
1262 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1264 ERR("Attempted to post message to window %p when the thread is in cleanup!\n", Wnd
);
1268 if ( Window
->state
& WNDS_DESTROYED
)
1270 ERR("Attempted to post message to window %p that is being destroyed!\n", Wnd
);
1271 /* FIXME: Last error code? */
1275 if ( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1277 if (!IntDdePostMessageHook(Window
, Msg
, wParam
, &lParam
, &ExtraInfo
))
1279 TRACE("Posting Exit DDE 0x%x\n",Msg
);
1282 Message
.lParam
= lParam
;
1285 MsqPostMessage(pti
, &Message
, FALSE
, QS_POSTMESSAGE
, 0, ExtraInfo
);
1291 co_IntSendMessage( HWND hWnd
,
1296 ULONG_PTR Result
= 0;
1298 if (co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1300 return (LRESULT
)Result
;
1305 static LRESULT FASTCALL
1306 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1312 ULONG_PTR
*uResult
)
1314 NTSTATUS Status
= STATUS_SUCCESS
;
1316 PMSGMEMORY MsgMemoryEntry
;
1317 INT lParamBufferSize
;
1318 LPARAM lParamPacked
;
1319 PTHREADINFO Win32Thread
, ptiSendTo
= NULL
;
1320 ULONG_PTR Result
= 0;
1321 DECLARE_RETURN(LRESULT
);
1322 USER_REFERENCE_ENTRY Ref
;
1323 BOOL DoCallBack
= TRUE
;
1325 if (!(Window
= UserGetWindowObject(hWnd
)))
1327 TRACE("SendMessageTimeoutSingle: Invalid handle 0x%p!\n",hWnd
);
1331 UserRefObjectCo(Window
, &Ref
);
1333 Win32Thread
= PsGetCurrentThreadWin32Thread();
1335 ptiSendTo
= IntSendTo(Window
, Win32Thread
, Msg
);
1337 if ( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1339 if (!IntDdeSendMessageHook(Window
, Msg
, wParam
, lParam
))
1341 ERR("Sending Exit DDE 0x%x\n",Msg
);
1348 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1350 /* Never send messages to exiting threads */
1354 if (Msg
& 0x80000000)
1356 TRACE("SMTS: Internal Message!\n");
1357 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1358 if (uResult
) *uResult
= Result
;
1362 // Only happens when calling the client!
1363 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1365 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1367 TRACE("SMT: Server Side Window Procedure\n");
1368 // Handle it here. Safeguard against excessive recursions.
1369 if (IoGetRemainingStackSize() < PAGE_SIZE
)
1371 ERR("Server Callback Exceeded Stack!\n");
1374 /* Return after server side call, IntCallWndProcRet will not be called. */
1375 switch(Window
->fnid
)
1378 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1380 case FNID_MESSAGEWND
:
1381 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1384 DoCallBack
= !PopupMenuWndProc( Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1389 if (uResult
) *uResult
= Result
;
1393 /* See if this message type is present in the table */
1394 MsgMemoryEntry
= FindMsgMemory(Msg
);
1395 if (NULL
== MsgMemoryEntry
)
1397 lParamBufferSize
= -1;
1401 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1402 // If zero, do not allow callback on client side to allocate a buffer!!!!! See CORE-7695.
1403 if (!lParamBufferSize
) lParamBufferSize
= -1;
1406 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1408 ERR("Failed to pack message parameters\n");
1412 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1424 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1426 ERR("Failed to unpack message parameters\n");
1430 // Only happens when calling the client!
1431 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1436 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(ptiSendTo
))
1438 // FIXME: Set window hung and add to a list.
1439 /* FIXME: Set a LastError? */
1443 if (Window
->state
& WNDS_DESTROYED
)
1445 /* FIXME: Last error? */
1446 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1452 Status
= co_MsqSendMessage( ptiSendTo
,
1458 (uFlags
& SMTO_BLOCK
),
1462 while ((STATUS_TIMEOUT
== Status
) &&
1463 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1464 !MsqIsHung(ptiSendTo
)); // FIXME: Set window hung and add to a list.
1466 if (Status
== STATUS_TIMEOUT
)
1470 * Microsoft Windows 2000: If GetLastError returns zero, then the function
1472 * XP+ : If the function fails or times out, the return value is zero.
1473 * To get extended error information, call GetLastError. If GetLastError
1474 * returns ERROR_TIMEOUT, then the function timed out.
1476 EngSetLastError(ERROR_TIMEOUT
);
1479 else if (!NT_SUCCESS(Status
))
1481 SetLastNtError(Status
);
1488 if (Window
) UserDerefObjectCo(Window
);
1493 co_IntSendMessageTimeout( HWND hWnd
,
1499 ULONG_PTR
*uResult
)
1505 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1507 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1510 if (!is_message_broadcastable(Msg
)) return TRUE
;
1512 DesktopWindow
= UserGetDesktopWindow();
1513 if (NULL
== DesktopWindow
)
1515 EngSetLastError(ERROR_INTERNAL_ERROR
);
1519 if (hWnd
!= HWND_TOPMOST
)
1521 /* Send message to the desktop window too! */
1522 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1525 Children
= IntWinListChildren(DesktopWindow
);
1526 if (NULL
== Children
)
1531 for (Child
= Children
; NULL
!= *Child
; Child
++)
1533 PWND pwnd
= UserGetWindowObject(*Child
);
1534 if (!pwnd
) continue;
1536 if ( pwnd
->fnid
== FNID_MENU
||
1537 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1540 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1543 ExFreePoolWithTag(Children
, USERTAG_WINDOWLIST
);
1545 return (LRESULT
) TRUE
;
1549 co_IntSendMessageNoWait(HWND hWnd
,
1554 ULONG_PTR Result
= 0;
1555 return co_IntSendMessageWithCallBack( hWnd
,
1564 If you send a message in the range below WM_USER to the asynchronous message
1565 functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its
1566 message parameters cannot include pointers. Otherwise, the operation will fail.
1567 The functions will return before the receiving thread has had a chance to
1568 process the message and the sender will free the memory before it is used.
1571 co_IntSendMessageWithCallBack( HWND hWnd
,
1575 SENDASYNCPROC CompletionCallback
,
1576 ULONG_PTR CompletionCallbackContext
,
1581 PMSGMEMORY MsgMemoryEntry
;
1582 INT lParamBufferSize
;
1583 LPARAM lParamPacked
;
1584 PTHREADINFO Win32Thread
, ptiSendTo
= NULL
;
1585 DECLARE_RETURN(LRESULT
);
1586 USER_REFERENCE_ENTRY Ref
;
1587 PUSER_SENT_MESSAGE Message
;
1588 BOOL DoCallBack
= TRUE
;
1590 if (!(Window
= UserGetWindowObject(hWnd
)))
1592 TRACE("SendMessageWithCallBack: Invalid handle 0x%p!\n",hWnd
);
1596 UserRefObjectCo(Window
, &Ref
);
1598 if (Window
->state
& WNDS_DESTROYED
)
1600 /* FIXME: last error? */
1601 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1605 Win32Thread
= PsGetCurrentThreadWin32Thread();
1607 if (Win32Thread
== NULL
||
1608 Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1613 ptiSendTo
= IntSendTo(Window
, Win32Thread
, Msg
);
1615 if (Msg
& 0x80000000 &&
1618 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
) RETURN( FALSE
);
1620 TRACE("SMWCB: Internal Message!\n");
1621 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1622 if (uResult
) *uResult
= Result
;
1626 /* See if this message type is present in the table */
1627 MsgMemoryEntry
= FindMsgMemory(Msg
);
1628 if (NULL
== MsgMemoryEntry
)
1630 lParamBufferSize
= -1;
1634 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1635 if (!lParamBufferSize
) lParamBufferSize
= -1;
1638 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, !!ptiSendTo
)))
1640 ERR("Failed to pack message parameters\n");
1644 /* If it can be sent now, then send it. */
1647 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1649 UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
);
1650 /* Never send messages to exiting threads */
1654 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1656 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1658 TRACE("SMWCB: Server Side Window Procedure\n");
1659 switch(Window
->fnid
)
1662 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParamPacked
, (LRESULT
*)&Result
);
1664 case FNID_MESSAGEWND
:
1665 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1668 DoCallBack
= !PopupMenuWndProc( Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1674 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1686 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1688 if (CompletionCallback
)
1690 co_IntCallSentMessageCallback(CompletionCallback
,
1693 CompletionCallbackContext
,
1700 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1702 ERR("Failed to unpack message parameters\n");
1707 if(!(Message
= AllocateUserMessage(FALSE
)))
1709 ERR("MsqSendMessage(): Not enough memory to allocate a message");
1713 Message
->Msg
.hwnd
= hWnd
;
1714 Message
->Msg
.message
= Msg
;
1715 Message
->Msg
.wParam
= wParam
;
1716 Message
->Msg
.lParam
= lParamPacked
;
1717 Message
->pkCompletionEvent
= NULL
; // No event needed.
1718 Message
->lResult
= 0;
1719 Message
->QS_Flags
= 0;
1720 Message
->ptiReceiver
= ptiSendTo
;
1721 Message
->ptiSender
= NULL
; // mjmartin, you are right! This is null.
1722 Message
->ptiCallBackSender
= Win32Thread
;
1723 Message
->CompletionCallback
= CompletionCallback
;
1724 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1725 Message
->HookMessage
= MSQ_NORMAL
;
1726 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1727 Message
->QS_Flags
= QS_SENDMESSAGE
;
1728 Message
->flags
= SMF_RECEIVERFREE
;
1730 if (Msg
& 0x80000000) // Higher priority event message!
1731 InsertHeadList(&ptiSendTo
->SentMessagesListHead
, &Message
->ListEntry
);
1733 InsertTailList(&ptiSendTo
->SentMessagesListHead
, &Message
->ListEntry
);
1734 MsqWakeQueue(ptiSendTo
, QS_SENDMESSAGE
, TRUE
);
1739 if (Window
) UserDerefObjectCo(Window
);
1745 This HACK function posts a message if the destination's message queue belongs to
1746 another thread, otherwise it sends the message. It does not support broadcast
1750 co_IntPostOrSendMessage( HWND hWnd
,
1759 if ( hWnd
== HWND_BROADCAST
)
1764 if(!(Window
= UserGetWindowObject(hWnd
)))
1766 TRACE("PostOrSendMessage: Invalid handle 0x%p!\n",hWnd
);
1770 pti
= PsGetCurrentThreadWin32Thread();
1772 if ( IntSendTo(Window
, pti
, Msg
) &&
1773 FindMsgMemory(Msg
) == 0 )
1775 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1779 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1785 return (LRESULT
)Result
;
1789 static LRESULT FASTCALL
1790 co_IntDoSendMessage( HWND hWnd
,
1796 LRESULT Result
= TRUE
;
1799 MSG UserModeMsg
, KernelModeMsg
;
1800 PMSGMEMORY MsgMemoryEntry
;
1801 PTHREADINFO ptiSendTo
;
1803 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1805 Window
= UserGetWindowObject(hWnd
);
1812 /* Check for an exiting window. */
1813 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1815 ERR("co_IntDoSendMessage Window Exiting!\n");
1818 /* See if the current thread can handle this message */
1819 ptiSendTo
= IntSendTo(Window
, gptiCurrent
, Msg
);
1821 // If broadcasting or sending to another thread, save the users data.
1822 if (!Window
|| ptiSendTo
)
1824 UserModeMsg
.hwnd
= hWnd
;
1825 UserModeMsg
.message
= Msg
;
1826 UserModeMsg
.wParam
= wParam
;
1827 UserModeMsg
.lParam
= lParam
;
1828 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1829 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1830 if (!NT_SUCCESS(Status
))
1832 EngSetLastError(ERROR_INVALID_PARAMETER
);
1833 return (dsm
? 0 : -1);
1838 KernelModeMsg
.hwnd
= hWnd
;
1839 KernelModeMsg
.message
= Msg
;
1840 KernelModeMsg
.wParam
= wParam
;
1841 KernelModeMsg
.lParam
= lParam
;
1846 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1847 KernelModeMsg
.message
,
1848 KernelModeMsg
.wParam
,
1849 KernelModeMsg
.lParam
);
1853 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1854 KernelModeMsg
.message
,
1855 KernelModeMsg
.wParam
,
1856 KernelModeMsg
.lParam
,
1862 if (!Window
|| ptiSendTo
)
1864 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1865 if (!NT_SUCCESS(Status
))
1867 EngSetLastError(ERROR_INVALID_PARAMETER
);
1868 return(dsm
? 0 : -1);
1872 return (LRESULT
)Result
;
1876 UserSendNotifyMessage( HWND hWnd
,
1883 if (is_pointer_message(Msg
))
1885 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1889 // Basicly the same as IntPostOrSendMessage
1890 if (hWnd
== HWND_BROADCAST
) // Handle Broadcast
1896 DesktopWindow
= UserGetDesktopWindow();
1897 List
= IntWinListChildren(DesktopWindow
);
1901 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1902 for (i
= 0; List
[i
]; i
++)
1904 PWND pwnd
= UserGetWindowObject(List
[i
]);
1905 if (!pwnd
) continue;
1907 if ( pwnd
->fnid
== FNID_MENU
||
1908 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1911 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1913 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1918 Ret
= co_IntSendMessageNoWait( hWnd
, Msg
, wParam
, lParam
);
1925 IntGetQueueStatus(DWORD Changes
)
1930 pti
= PsGetCurrentThreadWin32Thread();
1932 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1934 /* High word, types of messages currently in the queue.
1935 Low word, types of messages that have been added to the queue and that
1936 are still in the queue
1938 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1940 pti
->pcti
->fsChangeBits
&= ~Changes
;
1946 IntInitMessagePumpHook(VOID
)
1948 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1952 pti
->pcti
->dwcPumpHook
++;
1959 IntUninitMessagePumpHook(VOID
)
1961 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1965 if (pti
->pcti
->dwcPumpHook
<= 0)
1969 pti
->pcti
->dwcPumpHook
--;
1976 IntCallMsgFilter( LPMSG lpmsg
, INT code
)
1980 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)lpmsg
))
1986 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)lpmsg
);
1991 /** Functions ******************************************************************/
1997 POINT pt
) // Just like the User call.
2001 ULONG wDragWidth
, wDragHeight
;
2002 DECLARE_RETURN(BOOL
);
2004 TRACE("Enter NtUserDragDetect(%p)\n", hWnd
);
2005 UserEnterExclusive();
2007 wDragWidth
= UserGetSystemMetrics(SM_CXDRAG
);
2008 wDragHeight
= UserGetSystemMetrics(SM_CYDRAG
);
2010 rect
.left
= pt
.x
- wDragWidth
;
2011 rect
.right
= pt
.x
+ wDragWidth
;
2013 rect
.top
= pt
.y
- wDragHeight
;
2014 rect
.bottom
= pt
.y
+ wDragHeight
;
2016 co_UserSetCapture(hWnd
);
2020 while (co_IntGetPeekMessage( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, FALSE
) ||
2021 co_IntGetPeekMessage( &msg
, 0, WM_QUEUESYNC
, WM_QUEUESYNC
, PM_REMOVE
, FALSE
) ||
2022 co_IntGetPeekMessage( &msg
, 0, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
, FALSE
) )
2024 if ( msg
.message
== WM_LBUTTONUP
)
2026 co_UserSetCapture(NULL
);
2029 if ( msg
.message
== WM_MOUSEMOVE
)
2032 tmp
.x
= (short)LOWORD(msg
.lParam
);
2033 tmp
.y
= (short)HIWORD(msg
.lParam
);
2034 if( !RECTL_bPointInRect( &rect
, tmp
.x
, tmp
.y
) )
2036 co_UserSetCapture(NULL
);
2040 if ( msg
.message
== WM_KEYDOWN
)
2042 if ( msg
.wParam
== VK_ESCAPE
)
2044 co_UserSetCapture(NULL
);
2048 if ( msg
.message
== WM_QUEUESYNC
)
2050 co_HOOK_CallHooks( WH_CBT
, HCBT_QS
, 0, 0 );
2053 co_IntWaitMessage(NULL
, 0, 0);
2058 TRACE("Leave NtUserDragDetect, ret=%i\n",_ret_
);
2064 NtUserPostMessage(HWND hWnd
,
2071 UserEnterExclusive();
2073 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
2081 NtUserPostThreadMessage(DWORD idThread
,
2088 PTHREADINFO pThread
;
2091 UserEnterExclusive();
2093 Status
= PsLookupThreadByThreadId(UlongToHandle(idThread
), &peThread
);
2095 if ( Status
== STATUS_SUCCESS
)
2097 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
2099 !pThread
->MessageQueue
||
2100 (pThread
->TIF_flags
& TIF_INCLEANUP
))
2102 ObDereferenceObject( peThread
);
2105 ret
= UserPostThreadMessage( pThread
, Msg
, wParam
, lParam
);
2106 ObDereferenceObject( peThread
);
2110 SetLastNtError( Status
);
2118 NtUserWaitMessage(VOID
)
2122 UserEnterExclusive();
2123 TRACE("NtUserWaitMessage Enter\n");
2124 ret
= co_IntWaitMessage(NULL
, 0, 0);
2125 TRACE("NtUserWaitMessage Leave\n");
2132 NtUserGetMessage(PMSG pMsg
,
2140 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
2142 EngSetLastError(ERROR_INVALID_PARAMETER
);
2146 UserEnterExclusive();
2148 RtlZeroMemory(&Msg
, sizeof(MSG
));
2150 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
2158 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2159 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2161 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2163 SetLastNtError(_SEH2_GetExceptionCode());
2170 Ret
= Ret
? (WM_QUIT
!= pMsg
->message
) : FALSE
;
2176 NtUserPeekMessage( PMSG pMsg
,
2185 if ( RemoveMsg
& PM_BADMSGFLAGS
)
2187 EngSetLastError(ERROR_INVALID_FLAGS
);
2191 UserEnterExclusive();
2193 RtlZeroMemory(&Msg
, sizeof(MSG
));
2195 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
2203 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2204 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2206 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2208 SetLastNtError(_SEH2_GetExceptionCode());
2218 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
2225 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
2226 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
2228 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2230 _SEH2_YIELD(return FALSE
);
2234 UserEnterExclusive();
2236 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
2242 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
2249 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
2250 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
2252 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2262 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
2269 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
2270 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
2272 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2274 SetLastNtError(_SEH2_GetExceptionCode());
2275 _SEH2_YIELD(return FALSE
);
2279 UserEnterExclusive();
2281 Res
= IntDispatchMessage(&SafeMsg
);
2288 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
2296 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
2297 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
2299 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2301 SetLastNtError(_SEH2_GetExceptionCode());
2302 _SEH2_YIELD(return FALSE
);
2306 UserEnterExclusive();
2307 pWnd
= UserGetWindowObject(SafeMsg
.hwnd
);
2308 if (pWnd
) // Must have a window!
2310 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
2314 TRACE("No Window for Translate. hwnd 0x%p Msg %u\n", SafeMsg
.hwnd
, SafeMsg
.message
);
2322 LRESULT APIENTRY
ScrollBarWndProc(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
);
2325 NtUserMessageCall( HWND hWnd
,
2329 ULONG_PTR ResultInfo
,
2330 DWORD dwType
, // fnID?
2333 LRESULT lResult
= 0;
2336 USER_REFERENCE_ENTRY Ref
;
2338 UserEnterExclusive();
2342 case FNID_SCROLLBAR
:
2344 lResult
= ScrollBarWndProc(hWnd
, Msg
, wParam
, lParam
);
2349 Window
= UserGetWindowObject(hWnd
);
2352 //ERR("FNID_DESKTOP IN\n");
2353 Ret
= DesktopWindowProc(Window
, Msg
, wParam
, lParam
, &lResult
);
2354 //ERR("FNID_DESKTOP OUT\n");
2360 Window
= UserGetWindowObject(hWnd
);
2363 Ret
= PopupMenuWndProc( Window
, Msg
, wParam
, lParam
, &lResult
);
2367 case FNID_MESSAGEWND
:
2369 Window
= UserGetWindowObject(hWnd
);
2372 Ret
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
, &lResult
);
2376 case FNID_DEFWINDOWPROC
:
2377 /* Validate input */
2380 Window
= UserGetWindowObject(hWnd
);
2386 UserRefObjectCo(Window
, &Ref
);
2388 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2391 UserDerefObjectCo(Window
);
2393 case FNID_SENDNOTIFYMESSAGE
:
2394 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2396 case FNID_BROADCASTSYSTEMMESSAGE
:
2398 BROADCASTPARM parm
, *retparam
;
2399 DWORD_PTR RetVal
= 0;
2405 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2406 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2408 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2417 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2418 parm
.recipients
== BSM_ALLCOMPONENTS
)
2420 PLIST_ENTRY DesktopEntry
;
2422 HWND
*List
, hwndDenied
= NULL
;
2424 PWND pwnd
, pwndDesk
;
2428 for (DesktopEntry
= InputWindowStation
->DesktopListHead
.Flink
;
2429 DesktopEntry
!= &InputWindowStation
->DesktopListHead
;
2430 DesktopEntry
= DesktopEntry
->Flink
)
2432 rpdesk
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
2433 pwndDesk
= rpdesk
->pDeskInfo
->spwnd
;
2434 List
= IntWinListChildren(pwndDesk
);
2436 if (parm
.flags
& BSF_QUERY
)
2440 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2442 fuFlags
= SMTO_ABORTIFHUNG
;
2444 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2446 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2450 fuFlags
= SMTO_NORMAL
;
2452 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2460 for (i
= 0; List
[i
]; i
++)
2462 pwnd
= UserGetWindowObject(List
[i
]);
2463 if (!pwnd
) continue;
2465 if ( pwnd
->fnid
== FNID_MENU
||
2466 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2469 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2471 if ( pwnd
->head
.pti
== gptiCurrent
)
2474 co_IntSendMessageTimeout( List
[i
],
2482 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2484 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2487 if (RetVal
== BROADCAST_QUERY_DENY
)
2489 hwndDenied
= List
[i
];
2490 hDesk
= UserHMGetHandle(pwndDesk
);
2494 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2497 retparam
= (PBROADCASTPARM
) ResultInfo
;
2498 retparam
->hDesk
= hDesk
;
2499 retparam
->hWnd
= hwndDenied
;
2501 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2506 if (!Ret
) break; // Have a hit! Let everyone know!
2509 else if (parm
.flags
& BSF_POSTMESSAGE
)
2513 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2515 for (i
= 0; List
[i
]; i
++)
2517 pwnd
= UserGetWindowObject(List
[i
]);
2518 if (!pwnd
) continue;
2520 if ( pwnd
->fnid
== FNID_MENU
||
2521 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2524 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2526 if ( pwnd
->head
.pti
== gptiCurrent
)
2529 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2531 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2539 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2541 for (i
= 0; List
[i
]; i
++)
2543 pwnd
= UserGetWindowObject(List
[i
]);
2544 if (!pwnd
) continue;
2546 if ( pwnd
->fnid
== FNID_MENU
||
2547 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2550 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2552 if ( pwnd
->head
.pti
== gptiCurrent
)
2555 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2557 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2563 else if (parm
.recipients
& BSM_APPLICATIONS
)
2565 HWND
*List
, hwndDenied
= NULL
;
2567 PWND pwnd
, pwndDesk
;
2571 pwndDesk
= UserGetDesktopWindow();
2572 List
= IntWinListChildren(pwndDesk
);
2574 if (parm
.flags
& BSF_QUERY
)
2578 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2580 fuFlags
= SMTO_ABORTIFHUNG
;
2582 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2584 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2588 fuFlags
= SMTO_NORMAL
;
2590 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2598 for (i
= 0; List
[i
]; i
++)
2600 pwnd
= UserGetWindowObject(List
[i
]);
2601 if (!pwnd
) continue;
2603 if ( pwnd
->fnid
== FNID_MENU
||
2604 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2607 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2609 if ( pwnd
->head
.pti
== gptiCurrent
)
2612 co_IntSendMessageTimeout( List
[i
],
2620 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2622 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2625 if (RetVal
== BROADCAST_QUERY_DENY
)
2627 hwndDenied
= List
[i
];
2628 hDesk
= UserHMGetHandle(pwndDesk
);
2632 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2635 retparam
= (PBROADCASTPARM
) ResultInfo
;
2636 retparam
->hDesk
= hDesk
;
2637 retparam
->hWnd
= hwndDenied
;
2639 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2646 else if (parm
.flags
& BSF_POSTMESSAGE
)
2650 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2652 for (i
= 0; List
[i
]; i
++)
2654 pwnd
= UserGetWindowObject(List
[i
]);
2655 if (!pwnd
) continue;
2657 if ( pwnd
->fnid
== FNID_MENU
||
2658 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2661 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2663 if ( pwnd
->head
.pti
== gptiCurrent
)
2666 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2668 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2676 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2678 for (i
= 0; List
[i
]; i
++)
2680 pwnd
= UserGetWindowObject(List
[i
]);
2681 if (!pwnd
) continue;
2683 if ( pwnd
->fnid
== FNID_MENU
||
2684 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2687 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2689 if ( pwnd
->head
.pti
== gptiCurrent
)
2692 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2694 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2701 case FNID_SENDMESSAGECALLBACK
:
2703 CALL_BACK_INFO CallBackInfo
;
2708 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2709 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2711 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2717 if (is_pointer_message(Msg
))
2719 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
2723 if (!(Ret
= co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2724 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
)))
2726 ERR("Callback failure!\n");
2730 case FNID_SENDMESSAGE
:
2732 lResult
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2739 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2740 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(ULONG_PTR
));
2742 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2751 case FNID_SENDMESSAGEFF
:
2752 case FNID_SENDMESSAGEWTOOPTION
:
2754 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2759 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2760 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2762 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2769 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, pdsm
? &dsm
: NULL
);
2775 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2776 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2778 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2787 // CallNextHook bypass.
2788 case FNID_CALLWNDPROC
:
2789 case FNID_CALLWNDPROCRET
:
2792 PCLIENTINFO ClientInfo
;
2793 PHOOK NextObj
, Hook
;
2795 pti
= GetW32ThreadInfo();
2797 Hook
= pti
->sphkCurrent
;
2801 NextObj
= Hook
->phkNext
;
2802 ClientInfo
= pti
->pClientInfo
;
2805 ClientInfo
->phkCurrent
= NextObj
;
2807 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2813 if (!ClientInfo
|| !NextObj
) break;
2815 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2817 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2822 CWP
.wParam
= wParam
;
2823 CWP
.lParam
= lParam
;
2824 TRACE("WH_CALLWNDPROC: Hook %p NextHook %p\n", Hook
, NextObj
);
2826 lResult
= co_IntCallHookProc( Hook
->HookId
,
2828 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2841 CWPR
.wParam
= wParam
;
2842 CWPR
.lParam
= lParam
;
2843 CWPR
.lResult
= ClientInfo
->dwHookData
;
2845 lResult
= co_IntCallHookProc( Hook
->HookId
,
2847 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2861 case FNID_DEFWINDOWPROC
:
2862 case FNID_CALLWNDPROC
:
2863 case FNID_CALLWNDPROCRET
:
2864 case FNID_SCROLLBAR
:
2871 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2872 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2874 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2890 #define INFINITE 0xFFFFFFFF
2891 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2895 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2896 IN DWORD dwMilliseconds
,
2900 PPROCESSINFO W32Process
;
2904 LARGE_INTEGER Timeout
;
2905 KAPC_STATE ApcState
;
2907 UserEnterExclusive();
2909 Status
= ObReferenceObjectByHandle(hProcess
,
2910 PROCESS_QUERY_INFORMATION
,
2916 if (!NT_SUCCESS(Status
))
2919 SetLastNtError(Status
);
2923 pti
= PsGetCurrentThreadWin32Thread();
2925 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2927 if ( PsGetProcessExitProcessCalled(Process
) ||
2929 pti
->ppi
== W32Process
)
2931 ObDereferenceObject(Process
);
2933 EngSetLastError(ERROR_INVALID_PARAMETER
);
2937 Handles
[0] = Process
;
2938 Handles
[1] = W32Process
->InputIdleEvent
;
2939 Handles
[2] = pti
->pEventQueueServer
; // IntMsqSetWakeMask returns hEventQueueClient
2943 ObDereferenceObject(Process
);
2945 return STATUS_SUCCESS
; /* no event to wait on */
2948 if (dwMilliseconds
!= INFINITE
)
2949 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2951 KeStackAttachProcess(&Process
->Pcb
, &ApcState
);
2953 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2954 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2956 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2957 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2960 KeUnstackDetachProcess(&ApcState
);
2962 TRACE("WFII: ppi %p\n", W32Process
);
2963 TRACE("WFII: waiting for %p\n", Handles
[1] );
2966 * We must add a refcount to our current PROCESSINFO,
2967 * because anything could happen (including process death) we're leaving win32k
2969 IntReferenceProcessInfo(W32Process
);
2974 Status
= KeWaitForMultipleObjects( 3,
2980 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2982 UserEnterExclusive();
2984 if (!NT_SUCCESS(Status
))
2986 SetLastNtError(Status
);
2987 Status
= WAIT_FAILED
;
2999 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
3000 ERR("WFII: WAIT 2\n");
3004 case STATUS_TIMEOUT
:
3005 ERR("WFII: timeout\n");
3010 ERR("WFII: finished\n");
3011 Status
= STATUS_SUCCESS
;
3018 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
3020 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
3021 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
3023 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
3024 IntDereferenceProcessInfo(W32Process
);
3025 ObDereferenceObject(Process
);