2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
5 * FILE: subsystems/win32/win32k/ntuser/message.c
6 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
10 DBG_DEFAULT_CHANNEL(UserMsg
);
12 #define PM_BADMSGFLAGS ~((QS_RAWINPUT << 16)|PM_QS_SENDMESSAGE|PM_QS_PAINT|PM_QS_POSTMESSAGE|PM_QS_INPUT|PM_NOYIELD|PM_REMOVE)
14 /* FUNCTIONS *****************************************************************/
17 IntInitMessageImpl(VOID
)
19 return STATUS_SUCCESS
;
23 IntCleanupMessageImpl(VOID
)
25 return STATUS_SUCCESS
;
29 /* flag for messages that contain pointers */
30 /* 32 messages per entry, messages 0..31 map to bits 0..31 */
32 #define SET(msg) (1 << ((msg) & 31))
34 static const unsigned int message_pointer_flags
[] =
37 SET(WM_CREATE
) | SET(WM_SETTEXT
) | SET(WM_GETTEXT
) |
38 SET(WM_WININICHANGE
) | SET(WM_DEVMODECHANGE
),
40 SET(WM_GETMINMAXINFO
) | SET(WM_DRAWITEM
) | SET(WM_MEASUREITEM
) | SET(WM_DELETEITEM
) |
43 SET(WM_WINDOWPOSCHANGING
) | SET(WM_WINDOWPOSCHANGED
) | SET(WM_COPYDATA
) |
44 SET(WM_COPYGLOBALDATA
) | SET(WM_NOTIFY
) | SET(WM_HELP
),
46 SET(WM_STYLECHANGING
) | SET(WM_STYLECHANGED
),
48 SET(WM_NCCREATE
) | SET(WM_NCCALCSIZE
) | SET(WM_GETDLGCODE
),
50 SET(EM_GETSEL
) | SET(EM_GETRECT
) | SET(EM_SETRECT
) | SET(EM_SETRECTNP
),
52 SET(EM_REPLACESEL
) | SET(EM_GETLINE
) | SET(EM_SETTABSTOPS
),
54 SET(SBM_GETRANGE
) | SET(SBM_SETSCROLLINFO
) | SET(SBM_GETSCROLLINFO
) | SET(SBM_GETSCROLLBARINFO
),
60 SET(CB_GETEDITSEL
) | SET(CB_ADDSTRING
) | SET(CB_DIR
) | SET(CB_GETLBTEXT
) |
61 SET(CB_INSERTSTRING
) | SET(CB_FINDSTRING
) | SET(CB_SELECTSTRING
) |
62 SET(CB_GETDROPPEDCONTROLRECT
) | SET(CB_FINDSTRINGEXACT
),
66 SET(LB_ADDSTRING
) | SET(LB_INSERTSTRING
) | SET(LB_GETTEXT
) | SET(LB_SELECTSTRING
) |
67 SET(LB_DIR
) | SET(LB_FINDSTRING
) |
68 SET(LB_GETSELITEMS
) | SET(LB_SETTABSTOPS
) | SET(LB_ADDFILE
) | SET(LB_GETITEMRECT
),
70 SET(LB_FINDSTRINGEXACT
),
76 SET(WM_NEXTMENU
) | SET(WM_SIZING
) | SET(WM_MOVING
) | SET(WM_DEVICECHANGE
),
78 SET(WM_MDICREATE
) | SET(WM_MDIGETACTIVE
) | SET(WM_DROPOBJECT
) |
79 SET(WM_QUERYDROPOBJECT
) | SET(WM_DRAGLOOP
) | SET(WM_DRAGSELECT
) | SET(WM_DRAGMOVE
),
93 SET(WM_ASKCBFORMATNAME
)
96 /* check whether a given message type includes pointers */
97 static inline int is_pointer_message( UINT message
)
99 if (message
>= 8*sizeof(message_pointer_flags
)) return FALSE
;
100 return (message_pointer_flags
[message
/ 32] & SET(message
)) != 0;
104 #define MMS_SIZE_WPARAM -1
105 #define MMS_SIZE_WPARAMWCHAR -2
106 #define MMS_SIZE_LPARAMSZ -3
107 #define MMS_SIZE_SPECIAL -4
108 #define MMS_FLAG_READ 0x01
109 #define MMS_FLAG_WRITE 0x02
110 #define MMS_FLAG_READWRITE (MMS_FLAG_READ | MMS_FLAG_WRITE)
111 typedef struct tagMSGMEMORY
117 MSGMEMORY
, *PMSGMEMORY
;
119 static MSGMEMORY MsgMemory
[] =
121 { WM_CREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
122 { WM_DDE_ACK
, sizeof(KMDDELPARAM
), MMS_FLAG_READ
},
123 { WM_DDE_EXECUTE
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
124 { WM_GETMINMAXINFO
, sizeof(MINMAXINFO
), MMS_FLAG_READWRITE
},
125 { WM_GETTEXT
, MMS_SIZE_WPARAMWCHAR
, MMS_FLAG_WRITE
},
126 { WM_NCCALCSIZE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
127 { WM_NCCREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
128 { WM_SETTEXT
, MMS_SIZE_LPARAMSZ
, MMS_FLAG_READ
},
129 { WM_STYLECHANGED
, sizeof(STYLESTRUCT
), MMS_FLAG_READ
},
130 { WM_STYLECHANGING
, sizeof(STYLESTRUCT
), MMS_FLAG_READWRITE
},
131 { WM_COPYDATA
, MMS_SIZE_SPECIAL
, MMS_FLAG_READ
},
132 { WM_COPYGLOBALDATA
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
133 { WM_WINDOWPOSCHANGED
, sizeof(WINDOWPOS
), MMS_FLAG_READ
},
134 { WM_WINDOWPOSCHANGING
, sizeof(WINDOWPOS
), MMS_FLAG_READWRITE
},
137 static PMSGMEMORY FASTCALL
138 FindMsgMemory(UINT Msg
)
140 PMSGMEMORY MsgMemoryEntry
;
142 /* See if this message type is present in the table */
143 for (MsgMemoryEntry
= MsgMemory
;
144 MsgMemoryEntry
< MsgMemory
+ sizeof(MsgMemory
) / sizeof(MSGMEMORY
);
147 if (Msg
== MsgMemoryEntry
->Message
)
149 return MsgMemoryEntry
;
157 MsgMemorySize(PMSGMEMORY MsgMemoryEntry
, WPARAM wParam
, LPARAM lParam
)
160 PUNICODE_STRING WindowName
;
161 PUNICODE_STRING ClassName
;
166 if (MMS_SIZE_WPARAM
== MsgMemoryEntry
->Size
)
170 else if (MMS_SIZE_WPARAMWCHAR
== MsgMemoryEntry
->Size
)
172 Size
= (UINT
) (wParam
* sizeof(WCHAR
));
174 else if (MMS_SIZE_LPARAMSZ
== MsgMemoryEntry
->Size
)
176 Size
= (UINT
) ((wcslen((PWSTR
) lParam
) + 1) * sizeof(WCHAR
));
178 else if (MMS_SIZE_SPECIAL
== MsgMemoryEntry
->Size
)
180 switch(MsgMemoryEntry
->Message
)
184 Cs
= (CREATESTRUCTW
*) lParam
;
185 WindowName
= (PUNICODE_STRING
) Cs
->lpszName
;
186 ClassName
= (PUNICODE_STRING
) Cs
->lpszClass
;
187 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
188 if (IS_ATOM(ClassName
->Buffer
))
190 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
194 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
199 Size
= wParam
? sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
) : sizeof(RECT
);
203 Size
= sizeof(COPYDATASTRUCT
) + ((PCOPYDATASTRUCT
)lParam
)->cbData
;
214 Size
= MsgMemoryEntry
->Size
;
217 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
219 ERR("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH2_GetExceptionCode());
226 UINT
lParamMemorySize(UINT Msg
, WPARAM wParam
, LPARAM lParam
)
228 PMSGMEMORY MsgMemory
= FindMsgMemory(Msg
);
229 if(MsgMemory
== NULL
) return 0;
230 return MsgMemorySize(MsgMemory
, wParam
, lParam
);
234 PackParam(LPARAM
*lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolNeeded
)
236 NCCALCSIZE_PARAMS
*UnpackedNcCalcsize
;
237 NCCALCSIZE_PARAMS
*PackedNcCalcsize
;
238 CREATESTRUCTW
*UnpackedCs
;
239 CREATESTRUCTW
*PackedCs
;
240 PLARGE_STRING WindowName
;
241 PUNICODE_STRING ClassName
;
246 *lParamPacked
= lParam
;
248 if (NonPagedPoolNeeded
)
249 PoolType
= NonPagedPool
;
251 PoolType
= PagedPool
;
253 if (WM_NCCALCSIZE
== Msg
&& wParam
)
256 UnpackedNcCalcsize
= (NCCALCSIZE_PARAMS
*) lParam
;
257 PackedNcCalcsize
= ExAllocatePoolWithTag(PoolType
,
258 sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
),
261 if (NULL
== PackedNcCalcsize
)
263 ERR("Not enough memory to pack lParam\n");
264 return STATUS_NO_MEMORY
;
266 RtlCopyMemory(PackedNcCalcsize
, UnpackedNcCalcsize
, sizeof(NCCALCSIZE_PARAMS
));
267 PackedNcCalcsize
->lppos
= (PWINDOWPOS
) (PackedNcCalcsize
+ 1);
268 RtlCopyMemory(PackedNcCalcsize
->lppos
, UnpackedNcCalcsize
->lppos
, sizeof(WINDOWPOS
));
269 *lParamPacked
= (LPARAM
) PackedNcCalcsize
;
271 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
273 UnpackedCs
= (CREATESTRUCTW
*) lParam
;
274 WindowName
= (PLARGE_STRING
) UnpackedCs
->lpszName
;
275 ClassName
= (PUNICODE_STRING
) UnpackedCs
->lpszClass
;
276 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
277 if (IS_ATOM(ClassName
->Buffer
))
279 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
283 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
285 PackedCs
= ExAllocatePoolWithTag(PoolType
, Size
, TAG_MSG
);
286 if (NULL
== PackedCs
)
288 ERR("Not enough memory to pack lParam\n");
289 return STATUS_NO_MEMORY
;
291 RtlCopyMemory(PackedCs
, UnpackedCs
, sizeof(CREATESTRUCTW
));
292 CsData
= (PCHAR
) (PackedCs
+ 1);
293 PackedCs
->lpszName
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
294 RtlCopyMemory(CsData
, WindowName
->Buffer
, WindowName
->Length
);
295 CsData
+= WindowName
->Length
;
296 *((WCHAR
*) CsData
) = L
'\0';
297 CsData
+= sizeof(WCHAR
);
298 PackedCs
->lpszClass
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
299 if (IS_ATOM(ClassName
->Buffer
))
301 *((WCHAR
*) CsData
) = L
'A';
302 CsData
+= sizeof(WCHAR
);
303 *((ATOM
*) CsData
) = (ATOM
)(DWORD_PTR
) ClassName
->Buffer
;
304 CsData
+= sizeof(ATOM
);
308 *((WCHAR
*) CsData
) = L
'S';
309 CsData
+= sizeof(WCHAR
);
310 RtlCopyMemory(CsData
, ClassName
->Buffer
, ClassName
->Length
);
311 CsData
+= ClassName
->Length
;
312 *((WCHAR
*) CsData
) = L
'\0';
313 CsData
+= sizeof(WCHAR
);
315 ASSERT(CsData
== (PCHAR
) PackedCs
+ Size
);
316 *lParamPacked
= (LPARAM
) PackedCs
;
318 else if (PoolType
== NonPagedPool
)
320 PMSGMEMORY MsgMemoryEntry
;
324 MsgMemoryEntry
= FindMsgMemory(Msg
);
326 if ((!MsgMemoryEntry
) || (MsgMemoryEntry
->Size
< 0))
328 /* Keep previous behavior */
329 return STATUS_SUCCESS
;
331 size
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
334 ERR("No size for lParamPacked\n");
335 return STATUS_SUCCESS
;
337 PackedData
= ExAllocatePoolWithTag(NonPagedPool
, size
, TAG_MSG
);
338 if (PackedData
== NULL
)
340 ERR("Not enough memory to pack lParam\n");
341 return STATUS_NO_MEMORY
;
343 RtlCopyMemory(PackedData
, (PVOID
)lParam
, MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
));
344 *lParamPacked
= (LPARAM
)PackedData
;
347 return STATUS_SUCCESS
;
351 UnpackParam(LPARAM lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolUsed
)
353 NCCALCSIZE_PARAMS
*UnpackedParams
;
354 NCCALCSIZE_PARAMS
*PackedParams
;
355 PWINDOWPOS UnpackedWindowPos
;
357 if (lParamPacked
== lParam
)
359 return STATUS_SUCCESS
;
362 if (WM_NCCALCSIZE
== Msg
&& wParam
)
364 PackedParams
= (NCCALCSIZE_PARAMS
*) lParamPacked
;
365 UnpackedParams
= (NCCALCSIZE_PARAMS
*) lParam
;
366 UnpackedWindowPos
= UnpackedParams
->lppos
;
367 RtlCopyMemory(UnpackedParams
, PackedParams
, sizeof(NCCALCSIZE_PARAMS
));
368 UnpackedParams
->lppos
= UnpackedWindowPos
;
369 RtlCopyMemory(UnpackedWindowPos
, PackedParams
+ 1, sizeof(WINDOWPOS
));
370 ExFreePool((PVOID
) lParamPacked
);
372 return STATUS_SUCCESS
;
374 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
376 ExFreePool((PVOID
) lParamPacked
);
378 return STATUS_SUCCESS
;
380 else if (NonPagedPoolUsed
)
382 PMSGMEMORY MsgMemoryEntry
;
383 MsgMemoryEntry
= FindMsgMemory(Msg
);
384 ASSERT(MsgMemoryEntry
);
385 if (MsgMemoryEntry
->Size
< 0)
387 /* Keep previous behavior */
388 return STATUS_INVALID_PARAMETER
;
391 if (MsgMemory
->Flags
== MMS_FLAG_READWRITE
)
393 //RtlCopyMemory((PVOID)lParam, (PVOID)lParamPacked, MsgMemory->Size);
395 ExFreePool((PVOID
) lParamPacked
);
396 return STATUS_SUCCESS
;
401 return STATUS_INVALID_PARAMETER
;
404 static NTSTATUS FASTCALL
405 CopyMsgToKernelMem(MSG
*KernelModeMsg
, MSG
*UserModeMsg
, PMSGMEMORY MsgMemoryEntry
)
412 *KernelModeMsg
= *UserModeMsg
;
414 /* See if this message type is present in the table */
415 if (NULL
== MsgMemoryEntry
)
417 /* Not present, no copying needed */
418 return STATUS_SUCCESS
;
421 /* Determine required size */
422 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
426 /* Allocate kernel mem */
427 KernelMem
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
428 if (NULL
== KernelMem
)
430 ERR("Not enough memory to copy message to kernel mem\n");
431 return STATUS_NO_MEMORY
;
433 KernelModeMsg
->lParam
= (LPARAM
) KernelMem
;
435 /* Copy data if required */
436 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_READ
))
438 Status
= MmCopyFromCaller(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
439 if (! NT_SUCCESS(Status
))
441 ERR("Failed to copy message to kernel: invalid usermode buffer\n");
442 ExFreePoolWithTag(KernelMem
, TAG_MSG
);
448 /* Make sure we don't pass any secrets to usermode */
449 RtlZeroMemory(KernelMem
, Size
);
454 KernelModeMsg
->lParam
= 0;
457 return STATUS_SUCCESS
;
460 static NTSTATUS FASTCALL
461 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
464 PMSGMEMORY MsgMemoryEntry
;
467 /* See if this message type is present in the table */
468 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
469 if (NULL
== MsgMemoryEntry
)
471 /* Not present, no copying needed */
472 return STATUS_SUCCESS
;
475 /* Determine required size */
476 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
480 /* Copy data if required */
481 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
483 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
484 if (! NT_SUCCESS(Status
))
486 ERR("Failed to copy message from kernel: invalid usermode buffer\n");
487 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
492 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
495 return STATUS_SUCCESS
;
499 // Wakeup any thread/process waiting on idle input.
504 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
505 PUSER_MESSAGE_QUEUE ForegroundQueue
;
506 PTHREADINFO pti
, ptiForeground
= NULL
;
508 ForegroundQueue
= IntGetFocusMessageQueue();
511 ptiForeground
= ForegroundQueue
->Thread
->Tcb
.Win32Thread
;
513 pti
= PsGetCurrentThreadWin32Thread();
517 pti
->pClientInfo
->cSpins
= 0; // Reset spins.
519 if ( pti
->pDeskInfo
&& pti
== ptiForeground
)
521 if ( pti
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) ||
522 pti
->pDeskInfo
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) )
524 co_HOOK_CallHooks(WH_FOREGROUNDIDLE
,HC_ACTION
,0,0);
529 TRACE("IdlePing ppi 0x%x\n",ppi
);
530 if ( ppi
&& ppi
->InputIdleEvent
)
532 TRACE("InputIdleEvent\n");
533 KeSetEvent( ppi
->InputIdleEvent
, IO_NO_INCREMENT
, FALSE
);
540 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
542 TRACE("IdlePong ppi 0x%x\n",ppi
);
543 if ( ppi
&& ppi
->InputIdleEvent
)
545 KeClearEvent(ppi
->InputIdleEvent
);
550 GetWakeMask(UINT first
, UINT last
)
552 UINT mask
= QS_POSTMESSAGE
| QS_SENDMESSAGE
; /* Always selected */
556 if ((first
<= WM_KEYLAST
) && (last
>= WM_KEYFIRST
)) mask
|= QS_KEY
;
557 if ( ((first
<= WM_MOUSELAST
) && (last
>= WM_MOUSEFIRST
)) ||
558 ((first
<= WM_NCMOUSELAST
) && (last
>= WM_NCMOUSEFIRST
)) ) mask
|= QS_MOUSE
;
559 if ((first
<= WM_TIMER
) && (last
>= WM_TIMER
)) mask
|= QS_TIMER
;
560 if ((first
<= WM_SYSTIMER
) && (last
>= WM_SYSTIMER
)) mask
|= QS_TIMER
;
561 if ((first
<= WM_PAINT
) && (last
>= WM_PAINT
)) mask
|= QS_PAINT
;
563 else mask
= QS_ALLINPUT
;
569 IntCallWndProc( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
571 BOOL SameThread
= FALSE
;
574 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
581 co_HOOK_CallHooks( WH_CALLWNDPROC
, HC_ACTION
, SameThread
, (LPARAM
)&CWP
);
585 IntCallWndProcRet ( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*uResult
)
587 BOOL SameThread
= FALSE
;
590 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
595 CWPR
.wParam
= wParam
;
596 CWPR
.lParam
= lParam
;
597 CWPR
.lResult
= uResult
? (*uResult
) : 0;
598 co_HOOK_CallHooks( WH_CALLWNDPROCRET
, HC_ACTION
, SameThread
, (LPARAM
)&CWPR
);
601 static LRESULT
handle_internal_message( PWND pWnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
604 USER_REFERENCE_ENTRY Ref
;
607 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
608 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
611 TRACE("Internal Event Msg %p hWnd 0x%x\n",msg
,pWnd
->head
.h
);
615 case WM_ASYNC_SHOWWINDOW
:
616 return co_WinPosShowWindow( pWnd
, wparam
);
617 case WM_ASYNC_SETWINDOWPOS
:
619 PWINDOWPOS winpos
= (PWINDOWPOS
)lparam
;
620 if (!winpos
) return 0;
621 lRes
= co_WinPosSetWindowPos( pWnd
,
622 winpos
->hwndInsertAfter
,
628 ExFreePoolWithTag(winpos
, USERTAG_SWP
);
631 case WM_ASYNC_SETACTIVEWINDOW
:
633 PWND Window
= (PWND
)wparam
;
634 if (wparam
) UserRefObjectCo(Window
, &Ref
);
635 lRes
= (LRESULT
)co_IntSetActiveWindow(Window
,NULL
,(BOOL
)lparam
,TRUE
,TRUE
);
636 if (wparam
) UserDerefObjectCo(Window
);
644 IntDispatchMessage(PMSG pMsg
)
646 LARGE_INTEGER TickCount
;
652 BOOL DoCallBack
= TRUE
;
656 Window
= UserGetWindowObject(pMsg
->hwnd
);
657 if (!Window
) return 0;
660 pti
= PsGetCurrentThreadWin32Thread();
662 if ( Window
&& Window
->head
.pti
!= pti
)
664 EngSetLastError( ERROR_MESSAGE_SYNC_ONLY
);
668 if (((pMsg
->message
== WM_SYSTIMER
) ||
669 (pMsg
->message
== WM_TIMER
)) &&
672 if (pMsg
->message
== WM_TIMER
)
674 if (ValidateTimerCallback(pti
,pMsg
->lParam
))
676 KeQueryTickCount(&TickCount
);
677 Time
= MsqCalculateMessageTime(&TickCount
);
678 retval
= co_IntCallWindowProc((WNDPROC
)pMsg
->lParam
,
690 PTIMER pTimer
= FindSystemTimer(pMsg
);
691 if (pTimer
&& pTimer
->pfn
)
693 KeQueryTickCount(&TickCount
);
694 Time
= MsqCalculateMessageTime(&TickCount
);
695 pTimer
->pfn(pMsg
->hwnd
, WM_SYSTIMER
, (UINT
)pMsg
->wParam
, Time
);
701 if ( !Window
) return 0;
703 if (pMsg
->message
== WM_PAINT
) Window
->state
|= WNDS_PAINTNOTPROCESSED
;
705 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
707 TRACE("Dispatch: Server Side Window Procedure\n");
711 DoCallBack
= !DesktopWindowProc( Window
,
720 /* Since we are doing a callback on the same thread right away, there is
721 no need to copy the lparam to kernel mode and then back to usermode.
722 We just pretend it isn't a pointer */
725 retval
= co_IntCallWindowProc( Window
->lpfnWndProc
,
733 if (pMsg
->message
== WM_PAINT
)
735 Window
->state2
&= ~WNDS2_WMPAINTSENT
;
736 /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
737 hrgn
= IntSysCreateRectRgn( 0, 0, 0, 0 );
738 co_UserGetUpdateRgn( Window
, hrgn
, TRUE
);
739 GreDeleteObject(hrgn
);
746 * Internal version of PeekMessage() doing all the work
749 co_IntPeekMessage( PMSG Msg
,
757 LARGE_INTEGER LargeTickCount
;
758 PUSER_MESSAGE_QUEUE ThreadQueue
;
763 pti
= PsGetCurrentThreadWin32Thread();
764 ThreadQueue
= pti
->MessageQueue
;
766 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
767 ProcessMask
= HIWORD(RemoveMsg
);
769 if (ThreadQueue
->ptiSysLock
&& ThreadQueue
->ptiSysLock
!= pti
)
771 ERR("PeekMessage: Thread Q 0x%p is locked 0x%p to another pti 0x%p!\n", ThreadQueue
, ThreadQueue
->ptiSysLock
, pti
);
774 /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns
775 all available messages (that is, no range filtering is performed)". */
776 if (!ProcessMask
) ProcessMask
= (QS_ALLPOSTMESSAGE
|QS_ALLINPUT
);
782 KeQueryTickCount(&LargeTickCount
);
783 ThreadQueue
->LastMsgRead
= LargeTickCount
.u
.LowPart
;
784 pti
->pcti
->tickLastMsgChecked
= LargeTickCount
.u
.LowPart
;
786 /* Dispatch sent messages here. */
787 while ( co_MsqDispatchOneSentMessage(ThreadQueue
) )
789 /* if some PM_QS* flags were specified, only handle sent messages from now on */
790 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
; // wine does this; ProcessMask = QS_SENDMESSAGE;
792 if (Hit
) return FALSE
;
794 /* Clear changed bits so we can wait on them if we don't find a message */
795 if (ProcessMask
& QS_POSTMESSAGE
)
797 pti
->pcti
->fsChangeBits
&= ~(QS_POSTMESSAGE
| QS_HOTKEY
| QS_TIMER
);
798 if (MsgFilterMin
== 0 && MsgFilterMax
== 0) // Wine hack does this; ~0U)
800 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
804 if (ProcessMask
& QS_INPUT
)
806 pti
->pcti
->fsChangeBits
&= ~QS_INPUT
;
809 /* Now check for normal messages. */
810 if (( (ProcessMask
& QS_POSTMESSAGE
) ||
811 (ProcessMask
& QS_HOTKEY
) ) &&
812 MsqPeekMessage( ThreadQueue
,
823 /* Now look for a quit message. */
824 if (ThreadQueue
->QuitPosted
)
826 /* According to the PSDK, WM_QUIT messages are always returned, regardless
827 of the filter specified */
829 Msg
->message
= WM_QUIT
;
830 Msg
->wParam
= ThreadQueue
->QuitExitCode
;
834 ThreadQueue
->QuitPosted
= FALSE
;
835 ClearMsgBitsMask(ThreadQueue
, QS_POSTMESSAGE
);
836 pti
->pcti
->fsWakeBits
&= ~QS_ALLPOSTMESSAGE
;
837 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
842 /* Check for hardware events. */
843 if ((ProcessMask
& QS_MOUSE
) &&
844 co_MsqPeekMouseMove( ThreadQueue
,
854 if ((ProcessMask
& QS_INPUT
) &&
855 co_MsqPeekHardwareMessage( ThreadQueue
,
866 /* Check for sent messages again. */
867 while ( co_MsqDispatchOneSentMessage(ThreadQueue
) )
869 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
;
871 if (Hit
) return FALSE
;
873 /* Check for paint messages. */
874 if ((ProcessMask
& QS_PAINT
) &&
876 IntGetPaintMessage( Window
,
886 /* This is correct, check for the current threads timers waiting to be
887 posted to this threads message queue. If any we loop again.
889 if ((ProcessMask
& QS_TIMER
) &&
890 PostTimerMessages(Window
))
903 co_IntWaitMessage( PWND Window
,
908 PUSER_MESSAGE_QUEUE ThreadQueue
;
909 NTSTATUS Status
= STATUS_SUCCESS
;
912 pti
= PsGetCurrentThreadWin32Thread();
913 ThreadQueue
= pti
->MessageQueue
;
917 if ( co_IntPeekMessage( &Msg
, // Dont reenter!
921 MAKELONG( PM_NOREMOVE
, GetWakeMask( MsgFilterMin
, MsgFilterMax
)),
922 TRUE
) ) // act like GetMessage.
927 /* Nothing found. Wait for new messages. */
928 Status
= co_MsqWaitForNewMessages( ThreadQueue
,
932 if (!NT_SUCCESS(Status
))
934 SetLastNtError(Status
);
935 ERR("Exit co_IntWaitMessage on error!\n");
938 if (Status
== STATUS_USER_APC
|| Status
== STATUS_TIMEOUT
)
949 co_IntGetPeekMessage( PMSG pMsg
,
958 BOOL Present
= FALSE
;
961 if ( hWnd
== HWND_TOPMOST
|| hWnd
== HWND_BROADCAST
)
965 if (hWnd
&& hWnd
!= HWND_BOTTOM
)
967 if (!(Window
= UserGetWindowObject(hWnd
)))
980 if (MsgFilterMax
< MsgFilterMin
)
988 RemoveMsg
|= ((GetWakeMask( MsgFilterMin
, MsgFilterMax
))<< 16);
991 pti
= PsGetCurrentThreadWin32Thread();
992 pti
->pClientInfo
->cSpins
++; // Bump up the spin count.
996 Present
= co_IntPeekMessage( pMsg
,
1004 /* GetMessage or PostMessage must never get messages that contain pointers */
1005 ASSERT(FindMsgMemory(pMsg
->message
) == NULL
);
1007 if (pMsg
->message
!= WM_PAINT
&& pMsg
->message
!= WM_QUIT
)
1009 pti
->timeLast
= pMsg
->time
;
1010 pti
->ptLast
= pMsg
->pt
;
1013 // The WH_GETMESSAGE hook enables an application to monitor messages about to
1014 // be returned by the GetMessage or PeekMessage function.
1016 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)pMsg
);
1023 Status
= co_MsqWaitForNewMessages( pti
->MessageQueue
,
1027 if ( !NT_SUCCESS(Status
) ||
1028 Status
== STATUS_USER_APC
||
1029 Status
== STATUS_TIMEOUT
)
1037 if (!(RemoveMsg
& PM_NOYIELD
))
1040 // Yield this thread!
1043 UserEnterExclusive();
1044 // Fall through to exit.
1050 while( bGMSG
&& !Present
);
1052 // Been spinning, time to swap vinyl...
1053 if (pti
->pClientInfo
->cSpins
>= 100)
1055 // Clear the spin cycle to fix the mix.
1056 pti
->pClientInfo
->cSpins
= 0;
1057 //if (!(pti->TIF_flags & TIF_SPINNING)) // FIXME: Need to swap vinyl...
1063 UserPostThreadMessage( DWORD idThread
,
1070 PTHREADINFO pThread
;
1071 LARGE_INTEGER LargeTickCount
;
1074 if (is_pointer_message(Msg
))
1076 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1080 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
1082 if( Status
== STATUS_SUCCESS
)
1084 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
1086 !pThread
->MessageQueue
||
1087 (pThread
->TIF_flags
& TIF_INCLEANUP
))
1089 ObDereferenceObject( peThread
);
1093 Message
.hwnd
= NULL
;
1094 Message
.message
= Msg
;
1095 Message
.wParam
= wParam
;
1096 Message
.lParam
= lParam
;
1097 Message
.pt
= gpsi
->ptCursor
;
1099 KeQueryTickCount(&LargeTickCount
);
1100 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1101 MsqPostMessage(pThread
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
);
1102 ObDereferenceObject( peThread
);
1107 SetLastNtError( Status
);
1113 UserPostMessage( HWND Wnd
,
1119 MSG Message
, KernelModeMsg
;
1120 LARGE_INTEGER LargeTickCount
;
1123 Message
.message
= Msg
;
1124 Message
.wParam
= wParam
;
1125 Message
.lParam
= lParam
;
1126 Message
.pt
= gpsi
->ptCursor
;
1127 KeQueryTickCount(&LargeTickCount
);
1128 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1130 if (is_pointer_message(Message
.message
))
1132 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1136 if( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1139 PMSGMEMORY MsgMemoryEntry
;
1141 MsgMemoryEntry
= FindMsgMemory(Message
.message
);
1143 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &Message
, MsgMemoryEntry
);
1144 if (! NT_SUCCESS(Status
))
1146 EngSetLastError(ERROR_INVALID_PARAMETER
);
1149 co_IntSendMessageNoWait(KernelModeMsg
.hwnd
,
1150 KernelModeMsg
.message
,
1151 KernelModeMsg
.wParam
,
1152 KernelModeMsg
.lParam
);
1154 if (MsgMemoryEntry
&& KernelModeMsg
.lParam
)
1155 ExFreePool((PVOID
) KernelModeMsg
.lParam
);
1162 return UserPostThreadMessage( PtrToInt(PsGetCurrentThreadId()),
1167 if (Wnd
== HWND_BROADCAST
)
1173 DesktopWindow
= UserGetDesktopWindow();
1174 List
= IntWinListChildren(DesktopWindow
);
1178 UserPostMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1179 for (i
= 0; List
[i
]; i
++)
1181 PWND pwnd
= UserGetWindowObject(List
[i
]);
1182 if (!pwnd
) continue;
1184 if ( pwnd
->fnid
== FNID_MENU
|| // Also need pwnd->pcls->atomClassName == gaOleMainThreadWndClass
1185 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1188 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1190 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1197 Window
= UserGetWindowObject(Wnd
);
1200 ERR("UserPostMessage: Invalid handle 0x%p!\n",Wnd
);
1204 pti
= Window
->head
.pti
;
1205 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1207 ERR("Attempted to post message to window 0x%x when the thread is in cleanup!\n", Wnd
);
1211 if ( Window
->state
& WNDS_DESTROYED
)
1213 ERR("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd
);
1214 /* FIXME: Last error code? */
1220 MsqPostQuitMessage(Window
->head
.pti
->MessageQueue
, wParam
);
1224 MsqPostMessage(Window
->head
.pti
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
);
1231 co_IntSendMessage( HWND hWnd
,
1236 ULONG_PTR Result
= 0;
1237 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1239 return (LRESULT
)Result
;
1244 static LRESULT FASTCALL
1245 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1251 ULONG_PTR
*uResult
)
1255 PMSGMEMORY MsgMemoryEntry
;
1256 INT lParamBufferSize
;
1257 LPARAM lParamPacked
;
1258 PTHREADINFO Win32Thread
;
1259 ULONG_PTR Hi
, Lo
, Result
= 0;
1260 DECLARE_RETURN(LRESULT
);
1261 USER_REFERENCE_ENTRY Ref
;
1262 BOOL DoCallBack
= TRUE
;
1264 if (!(Window
= UserGetWindowObject(hWnd
)))
1266 TRACE("SendMessageTimeoutSingle: Invalid handle 0x%p!\n",hWnd
);
1270 UserRefObjectCo(Window
, &Ref
);
1272 Win32Thread
= PsGetCurrentThreadWin32Thread();
1275 Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1277 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1279 /* Never send messages to exiting threads */
1283 if (Msg
& 0x80000000)
1285 TRACE("SMTS: Internal Message!\n");
1286 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1287 if (uResult
) *uResult
= Result
;
1291 // Only happens when calling the client!
1292 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1294 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1296 TRACE("SMT: Server Side Window Procedure\n");
1297 IoGetStackLimits(&Lo
, &Hi
);
1298 // Handle it here. Safeguard against excessive recursions.
1299 if (((ULONG_PTR
)&uResult
- Lo
) < 4096 )
1301 ERR("Server Callback Exceeded Stack!\n");
1304 /* Return after server side call, IntCallWndProcRet will not be called. */
1305 switch(Window
->fnid
)
1308 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1313 if (uResult
) *uResult
= Result
;
1317 /* See if this message type is present in the table */
1318 MsgMemoryEntry
= FindMsgMemory(Msg
);
1319 if (NULL
== MsgMemoryEntry
)
1321 lParamBufferSize
= -1;
1325 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1328 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1330 ERR("Failed to pack message parameters\n");
1334 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1346 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1348 ERR("Failed to unpack message parameters\n");
1352 // Only happens when calling the client!
1353 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1358 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->head
.pti
->MessageQueue
))
1360 // FIXME: Set window hung and add to a list.
1361 /* FIXME: Set a LastError? */
1365 if (Window
->state
& WNDS_DESTROYED
)
1367 /* FIXME: Last error? */
1368 ERR("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1374 Status
= co_MsqSendMessage( Window
->head
.pti
->MessageQueue
,
1380 (uFlags
& SMTO_BLOCK
),
1384 while ((STATUS_TIMEOUT
== Status
) &&
1385 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1386 !MsqIsHung(Window
->head
.pti
->MessageQueue
)); // FIXME: Set window hung and add to a list.
1388 if (STATUS_TIMEOUT
== Status
)
1392 * Microsoft Windows 2000: If GetLastError returns zero, then the function
1394 * XP+ : If the function fails or times out, the return value is zero.
1395 * To get extended error information, call GetLastError. If GetLastError
1396 * returns ERROR_TIMEOUT, then the function timed out.
1398 EngSetLastError(ERROR_TIMEOUT
);
1401 else if (!NT_SUCCESS(Status
))
1403 SetLastNtError(Status
);
1410 if (Window
) UserDerefObjectCo(Window
);
1415 co_IntSendMessageTimeout( HWND hWnd
,
1421 ULONG_PTR
*uResult
)
1427 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1429 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1432 DesktopWindow
= UserGetDesktopWindow();
1433 if (NULL
== DesktopWindow
)
1435 EngSetLastError(ERROR_INTERNAL_ERROR
);
1439 if (hWnd
!= HWND_TOPMOST
)
1441 /* Send message to the desktop window too! */
1442 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1445 Children
= IntWinListChildren(DesktopWindow
);
1446 if (NULL
== Children
)
1451 for (Child
= Children
; NULL
!= *Child
; Child
++)
1453 if (hWnd
== HWND_TOPMOST
)
1455 DesktopWindow
= UserGetWindowObject(*Child
);
1456 if (DesktopWindow
&& DesktopWindow
->ExStyle
& WS_EX_TOPMOST
)
1458 ERR("HWND_TOPMOST Found\n");
1459 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1464 PWND pwnd
= UserGetWindowObject(*Child
);
1465 if (!pwnd
) continue;
1467 if ( pwnd
->fnid
== FNID_MENU
||
1468 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1471 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1475 ExFreePool(Children
);
1477 return (LRESULT
) TRUE
;
1481 co_IntSendMessageNoWait(HWND hWnd
,
1486 ULONG_PTR Result
= 0;
1487 return co_IntSendMessageWithCallBack( hWnd
,
1496 If you send a message in the range below WM_USER to the asynchronous message
1497 functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its
1498 message parameters cannot include pointers. Otherwise, the operation will fail.
1499 The functions will return before the receiving thread has had a chance to
1500 process the message and the sender will free the memory before it is used.
1503 co_IntSendMessageWithCallBack( HWND hWnd
,
1507 SENDASYNCPROC CompletionCallback
,
1508 ULONG_PTR CompletionCallbackContext
,
1513 PMSGMEMORY MsgMemoryEntry
;
1514 INT lParamBufferSize
;
1515 LPARAM lParamPacked
;
1516 PTHREADINFO Win32Thread
;
1517 DECLARE_RETURN(LRESULT
);
1518 USER_REFERENCE_ENTRY Ref
;
1519 PUSER_SENT_MESSAGE Message
;
1520 BOOL DoCallBack
= TRUE
;
1522 if (!(Window
= UserGetWindowObject(hWnd
)))
1524 TRACE("SendMessageWithCallBack: Invalid handle 0x%p!\n",hWnd
);
1528 UserRefObjectCo(Window
, &Ref
);
1530 if (Window
->state
& WNDS_DESTROYED
)
1532 /* FIXME: last error? */
1533 ERR("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1537 Win32Thread
= PsGetCurrentThreadWin32Thread();
1539 if (Win32Thread
== NULL
||
1540 Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1545 if (Msg
& 0x80000000 &&
1546 Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1548 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
) RETURN( FALSE
);
1550 ERR("SMWCB: Internal Message!\n");
1551 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1552 if (uResult
) *uResult
= Result
;
1556 /* See if this message type is present in the table */
1557 MsgMemoryEntry
= FindMsgMemory(Msg
);
1558 if (NULL
== MsgMemoryEntry
)
1560 lParamBufferSize
= -1;
1564 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1567 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, Window
->head
.pti
->MessageQueue
!= Win32Thread
->MessageQueue
)))
1569 ERR("Failed to pack message parameters\n");
1573 /* If it can be sent now, then send it. */
1574 if (Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1576 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1578 UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
);
1579 /* Never send messages to exiting threads */
1583 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1585 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1587 TRACE("SMWCB: Server Side Window Procedure\n");
1588 switch(Window
->fnid
)
1591 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParamPacked
, (LRESULT
*)&Result
);
1597 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1609 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1611 if (CompletionCallback
)
1613 co_IntCallSentMessageCallback(CompletionCallback
,
1616 CompletionCallbackContext
,
1621 if (Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1623 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1625 ERR("Failed to unpack message parameters\n");
1630 if(!(Message
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
1632 ERR("MsqSendMessage(): Not enough memory to allocate a message");
1636 IntReferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1637 /* Take reference on this MessageQueue if its a callback. It will be released
1638 when message is processed or removed from target hwnd MessageQueue */
1639 if (CompletionCallback
)
1640 IntReferenceMessageQueue(Win32Thread
->MessageQueue
);
1642 Message
->Msg
.hwnd
= hWnd
;
1643 Message
->Msg
.message
= Msg
;
1644 Message
->Msg
.wParam
= wParam
;
1645 Message
->Msg
.lParam
= lParamPacked
;
1646 Message
->CompletionEvent
= NULL
;
1647 Message
->Result
= 0;
1648 Message
->lResult
= 0;
1649 Message
->QS_Flags
= 0;
1650 Message
->SenderQueue
= NULL
; // mjmartin, you are right! This is null.
1651 Message
->CallBackSenderQueue
= Win32Thread
->MessageQueue
;
1652 Message
->DispatchingListEntry
.Flink
= NULL
;
1653 Message
->CompletionCallback
= CompletionCallback
;
1654 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1655 Message
->HookMessage
= MSQ_NORMAL
;
1656 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1657 Message
->QS_Flags
= QS_SENDMESSAGE
;
1659 InsertTailList(&Window
->head
.pti
->MessageQueue
->SentMessagesListHead
, &Message
->ListEntry
);
1660 MsqWakeQueue(Window
->head
.pti
->MessageQueue
, QS_SENDMESSAGE
, TRUE
);
1661 IntDereferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1666 if (Window
) UserDerefObjectCo(Window
);
1672 This HACK function posts a message if the destination's message queue belongs to
1673 another thread, otherwise it sends the message. It does not support broadcast
1677 co_IntPostOrSendMessage( HWND hWnd
,
1686 if ( hWnd
== HWND_BROADCAST
)
1691 if(!(Window
= UserGetWindowObject(hWnd
)))
1693 TRACE("PostOrSendMessage: Invalid handle 0x%p!\n",hWnd
);
1697 pti
= PsGetCurrentThreadWin32Thread();
1699 if ( Window
->head
.pti
->MessageQueue
!= pti
->MessageQueue
&&
1700 FindMsgMemory(Msg
) == 0 )
1702 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1706 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1712 return (LRESULT
)Result
;
1716 co_IntDoSendMessage( HWND hWnd
,
1723 LRESULT Result
= TRUE
;
1728 PMSGMEMORY MsgMemoryEntry
;
1730 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1732 Window
= UserGetWindowObject(hWnd
);
1739 /* Check for an exiting window. */
1740 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1742 ERR("co_IntDoSendMessage Window Exiting!\n");
1745 /* See if the current thread can handle the message */
1746 //pti = PsGetCurrentThreadWin32Thread();
1748 UserModeMsg
.hwnd
= hWnd
;
1749 UserModeMsg
.message
= Msg
;
1750 UserModeMsg
.wParam
= wParam
;
1751 UserModeMsg
.lParam
= lParam
;
1752 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1754 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1755 if (! NT_SUCCESS(Status
))
1757 EngSetLastError(ERROR_INVALID_PARAMETER
);
1758 return (dsm
? 0 : -1);
1763 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1764 KernelModeMsg
.message
,
1765 KernelModeMsg
.wParam
,
1766 KernelModeMsg
.lParam
);
1770 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1771 KernelModeMsg
.message
,
1772 KernelModeMsg
.wParam
,
1773 KernelModeMsg
.lParam
,
1779 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1780 if (! NT_SUCCESS(Status
))
1782 EngSetLastError(ERROR_INVALID_PARAMETER
);
1783 return(dsm
? 0 : -1);
1786 return (LRESULT
)Result
;
1790 UserSendNotifyMessage( HWND hWnd
,
1797 if (is_pointer_message(Msg
))
1799 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1803 // Basicly the same as IntPostOrSendMessage
1804 if (hWnd
== HWND_BROADCAST
) // Handle Broadcast
1810 DesktopWindow
= UserGetDesktopWindow();
1811 List
= IntWinListChildren(DesktopWindow
);
1815 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1816 for (i
= 0; List
[i
]; i
++)
1818 PWND pwnd
= UserGetWindowObject(List
[i
]);
1819 if (!pwnd
) continue;
1821 if ( pwnd
->fnid
== FNID_MENU
||
1822 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1825 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1832 Ret
= co_IntSendMessageNoWait( hWnd
, Msg
, wParam
, lParam
);
1839 IntGetQueueStatus(DWORD Changes
)
1844 pti
= PsGetCurrentThreadWin32Thread();
1846 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1848 /* High word, types of messages currently in the queue.
1849 Low word, types of messages that have been added to the queue and that
1850 are still in the queue
1852 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1854 pti
->pcti
->fsChangeBits
&= ~Changes
;
1860 IntInitMessagePumpHook()
1862 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1866 pti
->pcti
->dwcPumpHook
++;
1873 IntUninitMessagePumpHook()
1875 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1879 if (pti
->pcti
->dwcPumpHook
<= 0)
1883 pti
->pcti
->dwcPumpHook
--;
1889 /** Functions ******************************************************************/
1895 POINT pt
) // Just like the User call.
1899 ULONG wDragWidth
, wDragHeight
;
1900 DECLARE_RETURN(BOOL
);
1902 TRACE("Enter NtUserDragDetect(%x)\n", hWnd
);
1903 UserEnterExclusive();
1905 wDragWidth
= UserGetSystemMetrics(SM_CXDRAG
);
1906 wDragHeight
= UserGetSystemMetrics(SM_CYDRAG
);
1908 rect
.left
= pt
.x
- wDragWidth
;
1909 rect
.right
= pt
.x
+ wDragWidth
;
1911 rect
.top
= pt
.y
- wDragHeight
;
1912 rect
.bottom
= pt
.y
+ wDragHeight
;
1914 co_UserSetCapture(hWnd
);
1918 while (co_IntGetPeekMessage( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, FALSE
) ||
1919 co_IntGetPeekMessage( &msg
, 0, WM_QUEUESYNC
, WM_QUEUESYNC
, PM_REMOVE
, FALSE
) ||
1920 co_IntGetPeekMessage( &msg
, 0, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
, FALSE
) )
1922 if ( msg
.message
== WM_LBUTTONUP
)
1924 co_UserSetCapture(NULL
);
1927 if ( msg
.message
== WM_MOUSEMOVE
)
1930 tmp
.x
= (short)LOWORD(msg
.lParam
);
1931 tmp
.y
= (short)HIWORD(msg
.lParam
);
1932 if( !RECTL_bPointInRect( &rect
, tmp
.x
, tmp
.y
) )
1934 co_UserSetCapture(NULL
);
1938 if ( msg
.message
== WM_KEYDOWN
)
1940 if ( msg
.wParam
== VK_ESCAPE
)
1942 co_UserSetCapture(NULL
);
1946 if ( msg
.message
== WM_QUEUESYNC
)
1948 co_HOOK_CallHooks( WH_CBT
, HCBT_QS
, 0, 0 );
1951 co_IntWaitMessage(NULL
, 0, 0);
1956 TRACE("Leave NtUserDragDetect, ret=%i\n",_ret_
);
1962 NtUserPostMessage(HWND hWnd
,
1969 UserEnterExclusive();
1971 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1979 NtUserPostThreadMessage(DWORD idThread
,
1986 UserEnterExclusive();
1988 ret
= UserPostThreadMessage( idThread
, Msg
, wParam
, lParam
);
1996 NtUserWaitMessage(VOID
)
2000 UserEnterExclusive();
2001 TRACE("NtUserWaitMessage Enter\n");
2002 ret
= co_IntWaitMessage(NULL
, 0, 0);
2003 TRACE("NtUserWaitMessage Leave\n");
2010 NtUserGetMessage(PMSG pMsg
,
2018 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
2020 EngSetLastError(ERROR_INVALID_PARAMETER
);
2024 UserEnterExclusive();
2026 RtlZeroMemory(&Msg
, sizeof(MSG
));
2028 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
2036 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2037 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2039 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2041 SetLastNtError(_SEH2_GetExceptionCode());
2048 Ret
= Ret
? (WM_QUIT
!= pMsg
->message
) : FALSE
;
2054 NtUserPeekMessage( PMSG pMsg
,
2063 if ( RemoveMsg
& PM_BADMSGFLAGS
)
2065 EngSetLastError(ERROR_INVALID_FLAGS
);
2069 UserEnterExclusive();
2071 RtlZeroMemory(&Msg
, sizeof(MSG
));
2073 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
2081 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2082 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2084 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2086 SetLastNtError(_SEH2_GetExceptionCode());
2096 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
2103 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
2104 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
2106 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2108 _SEH2_YIELD(return FALSE
);
2112 UserEnterExclusive();
2114 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
2120 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
2127 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
2128 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
2130 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2140 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
2147 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
2148 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
2150 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2152 SetLastNtError(_SEH2_GetExceptionCode());
2153 _SEH2_YIELD(return FALSE
);
2157 UserEnterExclusive();
2159 Res
= IntDispatchMessage(&SafeMsg
);
2166 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
2174 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
2175 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
2177 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2179 SetLastNtError(_SEH2_GetExceptionCode());
2180 _SEH2_YIELD(return FALSE
);
2184 UserEnterExclusive();
2185 pWnd
= UserGetWindowObject(SafeMsg
.hwnd
);
2186 if (pWnd
) // Must have a window!
2188 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
2192 TRACE("No Window for Translate. hwnd 0x%p Msg %d\n",SafeMsg
.hwnd
,SafeMsg
.message
);
2200 LRESULT APIENTRY
ScrollBarWndProc(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
);
2203 NtUserMessageCall( HWND hWnd
,
2207 ULONG_PTR ResultInfo
,
2208 DWORD dwType
, // fnID?
2211 LRESULT lResult
= 0;
2214 USER_REFERENCE_ENTRY Ref
;
2216 UserEnterExclusive();
2220 case FNID_SCROLLBAR
:
2222 lResult
= ScrollBarWndProc(hWnd
, Msg
, wParam
, lParam
);
2227 Window
= UserGetWindowObject(hWnd
);
2230 //ERR("FNID_DESKTOP IN\n");
2231 Ret
= DesktopWindowProc(Window
, Msg
, wParam
, lParam
, &lResult
);
2232 //ERR("FNID_DESKTOP OUT\n");
2236 case FNID_DEFWINDOWPROC
:
2237 /* Validate input */
2240 Window
= UserGetWindowObject(hWnd
);
2246 UserRefObjectCo(Window
, &Ref
);
2248 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2251 UserDerefObjectCo(Window
);
2253 case FNID_SENDNOTIFYMESSAGE
:
2254 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2256 case FNID_BROADCASTSYSTEMMESSAGE
:
2258 BROADCASTPARM parm
, *retparam
;
2259 DWORD_PTR RetVal
= 0;
2265 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2266 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2268 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2277 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2278 parm
.recipients
== BSM_ALLCOMPONENTS
)
2280 PLIST_ENTRY DesktopEntry
;
2282 HWND
*List
, hwndDenied
= NULL
;
2284 PWND pwnd
, pwndDesk
;
2288 for (DesktopEntry
= InputWindowStation
->DesktopListHead
.Flink
;
2289 DesktopEntry
!= &InputWindowStation
->DesktopListHead
;
2290 DesktopEntry
= DesktopEntry
->Flink
)
2292 rpdesk
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
2293 pwndDesk
= rpdesk
->pDeskInfo
->spwnd
;
2294 List
= IntWinListChildren(pwndDesk
);
2296 if (parm
.flags
& BSF_QUERY
)
2300 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2302 fuFlags
= SMTO_ABORTIFHUNG
;
2304 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2306 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2310 fuFlags
= SMTO_NORMAL
;
2312 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2320 for (i
= 0; List
[i
]; i
++)
2322 pwnd
= UserGetWindowObject(List
[i
]);
2323 if (!pwnd
) continue;
2325 if ( pwnd
->fnid
== FNID_MENU
||
2326 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2329 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2331 if ( pwnd
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
2334 co_IntSendMessageTimeout( List
[i
],
2342 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2344 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2347 if (RetVal
== BROADCAST_QUERY_DENY
)
2349 hwndDenied
= List
[i
];
2350 hDesk
= UserHMGetHandle(pwndDesk
);
2354 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2357 retparam
= (PBROADCASTPARM
) ResultInfo
;
2358 retparam
->hDesk
= hDesk
;
2359 retparam
->hWnd
= hwndDenied
;
2361 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2366 if (!Ret
) break; // Have a hit! Let everyone know!
2369 else if (parm
.flags
& BSF_POSTMESSAGE
)
2373 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2375 for (i
= 0; List
[i
]; i
++)
2377 pwnd
= UserGetWindowObject(List
[i
]);
2378 if (!pwnd
) continue;
2380 if ( pwnd
->fnid
== FNID_MENU
||
2381 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2384 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2386 if ( pwnd
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
2389 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2391 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2399 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2401 for (i
= 0; List
[i
]; i
++)
2403 pwnd
= UserGetWindowObject(List
[i
]);
2404 if (!pwnd
) continue;
2406 if ( pwnd
->fnid
== FNID_MENU
||
2407 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2410 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2412 if ( pwnd
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
2415 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2417 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2423 else if (parm
.recipients
& BSM_APPLICATIONS
)
2425 HWND
*List
, hwndDenied
= NULL
;
2427 PWND pwnd
, pwndDesk
;
2431 pwndDesk
= UserGetDesktopWindow();
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
->MessageQueue
== gptiCurrent
->MessageQueue
)
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
)
2506 else if (parm
.flags
& BSF_POSTMESSAGE
)
2510 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2512 for (i
= 0; List
[i
]; i
++)
2514 pwnd
= UserGetWindowObject(List
[i
]);
2515 if (!pwnd
) continue;
2517 if ( pwnd
->fnid
== FNID_MENU
||
2518 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2521 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2523 if ( pwnd
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
2526 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2528 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2536 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2538 for (i
= 0; List
[i
]; i
++)
2540 pwnd
= UserGetWindowObject(List
[i
]);
2541 if (!pwnd
) continue;
2543 if ( pwnd
->fnid
== FNID_MENU
||
2544 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2547 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2549 if ( pwnd
->head
.pti
->MessageQueue
== gptiCurrent
->MessageQueue
)
2552 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2554 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2561 case FNID_SENDMESSAGECALLBACK
:
2563 CALL_BACK_INFO CallBackInfo
;
2568 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2569 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2571 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2577 if (is_pointer_message(Msg
))
2579 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
2583 if (!(Ret
= co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2584 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
)))
2586 ERR("Callback failure!\n");
2590 case FNID_SENDMESSAGE
:
2592 Ret
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2598 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2599 RtlCopyMemory((PVOID
)ResultInfo
, &Ret
, sizeof(ULONG_PTR
));
2601 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2610 case FNID_SENDMESSAGEFF
:
2611 case FNID_SENDMESSAGEWTOOPTION
:
2613 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2618 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2619 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2621 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2628 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, &dsm
);
2634 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2635 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2637 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2646 // CallNextHook bypass.
2647 case FNID_CALLWNDPROC
:
2648 case FNID_CALLWNDPROCRET
:
2651 PCLIENTINFO ClientInfo
;
2652 PHOOK NextObj
, Hook
;
2654 pti
= GetW32ThreadInfo();
2656 Hook
= pti
->sphkCurrent
;
2660 NextObj
= Hook
->phkNext
;
2661 ClientInfo
= pti
->pClientInfo
;
2664 ClientInfo
->phkCurrent
= NextObj
;
2666 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2672 if (!ClientInfo
|| !NextObj
) break;
2674 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2676 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2681 CWP
.wParam
= wParam
;
2682 CWP
.lParam
= lParam
;
2683 TRACE("WH_CALLWNDPROC: Hook %x NextHook %x\n", Hook
, NextObj
);
2685 lResult
= co_IntCallHookProc( Hook
->HookId
,
2687 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2698 CWPR
.wParam
= wParam
;
2699 CWPR
.lParam
= lParam
;
2700 CWPR
.lResult
= ClientInfo
->dwHookData
;
2702 lResult
= co_IntCallHookProc( Hook
->HookId
,
2704 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2716 case FNID_DEFWINDOWPROC
:
2717 case FNID_CALLWNDPROC
:
2718 case FNID_CALLWNDPROCRET
:
2719 case FNID_SCROLLBAR
:
2725 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2726 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2728 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2744 #define INFINITE 0xFFFFFFFF
2745 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2749 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2750 IN DWORD dwMilliseconds
,
2754 PPROCESSINFO W32Process
;
2758 LARGE_INTEGER Timeout
;
2760 UserEnterExclusive();
2762 Status
= ObReferenceObjectByHandle(hProcess
,
2763 PROCESS_QUERY_INFORMATION
,
2769 if (!NT_SUCCESS(Status
))
2772 SetLastNtError(Status
);
2776 pti
= PsGetCurrentThreadWin32Thread();
2778 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2780 if ( PsGetProcessExitProcessCalled(Process
) ||
2782 pti
->ppi
== W32Process
)
2784 ObDereferenceObject(Process
);
2786 EngSetLastError(ERROR_INVALID_PARAMETER
);
2790 Handles
[0] = Process
;
2791 Handles
[1] = W32Process
->InputIdleEvent
;
2792 Handles
[2] = pti
->MessageQueue
->NewMessages
; // pEventQueueServer; IntMsqSetWakeMask returns hEventQueueClient
2796 ObDereferenceObject(Process
);
2798 return STATUS_SUCCESS
; /* no event to wait on */
2801 if (dwMilliseconds
!= INFINITE
)
2802 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2804 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2805 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2807 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2808 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2811 TRACE("WFII: ppi 0x%x\n",W32Process
);
2812 TRACE("WFII: waiting for %p\n", Handles
[1] );
2816 Status
= KeWaitForMultipleObjects( 3,
2822 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2824 UserEnterExclusive();
2826 if (!NT_SUCCESS(Status
))
2828 SetLastNtError(Status
);
2829 Status
= WAIT_FAILED
;
2841 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2842 ERR("WFII: WAIT 2\n");
2846 case STATUS_TIMEOUT
:
2847 ERR("WFII: timeout\n");
2852 ERR("WFII: finished\n");
2853 Status
= STATUS_SUCCESS
;
2860 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2862 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
2863 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2865 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
2866 ObDereferenceObject(Process
);