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 g_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
= g_MsgMemory
;
144 MsgMemoryEntry
< g_MsgMemory
+ sizeof(g_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 MsgMemoryEntry
= FindMsgMemory(Msg
);
229 if(MsgMemoryEntry
== NULL
) return 0;
230 return MsgMemorySize(MsgMemoryEntry
, 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 (MsgMemoryEntry
->Flags
== MMS_FLAG_READWRITE
)
393 //RtlCopyMemory((PVOID)lParam, (PVOID)lParamPacked, MsgMemoryEntry->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
->ptiOwner
;
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 %p\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 %p\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 %u hWnd %p\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
,
717 case FNID_MESSAGEWND
:
718 DoCallBack
= !UserMessageWindowProc( Window
,
727 /* Since we are doing a callback on the same thread right away, there is
728 no need to copy the lparam to kernel mode and then back to usermode.
729 We just pretend it isn't a pointer */
732 retval
= co_IntCallWindowProc( Window
->lpfnWndProc
,
740 if (pMsg
->message
== WM_PAINT
)
742 Window
->state2
&= ~WNDS2_WMPAINTSENT
;
743 /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
744 hrgn
= IntSysCreateRectRgn( 0, 0, 0, 0 );
745 co_UserGetUpdateRgn( Window
, hrgn
, TRUE
);
746 GreDeleteObject(hrgn
);
753 * Internal version of PeekMessage() doing all the work
756 co_IntPeekMessage( PMSG Msg
,
764 LARGE_INTEGER LargeTickCount
;
769 pti
= PsGetCurrentThreadWin32Thread();
771 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
772 ProcessMask
= HIWORD(RemoveMsg
);
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 pti
->timeLast
= LargeTickCount
.u
.LowPart
;
784 pti
->pcti
->tickLastMsgChecked
= LargeTickCount
.u
.LowPart
;
786 /* Dispatch sent messages here. */
787 while ( co_MsqDispatchOneSentMessage(pti
) )
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
) ) &&
823 /* Now look for a quit message. */
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
= pti
->exitCode
;
834 pti
->QuitPosted
= FALSE
;
835 ClearMsgBitsMask(pti
, 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( pti
,
854 if ((ProcessMask
& QS_INPUT
) &&
855 co_MsqPeekHardwareMessage( pti
,
866 /* Check for sent messages again. */
867 while ( co_MsqDispatchOneSentMessage(pti
) )
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 NTSTATUS Status
= STATUS_SUCCESS
;
911 pti
= PsGetCurrentThreadWin32Thread();
915 if ( co_IntPeekMessage( &Msg
, // Dont reenter!
919 MAKELONG( PM_NOREMOVE
, GetWakeMask( MsgFilterMin
, MsgFilterMax
)),
920 TRUE
) ) // act like GetMessage.
925 /* Nothing found. Wait for new messages. */
926 Status
= co_MsqWaitForNewMessages( pti
,
930 if (!NT_SUCCESS(Status
))
932 SetLastNtError(Status
);
933 ERR("Exit co_IntWaitMessage on error!\n");
936 if (Status
== STATUS_USER_APC
|| Status
== STATUS_TIMEOUT
)
947 co_IntGetPeekMessage( PMSG pMsg
,
956 BOOL Present
= FALSE
;
959 if ( hWnd
== HWND_TOPMOST
|| hWnd
== HWND_BROADCAST
)
963 if (hWnd
&& hWnd
!= HWND_BOTTOM
)
965 if (!(Window
= UserGetWindowObject(hWnd
)))
978 if (MsgFilterMax
< MsgFilterMin
)
986 RemoveMsg
|= ((GetWakeMask( MsgFilterMin
, MsgFilterMax
))<< 16);
989 pti
= PsGetCurrentThreadWin32Thread();
990 pti
->pClientInfo
->cSpins
++; // Bump up the spin count.
994 Present
= co_IntPeekMessage( pMsg
,
1002 /* GetMessage or PostMessage must never get messages that contain pointers */
1003 ASSERT(FindMsgMemory(pMsg
->message
) == NULL
);
1005 if (pMsg
->message
!= WM_PAINT
&& pMsg
->message
!= WM_QUIT
)
1007 pti
->timeLast
= pMsg
->time
;
1008 pti
->ptLast
= pMsg
->pt
;
1011 // The WH_GETMESSAGE hook enables an application to monitor messages about to
1012 // be returned by the GetMessage or PeekMessage function.
1014 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)pMsg
);
1021 Status
= co_MsqWaitForNewMessages( pti
,
1025 if ( !NT_SUCCESS(Status
) ||
1026 Status
== STATUS_USER_APC
||
1027 Status
== STATUS_TIMEOUT
)
1035 if (!(RemoveMsg
& PM_NOYIELD
))
1038 // Yield this thread!
1041 UserEnterExclusive();
1042 // Fall through to exit.
1048 while( bGMSG
&& !Present
);
1050 // Been spinning, time to swap vinyl...
1051 if (pti
->pClientInfo
->cSpins
>= 100)
1053 // Clear the spin cycle to fix the mix.
1054 pti
->pClientInfo
->cSpins
= 0;
1055 //if (!(pti->TIF_flags & TIF_SPINNING)) // FIXME: Need to swap vinyl...
1061 UserPostThreadMessage( PTHREADINFO pti
,
1067 LARGE_INTEGER LargeTickCount
;
1069 if (is_pointer_message(Msg
))
1071 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1074 Message
.hwnd
= NULL
;
1075 Message
.message
= Msg
;
1076 Message
.wParam
= wParam
;
1077 Message
.lParam
= lParam
;
1078 Message
.pt
= gpsi
->ptCursor
;
1080 KeQueryTickCount(&LargeTickCount
);
1081 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1082 MsqPostMessage(pti
, &Message
, FALSE
, QS_POSTMESSAGE
, 0);
1087 UserPostMessage( HWND Wnd
,
1093 MSG Message
, KernelModeMsg
;
1094 LARGE_INTEGER LargeTickCount
;
1097 Message
.message
= Msg
;
1098 Message
.wParam
= wParam
;
1099 Message
.lParam
= lParam
;
1100 Message
.pt
= gpsi
->ptCursor
;
1101 KeQueryTickCount(&LargeTickCount
);
1102 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1104 if (is_pointer_message(Message
.message
))
1106 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1110 if( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1113 PMSGMEMORY MsgMemoryEntry
;
1115 MsgMemoryEntry
= FindMsgMemory(Message
.message
);
1117 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &Message
, MsgMemoryEntry
);
1118 if (! NT_SUCCESS(Status
))
1120 EngSetLastError(ERROR_INVALID_PARAMETER
);
1123 co_IntSendMessageNoWait(KernelModeMsg
.hwnd
,
1124 KernelModeMsg
.message
,
1125 KernelModeMsg
.wParam
,
1126 KernelModeMsg
.lParam
);
1128 if (MsgMemoryEntry
&& KernelModeMsg
.lParam
)
1129 ExFreePool((PVOID
) KernelModeMsg
.lParam
);
1136 pti
= PsGetCurrentThreadWin32Thread();
1137 return UserPostThreadMessage( pti
,
1142 if (Wnd
== HWND_BROADCAST
)
1148 DesktopWindow
= UserGetDesktopWindow();
1149 List
= IntWinListChildren(DesktopWindow
);
1153 UserPostMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1154 for (i
= 0; List
[i
]; i
++)
1156 PWND pwnd
= UserGetWindowObject(List
[i
]);
1157 if (!pwnd
) continue;
1159 if ( pwnd
->fnid
== FNID_MENU
|| // Also need pwnd->pcls->atomClassName == gaOleMainThreadWndClass
1160 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1163 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1165 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1172 Window
= UserGetWindowObject(Wnd
);
1175 ERR("UserPostMessage: Invalid handle 0x%p!\n",Wnd
);
1179 pti
= Window
->head
.pti
;
1180 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1182 ERR("Attempted to post message to window %p when the thread is in cleanup!\n", Wnd
);
1186 if ( Window
->state
& WNDS_DESTROYED
)
1188 ERR("Attempted to post message to window %p that is being destroyed!\n", Wnd
);
1189 /* FIXME: Last error code? */
1195 MsqPostQuitMessage(Window
->head
.pti
, wParam
);
1199 MsqPostMessage(Window
->head
.pti
, &Message
, FALSE
, QS_POSTMESSAGE
, 0);
1206 co_IntSendMessage( HWND hWnd
,
1211 ULONG_PTR Result
= 0;
1212 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1214 return (LRESULT
)Result
;
1219 static LRESULT FASTCALL
1220 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1226 ULONG_PTR
*uResult
)
1230 PMSGMEMORY MsgMemoryEntry
;
1231 INT lParamBufferSize
;
1232 LPARAM lParamPacked
;
1233 PTHREADINFO Win32Thread
;
1234 ULONG_PTR Hi
, Lo
, Result
= 0;
1235 DECLARE_RETURN(LRESULT
);
1236 USER_REFERENCE_ENTRY Ref
;
1237 BOOL DoCallBack
= TRUE
;
1239 if (!(Window
= UserGetWindowObject(hWnd
)))
1241 TRACE("SendMessageTimeoutSingle: Invalid handle 0x%p!\n",hWnd
);
1245 UserRefObjectCo(Window
, &Ref
);
1247 Win32Thread
= PsGetCurrentThreadWin32Thread();
1250 Window
->head
.pti
== Win32Thread
)
1252 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1254 /* Never send messages to exiting threads */
1258 if (Msg
& 0x80000000)
1260 TRACE("SMTS: Internal Message!\n");
1261 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1262 if (uResult
) *uResult
= Result
;
1266 // Only happens when calling the client!
1267 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1269 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1271 TRACE("SMT: Server Side Window Procedure\n");
1272 IoGetStackLimits(&Lo
, &Hi
);
1273 // Handle it here. Safeguard against excessive recursions.
1274 if (((ULONG_PTR
)&uResult
- Lo
) < 4096 )
1276 ERR("Server Callback Exceeded Stack!\n");
1279 /* Return after server side call, IntCallWndProcRet will not be called. */
1280 switch(Window
->fnid
)
1283 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1285 case FNID_MESSAGEWND
:
1286 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1291 if (uResult
) *uResult
= Result
;
1295 /* See if this message type is present in the table */
1296 MsgMemoryEntry
= FindMsgMemory(Msg
);
1297 if (NULL
== MsgMemoryEntry
)
1299 lParamBufferSize
= -1;
1303 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1306 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1308 ERR("Failed to pack message parameters\n");
1312 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1324 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1326 ERR("Failed to unpack message parameters\n");
1330 // Only happens when calling the client!
1331 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1336 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->head
.pti
))
1338 // FIXME: Set window hung and add to a list.
1339 /* FIXME: Set a LastError? */
1343 if (Window
->state
& WNDS_DESTROYED
)
1345 /* FIXME: Last error? */
1346 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1352 Status
= co_MsqSendMessage( Window
->head
.pti
,
1358 (uFlags
& SMTO_BLOCK
),
1362 while ((STATUS_TIMEOUT
== Status
) &&
1363 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1364 !MsqIsHung(Window
->head
.pti
)); // FIXME: Set window hung and add to a list.
1366 if (STATUS_TIMEOUT
== Status
)
1370 * Microsoft Windows 2000: If GetLastError returns zero, then the function
1372 * XP+ : If the function fails or times out, the return value is zero.
1373 * To get extended error information, call GetLastError. If GetLastError
1374 * returns ERROR_TIMEOUT, then the function timed out.
1376 EngSetLastError(ERROR_TIMEOUT
);
1379 else if (!NT_SUCCESS(Status
))
1381 SetLastNtError(Status
);
1388 if (Window
) UserDerefObjectCo(Window
);
1393 co_IntSendMessageTimeout( HWND hWnd
,
1399 ULONG_PTR
*uResult
)
1405 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1407 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1410 DesktopWindow
= UserGetDesktopWindow();
1411 if (NULL
== DesktopWindow
)
1413 EngSetLastError(ERROR_INTERNAL_ERROR
);
1417 if (hWnd
!= HWND_TOPMOST
)
1419 /* Send message to the desktop window too! */
1420 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1423 Children
= IntWinListChildren(DesktopWindow
);
1424 if (NULL
== Children
)
1429 for (Child
= Children
; NULL
!= *Child
; Child
++)
1431 if (hWnd
== HWND_TOPMOST
)
1433 DesktopWindow
= UserGetWindowObject(*Child
);
1434 if (DesktopWindow
&& DesktopWindow
->ExStyle
& WS_EX_TOPMOST
)
1436 ERR("HWND_TOPMOST Found\n");
1437 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1442 PWND pwnd
= UserGetWindowObject(*Child
);
1443 if (!pwnd
) continue;
1445 if ( pwnd
->fnid
== FNID_MENU
||
1446 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1449 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1453 ExFreePool(Children
);
1455 return (LRESULT
) TRUE
;
1459 co_IntSendMessageNoWait(HWND hWnd
,
1464 ULONG_PTR Result
= 0;
1465 return co_IntSendMessageWithCallBack( hWnd
,
1474 If you send a message in the range below WM_USER to the asynchronous message
1475 functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its
1476 message parameters cannot include pointers. Otherwise, the operation will fail.
1477 The functions will return before the receiving thread has had a chance to
1478 process the message and the sender will free the memory before it is used.
1481 co_IntSendMessageWithCallBack( HWND hWnd
,
1485 SENDASYNCPROC CompletionCallback
,
1486 ULONG_PTR CompletionCallbackContext
,
1491 PMSGMEMORY MsgMemoryEntry
;
1492 INT lParamBufferSize
;
1493 LPARAM lParamPacked
;
1494 PTHREADINFO Win32Thread
;
1495 DECLARE_RETURN(LRESULT
);
1496 USER_REFERENCE_ENTRY Ref
;
1497 PUSER_SENT_MESSAGE Message
;
1498 BOOL DoCallBack
= TRUE
;
1500 if (!(Window
= UserGetWindowObject(hWnd
)))
1502 TRACE("SendMessageWithCallBack: Invalid handle 0x%p!\n",hWnd
);
1506 UserRefObjectCo(Window
, &Ref
);
1508 if (Window
->state
& WNDS_DESTROYED
)
1510 /* FIXME: last error? */
1511 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1515 Win32Thread
= PsGetCurrentThreadWin32Thread();
1517 if (Win32Thread
== NULL
||
1518 Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1523 if (Msg
& 0x80000000 &&
1524 Window
->head
.pti
== Win32Thread
)
1526 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
) RETURN( FALSE
);
1528 TRACE("SMWCB: Internal Message!\n");
1529 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1530 if (uResult
) *uResult
= Result
;
1534 /* See if this message type is present in the table */
1535 MsgMemoryEntry
= FindMsgMemory(Msg
);
1536 if (NULL
== MsgMemoryEntry
)
1538 lParamBufferSize
= -1;
1542 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1545 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, Window
->head
.pti
!= Win32Thread
)))
1547 ERR("Failed to pack message parameters\n");
1551 /* If it can be sent now, then send it. */
1552 if (Window
->head
.pti
== Win32Thread
)
1554 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1556 UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
);
1557 /* Never send messages to exiting threads */
1561 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1563 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1565 TRACE("SMWCB: Server Side Window Procedure\n");
1566 switch(Window
->fnid
)
1569 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParamPacked
, (LRESULT
*)&Result
);
1571 case FNID_MESSAGEWND
:
1572 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1578 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1590 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1592 if (CompletionCallback
)
1594 co_IntCallSentMessageCallback(CompletionCallback
,
1597 CompletionCallbackContext
,
1602 if (Window
->head
.pti
== Win32Thread
)
1604 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1606 ERR("Failed to unpack message parameters\n");
1611 if(!(Message
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
1613 ERR("MsqSendMessage(): Not enough memory to allocate a message");
1617 Message
->Msg
.hwnd
= hWnd
;
1618 Message
->Msg
.message
= Msg
;
1619 Message
->Msg
.wParam
= wParam
;
1620 Message
->Msg
.lParam
= lParamPacked
;
1621 Message
->CompletionEvent
= NULL
;
1622 Message
->Result
= 0;
1623 Message
->lResult
= 0;
1624 Message
->QS_Flags
= 0;
1625 Message
->ptiReceiver
= Window
->head
.pti
;
1626 Message
->ptiSender
= NULL
; // mjmartin, you are right! This is null.
1627 Message
->ptiCallBackSender
= Win32Thread
;
1628 Message
->DispatchingListEntry
.Flink
= NULL
;
1629 Message
->CompletionCallback
= CompletionCallback
;
1630 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1631 Message
->HookMessage
= MSQ_NORMAL
;
1632 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1633 Message
->QS_Flags
= QS_SENDMESSAGE
;
1635 if (Msg
& 0x80000000) // Higher priority event message!
1636 InsertHeadList(&Window
->head
.pti
->SentMessagesListHead
, &Message
->ListEntry
);
1638 InsertTailList(&Window
->head
.pti
->SentMessagesListHead
, &Message
->ListEntry
);
1639 MsqWakeQueue(Window
->head
.pti
, QS_SENDMESSAGE
, TRUE
);
1644 if (Window
) UserDerefObjectCo(Window
);
1650 This HACK function posts a message if the destination's message queue belongs to
1651 another thread, otherwise it sends the message. It does not support broadcast
1655 co_IntPostOrSendMessage( HWND hWnd
,
1664 if ( hWnd
== HWND_BROADCAST
)
1669 if(!(Window
= UserGetWindowObject(hWnd
)))
1671 TRACE("PostOrSendMessage: Invalid handle 0x%p!\n",hWnd
);
1675 pti
= PsGetCurrentThreadWin32Thread();
1677 if ( Window
->head
.pti
->MessageQueue
!= pti
->MessageQueue
&&
1678 FindMsgMemory(Msg
) == 0 )
1680 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1684 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1690 return (LRESULT
)Result
;
1694 co_IntDoSendMessage( HWND hWnd
,
1701 LRESULT Result
= TRUE
;
1706 PMSGMEMORY MsgMemoryEntry
;
1708 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1710 Window
= UserGetWindowObject(hWnd
);
1717 /* Check for an exiting window. */
1718 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1720 ERR("co_IntDoSendMessage Window Exiting!\n");
1723 /* See if the current thread can handle the message */
1724 //pti = PsGetCurrentThreadWin32Thread();
1726 UserModeMsg
.hwnd
= hWnd
;
1727 UserModeMsg
.message
= Msg
;
1728 UserModeMsg
.wParam
= wParam
;
1729 UserModeMsg
.lParam
= lParam
;
1730 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1732 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1733 if (! NT_SUCCESS(Status
))
1735 EngSetLastError(ERROR_INVALID_PARAMETER
);
1736 return (dsm
? 0 : -1);
1741 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1742 KernelModeMsg
.message
,
1743 KernelModeMsg
.wParam
,
1744 KernelModeMsg
.lParam
);
1748 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1749 KernelModeMsg
.message
,
1750 KernelModeMsg
.wParam
,
1751 KernelModeMsg
.lParam
,
1757 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1758 if (! NT_SUCCESS(Status
))
1760 EngSetLastError(ERROR_INVALID_PARAMETER
);
1761 return(dsm
? 0 : -1);
1764 return (LRESULT
)Result
;
1768 UserSendNotifyMessage( HWND hWnd
,
1775 if (is_pointer_message(Msg
))
1777 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1781 // Basicly the same as IntPostOrSendMessage
1782 if (hWnd
== HWND_BROADCAST
) // Handle Broadcast
1788 DesktopWindow
= UserGetDesktopWindow();
1789 List
= IntWinListChildren(DesktopWindow
);
1793 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1794 for (i
= 0; List
[i
]; i
++)
1796 PWND pwnd
= UserGetWindowObject(List
[i
]);
1797 if (!pwnd
) continue;
1799 if ( pwnd
->fnid
== FNID_MENU
||
1800 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1803 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1810 Ret
= co_IntSendMessageNoWait( hWnd
, Msg
, wParam
, lParam
);
1817 IntGetQueueStatus(DWORD Changes
)
1822 pti
= PsGetCurrentThreadWin32Thread();
1824 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1826 /* High word, types of messages currently in the queue.
1827 Low word, types of messages that have been added to the queue and that
1828 are still in the queue
1830 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1832 pti
->pcti
->fsChangeBits
&= ~Changes
;
1838 IntInitMessagePumpHook()
1840 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1844 pti
->pcti
->dwcPumpHook
++;
1851 IntUninitMessagePumpHook()
1853 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1857 if (pti
->pcti
->dwcPumpHook
<= 0)
1861 pti
->pcti
->dwcPumpHook
--;
1867 /** Functions ******************************************************************/
1873 POINT pt
) // Just like the User call.
1877 ULONG wDragWidth
, wDragHeight
;
1878 DECLARE_RETURN(BOOL
);
1880 TRACE("Enter NtUserDragDetect(%p)\n", hWnd
);
1881 UserEnterExclusive();
1883 wDragWidth
= UserGetSystemMetrics(SM_CXDRAG
);
1884 wDragHeight
= UserGetSystemMetrics(SM_CYDRAG
);
1886 rect
.left
= pt
.x
- wDragWidth
;
1887 rect
.right
= pt
.x
+ wDragWidth
;
1889 rect
.top
= pt
.y
- wDragHeight
;
1890 rect
.bottom
= pt
.y
+ wDragHeight
;
1892 co_UserSetCapture(hWnd
);
1896 while (co_IntGetPeekMessage( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, FALSE
) ||
1897 co_IntGetPeekMessage( &msg
, 0, WM_QUEUESYNC
, WM_QUEUESYNC
, PM_REMOVE
, FALSE
) ||
1898 co_IntGetPeekMessage( &msg
, 0, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
, FALSE
) )
1900 if ( msg
.message
== WM_LBUTTONUP
)
1902 co_UserSetCapture(NULL
);
1905 if ( msg
.message
== WM_MOUSEMOVE
)
1908 tmp
.x
= (short)LOWORD(msg
.lParam
);
1909 tmp
.y
= (short)HIWORD(msg
.lParam
);
1910 if( !RECTL_bPointInRect( &rect
, tmp
.x
, tmp
.y
) )
1912 co_UserSetCapture(NULL
);
1916 if ( msg
.message
== WM_KEYDOWN
)
1918 if ( msg
.wParam
== VK_ESCAPE
)
1920 co_UserSetCapture(NULL
);
1924 if ( msg
.message
== WM_QUEUESYNC
)
1926 co_HOOK_CallHooks( WH_CBT
, HCBT_QS
, 0, 0 );
1929 co_IntWaitMessage(NULL
, 0, 0);
1934 TRACE("Leave NtUserDragDetect, ret=%i\n",_ret_
);
1940 NtUserPostMessage(HWND hWnd
,
1947 UserEnterExclusive();
1949 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1957 NtUserPostThreadMessage(DWORD idThread
,
1964 PTHREADINFO pThread
;
1967 UserEnterExclusive();
1969 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
1971 if ( Status
== STATUS_SUCCESS
)
1973 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
1975 !pThread
->MessageQueue
||
1976 (pThread
->TIF_flags
& TIF_INCLEANUP
))
1978 ObDereferenceObject( peThread
);
1981 ret
= UserPostThreadMessage( pThread
, Msg
, wParam
, lParam
);
1982 ObDereferenceObject( peThread
);
1986 SetLastNtError( Status
);
1994 NtUserWaitMessage(VOID
)
1998 UserEnterExclusive();
1999 TRACE("NtUserWaitMessage Enter\n");
2000 ret
= co_IntWaitMessage(NULL
, 0, 0);
2001 TRACE("NtUserWaitMessage Leave\n");
2008 NtUserGetMessage(PMSG pMsg
,
2016 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
2018 EngSetLastError(ERROR_INVALID_PARAMETER
);
2022 UserEnterExclusive();
2024 RtlZeroMemory(&Msg
, sizeof(MSG
));
2026 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
2034 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2035 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2037 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2039 SetLastNtError(_SEH2_GetExceptionCode());
2046 Ret
= Ret
? (WM_QUIT
!= pMsg
->message
) : FALSE
;
2052 NtUserPeekMessage( PMSG pMsg
,
2061 if ( RemoveMsg
& PM_BADMSGFLAGS
)
2063 EngSetLastError(ERROR_INVALID_FLAGS
);
2067 UserEnterExclusive();
2069 RtlZeroMemory(&Msg
, sizeof(MSG
));
2071 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
2079 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2080 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2082 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2084 SetLastNtError(_SEH2_GetExceptionCode());
2094 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
2101 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
2102 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
2104 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2106 _SEH2_YIELD(return FALSE
);
2110 UserEnterExclusive();
2112 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
2118 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
2125 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
2126 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
2128 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2138 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
2145 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
2146 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
2148 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2150 SetLastNtError(_SEH2_GetExceptionCode());
2151 _SEH2_YIELD(return FALSE
);
2155 UserEnterExclusive();
2157 Res
= IntDispatchMessage(&SafeMsg
);
2164 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
2172 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
2173 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
2175 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2177 SetLastNtError(_SEH2_GetExceptionCode());
2178 _SEH2_YIELD(return FALSE
);
2182 UserEnterExclusive();
2183 pWnd
= UserGetWindowObject(SafeMsg
.hwnd
);
2184 if (pWnd
) // Must have a window!
2186 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
2190 TRACE("No Window for Translate. hwnd 0x%p Msg %u\n", SafeMsg
.hwnd
, SafeMsg
.message
);
2198 LRESULT APIENTRY
ScrollBarWndProc(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
);
2201 NtUserMessageCall( HWND hWnd
,
2205 ULONG_PTR ResultInfo
,
2206 DWORD dwType
, // fnID?
2209 LRESULT lResult
= 0;
2212 USER_REFERENCE_ENTRY Ref
;
2214 UserEnterExclusive();
2218 case FNID_SCROLLBAR
:
2220 lResult
= ScrollBarWndProc(hWnd
, Msg
, wParam
, lParam
);
2225 Window
= UserGetWindowObject(hWnd
);
2228 //ERR("FNID_DESKTOP IN\n");
2229 Ret
= DesktopWindowProc(Window
, Msg
, wParam
, lParam
, &lResult
);
2230 //ERR("FNID_DESKTOP OUT\n");
2235 case FNID_MESSAGEWND
:
2237 Window
= UserGetWindowObject(hWnd
);
2240 Ret
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,&lResult
);
2244 case FNID_DEFWINDOWPROC
:
2245 /* Validate input */
2248 Window
= UserGetWindowObject(hWnd
);
2254 UserRefObjectCo(Window
, &Ref
);
2256 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2259 UserDerefObjectCo(Window
);
2261 case FNID_SENDNOTIFYMESSAGE
:
2262 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2264 case FNID_BROADCASTSYSTEMMESSAGE
:
2266 BROADCASTPARM parm
, *retparam
;
2267 DWORD_PTR RetVal
= 0;
2273 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2274 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2276 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2285 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2286 parm
.recipients
== BSM_ALLCOMPONENTS
)
2288 PLIST_ENTRY DesktopEntry
;
2290 HWND
*List
, hwndDenied
= NULL
;
2292 PWND pwnd
, pwndDesk
;
2296 for (DesktopEntry
= InputWindowStation
->DesktopListHead
.Flink
;
2297 DesktopEntry
!= &InputWindowStation
->DesktopListHead
;
2298 DesktopEntry
= DesktopEntry
->Flink
)
2300 rpdesk
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
2301 pwndDesk
= rpdesk
->pDeskInfo
->spwnd
;
2302 List
= IntWinListChildren(pwndDesk
);
2304 if (parm
.flags
& BSF_QUERY
)
2308 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2310 fuFlags
= SMTO_ABORTIFHUNG
;
2312 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2314 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2318 fuFlags
= SMTO_NORMAL
;
2320 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2328 for (i
= 0; List
[i
]; i
++)
2330 pwnd
= UserGetWindowObject(List
[i
]);
2331 if (!pwnd
) continue;
2333 if ( pwnd
->fnid
== FNID_MENU
||
2334 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2337 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2339 if ( pwnd
->head
.pti
== gptiCurrent
)
2342 co_IntSendMessageTimeout( List
[i
],
2350 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2352 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2355 if (RetVal
== BROADCAST_QUERY_DENY
)
2357 hwndDenied
= List
[i
];
2358 hDesk
= UserHMGetHandle(pwndDesk
);
2362 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2365 retparam
= (PBROADCASTPARM
) ResultInfo
;
2366 retparam
->hDesk
= hDesk
;
2367 retparam
->hWnd
= hwndDenied
;
2369 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2374 if (!Ret
) break; // Have a hit! Let everyone know!
2377 else if (parm
.flags
& BSF_POSTMESSAGE
)
2381 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2383 for (i
= 0; List
[i
]; i
++)
2385 pwnd
= UserGetWindowObject(List
[i
]);
2386 if (!pwnd
) continue;
2388 if ( pwnd
->fnid
== FNID_MENU
||
2389 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2392 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2394 if ( pwnd
->head
.pti
== gptiCurrent
)
2397 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2399 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2407 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2409 for (i
= 0; List
[i
]; i
++)
2411 pwnd
= UserGetWindowObject(List
[i
]);
2412 if (!pwnd
) continue;
2414 if ( pwnd
->fnid
== FNID_MENU
||
2415 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2418 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2420 if ( pwnd
->head
.pti
== gptiCurrent
)
2423 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2425 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2431 else if (parm
.recipients
& BSM_APPLICATIONS
)
2433 HWND
*List
, hwndDenied
= NULL
;
2435 PWND pwnd
, pwndDesk
;
2439 pwndDesk
= UserGetDesktopWindow();
2440 List
= IntWinListChildren(pwndDesk
);
2442 if (parm
.flags
& BSF_QUERY
)
2446 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2448 fuFlags
= SMTO_ABORTIFHUNG
;
2450 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2452 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2456 fuFlags
= SMTO_NORMAL
;
2458 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2466 for (i
= 0; List
[i
]; i
++)
2468 pwnd
= UserGetWindowObject(List
[i
]);
2469 if (!pwnd
) continue;
2471 if ( pwnd
->fnid
== FNID_MENU
||
2472 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2475 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2477 if ( pwnd
->head
.pti
== gptiCurrent
)
2480 co_IntSendMessageTimeout( List
[i
],
2488 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2490 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2493 if (RetVal
== BROADCAST_QUERY_DENY
)
2495 hwndDenied
= List
[i
];
2496 hDesk
= UserHMGetHandle(pwndDesk
);
2500 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2503 retparam
= (PBROADCASTPARM
) ResultInfo
;
2504 retparam
->hDesk
= hDesk
;
2505 retparam
->hWnd
= hwndDenied
;
2507 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2514 else if (parm
.flags
& BSF_POSTMESSAGE
)
2518 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2520 for (i
= 0; List
[i
]; i
++)
2522 pwnd
= UserGetWindowObject(List
[i
]);
2523 if (!pwnd
) continue;
2525 if ( pwnd
->fnid
== FNID_MENU
||
2526 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2529 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2531 if ( pwnd
->head
.pti
== gptiCurrent
)
2534 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2536 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2544 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2546 for (i
= 0; List
[i
]; i
++)
2548 pwnd
= UserGetWindowObject(List
[i
]);
2549 if (!pwnd
) continue;
2551 if ( pwnd
->fnid
== FNID_MENU
||
2552 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2555 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2557 if ( pwnd
->head
.pti
== gptiCurrent
)
2560 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2562 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2569 case FNID_SENDMESSAGECALLBACK
:
2571 CALL_BACK_INFO CallBackInfo
;
2576 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2577 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2579 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2585 if (is_pointer_message(Msg
))
2587 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
2591 if (!(Ret
= co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2592 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
)))
2594 ERR("Callback failure!\n");
2598 case FNID_SENDMESSAGE
:
2600 Ret
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2606 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2607 RtlCopyMemory((PVOID
)ResultInfo
, &Ret
, sizeof(ULONG_PTR
));
2609 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2618 case FNID_SENDMESSAGEFF
:
2619 case FNID_SENDMESSAGEWTOOPTION
:
2621 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2626 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2627 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2629 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2636 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, &dsm
);
2642 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2643 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2645 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2654 // CallNextHook bypass.
2655 case FNID_CALLWNDPROC
:
2656 case FNID_CALLWNDPROCRET
:
2659 PCLIENTINFO ClientInfo
;
2660 PHOOK NextObj
, Hook
;
2662 pti
= GetW32ThreadInfo();
2664 Hook
= pti
->sphkCurrent
;
2668 NextObj
= Hook
->phkNext
;
2669 ClientInfo
= pti
->pClientInfo
;
2672 ClientInfo
->phkCurrent
= NextObj
;
2674 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2680 if (!ClientInfo
|| !NextObj
) break;
2682 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2684 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2689 CWP
.wParam
= wParam
;
2690 CWP
.lParam
= lParam
;
2691 TRACE("WH_CALLWNDPROC: Hook %p NextHook %p\n", Hook
, NextObj
);
2693 lResult
= co_IntCallHookProc( Hook
->HookId
,
2695 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2708 CWPR
.wParam
= wParam
;
2709 CWPR
.lParam
= lParam
;
2710 CWPR
.lResult
= ClientInfo
->dwHookData
;
2712 lResult
= co_IntCallHookProc( Hook
->HookId
,
2714 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2728 case FNID_DEFWINDOWPROC
:
2729 case FNID_CALLWNDPROC
:
2730 case FNID_CALLWNDPROCRET
:
2731 case FNID_SCROLLBAR
:
2737 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2738 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2740 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2756 #define INFINITE 0xFFFFFFFF
2757 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2761 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2762 IN DWORD dwMilliseconds
,
2766 PPROCESSINFO W32Process
;
2770 LARGE_INTEGER Timeout
;
2772 UserEnterExclusive();
2774 Status
= ObReferenceObjectByHandle(hProcess
,
2775 PROCESS_QUERY_INFORMATION
,
2781 if (!NT_SUCCESS(Status
))
2784 SetLastNtError(Status
);
2788 pti
= PsGetCurrentThreadWin32Thread();
2790 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2792 if ( PsGetProcessExitProcessCalled(Process
) ||
2794 pti
->ppi
== W32Process
)
2796 ObDereferenceObject(Process
);
2798 EngSetLastError(ERROR_INVALID_PARAMETER
);
2802 Handles
[0] = Process
;
2803 Handles
[1] = W32Process
->InputIdleEvent
;
2804 Handles
[2] = pti
->pEventQueueServer
; // IntMsqSetWakeMask returns hEventQueueClient
2808 ObDereferenceObject(Process
);
2810 return STATUS_SUCCESS
; /* no event to wait on */
2813 if (dwMilliseconds
!= INFINITE
)
2814 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2816 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2817 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2819 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2820 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2823 TRACE("WFII: ppi %p\n", W32Process
);
2824 TRACE("WFII: waiting for %p\n", Handles
[1] );
2828 Status
= KeWaitForMultipleObjects( 3,
2834 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2836 UserEnterExclusive();
2838 if (!NT_SUCCESS(Status
))
2840 SetLastNtError(Status
);
2841 Status
= WAIT_FAILED
;
2853 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2854 ERR("WFII: WAIT 2\n");
2858 case STATUS_TIMEOUT
:
2859 ERR("WFII: timeout\n");
2864 ERR("WFII: finished\n");
2865 Status
= STATUS_SUCCESS
;
2872 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2874 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
2875 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2877 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
2878 ObDereferenceObject(Process
);