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)
13 DBG_DEFAULT_CHANNEL(UserMsg
);
15 #define PM_BADMSGFLAGS ~((QS_RAWINPUT << 16)|PM_QS_SENDMESSAGE|PM_QS_PAINT|PM_QS_POSTMESSAGE|PM_QS_INPUT|PM_NOYIELD|PM_REMOVE)
17 /* FUNCTIONS *****************************************************************/
20 IntInitMessageImpl(VOID
)
22 return STATUS_SUCCESS
;
26 IntCleanupMessageImpl(VOID
)
28 return STATUS_SUCCESS
;
32 /* flag for messages that contain pointers */
33 /* 32 messages per entry, messages 0..31 map to bits 0..31 */
35 #define SET(msg) (1 << ((msg) & 31))
37 static const unsigned int message_pointer_flags
[] =
40 SET(WM_CREATE
) | SET(WM_SETTEXT
) | SET(WM_GETTEXT
) |
41 SET(WM_WININICHANGE
) | SET(WM_DEVMODECHANGE
),
43 SET(WM_GETMINMAXINFO
) | SET(WM_DRAWITEM
) | SET(WM_MEASUREITEM
) | SET(WM_DELETEITEM
) |
46 SET(WM_WINDOWPOSCHANGING
) | SET(WM_WINDOWPOSCHANGED
) | SET(WM_COPYDATA
) |
47 SET(WM_COPYGLOBALDATA
) | SET(WM_NOTIFY
) | SET(WM_HELP
),
49 SET(WM_STYLECHANGING
) | SET(WM_STYLECHANGED
),
51 SET(WM_NCCREATE
) | SET(WM_NCCALCSIZE
) | SET(WM_GETDLGCODE
),
53 SET(EM_GETSEL
) | SET(EM_GETRECT
) | SET(EM_SETRECT
) | SET(EM_SETRECTNP
),
55 SET(EM_REPLACESEL
) | SET(EM_GETLINE
) | SET(EM_SETTABSTOPS
),
57 SET(SBM_GETRANGE
) | SET(SBM_SETSCROLLINFO
) | SET(SBM_GETSCROLLINFO
) | SET(SBM_GETSCROLLBARINFO
),
63 SET(CB_GETEDITSEL
) | SET(CB_ADDSTRING
) | SET(CB_DIR
) | SET(CB_GETLBTEXT
) |
64 SET(CB_INSERTSTRING
) | SET(CB_FINDSTRING
) | SET(CB_SELECTSTRING
) |
65 SET(CB_GETDROPPEDCONTROLRECT
) | SET(CB_FINDSTRINGEXACT
),
69 SET(LB_ADDSTRING
) | SET(LB_INSERTSTRING
) | SET(LB_GETTEXT
) | SET(LB_SELECTSTRING
) |
70 SET(LB_DIR
) | SET(LB_FINDSTRING
) |
71 SET(LB_GETSELITEMS
) | SET(LB_SETTABSTOPS
) | SET(LB_ADDFILE
) | SET(LB_GETITEMRECT
),
73 SET(LB_FINDSTRINGEXACT
),
79 SET(WM_NEXTMENU
) | SET(WM_SIZING
) | SET(WM_MOVING
) | SET(WM_DEVICECHANGE
),
81 SET(WM_MDICREATE
) | SET(WM_MDIGETACTIVE
) | SET(WM_DROPOBJECT
) |
82 SET(WM_QUERYDROPOBJECT
) | SET(WM_DRAGLOOP
) | SET(WM_DRAGSELECT
) | SET(WM_DRAGMOVE
),
96 SET(WM_ASKCBFORMATNAME
)
99 /* check whether a given message type includes pointers */
100 static inline int is_pointer_message( UINT message
)
102 if (message
>= 8*sizeof(message_pointer_flags
)) return FALSE
;
103 return (message_pointer_flags
[message
/ 32] & SET(message
)) != 0;
107 #define MMS_SIZE_WPARAM -1
108 #define MMS_SIZE_WPARAMWCHAR -2
109 #define MMS_SIZE_LPARAMSZ -3
110 #define MMS_SIZE_SPECIAL -4
111 #define MMS_FLAG_READ 0x01
112 #define MMS_FLAG_WRITE 0x02
113 #define MMS_FLAG_READWRITE (MMS_FLAG_READ | MMS_FLAG_WRITE)
114 typedef struct tagMSGMEMORY
120 MSGMEMORY
, *PMSGMEMORY
;
122 static MSGMEMORY g_MsgMemory
[] =
124 { WM_CREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
125 { WM_DDE_ACK
, sizeof(KMDDELPARAM
), MMS_FLAG_READ
},
126 { WM_DDE_EXECUTE
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
127 { WM_GETMINMAXINFO
, sizeof(MINMAXINFO
), MMS_FLAG_READWRITE
},
128 { WM_GETTEXT
, MMS_SIZE_WPARAMWCHAR
, MMS_FLAG_WRITE
},
129 { WM_NCCALCSIZE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
130 { WM_NCCREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
131 { WM_SETTEXT
, MMS_SIZE_LPARAMSZ
, MMS_FLAG_READ
},
132 { WM_STYLECHANGED
, sizeof(STYLESTRUCT
), MMS_FLAG_READ
},
133 { WM_STYLECHANGING
, sizeof(STYLESTRUCT
), MMS_FLAG_READWRITE
},
134 { WM_SETTINGCHANGE
, MMS_SIZE_LPARAMSZ
, MMS_FLAG_READ
},
135 { WM_COPYDATA
, MMS_SIZE_SPECIAL
, MMS_FLAG_READ
},
136 { WM_COPYGLOBALDATA
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
137 { WM_WINDOWPOSCHANGED
, sizeof(WINDOWPOS
), MMS_FLAG_READ
},
138 { WM_WINDOWPOSCHANGING
, sizeof(WINDOWPOS
), MMS_FLAG_READWRITE
},
141 static PMSGMEMORY FASTCALL
142 FindMsgMemory(UINT Msg
)
144 PMSGMEMORY MsgMemoryEntry
;
146 /* See if this message type is present in the table */
147 for (MsgMemoryEntry
= g_MsgMemory
;
148 MsgMemoryEntry
< g_MsgMemory
+ sizeof(g_MsgMemory
) / sizeof(MSGMEMORY
);
151 if (Msg
== MsgMemoryEntry
->Message
)
153 return MsgMemoryEntry
;
161 MsgMemorySize(PMSGMEMORY MsgMemoryEntry
, WPARAM wParam
, LPARAM lParam
)
164 PUNICODE_STRING WindowName
;
165 PUNICODE_STRING ClassName
;
170 if (MMS_SIZE_WPARAM
== MsgMemoryEntry
->Size
)
174 else if (MMS_SIZE_WPARAMWCHAR
== MsgMemoryEntry
->Size
)
176 Size
= (UINT
) (wParam
* sizeof(WCHAR
));
178 else if (MMS_SIZE_LPARAMSZ
== MsgMemoryEntry
->Size
)
180 // WM_SETTEXT and WM_SETTINGCHANGE can be null!
183 TRACE("lParam is NULL!\n");
187 Size
= (UINT
) ((wcslen((PWSTR
) lParam
) + 1) * sizeof(WCHAR
));
189 else if (MMS_SIZE_SPECIAL
== MsgMemoryEntry
->Size
)
191 switch(MsgMemoryEntry
->Message
)
195 Cs
= (CREATESTRUCTW
*) lParam
;
196 WindowName
= (PUNICODE_STRING
) Cs
->lpszName
;
197 ClassName
= (PUNICODE_STRING
) Cs
->lpszClass
;
198 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
199 if (IS_ATOM(ClassName
->Buffer
))
201 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
205 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
210 Size
= wParam
? sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
) : sizeof(RECT
);
214 Size
= sizeof(COPYDATASTRUCT
) + ((PCOPYDATASTRUCT
)lParam
)->cbData
;
225 Size
= MsgMemoryEntry
->Size
;
228 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
230 ERR("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH2_GetExceptionCode());
237 UINT
lParamMemorySize(UINT Msg
, WPARAM wParam
, LPARAM lParam
)
239 PMSGMEMORY MsgMemoryEntry
= FindMsgMemory(Msg
);
240 if(MsgMemoryEntry
== NULL
) return 0;
241 return MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
245 PackParam(LPARAM
*lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolNeeded
)
247 NCCALCSIZE_PARAMS
*UnpackedNcCalcsize
;
248 NCCALCSIZE_PARAMS
*PackedNcCalcsize
;
249 CREATESTRUCTW
*UnpackedCs
;
250 CREATESTRUCTW
*PackedCs
;
251 PLARGE_STRING WindowName
;
252 PUNICODE_STRING ClassName
;
257 *lParamPacked
= lParam
;
259 if (NonPagedPoolNeeded
)
260 PoolType
= NonPagedPool
;
262 PoolType
= PagedPool
;
264 if (WM_NCCALCSIZE
== Msg
&& wParam
)
267 UnpackedNcCalcsize
= (NCCALCSIZE_PARAMS
*) lParam
;
268 PackedNcCalcsize
= ExAllocatePoolWithTag(PoolType
,
269 sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
),
272 if (NULL
== PackedNcCalcsize
)
274 ERR("Not enough memory to pack lParam\n");
275 return STATUS_NO_MEMORY
;
277 RtlCopyMemory(PackedNcCalcsize
, UnpackedNcCalcsize
, sizeof(NCCALCSIZE_PARAMS
));
278 PackedNcCalcsize
->lppos
= (PWINDOWPOS
) (PackedNcCalcsize
+ 1);
279 RtlCopyMemory(PackedNcCalcsize
->lppos
, UnpackedNcCalcsize
->lppos
, sizeof(WINDOWPOS
));
280 *lParamPacked
= (LPARAM
) PackedNcCalcsize
;
282 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
284 UnpackedCs
= (CREATESTRUCTW
*) lParam
;
285 WindowName
= (PLARGE_STRING
) UnpackedCs
->lpszName
;
286 ClassName
= (PUNICODE_STRING
) UnpackedCs
->lpszClass
;
287 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
288 if (IS_ATOM(ClassName
->Buffer
))
290 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
294 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
296 PackedCs
= ExAllocatePoolWithTag(PoolType
, Size
, TAG_MSG
);
297 if (NULL
== PackedCs
)
299 ERR("Not enough memory to pack lParam\n");
300 return STATUS_NO_MEMORY
;
302 RtlCopyMemory(PackedCs
, UnpackedCs
, sizeof(CREATESTRUCTW
));
303 CsData
= (PCHAR
) (PackedCs
+ 1);
304 PackedCs
->lpszName
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
305 RtlCopyMemory(CsData
, WindowName
->Buffer
, WindowName
->Length
);
306 CsData
+= WindowName
->Length
;
307 *((WCHAR
*) CsData
) = L
'\0';
308 CsData
+= sizeof(WCHAR
);
309 PackedCs
->lpszClass
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
310 if (IS_ATOM(ClassName
->Buffer
))
312 *((WCHAR
*) CsData
) = L
'A';
313 CsData
+= sizeof(WCHAR
);
314 *((ATOM
*) CsData
) = (ATOM
)(DWORD_PTR
) ClassName
->Buffer
;
315 CsData
+= sizeof(ATOM
);
319 *((WCHAR
*) CsData
) = L
'S';
320 CsData
+= sizeof(WCHAR
);
321 RtlCopyMemory(CsData
, ClassName
->Buffer
, ClassName
->Length
);
322 CsData
+= ClassName
->Length
;
323 *((WCHAR
*) CsData
) = L
'\0';
324 CsData
+= sizeof(WCHAR
);
326 ASSERT(CsData
== (PCHAR
) PackedCs
+ Size
);
327 *lParamPacked
= (LPARAM
) PackedCs
;
329 else if (PoolType
== NonPagedPool
)
331 PMSGMEMORY MsgMemoryEntry
;
335 MsgMemoryEntry
= FindMsgMemory(Msg
);
339 /* Keep previous behavior */
340 return STATUS_SUCCESS
;
342 size
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
345 ERR("No size for lParamPacked\n");
346 return STATUS_SUCCESS
;
348 PackedData
= ExAllocatePoolWithTag(NonPagedPool
, size
, TAG_MSG
);
349 if (PackedData
== NULL
)
351 ERR("Not enough memory to pack lParam\n");
352 return STATUS_NO_MEMORY
;
354 RtlCopyMemory(PackedData
, (PVOID
)lParam
, MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
));
355 *lParamPacked
= (LPARAM
)PackedData
;
358 return STATUS_SUCCESS
;
362 UnpackParam(LPARAM lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolUsed
)
364 NCCALCSIZE_PARAMS
*UnpackedParams
;
365 NCCALCSIZE_PARAMS
*PackedParams
;
366 PWINDOWPOS UnpackedWindowPos
;
368 if (lParamPacked
== lParam
)
370 return STATUS_SUCCESS
;
373 if (WM_NCCALCSIZE
== Msg
&& wParam
)
375 PackedParams
= (NCCALCSIZE_PARAMS
*) lParamPacked
;
376 UnpackedParams
= (NCCALCSIZE_PARAMS
*) lParam
;
377 UnpackedWindowPos
= UnpackedParams
->lppos
;
378 RtlCopyMemory(UnpackedParams
, PackedParams
, sizeof(NCCALCSIZE_PARAMS
));
379 UnpackedParams
->lppos
= UnpackedWindowPos
;
380 RtlCopyMemory(UnpackedWindowPos
, PackedParams
+ 1, sizeof(WINDOWPOS
));
381 ExFreePool((PVOID
) lParamPacked
);
383 return STATUS_SUCCESS
;
385 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
387 ExFreePool((PVOID
) lParamPacked
);
389 return STATUS_SUCCESS
;
391 else if (NonPagedPoolUsed
)
393 PMSGMEMORY MsgMemoryEntry
;
394 MsgMemoryEntry
= FindMsgMemory(Msg
);
395 ASSERT(MsgMemoryEntry
);
397 if (MsgMemoryEntry
->Flags
== MMS_FLAG_READWRITE
)
399 //RtlCopyMemory((PVOID)lParam, (PVOID)lParamPacked, MsgMemoryEntry->Size);
401 ExFreePool((PVOID
) lParamPacked
);
402 return STATUS_SUCCESS
;
407 return STATUS_INVALID_PARAMETER
;
410 static NTSTATUS FASTCALL
411 CopyMsgToKernelMem(MSG
*KernelModeMsg
, MSG
*UserModeMsg
, PMSGMEMORY MsgMemoryEntry
)
418 *KernelModeMsg
= *UserModeMsg
;
420 /* See if this message type is present in the table */
421 if (NULL
== MsgMemoryEntry
)
423 /* Not present, no copying needed */
424 return STATUS_SUCCESS
;
427 /* Determine required size */
428 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
432 /* Allocate kernel mem */
433 KernelMem
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
434 if (NULL
== KernelMem
)
436 ERR("Not enough memory to copy message to kernel mem\n");
437 return STATUS_NO_MEMORY
;
439 KernelModeMsg
->lParam
= (LPARAM
) KernelMem
;
441 /* Copy data if required */
442 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_READ
))
444 TRACE("Copy Message %d from usermode buffer\n", KernelModeMsg
->message
);
445 Status
= MmCopyFromCaller(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
446 if (! NT_SUCCESS(Status
))
448 ERR("Failed to copy message to kernel: invalid usermode lParam buffer\n");
449 ExFreePoolWithTag(KernelMem
, TAG_MSG
);
455 /* Make sure we don't pass any secrets to usermode */
456 RtlZeroMemory(KernelMem
, Size
);
461 KernelModeMsg
->lParam
= 0;
464 return STATUS_SUCCESS
;
467 static NTSTATUS FASTCALL
468 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
471 PMSGMEMORY MsgMemoryEntry
;
474 /* See if this message type is present in the table */
475 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
476 if (NULL
== MsgMemoryEntry
)
478 /* Not present, no copying needed */
479 return STATUS_SUCCESS
;
482 /* Determine required size */
483 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
487 /* Copy data if required */
488 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
490 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
491 if (! NT_SUCCESS(Status
))
493 ERR("Failed to copy message from kernel: invalid usermode lParam buffer\n");
494 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
499 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
502 return STATUS_SUCCESS
;
506 // Wakeup any thread/process waiting on idle input.
511 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
514 pti
= PsGetCurrentThreadWin32Thread();
518 pti
->pClientInfo
->cSpins
= 0; // Reset spins.
520 if ( pti
->pDeskInfo
&& pti
== gptiForeground
)
522 if ( pti
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) ||
523 pti
->pDeskInfo
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) )
525 co_HOOK_CallHooks(WH_FOREGROUNDIDLE
,HC_ACTION
,0,0);
530 TRACE("IdlePing ppi %p\n", ppi
);
531 if ( ppi
&& ppi
->InputIdleEvent
)
533 TRACE("InputIdleEvent\n");
534 KeSetEvent( ppi
->InputIdleEvent
, IO_NO_INCREMENT
, FALSE
);
541 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
543 TRACE("IdlePong ppi %p\n", ppi
);
544 if ( ppi
&& ppi
->InputIdleEvent
)
546 KeClearEvent(ppi
->InputIdleEvent
);
551 GetWakeMask(UINT first
, UINT last
)
553 UINT mask
= QS_POSTMESSAGE
| QS_SENDMESSAGE
; /* Always selected */
557 if ((first
<= WM_KEYLAST
) && (last
>= WM_KEYFIRST
)) mask
|= QS_KEY
;
558 if ( ((first
<= WM_MOUSELAST
) && (last
>= WM_MOUSEFIRST
)) ||
559 ((first
<= WM_NCMOUSELAST
) && (last
>= WM_NCMOUSEFIRST
)) ) mask
|= QS_MOUSE
;
560 if ((first
<= WM_TIMER
) && (last
>= WM_TIMER
)) mask
|= QS_TIMER
;
561 if ((first
<= WM_SYSTIMER
) && (last
>= WM_SYSTIMER
)) mask
|= QS_TIMER
;
562 if ((first
<= WM_PAINT
) && (last
>= WM_PAINT
)) mask
|= QS_PAINT
;
564 else mask
= QS_ALLINPUT
;
570 IntCallWndProc( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
572 BOOL SameThread
= FALSE
;
575 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
582 co_HOOK_CallHooks( WH_CALLWNDPROC
, HC_ACTION
, SameThread
, (LPARAM
)&CWP
);
586 IntCallWndProcRet ( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*uResult
)
588 BOOL SameThread
= FALSE
;
591 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
596 CWPR
.wParam
= wParam
;
597 CWPR
.lParam
= lParam
;
598 CWPR
.lResult
= uResult
? (*uResult
) : 0;
599 co_HOOK_CallHooks( WH_CALLWNDPROCRET
, HC_ACTION
, SameThread
, (LPARAM
)&CWPR
);
602 static LRESULT
handle_internal_message( PWND pWnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
605 USER_REFERENCE_ENTRY Ref
;
606 // PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
609 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
610 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
613 TRACE("Internal Event Msg %p hWnd 0x%x\n",msg
,pWnd
->head
.h
);
617 case WM_ASYNC_SHOWWINDOW
:
618 return co_WinPosShowWindow( pWnd
, wparam
);
619 case WM_ASYNC_SETWINDOWPOS
:
621 PWINDOWPOS winpos
= (PWINDOWPOS
)lparam
;
622 if (!winpos
) return 0;
623 lRes
= co_WinPosSetWindowPos( pWnd
,
624 winpos
->hwndInsertAfter
,
630 ExFreePoolWithTag(winpos
, USERTAG_SWP
);
633 case WM_ASYNC_SETACTIVEWINDOW
:
635 PWND Window
= (PWND
)wparam
;
636 if (wparam
) UserRefObjectCo(Window
, &Ref
);
637 lRes
= (LRESULT
)co_IntSetActiveWindow(Window
,(BOOL
)lparam
,TRUE
,TRUE
);
638 if (wparam
) UserDerefObjectCo(Window
);
646 IntDispatchMessage(PMSG pMsg
)
648 LARGE_INTEGER TickCount
;
654 BOOL DoCallBack
= TRUE
;
658 Window
= UserGetWindowObject(pMsg
->hwnd
);
659 if (!Window
) return 0;
662 pti
= PsGetCurrentThreadWin32Thread();
664 if ( Window
&& Window
->head
.pti
!= pti
)
666 EngSetLastError( ERROR_MESSAGE_SYNC_ONLY
);
670 if (((pMsg
->message
== WM_SYSTIMER
) ||
671 (pMsg
->message
== WM_TIMER
)) &&
674 if (pMsg
->message
== WM_TIMER
)
676 if (ValidateTimerCallback(pti
,pMsg
->lParam
))
678 KeQueryTickCount(&TickCount
);
679 Time
= MsqCalculateMessageTime(&TickCount
);
680 retval
= co_IntCallWindowProc((WNDPROC
)pMsg
->lParam
,
692 PTIMER pTimer
= FindSystemTimer(pMsg
);
693 if (pTimer
&& pTimer
->pfn
)
695 KeQueryTickCount(&TickCount
);
696 Time
= MsqCalculateMessageTime(&TickCount
);
697 pTimer
->pfn(pMsg
->hwnd
, WM_SYSTIMER
, (UINT
)pMsg
->wParam
, Time
);
703 if ( !Window
) return 0;
705 if (pMsg
->message
== WM_PAINT
) Window
->state
|= WNDS_PAINTNOTPROCESSED
;
707 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
709 TRACE("Dispatch: Server Side Window Procedure\n");
713 DoCallBack
= !DesktopWindowProc( Window
,
719 case FNID_MESSAGEWND
:
720 DoCallBack
= !UserMessageWindowProc( Window
,
729 /* Since we are doing a callback on the same thread right away, there is
730 no need to copy the lparam to kernel mode and then back to usermode.
731 We just pretend it isn't a pointer */
734 retval
= co_IntCallWindowProc( Window
->lpfnWndProc
,
742 if (pMsg
->message
== WM_PAINT
)
744 Window
->state2
&= ~WNDS2_WMPAINTSENT
;
745 /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
746 hrgn
= IntSysCreateRectRgn( 0, 0, 0, 0 );
747 co_UserGetUpdateRgn( Window
, hrgn
, TRUE
);
748 GreDeleteObject(hrgn
);
755 * Internal version of PeekMessage() doing all the work
760 * Input (hardware) messages and system internal events
761 * Sent messages (again)
766 co_IntPeekMessage( PMSG Msg
,
774 LARGE_INTEGER LargeTickCount
;
779 pti
= PsGetCurrentThreadWin32Thread();
781 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
782 ProcessMask
= HIWORD(RemoveMsg
);
784 /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns
785 all available messages (that is, no range filtering is performed)". */
786 if (!ProcessMask
) ProcessMask
= (QS_ALLPOSTMESSAGE
|QS_ALLINPUT
);
792 KeQueryTickCount(&LargeTickCount
);
793 pti
->timeLast
= LargeTickCount
.u
.LowPart
;
794 pti
->pcti
->tickLastMsgChecked
= LargeTickCount
.u
.LowPart
;
796 /* Dispatch sent messages here. */
797 while ( co_MsqDispatchOneSentMessage(pti
) )
799 /* if some PM_QS* flags were specified, only handle sent messages from now on */
800 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
; // wine does this; ProcessMask = QS_SENDMESSAGE;
802 if (Hit
) return FALSE
;
804 /* Clear changed bits so we can wait on them if we don't find a message */
805 if (ProcessMask
& QS_POSTMESSAGE
)
807 pti
->pcti
->fsChangeBits
&= ~(QS_POSTMESSAGE
| QS_HOTKEY
| QS_TIMER
);
808 if (MsgFilterMin
== 0 && MsgFilterMax
== 0) // Wine hack does this; ~0U)
810 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
814 if (ProcessMask
& QS_INPUT
)
816 pti
->pcti
->fsChangeBits
&= ~QS_INPUT
;
819 /* Now check for normal messages. */
820 if (( (ProcessMask
& QS_POSTMESSAGE
) ||
821 (ProcessMask
& QS_HOTKEY
) ) &&
833 /* Now look for a quit message. */
836 /* According to the PSDK, WM_QUIT messages are always returned, regardless
837 of the filter specified */
839 Msg
->message
= WM_QUIT
;
840 Msg
->wParam
= pti
->exitCode
;
844 pti
->QuitPosted
= FALSE
;
845 ClearMsgBitsMask(pti
, QS_POSTMESSAGE
);
846 pti
->pcti
->fsWakeBits
&= ~QS_ALLPOSTMESSAGE
;
847 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
852 /* Check for hardware events. */
853 if ((ProcessMask
& QS_MOUSE
) &&
854 co_MsqPeekMouseMove( pti
,
864 if ((ProcessMask
& QS_INPUT
) &&
865 co_MsqPeekHardwareMessage( pti
,
876 /* Check for sent messages again. */
877 while ( co_MsqDispatchOneSentMessage(pti
) )
879 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
;
881 if (Hit
) return FALSE
;
883 /* Check for paint messages. */
884 if ((ProcessMask
& QS_PAINT
) &&
886 IntGetPaintMessage( Window
,
896 /* This is correct, check for the current threads timers waiting to be
897 posted to this threads message queue. If any we loop again.
899 if ((ProcessMask
& QS_TIMER
) &&
900 PostTimerMessages(Window
))
913 co_IntWaitMessage( PWND Window
,
918 NTSTATUS Status
= STATUS_SUCCESS
;
921 pti
= PsGetCurrentThreadWin32Thread();
925 if ( co_IntPeekMessage( &Msg
, // Dont reenter!
929 MAKELONG( PM_NOREMOVE
, GetWakeMask( MsgFilterMin
, MsgFilterMax
)),
930 TRUE
) ) // act like GetMessage.
935 /* Nothing found. Wait for new messages. */
936 Status
= co_MsqWaitForNewMessages( pti
,
940 if (!NT_SUCCESS(Status
))
942 SetLastNtError(Status
);
943 ERR("Exit co_IntWaitMessage on error!\n");
946 if (Status
== STATUS_USER_APC
|| Status
== STATUS_TIMEOUT
)
957 co_IntGetPeekMessage( PMSG pMsg
,
966 BOOL Present
= FALSE
;
969 if ( hWnd
== HWND_TOPMOST
|| hWnd
== HWND_BROADCAST
)
973 if (hWnd
&& hWnd
!= HWND_BOTTOM
)
975 if (!(Window
= UserGetWindowObject(hWnd
)))
988 if (MsgFilterMax
< MsgFilterMin
)
996 RemoveMsg
|= ((GetWakeMask( MsgFilterMin
, MsgFilterMax
))<< 16);
999 pti
= PsGetCurrentThreadWin32Thread();
1000 pti
->pClientInfo
->cSpins
++; // Bump up the spin count.
1004 Present
= co_IntPeekMessage( pMsg
,
1012 /* GetMessage or PostMessage must never get messages that contain pointers */
1013 ASSERT(FindMsgMemory(pMsg
->message
) == NULL
);
1015 if (pMsg
->message
!= WM_PAINT
&& pMsg
->message
!= WM_QUIT
)
1017 pti
->timeLast
= pMsg
->time
;
1018 pti
->ptLast
= pMsg
->pt
;
1021 // The WH_GETMESSAGE hook enables an application to monitor messages about to
1022 // be returned by the GetMessage or PeekMessage function.
1024 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)pMsg
);
1031 Status
= co_MsqWaitForNewMessages( pti
,
1035 if ( !NT_SUCCESS(Status
) ||
1036 Status
== STATUS_USER_APC
||
1037 Status
== STATUS_TIMEOUT
)
1045 if (!(RemoveMsg
& PM_NOYIELD
))
1048 // Yield this thread!
1051 UserEnterExclusive();
1052 // Fall through to exit.
1058 while( bGMSG
&& !Present
);
1060 // Been spinning, time to swap vinyl...
1061 if (pti
->pClientInfo
->cSpins
>= 100)
1063 // Clear the spin cycle to fix the mix.
1064 pti
->pClientInfo
->cSpins
= 0;
1065 //if (!(pti->TIF_flags & TIF_SPINNING)) // FIXME: Need to swap vinyl...
1071 UserPostThreadMessage( PTHREADINFO pti
,
1077 LARGE_INTEGER LargeTickCount
;
1079 if (is_pointer_message(Msg
))
1081 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1084 Message
.hwnd
= NULL
;
1085 Message
.message
= Msg
;
1086 Message
.wParam
= wParam
;
1087 Message
.lParam
= lParam
;
1088 Message
.pt
= gpsi
->ptCursor
;
1090 KeQueryTickCount(&LargeTickCount
);
1091 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1092 MsqPostMessage(pti
, &Message
, FALSE
, QS_POSTMESSAGE
, 0);
1096 PTHREADINFO FASTCALL
1097 IntSendTo(PWND Window
, PTHREADINFO ptiCur
, UINT Msg
)
1102 Window
->head
.pti
->MessageQueue
== ptiCur
->MessageQueue
)
1107 return Window
? Window
->head
.pti
: NULL
;
1111 UserPostMessage( HWND Wnd
,
1117 MSG Message
, KernelModeMsg
;
1118 LARGE_INTEGER LargeTickCount
;
1121 Message
.message
= Msg
;
1122 Message
.wParam
= wParam
;
1123 Message
.lParam
= lParam
;
1124 Message
.pt
= gpsi
->ptCursor
;
1125 KeQueryTickCount(&LargeTickCount
);
1126 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1128 if (is_pointer_message(Message
.message
))
1130 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1134 if( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1137 PMSGMEMORY MsgMemoryEntry
;
1139 MsgMemoryEntry
= FindMsgMemory(Message
.message
);
1141 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &Message
, MsgMemoryEntry
);
1142 if (! NT_SUCCESS(Status
))
1144 EngSetLastError(ERROR_INVALID_PARAMETER
);
1147 co_IntSendMessageNoWait(KernelModeMsg
.hwnd
,
1148 KernelModeMsg
.message
,
1149 KernelModeMsg
.wParam
,
1150 KernelModeMsg
.lParam
);
1152 if (MsgMemoryEntry
&& KernelModeMsg
.lParam
)
1153 ExFreePool((PVOID
) KernelModeMsg
.lParam
);
1160 pti
= PsGetCurrentThreadWin32Thread();
1161 return UserPostThreadMessage( pti
,
1166 if (Wnd
== HWND_BROADCAST
)
1172 DesktopWindow
= UserGetDesktopWindow();
1173 List
= IntWinListChildren(DesktopWindow
);
1177 UserPostMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1178 for (i
= 0; List
[i
]; i
++)
1180 PWND pwnd
= UserGetWindowObject(List
[i
]);
1181 if (!pwnd
) continue;
1183 if ( pwnd
->fnid
== FNID_MENU
|| // Also need pwnd->pcls->atomClassName == gaOleMainThreadWndClass
1184 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1187 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1189 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1196 Window
= UserGetWindowObject(Wnd
);
1199 ERR("UserPostMessage: Invalid handle 0x%p!\n",Wnd
);
1203 pti
= Window
->head
.pti
;
1204 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1206 ERR("Attempted to post message to window %p when the thread is in cleanup!\n", Wnd
);
1210 if ( Window
->state
& WNDS_DESTROYED
)
1212 ERR("Attempted to post message to window %p that is being destroyed!\n", Wnd
);
1213 /* FIXME: Last error code? */
1219 MsqPostQuitMessage(pti
, wParam
);
1223 MsqPostMessage(pti
, &Message
, FALSE
, QS_POSTMESSAGE
, 0);
1230 co_IntSendMessage( HWND hWnd
,
1235 ULONG_PTR Result
= 0;
1236 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1238 return (LRESULT
)Result
;
1243 static LRESULT FASTCALL
1244 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1250 ULONG_PTR
*uResult
)
1254 PMSGMEMORY MsgMemoryEntry
;
1255 INT lParamBufferSize
;
1256 LPARAM lParamPacked
;
1257 PTHREADINFO Win32Thread
, ptiSendTo
= NULL
;
1258 ULONG_PTR Hi
, Lo
, Result
= 0;
1259 DECLARE_RETURN(LRESULT
);
1260 USER_REFERENCE_ENTRY Ref
;
1261 BOOL DoCallBack
= TRUE
;
1263 if (!(Window
= UserGetWindowObject(hWnd
)))
1265 TRACE("SendMessageTimeoutSingle: Invalid handle 0x%p!\n",hWnd
);
1269 UserRefObjectCo(Window
, &Ref
);
1271 Win32Thread
= PsGetCurrentThreadWin32Thread();
1273 ptiSendTo
= IntSendTo(Window
, Win32Thread
, Msg
);
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
);
1310 case FNID_MESSAGEWND
:
1311 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1316 if (uResult
) *uResult
= Result
;
1320 /* See if this message type is present in the table */
1321 MsgMemoryEntry
= FindMsgMemory(Msg
);
1322 if (NULL
== MsgMemoryEntry
)
1324 lParamBufferSize
= -1;
1328 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1329 // If zero, do not allow callback on client side to allocate a buffer!!!!! See CORE-7695.
1330 if (!lParamBufferSize
) lParamBufferSize
= -1;
1333 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1335 ERR("Failed to pack message parameters\n");
1339 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1351 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1353 ERR("Failed to unpack message parameters\n");
1357 // Only happens when calling the client!
1358 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1363 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(ptiSendTo
))
1365 // FIXME: Set window hung and add to a list.
1366 /* FIXME: Set a LastError? */
1370 if (Window
->state
& WNDS_DESTROYED
)
1372 /* FIXME: Last error? */
1373 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1379 Status
= co_MsqSendMessage( ptiSendTo
,
1385 (uFlags
& SMTO_BLOCK
),
1389 while ((STATUS_TIMEOUT
== Status
) &&
1390 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1391 !MsqIsHung(ptiSendTo
)); // FIXME: Set window hung and add to a list.
1393 if (STATUS_TIMEOUT
== Status
)
1397 * Microsoft Windows 2000: If GetLastError returns zero, then the function
1399 * XP+ : If the function fails or times out, the return value is zero.
1400 * To get extended error information, call GetLastError. If GetLastError
1401 * returns ERROR_TIMEOUT, then the function timed out.
1403 EngSetLastError(ERROR_TIMEOUT
);
1406 else if (!NT_SUCCESS(Status
))
1408 SetLastNtError(Status
);
1415 if (Window
) UserDerefObjectCo(Window
);
1420 co_IntSendMessageTimeout( HWND hWnd
,
1426 ULONG_PTR
*uResult
)
1432 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1434 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1437 DesktopWindow
= UserGetDesktopWindow();
1438 if (NULL
== DesktopWindow
)
1440 EngSetLastError(ERROR_INTERNAL_ERROR
);
1444 if (hWnd
!= HWND_TOPMOST
)
1446 /* Send message to the desktop window too! */
1447 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1450 Children
= IntWinListChildren(DesktopWindow
);
1451 if (NULL
== Children
)
1456 for (Child
= Children
; NULL
!= *Child
; Child
++)
1458 if (hWnd
== HWND_TOPMOST
)
1460 DesktopWindow
= UserGetWindowObject(*Child
);
1461 if (DesktopWindow
&& DesktopWindow
->ExStyle
& WS_EX_TOPMOST
)
1463 ERR("HWND_TOPMOST Found\n");
1464 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1469 PWND pwnd
= UserGetWindowObject(*Child
);
1470 if (!pwnd
) continue;
1472 if ( pwnd
->fnid
== FNID_MENU
||
1473 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1476 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1480 ExFreePool(Children
);
1482 return (LRESULT
) TRUE
;
1486 co_IntSendMessageNoWait(HWND hWnd
,
1491 ULONG_PTR Result
= 0;
1492 return co_IntSendMessageWithCallBack( hWnd
,
1501 If you send a message in the range below WM_USER to the asynchronous message
1502 functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its
1503 message parameters cannot include pointers. Otherwise, the operation will fail.
1504 The functions will return before the receiving thread has had a chance to
1505 process the message and the sender will free the memory before it is used.
1508 co_IntSendMessageWithCallBack( HWND hWnd
,
1512 SENDASYNCPROC CompletionCallback
,
1513 ULONG_PTR CompletionCallbackContext
,
1518 PMSGMEMORY MsgMemoryEntry
;
1519 INT lParamBufferSize
;
1520 LPARAM lParamPacked
;
1521 PTHREADINFO Win32Thread
, ptiSendTo
= NULL
;
1522 DECLARE_RETURN(LRESULT
);
1523 USER_REFERENCE_ENTRY Ref
;
1524 PUSER_SENT_MESSAGE Message
;
1525 BOOL DoCallBack
= TRUE
;
1527 if (!(Window
= UserGetWindowObject(hWnd
)))
1529 TRACE("SendMessageWithCallBack: Invalid handle 0x%p!\n",hWnd
);
1533 UserRefObjectCo(Window
, &Ref
);
1535 if (Window
->state
& WNDS_DESTROYED
)
1537 /* FIXME: last error? */
1538 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1542 Win32Thread
= PsGetCurrentThreadWin32Thread();
1544 if (Win32Thread
== NULL
||
1545 Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1550 ptiSendTo
= IntSendTo(Window
, Win32Thread
, Msg
);
1552 if (Msg
& 0x80000000 &&
1555 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
) RETURN( FALSE
);
1557 TRACE("SMWCB: Internal Message!\n");
1558 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1559 if (uResult
) *uResult
= Result
;
1563 /* See if this message type is present in the table */
1564 MsgMemoryEntry
= FindMsgMemory(Msg
);
1565 if (NULL
== MsgMemoryEntry
)
1567 lParamBufferSize
= -1;
1571 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1572 if (!lParamBufferSize
) lParamBufferSize
= -1;
1575 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, !!ptiSendTo
)))
1577 ERR("Failed to pack message parameters\n");
1581 /* If it can be sent now, then send it. */
1584 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1586 UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
);
1587 /* Never send messages to exiting threads */
1591 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1593 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1595 TRACE("SMWCB: Server Side Window Procedure\n");
1596 switch(Window
->fnid
)
1599 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParamPacked
, (LRESULT
*)&Result
);
1601 case FNID_MESSAGEWND
:
1602 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1608 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1620 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1622 if (CompletionCallback
)
1624 co_IntCallSentMessageCallback(CompletionCallback
,
1627 CompletionCallbackContext
,
1634 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1636 ERR("Failed to unpack message parameters\n");
1641 if(!(Message
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
1643 ERR("MsqSendMessage(): Not enough memory to allocate a message");
1647 Message
->Msg
.hwnd
= hWnd
;
1648 Message
->Msg
.message
= Msg
;
1649 Message
->Msg
.wParam
= wParam
;
1650 Message
->Msg
.lParam
= lParamPacked
;
1651 Message
->CompletionEvent
= NULL
;
1652 Message
->Result
= 0;
1653 Message
->lResult
= 0;
1654 Message
->QS_Flags
= 0;
1655 Message
->ptiReceiver
= ptiSendTo
;
1656 Message
->ptiSender
= NULL
; // mjmartin, you are right! This is null.
1657 Message
->ptiCallBackSender
= Win32Thread
;
1658 Message
->DispatchingListEntry
.Flink
= NULL
;
1659 Message
->CompletionCallback
= CompletionCallback
;
1660 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1661 Message
->HookMessage
= MSQ_NORMAL
;
1662 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1663 Message
->QS_Flags
= QS_SENDMESSAGE
;
1665 if (Msg
& 0x80000000) // Higher priority event message!
1666 InsertHeadList(&ptiSendTo
->SentMessagesListHead
, &Message
->ListEntry
);
1668 InsertTailList(&ptiSendTo
->SentMessagesListHead
, &Message
->ListEntry
);
1669 MsqWakeQueue(ptiSendTo
, QS_SENDMESSAGE
, TRUE
);
1674 if (Window
) UserDerefObjectCo(Window
);
1680 This HACK function posts a message if the destination's message queue belongs to
1681 another thread, otherwise it sends the message. It does not support broadcast
1685 co_IntPostOrSendMessage( HWND hWnd
,
1694 if ( hWnd
== HWND_BROADCAST
)
1699 if(!(Window
= UserGetWindowObject(hWnd
)))
1701 TRACE("PostOrSendMessage: Invalid handle 0x%p!\n",hWnd
);
1705 pti
= PsGetCurrentThreadWin32Thread();
1707 if ( IntSendTo(Window
, pti
, Msg
) &&
1708 FindMsgMemory(Msg
) == 0 )
1710 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1714 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1720 return (LRESULT
)Result
;
1723 static LRESULT FASTCALL
1724 co_IntDoSendMessage( HWND hWnd
,
1730 LRESULT Result
= TRUE
;
1733 MSG UserModeMsg
, KernelModeMsg
;
1734 PMSGMEMORY MsgMemoryEntry
;
1735 PTHREADINFO ptiSendTo
;
1737 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1739 Window
= UserGetWindowObject(hWnd
);
1746 /* Check for an exiting window. */
1747 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1749 ERR("co_IntDoSendMessage Window Exiting!\n");
1752 /* See if the current thread can handle this message */
1753 ptiSendTo
= IntSendTo(Window
, gptiCurrent
, Msg
);
1755 // If broadcasting or sending to another thread, save the users data.
1756 if (!Window
|| ptiSendTo
)
1758 UserModeMsg
.hwnd
= hWnd
;
1759 UserModeMsg
.message
= Msg
;
1760 UserModeMsg
.wParam
= wParam
;
1761 UserModeMsg
.lParam
= lParam
;
1762 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1763 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1764 if (!NT_SUCCESS(Status
))
1766 EngSetLastError(ERROR_INVALID_PARAMETER
);
1767 return (dsm
? 0 : -1);
1772 KernelModeMsg
.hwnd
= hWnd
;
1773 KernelModeMsg
.message
= Msg
;
1774 KernelModeMsg
.wParam
= wParam
;
1775 KernelModeMsg
.lParam
= lParam
;
1780 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1781 KernelModeMsg
.message
,
1782 KernelModeMsg
.wParam
,
1783 KernelModeMsg
.lParam
);
1787 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1788 KernelModeMsg
.message
,
1789 KernelModeMsg
.wParam
,
1790 KernelModeMsg
.lParam
,
1796 if (!Window
|| ptiSendTo
)
1798 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1799 if (!NT_SUCCESS(Status
))
1801 EngSetLastError(ERROR_INVALID_PARAMETER
);
1802 return(dsm
? 0 : -1);
1806 return (LRESULT
)Result
;
1810 UserSendNotifyMessage( HWND hWnd
,
1817 if (is_pointer_message(Msg
))
1819 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1823 // Basicly the same as IntPostOrSendMessage
1824 if (hWnd
== HWND_BROADCAST
) // Handle Broadcast
1830 DesktopWindow
= UserGetDesktopWindow();
1831 List
= IntWinListChildren(DesktopWindow
);
1835 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1836 for (i
= 0; List
[i
]; i
++)
1838 PWND pwnd
= UserGetWindowObject(List
[i
]);
1839 if (!pwnd
) continue;
1841 if ( pwnd
->fnid
== FNID_MENU
||
1842 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1845 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1852 Ret
= co_IntSendMessageNoWait( hWnd
, Msg
, wParam
, lParam
);
1859 IntGetQueueStatus(DWORD Changes
)
1864 pti
= PsGetCurrentThreadWin32Thread();
1866 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1868 /* High word, types of messages currently in the queue.
1869 Low word, types of messages that have been added to the queue and that
1870 are still in the queue
1872 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1874 pti
->pcti
->fsChangeBits
&= ~Changes
;
1880 IntInitMessagePumpHook()
1882 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1886 pti
->pcti
->dwcPumpHook
++;
1893 IntUninitMessagePumpHook()
1895 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1899 if (pti
->pcti
->dwcPumpHook
<= 0)
1903 pti
->pcti
->dwcPumpHook
--;
1909 /** Functions ******************************************************************/
1915 POINT pt
) // Just like the User call.
1919 ULONG wDragWidth
, wDragHeight
;
1920 DECLARE_RETURN(BOOL
);
1922 TRACE("Enter NtUserDragDetect(%p)\n", hWnd
);
1923 UserEnterExclusive();
1925 wDragWidth
= UserGetSystemMetrics(SM_CXDRAG
);
1926 wDragHeight
= UserGetSystemMetrics(SM_CYDRAG
);
1928 rect
.left
= pt
.x
- wDragWidth
;
1929 rect
.right
= pt
.x
+ wDragWidth
;
1931 rect
.top
= pt
.y
- wDragHeight
;
1932 rect
.bottom
= pt
.y
+ wDragHeight
;
1934 co_UserSetCapture(hWnd
);
1938 while (co_IntGetPeekMessage( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, FALSE
) ||
1939 co_IntGetPeekMessage( &msg
, 0, WM_QUEUESYNC
, WM_QUEUESYNC
, PM_REMOVE
, FALSE
) ||
1940 co_IntGetPeekMessage( &msg
, 0, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
, FALSE
) )
1942 if ( msg
.message
== WM_LBUTTONUP
)
1944 co_UserSetCapture(NULL
);
1947 if ( msg
.message
== WM_MOUSEMOVE
)
1950 tmp
.x
= (short)LOWORD(msg
.lParam
);
1951 tmp
.y
= (short)HIWORD(msg
.lParam
);
1952 if( !RECTL_bPointInRect( &rect
, tmp
.x
, tmp
.y
) )
1954 co_UserSetCapture(NULL
);
1958 if ( msg
.message
== WM_KEYDOWN
)
1960 if ( msg
.wParam
== VK_ESCAPE
)
1962 co_UserSetCapture(NULL
);
1966 if ( msg
.message
== WM_QUEUESYNC
)
1968 co_HOOK_CallHooks( WH_CBT
, HCBT_QS
, 0, 0 );
1971 co_IntWaitMessage(NULL
, 0, 0);
1976 TRACE("Leave NtUserDragDetect, ret=%i\n",_ret_
);
1982 NtUserPostMessage(HWND hWnd
,
1989 UserEnterExclusive();
1991 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1999 NtUserPostThreadMessage(DWORD idThread
,
2006 PTHREADINFO pThread
;
2009 UserEnterExclusive();
2011 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
2013 if ( Status
== STATUS_SUCCESS
)
2015 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
2017 !pThread
->MessageQueue
||
2018 (pThread
->TIF_flags
& TIF_INCLEANUP
))
2020 ObDereferenceObject( peThread
);
2023 ret
= UserPostThreadMessage( pThread
, Msg
, wParam
, lParam
);
2024 ObDereferenceObject( peThread
);
2028 SetLastNtError( Status
);
2036 NtUserWaitMessage(VOID
)
2040 UserEnterExclusive();
2041 TRACE("NtUserWaitMessage Enter\n");
2042 ret
= co_IntWaitMessage(NULL
, 0, 0);
2043 TRACE("NtUserWaitMessage Leave\n");
2050 NtUserGetMessage(PMSG pMsg
,
2058 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
2060 EngSetLastError(ERROR_INVALID_PARAMETER
);
2064 UserEnterExclusive();
2066 RtlZeroMemory(&Msg
, sizeof(MSG
));
2068 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
2076 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2077 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2079 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2081 SetLastNtError(_SEH2_GetExceptionCode());
2088 Ret
= Ret
? (WM_QUIT
!= pMsg
->message
) : FALSE
;
2094 NtUserPeekMessage( PMSG pMsg
,
2103 if ( RemoveMsg
& PM_BADMSGFLAGS
)
2105 EngSetLastError(ERROR_INVALID_FLAGS
);
2109 UserEnterExclusive();
2111 RtlZeroMemory(&Msg
, sizeof(MSG
));
2113 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
2121 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2122 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2124 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2126 SetLastNtError(_SEH2_GetExceptionCode());
2136 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
2143 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
2144 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
2146 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2148 _SEH2_YIELD(return FALSE
);
2152 UserEnterExclusive();
2154 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
2160 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
2167 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
2168 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
2170 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2180 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
2187 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
2188 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
2190 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2192 SetLastNtError(_SEH2_GetExceptionCode());
2193 _SEH2_YIELD(return FALSE
);
2197 UserEnterExclusive();
2199 Res
= IntDispatchMessage(&SafeMsg
);
2206 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
2214 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
2215 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
2217 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2219 SetLastNtError(_SEH2_GetExceptionCode());
2220 _SEH2_YIELD(return FALSE
);
2224 UserEnterExclusive();
2225 pWnd
= UserGetWindowObject(SafeMsg
.hwnd
);
2226 if (pWnd
) // Must have a window!
2228 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
2232 TRACE("No Window for Translate. hwnd 0x%p Msg %u\n", SafeMsg
.hwnd
, SafeMsg
.message
);
2240 LRESULT APIENTRY
ScrollBarWndProc(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
);
2243 NtUserMessageCall( HWND hWnd
,
2247 ULONG_PTR ResultInfo
,
2248 DWORD dwType
, // fnID?
2251 LRESULT lResult
= 0;
2254 USER_REFERENCE_ENTRY Ref
;
2256 UserEnterExclusive();
2260 case FNID_SCROLLBAR
:
2262 lResult
= ScrollBarWndProc(hWnd
, Msg
, wParam
, lParam
);
2267 Window
= UserGetWindowObject(hWnd
);
2270 //ERR("FNID_DESKTOP IN\n");
2271 Ret
= DesktopWindowProc(Window
, Msg
, wParam
, lParam
, &lResult
);
2272 //ERR("FNID_DESKTOP OUT\n");
2277 case FNID_MESSAGEWND
:
2279 Window
= UserGetWindowObject(hWnd
);
2282 Ret
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,&lResult
);
2286 case FNID_DEFWINDOWPROC
:
2287 /* Validate input */
2290 Window
= UserGetWindowObject(hWnd
);
2296 UserRefObjectCo(Window
, &Ref
);
2298 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2301 UserDerefObjectCo(Window
);
2303 case FNID_SENDNOTIFYMESSAGE
:
2304 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2306 case FNID_BROADCASTSYSTEMMESSAGE
:
2308 BROADCASTPARM parm
, *retparam
;
2309 DWORD_PTR RetVal
= 0;
2315 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2316 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2318 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2327 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2328 parm
.recipients
== BSM_ALLCOMPONENTS
)
2330 PLIST_ENTRY DesktopEntry
;
2332 HWND
*List
, hwndDenied
= NULL
;
2334 PWND pwnd
, pwndDesk
;
2338 for (DesktopEntry
= InputWindowStation
->DesktopListHead
.Flink
;
2339 DesktopEntry
!= &InputWindowStation
->DesktopListHead
;
2340 DesktopEntry
= DesktopEntry
->Flink
)
2342 rpdesk
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
2343 pwndDesk
= rpdesk
->pDeskInfo
->spwnd
;
2344 List
= IntWinListChildren(pwndDesk
);
2346 if (parm
.flags
& BSF_QUERY
)
2350 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2352 fuFlags
= SMTO_ABORTIFHUNG
;
2354 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2356 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2360 fuFlags
= SMTO_NORMAL
;
2362 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2370 for (i
= 0; List
[i
]; i
++)
2372 pwnd
= UserGetWindowObject(List
[i
]);
2373 if (!pwnd
) continue;
2375 if ( pwnd
->fnid
== FNID_MENU
||
2376 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2379 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2381 if ( pwnd
->head
.pti
== gptiCurrent
)
2384 co_IntSendMessageTimeout( List
[i
],
2392 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2394 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2397 if (RetVal
== BROADCAST_QUERY_DENY
)
2399 hwndDenied
= List
[i
];
2400 hDesk
= UserHMGetHandle(pwndDesk
);
2404 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2407 retparam
= (PBROADCASTPARM
) ResultInfo
;
2408 retparam
->hDesk
= hDesk
;
2409 retparam
->hWnd
= hwndDenied
;
2411 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2416 if (!Ret
) break; // Have a hit! Let everyone know!
2419 else if (parm
.flags
& BSF_POSTMESSAGE
)
2423 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2425 for (i
= 0; List
[i
]; i
++)
2427 pwnd
= UserGetWindowObject(List
[i
]);
2428 if (!pwnd
) continue;
2430 if ( pwnd
->fnid
== FNID_MENU
||
2431 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2434 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2436 if ( pwnd
->head
.pti
== gptiCurrent
)
2439 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2441 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2449 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2451 for (i
= 0; List
[i
]; i
++)
2453 pwnd
= UserGetWindowObject(List
[i
]);
2454 if (!pwnd
) continue;
2456 if ( pwnd
->fnid
== FNID_MENU
||
2457 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2460 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2462 if ( pwnd
->head
.pti
== gptiCurrent
)
2465 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2467 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2473 else if (parm
.recipients
& BSM_APPLICATIONS
)
2475 HWND
*List
, hwndDenied
= NULL
;
2477 PWND pwnd
, pwndDesk
;
2481 pwndDesk
= UserGetDesktopWindow();
2482 List
= IntWinListChildren(pwndDesk
);
2484 if (parm
.flags
& BSF_QUERY
)
2488 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2490 fuFlags
= SMTO_ABORTIFHUNG
;
2492 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2494 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2498 fuFlags
= SMTO_NORMAL
;
2500 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2508 for (i
= 0; List
[i
]; i
++)
2510 pwnd
= UserGetWindowObject(List
[i
]);
2511 if (!pwnd
) continue;
2513 if ( pwnd
->fnid
== FNID_MENU
||
2514 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2517 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2519 if ( pwnd
->head
.pti
== gptiCurrent
)
2522 co_IntSendMessageTimeout( List
[i
],
2530 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2532 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2535 if (RetVal
== BROADCAST_QUERY_DENY
)
2537 hwndDenied
= List
[i
];
2538 hDesk
= UserHMGetHandle(pwndDesk
);
2542 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2545 retparam
= (PBROADCASTPARM
) ResultInfo
;
2546 retparam
->hDesk
= hDesk
;
2547 retparam
->hWnd
= hwndDenied
;
2549 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2556 else if (parm
.flags
& BSF_POSTMESSAGE
)
2560 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2562 for (i
= 0; List
[i
]; i
++)
2564 pwnd
= UserGetWindowObject(List
[i
]);
2565 if (!pwnd
) continue;
2567 if ( pwnd
->fnid
== FNID_MENU
||
2568 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2571 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2573 if ( pwnd
->head
.pti
== gptiCurrent
)
2576 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2578 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2586 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2588 for (i
= 0; List
[i
]; i
++)
2590 pwnd
= UserGetWindowObject(List
[i
]);
2591 if (!pwnd
) continue;
2593 if ( pwnd
->fnid
== FNID_MENU
||
2594 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2597 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2599 if ( pwnd
->head
.pti
== gptiCurrent
)
2602 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2604 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2611 case FNID_SENDMESSAGECALLBACK
:
2613 CALL_BACK_INFO CallBackInfo
;
2618 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2619 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2621 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2627 if (is_pointer_message(Msg
))
2629 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
2633 if (!(Ret
= co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2634 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
)))
2636 ERR("Callback failure!\n");
2640 case FNID_SENDMESSAGE
:
2642 Ret
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2648 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2649 RtlCopyMemory((PVOID
)ResultInfo
, &Ret
, sizeof(ULONG_PTR
));
2651 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2660 case FNID_SENDMESSAGEFF
:
2661 case FNID_SENDMESSAGEWTOOPTION
:
2663 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2668 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2669 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2671 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2678 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, &dsm
);
2684 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2685 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2687 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2696 // CallNextHook bypass.
2697 case FNID_CALLWNDPROC
:
2698 case FNID_CALLWNDPROCRET
:
2701 PCLIENTINFO ClientInfo
;
2702 PHOOK NextObj
, Hook
;
2704 pti
= GetW32ThreadInfo();
2706 Hook
= pti
->sphkCurrent
;
2710 NextObj
= Hook
->phkNext
;
2711 ClientInfo
= pti
->pClientInfo
;
2714 ClientInfo
->phkCurrent
= NextObj
;
2716 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2722 if (!ClientInfo
|| !NextObj
) break;
2724 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2726 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2731 CWP
.wParam
= wParam
;
2732 CWP
.lParam
= lParam
;
2733 TRACE("WH_CALLWNDPROC: Hook %p NextHook %p\n", Hook
, NextObj
);
2735 lResult
= co_IntCallHookProc( Hook
->HookId
,
2737 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2750 CWPR
.wParam
= wParam
;
2751 CWPR
.lParam
= lParam
;
2752 CWPR
.lResult
= ClientInfo
->dwHookData
;
2754 lResult
= co_IntCallHookProc( Hook
->HookId
,
2756 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2770 case FNID_DEFWINDOWPROC
:
2771 case FNID_CALLWNDPROC
:
2772 case FNID_CALLWNDPROCRET
:
2773 case FNID_SCROLLBAR
:
2779 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2780 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2782 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2798 #define INFINITE 0xFFFFFFFF
2799 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2803 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2804 IN DWORD dwMilliseconds
,
2808 PPROCESSINFO W32Process
;
2812 LARGE_INTEGER Timeout
;
2814 UserEnterExclusive();
2816 Status
= ObReferenceObjectByHandle(hProcess
,
2817 PROCESS_QUERY_INFORMATION
,
2823 if (!NT_SUCCESS(Status
))
2826 SetLastNtError(Status
);
2830 pti
= PsGetCurrentThreadWin32Thread();
2832 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2834 if ( PsGetProcessExitProcessCalled(Process
) ||
2836 pti
->ppi
== W32Process
)
2838 ObDereferenceObject(Process
);
2840 EngSetLastError(ERROR_INVALID_PARAMETER
);
2844 Handles
[0] = Process
;
2845 Handles
[1] = W32Process
->InputIdleEvent
;
2846 Handles
[2] = pti
->pEventQueueServer
; // IntMsqSetWakeMask returns hEventQueueClient
2850 ObDereferenceObject(Process
);
2852 return STATUS_SUCCESS
; /* no event to wait on */
2855 if (dwMilliseconds
!= INFINITE
)
2856 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2858 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2859 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2861 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2862 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2865 TRACE("WFII: ppi %p\n", W32Process
);
2866 TRACE("WFII: waiting for %p\n", Handles
[1] );
2870 Status
= KeWaitForMultipleObjects( 3,
2876 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2878 UserEnterExclusive();
2880 if (!NT_SUCCESS(Status
))
2882 SetLastNtError(Status
);
2883 Status
= WAIT_FAILED
;
2895 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2896 ERR("WFII: WAIT 2\n");
2900 case STATUS_TIMEOUT
:
2901 ERR("WFII: timeout\n");
2906 ERR("WFII: finished\n");
2907 Status
= STATUS_SUCCESS
;
2914 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2916 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
2917 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2919 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
2920 ObDereferenceObject(Process
);