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 PLARGE_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
= (PLARGE_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
)
688 BOOL DoCallBack
= TRUE
;
692 Window
= UserGetWindowObject(pMsg
->hwnd
);
693 if (!Window
) return 0;
696 pti
= PsGetCurrentThreadWin32Thread();
698 if ( Window
&& Window
->head
.pti
!= pti
)
700 EngSetLastError( ERROR_MESSAGE_SYNC_ONLY
);
704 if (((pMsg
->message
== WM_SYSTIMER
) ||
705 (pMsg
->message
== WM_TIMER
)) &&
708 if (pMsg
->message
== WM_TIMER
)
710 if (ValidateTimerCallback(pti
,pMsg
->lParam
))
712 Time
= EngGetTickCount32();
713 retval
= co_IntCallWindowProc((WNDPROC
)pMsg
->lParam
,
725 PTIMER pTimer
= FindSystemTimer(pMsg
);
726 if (pTimer
&& pTimer
->pfn
)
728 Time
= EngGetTickCount32();
729 pTimer
->pfn(pMsg
->hwnd
, WM_SYSTIMER
, (UINT
)pMsg
->wParam
, Time
);
735 if ( !Window
) return 0;
737 if (pMsg
->message
== WM_PAINT
) Window
->state
|= WNDS_PAINTNOTPROCESSED
;
739 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
741 TRACE("Dispatch: Server Side Window Procedure\n");
745 DoCallBack
= !DesktopWindowProc( Window
,
751 case FNID_MESSAGEWND
:
752 DoCallBack
= !UserMessageWindowProc( Window
,
759 DoCallBack
= !PopupMenuWndProc( Window
,
768 /* Since we are doing a callback on the same thread right away, there is
769 no need to copy the lparam to kernel mode and then back to usermode.
770 We just pretend it isn't a pointer */
773 retval
= co_IntCallWindowProc( Window
->lpfnWndProc
,
781 if ( pMsg
->message
== WM_PAINT
&&
783 Window
->state
& WNDS_PAINTNOTPROCESSED
) // <--- Cleared, paint was already processed!
785 Window
->state2
&= ~WNDS2_WMPAINTSENT
;
786 /* send a WM_ERASEBKGND if the non-client area is still invalid */
787 ERR("Message WM_PAINT count %d Internal Paint Set? %s\n",Window
->head
.pti
->cPaintsReady
, Window
->state
& WNDS_INTERNALPAINT
? "TRUE" : "FALSE");
788 IntPaintWindow( Window
);
795 * Internal version of PeekMessage() doing all the work
800 * Input (hardware) messages and system internal events
801 * Sent messages (again)
806 co_IntPeekMessage( PMSG Msg
,
819 pti
= PsGetCurrentThreadWin32Thread();
821 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
822 ProcessMask
= HIWORD(RemoveMsg
);
824 /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns
825 all available messages (that is, no range filtering is performed)". */
826 if (!ProcessMask
) ProcessMask
= (QS_ALLPOSTMESSAGE
|QS_ALLINPUT
);
832 pti
->timeLast
= EngGetTickCount32();
833 pti
->pcti
->tickLastMsgChecked
= pti
->timeLast
;
835 // Post mouse moves while looping through peek messages.
836 if (pti
->MessageQueue
->QF_flags
& QF_MOUSEMOVED
)
838 IntCoalesceMouseMove(pti
);
841 /* Dispatch sent messages here. */
842 while ( co_MsqDispatchOneSentMessage(pti
) )
844 /* if some PM_QS* flags were specified, only handle sent messages from now on */
845 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
; // wine does this; ProcessMask = QS_SENDMESSAGE;
847 if (Hit
) return FALSE
;
849 /* Clear changed bits so we can wait on them if we don't find a message */
850 if (ProcessMask
& QS_POSTMESSAGE
)
852 pti
->pcti
->fsChangeBits
&= ~(QS_POSTMESSAGE
| QS_HOTKEY
| QS_TIMER
);
853 if (MsgFilterMin
== 0 && MsgFilterMax
== 0) // Wine hack does this; ~0U)
855 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
859 if (ProcessMask
& QS_INPUT
)
861 pti
->pcti
->fsChangeBits
&= ~QS_INPUT
;
864 /* Now check for normal messages. */
865 if (( (ProcessMask
& QS_POSTMESSAGE
) ||
866 (ProcessMask
& QS_HOTKEY
) ) &&
880 /* Only check for quit messages if not posted messages pending. */
881 if (ProcessMask
& QS_POSTMESSAGE
&& pti
->QuitPosted
)
883 /* According to the PSDK, WM_QUIT messages are always returned, regardless
884 of the filter specified */
886 Msg
->message
= WM_QUIT
;
887 Msg
->wParam
= pti
->exitCode
;
891 pti
->QuitPosted
= FALSE
;
892 ClearMsgBitsMask(pti
, QS_POSTMESSAGE
);
893 pti
->pcti
->fsWakeBits
&= ~QS_ALLPOSTMESSAGE
;
894 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
899 /* Check for hardware events. */
900 if ((ProcessMask
& QS_INPUT
) &&
901 co_MsqPeekHardwareMessage( pti
,
912 /* Now check for System Event messages. */
917 if (MsqPeekMessage( pti
,
927 handle_internal_events( pti
, Window
, dwQEvent
, eExtraInfo
, &eMsg
);
932 /* Check for sent messages again. */
933 while ( co_MsqDispatchOneSentMessage(pti
) )
935 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
;
937 if (Hit
) return FALSE
;
939 /* Check for paint messages. */
940 if ((ProcessMask
& QS_PAINT
) &&
942 IntGetPaintMessage( Window
,
952 /* This is correct, check for the current threads timers waiting to be
953 posted to this threads message queue. If any we loop again.
955 if ((ProcessMask
& QS_TIMER
) &&
956 PostTimerMessages(Window
))
969 co_IntWaitMessage( PWND Window
,
974 NTSTATUS Status
= STATUS_SUCCESS
;
976 LONG_PTR ExtraInfo
= 0;
978 pti
= PsGetCurrentThreadWin32Thread();
982 if ( co_IntPeekMessage( &Msg
, // Dont reenter!
986 MAKELONG( PM_NOREMOVE
, GetWakeMask( MsgFilterMin
, MsgFilterMax
)),
988 TRUE
) ) // act like GetMessage.
993 /* Nothing found. Wait for new messages. */
994 Status
= co_MsqWaitForNewMessages( pti
,
998 if (!NT_SUCCESS(Status
))
1000 SetLastNtError(Status
);
1001 ERR("Exit co_IntWaitMessage on error!\n");
1004 if (Status
== STATUS_USER_APC
|| Status
== STATUS_TIMEOUT
)
1015 co_IntGetPeekMessage( PMSG pMsg
,
1024 BOOL Present
= FALSE
;
1026 LONG_PTR ExtraInfo
= 0;
1028 if ( hWnd
== HWND_TOPMOST
|| hWnd
== HWND_BROADCAST
)
1031 /* Validate input */
1032 if (hWnd
&& hWnd
!= HWND_BOTTOM
)
1034 if (!(Window
= UserGetWindowObject(hWnd
)))
1044 Window
= (PWND
)hWnd
;
1047 if (MsgFilterMax
< MsgFilterMin
)
1055 RemoveMsg
|= ((GetWakeMask( MsgFilterMin
, MsgFilterMax
))<< 16);
1058 pti
= PsGetCurrentThreadWin32Thread();
1059 pti
->pClientInfo
->cSpins
++; // Bump up the spin count.
1063 Present
= co_IntPeekMessage( pMsg
,
1072 /* GetMessage or PostMessage must never get messages that contain pointers */
1073 ASSERT(FindMsgMemory(pMsg
->message
) == NULL
);
1075 if ( pMsg
->message
>= WM_DDE_FIRST
&& pMsg
->message
<= WM_DDE_LAST
)
1077 if (!IntDdeGetMessageHook(pMsg
, ExtraInfo
))
1079 TRACE("DDE Get return ERROR\n");
1084 if (pMsg
->message
!= WM_PAINT
&& pMsg
->message
!= WM_QUIT
)
1086 if (!RtlEqualMemory(&pti
->ptLast
, &pMsg
->pt
, sizeof(POINT
)))
1088 pti
->TIF_flags
|= TIF_MSGPOSCHANGED
;
1090 pti
->timeLast
= pMsg
->time
;
1091 pti
->ptLast
= pMsg
->pt
;
1094 // The WH_GETMESSAGE hook enables an application to monitor messages about to
1095 // be returned by the GetMessage or PeekMessage function.
1097 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)pMsg
);
1099 if ( bGMSG
|| pMsg
->message
== WM_PAINT
) break;
1104 Status
= co_MsqWaitForNewMessages( pti
,
1108 if ( !NT_SUCCESS(Status
) ||
1109 Status
== STATUS_USER_APC
||
1110 Status
== STATUS_TIMEOUT
)
1118 if (!(RemoveMsg
& PM_NOYIELD
))
1121 // Yield this thread!
1124 UserEnterExclusive();
1125 // Fall through to exit.
1131 while( bGMSG
&& !Present
);
1133 // Been spinning, time to swap vinyl...
1134 if (pti
->pClientInfo
->cSpins
>= 100)
1136 // Clear the spin cycle to fix the mix.
1137 pti
->pClientInfo
->cSpins
= 0;
1138 //if (!(pti->TIF_flags & TIF_SPINNING)) // FIXME: Need to swap vinyl...
1144 UserPostThreadMessage( PTHREADINFO pti
,
1151 if (is_pointer_message(Msg
))
1153 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1156 Message
.hwnd
= NULL
;
1157 Message
.message
= Msg
;
1158 Message
.wParam
= wParam
;
1159 Message
.lParam
= lParam
;
1160 Message
.pt
= gpsi
->ptCursor
;
1161 Message
.time
= EngGetTickCount32();
1162 MsqPostMessage(pti
, &Message
, FALSE
, QS_POSTMESSAGE
, 0, 0);
1166 PTHREADINFO FASTCALL
1167 IntSendTo(PWND Window
, PTHREADINFO ptiCur
, UINT Msg
)
1172 Window
->head
.pti
== ptiCur
)
1177 return Window
? Window
->head
.pti
: NULL
;
1181 UserPostMessage( HWND Wnd
,
1188 LONG_PTR ExtraInfo
= 0;
1191 Message
.message
= Msg
;
1192 Message
.wParam
= wParam
;
1193 Message
.lParam
= lParam
;
1194 Message
.pt
= gpsi
->ptCursor
;
1195 Message
.time
= EngGetTickCount32();
1197 if (is_pointer_message(Message
.message
))
1199 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1203 if (Wnd
== HWND_BROADCAST
|| Wnd
== HWND_TOPMOST
)
1209 if (!is_message_broadcastable(Msg
)) return TRUE
;
1211 DesktopWindow
= UserGetDesktopWindow();
1212 List
= IntWinListChildren(DesktopWindow
);
1216 UserPostMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1217 for (i
= 0; List
[i
]; i
++)
1219 PWND pwnd
= UserGetWindowObject(List
[i
]);
1220 if (!pwnd
) continue;
1222 if ( pwnd
->fnid
== FNID_MENU
|| // Also need pwnd->pcls->atomClassName == gaOleMainThreadWndClass
1223 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1226 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1228 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1237 return UserPostThreadMessage( gptiCurrent
,
1243 Window
= UserGetWindowObject(Wnd
);
1246 ERR("UserPostMessage: Invalid handle 0x%p Msg 0x%x!\n", Wnd
, Msg
);
1250 pti
= Window
->head
.pti
;
1252 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1254 ERR("Attempted to post message to window %p when the thread is in cleanup!\n", Wnd
);
1258 if ( Window
->state
& WNDS_DESTROYED
)
1260 ERR("Attempted to post message to window %p that is being destroyed!\n", Wnd
);
1261 /* FIXME: Last error code? */
1265 if ( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1267 if (!IntDdePostMessageHook(Window
, Msg
, wParam
, &lParam
, &ExtraInfo
))
1269 TRACE("Posting Exit DDE 0x%x\n",Msg
);
1272 Message
.lParam
= lParam
;
1275 MsqPostMessage(pti
, &Message
, FALSE
, QS_POSTMESSAGE
, 0, ExtraInfo
);
1281 co_IntSendMessage( HWND hWnd
,
1286 ULONG_PTR Result
= 0;
1288 if (co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1290 return (LRESULT
)Result
;
1295 static LRESULT FASTCALL
1296 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1302 ULONG_PTR
*uResult
)
1304 NTSTATUS Status
= STATUS_SUCCESS
;
1306 PMSGMEMORY MsgMemoryEntry
;
1307 INT lParamBufferSize
;
1308 LPARAM lParamPacked
;
1309 PTHREADINFO Win32Thread
, ptiSendTo
= NULL
;
1310 ULONG_PTR Result
= 0;
1311 DECLARE_RETURN(LRESULT
);
1312 USER_REFERENCE_ENTRY Ref
;
1313 BOOL DoCallBack
= TRUE
;
1315 if (!(Window
= UserGetWindowObject(hWnd
)))
1317 TRACE("SendMessageTimeoutSingle: Invalid handle 0x%p!\n",hWnd
);
1321 UserRefObjectCo(Window
, &Ref
);
1323 Win32Thread
= PsGetCurrentThreadWin32Thread();
1325 ptiSendTo
= IntSendTo(Window
, Win32Thread
, Msg
);
1327 if ( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1329 if (!IntDdeSendMessageHook(Window
, Msg
, wParam
, lParam
))
1331 ERR("Sending Exit DDE 0x%x\n",Msg
);
1338 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1340 /* Never send messages to exiting threads */
1344 if (Msg
& 0x80000000)
1346 TRACE("SMTS: Internal Message!\n");
1347 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1348 if (uResult
) *uResult
= Result
;
1352 // Only happens when calling the client!
1353 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1355 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1357 TRACE("SMT: Server Side Window Procedure\n");
1358 // Handle it here. Safeguard against excessive recursions.
1359 if (IoGetRemainingStackSize() < PAGE_SIZE
)
1361 ERR("Server Callback Exceeded Stack!\n");
1364 /* Return after server side call, IntCallWndProcRet will not be called. */
1365 switch(Window
->fnid
)
1368 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1370 case FNID_MESSAGEWND
:
1371 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1374 DoCallBack
= !PopupMenuWndProc( Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1379 if (uResult
) *uResult
= Result
;
1383 /* See if this message type is present in the table */
1384 MsgMemoryEntry
= FindMsgMemory(Msg
);
1385 if (NULL
== MsgMemoryEntry
)
1387 lParamBufferSize
= -1;
1391 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1392 // If zero, do not allow callback on client side to allocate a buffer!!!!! See CORE-7695.
1393 if (!lParamBufferSize
) lParamBufferSize
= -1;
1396 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1398 ERR("Failed to pack message parameters\n");
1402 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1414 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1416 ERR("Failed to unpack message parameters\n");
1420 // Only happens when calling the client!
1421 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1426 if (MsqIsHung(ptiSendTo
))
1428 if (uFlags
& SMTO_ABORTIFHUNG
)
1430 // FIXME: Set window hung and add to a list.
1431 /* FIXME: Set a LastError? */
1436 if (Window
->state
& WNDS_DESTROYED
)
1438 /* FIXME: Last error? */
1439 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1445 Status
= co_MsqSendMessage( ptiSendTo
,
1451 (uFlags
& SMTO_BLOCK
),
1455 while ((STATUS_TIMEOUT
== Status
) &&
1456 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1457 !MsqIsHung(ptiSendTo
)); // FIXME: Set window hung and add to a list.
1459 if (Status
== STATUS_TIMEOUT
)
1461 if (0 && MsqIsHung(ptiSendTo
))
1463 TRACE("Let's go Ghost!\n");
1464 IntMakeHungWindowGhosted(hWnd
);
1468 * Microsoft Windows 2000: If GetLastError returns zero, then the function
1470 * XP+ : If the function fails or times out, the return value is zero.
1471 * To get extended error information, call GetLastError. If GetLastError
1472 * returns ERROR_TIMEOUT, then the function timed out.
1474 EngSetLastError(ERROR_TIMEOUT
);
1477 else if (!NT_SUCCESS(Status
))
1479 SetLastNtError(Status
);
1486 if (Window
) UserDerefObjectCo(Window
);
1491 co_IntSendMessageTimeout( HWND hWnd
,
1497 ULONG_PTR
*uResult
)
1503 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1505 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1508 if (!is_message_broadcastable(Msg
)) return TRUE
;
1510 DesktopWindow
= UserGetDesktopWindow();
1511 if (NULL
== DesktopWindow
)
1513 EngSetLastError(ERROR_INTERNAL_ERROR
);
1517 if (hWnd
!= HWND_TOPMOST
)
1519 /* Send message to the desktop window too! */
1520 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1523 Children
= IntWinListChildren(DesktopWindow
);
1524 if (NULL
== Children
)
1529 for (Child
= Children
; NULL
!= *Child
; Child
++)
1531 PWND pwnd
= UserGetWindowObject(*Child
);
1532 if (!pwnd
) continue;
1534 if ( pwnd
->fnid
== FNID_MENU
||
1535 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1538 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1541 ExFreePoolWithTag(Children
, USERTAG_WINDOWLIST
);
1543 return (LRESULT
) TRUE
;
1547 co_IntSendMessageNoWait(HWND hWnd
,
1552 ULONG_PTR Result
= 0;
1553 return co_IntSendMessageWithCallBack( hWnd
,
1562 If you send a message in the range below WM_USER to the asynchronous message
1563 functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its
1564 message parameters cannot include pointers. Otherwise, the operation will fail.
1565 The functions will return before the receiving thread has had a chance to
1566 process the message and the sender will free the memory before it is used.
1569 co_IntSendMessageWithCallBack( HWND hWnd
,
1573 SENDASYNCPROC CompletionCallback
,
1574 ULONG_PTR CompletionCallbackContext
,
1579 PMSGMEMORY MsgMemoryEntry
;
1580 INT lParamBufferSize
;
1581 LPARAM lParamPacked
;
1582 PTHREADINFO Win32Thread
, ptiSendTo
= NULL
;
1583 DECLARE_RETURN(LRESULT
);
1584 USER_REFERENCE_ENTRY Ref
;
1585 PUSER_SENT_MESSAGE Message
;
1586 BOOL DoCallBack
= TRUE
;
1588 if (!(Window
= UserGetWindowObject(hWnd
)))
1590 TRACE("SendMessageWithCallBack: Invalid handle 0x%p!\n",hWnd
);
1594 UserRefObjectCo(Window
, &Ref
);
1596 if (Window
->state
& WNDS_DESTROYED
)
1598 /* FIXME: last error? */
1599 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1603 Win32Thread
= PsGetCurrentThreadWin32Thread();
1605 if (Win32Thread
== NULL
||
1606 Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1611 ptiSendTo
= IntSendTo(Window
, Win32Thread
, Msg
);
1613 if (Msg
& 0x80000000 &&
1616 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
) RETURN( FALSE
);
1618 TRACE("SMWCB: Internal Message!\n");
1619 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1620 if (uResult
) *uResult
= Result
;
1624 /* See if this message type is present in the table */
1625 MsgMemoryEntry
= FindMsgMemory(Msg
);
1626 if (NULL
== MsgMemoryEntry
)
1628 lParamBufferSize
= -1;
1632 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1633 if (!lParamBufferSize
) lParamBufferSize
= -1;
1636 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, !!ptiSendTo
)))
1638 ERR("Failed to pack message parameters\n");
1642 /* If it can be sent now, then send it. */
1645 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1647 UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
);
1648 /* Never send messages to exiting threads */
1652 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1654 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1656 TRACE("SMWCB: Server Side Window Procedure\n");
1657 switch(Window
->fnid
)
1660 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParamPacked
, (LRESULT
*)&Result
);
1662 case FNID_MESSAGEWND
:
1663 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1666 DoCallBack
= !PopupMenuWndProc( Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1672 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1684 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1686 if (CompletionCallback
)
1688 co_IntCallSentMessageCallback(CompletionCallback
,
1691 CompletionCallbackContext
,
1698 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1700 ERR("Failed to unpack message parameters\n");
1705 if(!(Message
= AllocateUserMessage(FALSE
)))
1707 ERR("MsqSendMessage(): Not enough memory to allocate a message");
1711 Message
->Msg
.hwnd
= hWnd
;
1712 Message
->Msg
.message
= Msg
;
1713 Message
->Msg
.wParam
= wParam
;
1714 Message
->Msg
.lParam
= lParamPacked
;
1715 Message
->pkCompletionEvent
= NULL
; // No event needed.
1716 Message
->lResult
= 0;
1717 Message
->QS_Flags
= 0;
1718 Message
->ptiReceiver
= ptiSendTo
;
1719 Message
->ptiSender
= NULL
; // mjmartin, you are right! This is null.
1720 Message
->ptiCallBackSender
= Win32Thread
;
1721 Message
->CompletionCallback
= CompletionCallback
;
1722 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1723 Message
->HookMessage
= MSQ_NORMAL
;
1724 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1725 Message
->QS_Flags
= QS_SENDMESSAGE
;
1726 Message
->flags
= SMF_RECEIVERFREE
;
1728 if (Msg
& 0x80000000) // Higher priority event message!
1729 InsertHeadList(&ptiSendTo
->SentMessagesListHead
, &Message
->ListEntry
);
1731 InsertTailList(&ptiSendTo
->SentMessagesListHead
, &Message
->ListEntry
);
1732 MsqWakeQueue(ptiSendTo
, QS_SENDMESSAGE
, TRUE
);
1737 if (Window
) UserDerefObjectCo(Window
);
1743 This HACK function posts a message if the destination's message queue belongs to
1744 another thread, otherwise it sends the message. It does not support broadcast
1748 co_IntPostOrSendMessage( HWND hWnd
,
1757 if ( hWnd
== HWND_BROADCAST
)
1762 if(!(Window
= UserGetWindowObject(hWnd
)))
1764 TRACE("PostOrSendMessage: Invalid handle 0x%p!\n",hWnd
);
1768 pti
= PsGetCurrentThreadWin32Thread();
1770 if ( IntSendTo(Window
, pti
, Msg
) &&
1771 FindMsgMemory(Msg
) == 0 )
1773 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1777 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1783 return (LRESULT
)Result
;
1787 static LRESULT FASTCALL
1788 co_IntDoSendMessage( HWND hWnd
,
1794 LRESULT Result
= TRUE
;
1797 MSG UserModeMsg
, KernelModeMsg
;
1798 PMSGMEMORY MsgMemoryEntry
;
1799 PTHREADINFO ptiSendTo
;
1801 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1803 Window
= UserGetWindowObject(hWnd
);
1810 /* Check for an exiting window. */
1811 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1813 ERR("co_IntDoSendMessage Window Exiting!\n");
1816 /* See if the current thread can handle this message */
1817 ptiSendTo
= IntSendTo(Window
, gptiCurrent
, Msg
);
1819 // If broadcasting or sending to another thread, save the users data.
1820 if (!Window
|| ptiSendTo
)
1822 UserModeMsg
.hwnd
= hWnd
;
1823 UserModeMsg
.message
= Msg
;
1824 UserModeMsg
.wParam
= wParam
;
1825 UserModeMsg
.lParam
= lParam
;
1826 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1827 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1828 if (!NT_SUCCESS(Status
))
1830 EngSetLastError(ERROR_INVALID_PARAMETER
);
1831 return (dsm
? 0 : -1);
1836 KernelModeMsg
.hwnd
= hWnd
;
1837 KernelModeMsg
.message
= Msg
;
1838 KernelModeMsg
.wParam
= wParam
;
1839 KernelModeMsg
.lParam
= lParam
;
1844 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1845 KernelModeMsg
.message
,
1846 KernelModeMsg
.wParam
,
1847 KernelModeMsg
.lParam
);
1851 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1852 KernelModeMsg
.message
,
1853 KernelModeMsg
.wParam
,
1854 KernelModeMsg
.lParam
,
1860 if (!Window
|| ptiSendTo
)
1862 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1863 if (!NT_SUCCESS(Status
))
1865 EngSetLastError(ERROR_INVALID_PARAMETER
);
1866 return(dsm
? 0 : -1);
1870 return (LRESULT
)Result
;
1874 UserSendNotifyMessage( HWND hWnd
,
1881 if (is_pointer_message(Msg
))
1883 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1887 // Basicly the same as IntPostOrSendMessage
1888 if (hWnd
== HWND_BROADCAST
) // Handle Broadcast
1894 DesktopWindow
= UserGetDesktopWindow();
1895 List
= IntWinListChildren(DesktopWindow
);
1899 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1900 for (i
= 0; List
[i
]; i
++)
1902 PWND pwnd
= UserGetWindowObject(List
[i
]);
1903 if (!pwnd
) continue;
1905 if ( pwnd
->fnid
== FNID_MENU
||
1906 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1909 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1911 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1916 Ret
= co_IntSendMessageNoWait( hWnd
, Msg
, wParam
, lParam
);
1923 IntGetQueueStatus(DWORD Changes
)
1928 pti
= PsGetCurrentThreadWin32Thread();
1930 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1932 /* High word, types of messages currently in the queue.
1933 Low word, types of messages that have been added to the queue and that
1934 are still in the queue
1936 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1938 pti
->pcti
->fsChangeBits
&= ~Changes
;
1944 IntInitMessagePumpHook(VOID
)
1946 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1950 pti
->pcti
->dwcPumpHook
++;
1957 IntUninitMessagePumpHook(VOID
)
1959 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1963 if (pti
->pcti
->dwcPumpHook
<= 0)
1967 pti
->pcti
->dwcPumpHook
--;
1974 IntCallMsgFilter( LPMSG lpmsg
, INT code
)
1978 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)lpmsg
))
1984 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)lpmsg
);
1989 /** Functions ******************************************************************/
1995 POINT pt
) // Just like the User call.
1999 ULONG wDragWidth
, wDragHeight
;
2000 DECLARE_RETURN(BOOL
);
2002 TRACE("Enter NtUserDragDetect(%p)\n", hWnd
);
2003 UserEnterExclusive();
2005 wDragWidth
= UserGetSystemMetrics(SM_CXDRAG
);
2006 wDragHeight
= UserGetSystemMetrics(SM_CYDRAG
);
2008 rect
.left
= pt
.x
- wDragWidth
;
2009 rect
.right
= pt
.x
+ wDragWidth
;
2011 rect
.top
= pt
.y
- wDragHeight
;
2012 rect
.bottom
= pt
.y
+ wDragHeight
;
2014 co_UserSetCapture(hWnd
);
2018 while (co_IntGetPeekMessage( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, FALSE
) ||
2019 co_IntGetPeekMessage( &msg
, 0, WM_QUEUESYNC
, WM_QUEUESYNC
, PM_REMOVE
, FALSE
) ||
2020 co_IntGetPeekMessage( &msg
, 0, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
, FALSE
) )
2022 if ( msg
.message
== WM_LBUTTONUP
)
2024 co_UserSetCapture(NULL
);
2027 if ( msg
.message
== WM_MOUSEMOVE
)
2030 tmp
.x
= (short)LOWORD(msg
.lParam
);
2031 tmp
.y
= (short)HIWORD(msg
.lParam
);
2032 if( !RECTL_bPointInRect( &rect
, tmp
.x
, tmp
.y
) )
2034 co_UserSetCapture(NULL
);
2038 if ( msg
.message
== WM_KEYDOWN
)
2040 if ( msg
.wParam
== VK_ESCAPE
)
2042 co_UserSetCapture(NULL
);
2046 if ( msg
.message
== WM_QUEUESYNC
)
2048 co_HOOK_CallHooks( WH_CBT
, HCBT_QS
, 0, 0 );
2051 co_IntWaitMessage(NULL
, 0, 0);
2056 TRACE("Leave NtUserDragDetect, ret=%i\n",_ret_
);
2062 NtUserPostMessage(HWND hWnd
,
2069 UserEnterExclusive();
2071 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
2079 NtUserPostThreadMessage(DWORD idThread
,
2086 PTHREADINFO pThread
;
2089 UserEnterExclusive();
2091 Status
= PsLookupThreadByThreadId(UlongToHandle(idThread
), &peThread
);
2093 if ( Status
== STATUS_SUCCESS
)
2095 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
2097 !pThread
->MessageQueue
||
2098 (pThread
->TIF_flags
& TIF_INCLEANUP
))
2100 ObDereferenceObject( peThread
);
2103 ret
= UserPostThreadMessage( pThread
, Msg
, wParam
, lParam
);
2104 ObDereferenceObject( peThread
);
2108 SetLastNtError( Status
);
2116 NtUserWaitMessage(VOID
)
2120 UserEnterExclusive();
2121 TRACE("NtUserWaitMessage Enter\n");
2122 ret
= co_IntWaitMessage(NULL
, 0, 0);
2123 TRACE("NtUserWaitMessage Leave\n");
2130 NtUserGetMessage(PMSG pMsg
,
2138 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
2140 EngSetLastError(ERROR_INVALID_PARAMETER
);
2144 UserEnterExclusive();
2146 RtlZeroMemory(&Msg
, sizeof(MSG
));
2148 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
2156 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2157 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2159 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2161 SetLastNtError(_SEH2_GetExceptionCode());
2168 Ret
= Ret
? (WM_QUIT
!= pMsg
->message
) : FALSE
;
2174 NtUserPeekMessage( PMSG pMsg
,
2183 if ( RemoveMsg
& PM_BADMSGFLAGS
)
2185 EngSetLastError(ERROR_INVALID_FLAGS
);
2189 UserEnterExclusive();
2191 RtlZeroMemory(&Msg
, sizeof(MSG
));
2193 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
2201 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2202 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2204 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2206 SetLastNtError(_SEH2_GetExceptionCode());
2216 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
2223 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
2224 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
2226 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2228 _SEH2_YIELD(return FALSE
);
2232 UserEnterExclusive();
2234 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
2240 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
2247 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
2248 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
2250 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2260 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
2267 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
2268 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
2270 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2272 SetLastNtError(_SEH2_GetExceptionCode());
2273 _SEH2_YIELD(return FALSE
);
2277 UserEnterExclusive();
2279 Res
= IntDispatchMessage(&SafeMsg
);
2286 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
2294 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
2295 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
2297 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2299 SetLastNtError(_SEH2_GetExceptionCode());
2300 _SEH2_YIELD(return FALSE
);
2304 UserEnterExclusive();
2305 pWnd
= UserGetWindowObject(SafeMsg
.hwnd
);
2306 if (pWnd
) // Must have a window!
2308 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
2312 TRACE("No Window for Translate. hwnd 0x%p Msg %u\n", SafeMsg
.hwnd
, SafeMsg
.message
);
2320 LRESULT APIENTRY
ScrollBarWndProc(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
);
2323 NtUserMessageCall( HWND hWnd
,
2327 ULONG_PTR ResultInfo
,
2328 DWORD dwType
, // fnID?
2331 LRESULT lResult
= 0;
2334 USER_REFERENCE_ENTRY Ref
;
2336 UserEnterExclusive();
2340 case FNID_SCROLLBAR
:
2342 lResult
= ScrollBarWndProc(hWnd
, Msg
, wParam
, lParam
);
2347 Window
= UserGetWindowObject(hWnd
);
2350 //ERR("FNID_DESKTOP IN\n");
2351 Ret
= DesktopWindowProc(Window
, Msg
, wParam
, lParam
, &lResult
);
2352 //ERR("FNID_DESKTOP OUT\n");
2358 Window
= UserGetWindowObject(hWnd
);
2361 Ret
= PopupMenuWndProc( Window
, Msg
, wParam
, lParam
, &lResult
);
2365 case FNID_MESSAGEWND
:
2367 Window
= UserGetWindowObject(hWnd
);
2370 Ret
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
, &lResult
);
2374 case FNID_DEFWINDOWPROC
:
2375 /* Validate input */
2378 Window
= UserGetWindowObject(hWnd
);
2384 UserRefObjectCo(Window
, &Ref
);
2386 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2389 UserDerefObjectCo(Window
);
2391 case FNID_SENDNOTIFYMESSAGE
:
2392 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2394 case FNID_BROADCASTSYSTEMMESSAGE
:
2396 BROADCASTPARM parm
, *retparam
;
2397 DWORD_PTR RetVal
= 0;
2403 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2404 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2406 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2415 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2416 parm
.recipients
== BSM_ALLCOMPONENTS
)
2418 PLIST_ENTRY DesktopEntry
;
2420 HWND
*List
, hwndDenied
= NULL
;
2422 PWND pwnd
, pwndDesk
;
2426 for (DesktopEntry
= InputWindowStation
->DesktopListHead
.Flink
;
2427 DesktopEntry
!= &InputWindowStation
->DesktopListHead
;
2428 DesktopEntry
= DesktopEntry
->Flink
)
2430 rpdesk
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
2431 pwndDesk
= rpdesk
->pDeskInfo
->spwnd
;
2432 List
= IntWinListChildren(pwndDesk
);
2434 if (parm
.flags
& BSF_QUERY
)
2438 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2440 fuFlags
= SMTO_ABORTIFHUNG
;
2442 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2444 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2448 fuFlags
= SMTO_NORMAL
;
2450 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2458 for (i
= 0; List
[i
]; i
++)
2460 pwnd
= UserGetWindowObject(List
[i
]);
2461 if (!pwnd
) continue;
2463 if ( pwnd
->fnid
== FNID_MENU
||
2464 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2467 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2469 if ( pwnd
->head
.pti
== gptiCurrent
)
2472 co_IntSendMessageTimeout( List
[i
],
2480 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2482 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2485 if (RetVal
== BROADCAST_QUERY_DENY
)
2487 hwndDenied
= List
[i
];
2488 hDesk
= UserHMGetHandle(pwndDesk
);
2492 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2495 retparam
= (PBROADCASTPARM
) ResultInfo
;
2496 retparam
->hDesk
= hDesk
;
2497 retparam
->hWnd
= hwndDenied
;
2499 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2504 if (!Ret
) break; // Have a hit! Let everyone know!
2507 else if (parm
.flags
& BSF_POSTMESSAGE
)
2511 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2513 for (i
= 0; List
[i
]; i
++)
2515 pwnd
= UserGetWindowObject(List
[i
]);
2516 if (!pwnd
) continue;
2518 if ( pwnd
->fnid
== FNID_MENU
||
2519 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2522 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2524 if ( pwnd
->head
.pti
== gptiCurrent
)
2527 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2529 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2537 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2539 for (i
= 0; List
[i
]; i
++)
2541 pwnd
= UserGetWindowObject(List
[i
]);
2542 if (!pwnd
) continue;
2544 if ( pwnd
->fnid
== FNID_MENU
||
2545 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2548 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2550 if ( pwnd
->head
.pti
== gptiCurrent
)
2553 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2555 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2561 else if (parm
.recipients
& BSM_APPLICATIONS
)
2563 HWND
*List
, hwndDenied
= NULL
;
2565 PWND pwnd
, pwndDesk
;
2569 pwndDesk
= UserGetDesktopWindow();
2570 List
= IntWinListChildren(pwndDesk
);
2572 if (parm
.flags
& BSF_QUERY
)
2576 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2578 fuFlags
= SMTO_ABORTIFHUNG
;
2580 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2582 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2586 fuFlags
= SMTO_NORMAL
;
2588 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2596 for (i
= 0; List
[i
]; i
++)
2598 pwnd
= UserGetWindowObject(List
[i
]);
2599 if (!pwnd
) continue;
2601 if ( pwnd
->fnid
== FNID_MENU
||
2602 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2605 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2607 if ( pwnd
->head
.pti
== gptiCurrent
)
2610 co_IntSendMessageTimeout( List
[i
],
2618 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2620 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2623 if (RetVal
== BROADCAST_QUERY_DENY
)
2625 hwndDenied
= List
[i
];
2626 hDesk
= UserHMGetHandle(pwndDesk
);
2630 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2633 retparam
= (PBROADCASTPARM
) ResultInfo
;
2634 retparam
->hDesk
= hDesk
;
2635 retparam
->hWnd
= hwndDenied
;
2637 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2644 else if (parm
.flags
& BSF_POSTMESSAGE
)
2648 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2650 for (i
= 0; List
[i
]; i
++)
2652 pwnd
= UserGetWindowObject(List
[i
]);
2653 if (!pwnd
) continue;
2655 if ( pwnd
->fnid
== FNID_MENU
||
2656 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2659 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2661 if ( pwnd
->head
.pti
== gptiCurrent
)
2664 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2666 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2674 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2676 for (i
= 0; List
[i
]; i
++)
2678 pwnd
= UserGetWindowObject(List
[i
]);
2679 if (!pwnd
) continue;
2681 if ( pwnd
->fnid
== FNID_MENU
||
2682 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2685 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2687 if ( pwnd
->head
.pti
== gptiCurrent
)
2690 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2692 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2699 case FNID_SENDMESSAGECALLBACK
:
2701 CALL_BACK_INFO CallBackInfo
;
2706 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2707 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2709 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2715 if (is_pointer_message(Msg
))
2717 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
2721 if (!(Ret
= co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2722 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
)))
2724 ERR("Callback failure!\n");
2728 case FNID_SENDMESSAGE
:
2730 lResult
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2737 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2738 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(ULONG_PTR
));
2740 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2749 case FNID_SENDMESSAGEFF
:
2750 case FNID_SENDMESSAGEWTOOPTION
:
2752 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2757 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2758 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2760 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2767 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, pdsm
? &dsm
: NULL
);
2773 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2774 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2776 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2785 // CallNextHook bypass.
2786 case FNID_CALLWNDPROC
:
2787 case FNID_CALLWNDPROCRET
:
2790 PCLIENTINFO ClientInfo
;
2791 PHOOK NextObj
, Hook
;
2793 pti
= GetW32ThreadInfo();
2795 Hook
= pti
->sphkCurrent
;
2799 NextObj
= Hook
->phkNext
;
2800 ClientInfo
= pti
->pClientInfo
;
2803 ClientInfo
->phkCurrent
= NextObj
;
2805 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2811 if (!ClientInfo
|| !NextObj
) break;
2813 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2815 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2820 CWP
.wParam
= wParam
;
2821 CWP
.lParam
= lParam
;
2822 TRACE("WH_CALLWNDPROC: Hook %p NextHook %p\n", Hook
, NextObj
);
2824 lResult
= co_IntCallHookProc( Hook
->HookId
,
2826 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2839 CWPR
.wParam
= wParam
;
2840 CWPR
.lParam
= lParam
;
2841 CWPR
.lResult
= ClientInfo
->dwHookData
;
2843 lResult
= co_IntCallHookProc( Hook
->HookId
,
2845 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2859 case FNID_DEFWINDOWPROC
:
2860 case FNID_CALLWNDPROC
:
2861 case FNID_CALLWNDPROCRET
:
2862 case FNID_SCROLLBAR
:
2869 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2870 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2872 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2888 #define INFINITE 0xFFFFFFFF
2889 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2893 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2894 IN DWORD dwMilliseconds
,
2898 PPROCESSINFO W32Process
;
2902 LARGE_INTEGER Timeout
;
2903 KAPC_STATE ApcState
;
2905 UserEnterExclusive();
2907 Status
= ObReferenceObjectByHandle(hProcess
,
2908 PROCESS_QUERY_INFORMATION
,
2914 if (!NT_SUCCESS(Status
))
2917 SetLastNtError(Status
);
2921 pti
= PsGetCurrentThreadWin32Thread();
2923 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2925 if ( PsGetProcessExitProcessCalled(Process
) ||
2927 pti
->ppi
== W32Process
)
2929 ObDereferenceObject(Process
);
2931 EngSetLastError(ERROR_INVALID_PARAMETER
);
2935 Handles
[0] = Process
;
2936 Handles
[1] = W32Process
->InputIdleEvent
;
2937 Handles
[2] = pti
->pEventQueueServer
; // IntMsqSetWakeMask returns hEventQueueClient
2941 ObDereferenceObject(Process
);
2943 return STATUS_SUCCESS
; /* no event to wait on */
2946 if (dwMilliseconds
!= INFINITE
)
2947 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2949 KeStackAttachProcess(&Process
->Pcb
, &ApcState
);
2951 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2952 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2954 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2955 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2958 KeUnstackDetachProcess(&ApcState
);
2960 TRACE("WFII: ppi %p\n", W32Process
);
2961 TRACE("WFII: waiting for %p\n", Handles
[1] );
2964 * We must add a refcount to our current PROCESSINFO,
2965 * because anything could happen (including process death) we're leaving win32k
2967 IntReferenceProcessInfo(W32Process
);
2972 Status
= KeWaitForMultipleObjects( 3,
2978 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2980 UserEnterExclusive();
2982 if (!NT_SUCCESS(Status
))
2984 SetLastNtError(Status
);
2985 Status
= WAIT_FAILED
;
2997 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2998 ERR("WFII: WAIT 2\n");
3002 case STATUS_TIMEOUT
:
3003 ERR("WFII: timeout\n");
3008 ERR("WFII: finished\n");
3009 Status
= STATUS_SUCCESS
;
3016 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
3018 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
3019 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
3021 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
3022 IntDereferenceProcessInfo(W32Process
);
3023 ObDereferenceObject(Process
);