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( DWORD idThread
,
1068 PTHREADINFO pThread
;
1069 LARGE_INTEGER LargeTickCount
;
1072 if (is_pointer_message(Msg
))
1074 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1078 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
1080 if( Status
== STATUS_SUCCESS
)
1082 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
1084 !pThread
->MessageQueue
||
1085 (pThread
->TIF_flags
& TIF_INCLEANUP
))
1087 ObDereferenceObject( peThread
);
1091 Message
.hwnd
= NULL
;
1092 Message
.message
= Msg
;
1093 Message
.wParam
= wParam
;
1094 Message
.lParam
= lParam
;
1095 Message
.pt
= gpsi
->ptCursor
;
1097 KeQueryTickCount(&LargeTickCount
);
1098 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1099 MsqPostMessage(pThread
, &Message
, FALSE
, QS_POSTMESSAGE
, 0);
1100 ObDereferenceObject( peThread
);
1105 SetLastNtError( Status
);
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 return UserPostThreadMessage( PtrToInt(PsGetCurrentThreadId()),
1165 if (Wnd
== HWND_BROADCAST
)
1171 DesktopWindow
= UserGetDesktopWindow();
1172 List
= IntWinListChildren(DesktopWindow
);
1176 UserPostMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1177 for (i
= 0; List
[i
]; i
++)
1179 PWND pwnd
= UserGetWindowObject(List
[i
]);
1180 if (!pwnd
) continue;
1182 if ( pwnd
->fnid
== FNID_MENU
|| // Also need pwnd->pcls->atomClassName == gaOleMainThreadWndClass
1183 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1186 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1188 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1195 Window
= UserGetWindowObject(Wnd
);
1198 ERR("UserPostMessage: Invalid handle 0x%p!\n",Wnd
);
1202 pti
= Window
->head
.pti
;
1203 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1205 ERR("Attempted to post message to window %p when the thread is in cleanup!\n", Wnd
);
1209 if ( Window
->state
& WNDS_DESTROYED
)
1211 ERR("Attempted to post message to window %p that is being destroyed!\n", Wnd
);
1212 /* FIXME: Last error code? */
1218 MsqPostQuitMessage(Window
->head
.pti
, wParam
);
1222 MsqPostMessage(Window
->head
.pti
, &Message
, FALSE
, QS_POSTMESSAGE
, 0);
1229 co_IntSendMessage( HWND hWnd
,
1234 ULONG_PTR Result
= 0;
1235 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1237 return (LRESULT
)Result
;
1242 static LRESULT FASTCALL
1243 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1249 ULONG_PTR
*uResult
)
1253 PMSGMEMORY MsgMemoryEntry
;
1254 INT lParamBufferSize
;
1255 LPARAM lParamPacked
;
1256 PTHREADINFO Win32Thread
;
1257 ULONG_PTR Hi
, Lo
, Result
= 0;
1258 DECLARE_RETURN(LRESULT
);
1259 USER_REFERENCE_ENTRY Ref
;
1260 BOOL DoCallBack
= TRUE
;
1262 if (!(Window
= UserGetWindowObject(hWnd
)))
1264 TRACE("SendMessageTimeoutSingle: Invalid handle 0x%p!\n",hWnd
);
1268 UserRefObjectCo(Window
, &Ref
);
1270 Win32Thread
= PsGetCurrentThreadWin32Thread();
1273 Window
->head
.pti
== Win32Thread
)
1275 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1277 /* Never send messages to exiting threads */
1281 if (Msg
& 0x80000000)
1283 TRACE("SMTS: Internal Message!\n");
1284 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1285 if (uResult
) *uResult
= Result
;
1289 // Only happens when calling the client!
1290 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1292 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1294 TRACE("SMT: Server Side Window Procedure\n");
1295 IoGetStackLimits(&Lo
, &Hi
);
1296 // Handle it here. Safeguard against excessive recursions.
1297 if (((ULONG_PTR
)&uResult
- Lo
) < 4096 )
1299 ERR("Server Callback Exceeded Stack!\n");
1302 /* Return after server side call, IntCallWndProcRet will not be called. */
1303 switch(Window
->fnid
)
1306 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1308 case FNID_MESSAGEWND
:
1309 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1314 if (uResult
) *uResult
= Result
;
1318 /* See if this message type is present in the table */
1319 MsgMemoryEntry
= FindMsgMemory(Msg
);
1320 if (NULL
== MsgMemoryEntry
)
1322 lParamBufferSize
= -1;
1326 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1329 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1331 ERR("Failed to pack message parameters\n");
1335 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1347 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1349 ERR("Failed to unpack message parameters\n");
1353 // Only happens when calling the client!
1354 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1359 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->head
.pti
))
1361 // FIXME: Set window hung and add to a list.
1362 /* FIXME: Set a LastError? */
1366 if (Window
->state
& WNDS_DESTROYED
)
1368 /* FIXME: Last error? */
1369 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1375 Status
= co_MsqSendMessage( Window
->head
.pti
,
1381 (uFlags
& SMTO_BLOCK
),
1385 while ((STATUS_TIMEOUT
== Status
) &&
1386 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1387 !MsqIsHung(Window
->head
.pti
)); // FIXME: Set window hung and add to a list.
1389 if (STATUS_TIMEOUT
== Status
)
1393 * Microsoft Windows 2000: If GetLastError returns zero, then the function
1395 * XP+ : If the function fails or times out, the return value is zero.
1396 * To get extended error information, call GetLastError. If GetLastError
1397 * returns ERROR_TIMEOUT, then the function timed out.
1399 EngSetLastError(ERROR_TIMEOUT
);
1402 else if (!NT_SUCCESS(Status
))
1404 SetLastNtError(Status
);
1411 if (Window
) UserDerefObjectCo(Window
);
1416 co_IntSendMessageTimeout( HWND hWnd
,
1422 ULONG_PTR
*uResult
)
1428 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1430 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1433 DesktopWindow
= UserGetDesktopWindow();
1434 if (NULL
== DesktopWindow
)
1436 EngSetLastError(ERROR_INTERNAL_ERROR
);
1440 if (hWnd
!= HWND_TOPMOST
)
1442 /* Send message to the desktop window too! */
1443 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1446 Children
= IntWinListChildren(DesktopWindow
);
1447 if (NULL
== Children
)
1452 for (Child
= Children
; NULL
!= *Child
; Child
++)
1454 if (hWnd
== HWND_TOPMOST
)
1456 DesktopWindow
= UserGetWindowObject(*Child
);
1457 if (DesktopWindow
&& DesktopWindow
->ExStyle
& WS_EX_TOPMOST
)
1459 ERR("HWND_TOPMOST Found\n");
1460 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1465 PWND pwnd
= UserGetWindowObject(*Child
);
1466 if (!pwnd
) continue;
1468 if ( pwnd
->fnid
== FNID_MENU
||
1469 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1472 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1476 ExFreePool(Children
);
1478 return (LRESULT
) TRUE
;
1482 co_IntSendMessageNoWait(HWND hWnd
,
1487 ULONG_PTR Result
= 0;
1488 return co_IntSendMessageWithCallBack( hWnd
,
1497 If you send a message in the range below WM_USER to the asynchronous message
1498 functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its
1499 message parameters cannot include pointers. Otherwise, the operation will fail.
1500 The functions will return before the receiving thread has had a chance to
1501 process the message and the sender will free the memory before it is used.
1504 co_IntSendMessageWithCallBack( HWND hWnd
,
1508 SENDASYNCPROC CompletionCallback
,
1509 ULONG_PTR CompletionCallbackContext
,
1514 PMSGMEMORY MsgMemoryEntry
;
1515 INT lParamBufferSize
;
1516 LPARAM lParamPacked
;
1517 PTHREADINFO Win32Thread
;
1518 DECLARE_RETURN(LRESULT
);
1519 USER_REFERENCE_ENTRY Ref
;
1520 PUSER_SENT_MESSAGE Message
;
1521 BOOL DoCallBack
= TRUE
;
1523 if (!(Window
= UserGetWindowObject(hWnd
)))
1525 TRACE("SendMessageWithCallBack: Invalid handle 0x%p!\n",hWnd
);
1529 UserRefObjectCo(Window
, &Ref
);
1531 if (Window
->state
& WNDS_DESTROYED
)
1533 /* FIXME: last error? */
1534 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1538 Win32Thread
= PsGetCurrentThreadWin32Thread();
1540 if (Win32Thread
== NULL
||
1541 Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1546 if (Msg
& 0x80000000 &&
1547 Window
->head
.pti
== Win32Thread
)
1549 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
) RETURN( FALSE
);
1551 TRACE("SMWCB: Internal Message!\n");
1552 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1553 if (uResult
) *uResult
= Result
;
1557 /* See if this message type is present in the table */
1558 MsgMemoryEntry
= FindMsgMemory(Msg
);
1559 if (NULL
== MsgMemoryEntry
)
1561 lParamBufferSize
= -1;
1565 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1568 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, Window
->head
.pti
!= Win32Thread
)))
1570 ERR("Failed to pack message parameters\n");
1574 /* If it can be sent now, then send it. */
1575 if (Window
->head
.pti
== Win32Thread
)
1577 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1579 UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
);
1580 /* Never send messages to exiting threads */
1584 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1586 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1588 TRACE("SMWCB: Server Side Window Procedure\n");
1589 switch(Window
->fnid
)
1592 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParamPacked
, (LRESULT
*)&Result
);
1594 case FNID_MESSAGEWND
:
1595 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1601 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1613 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1615 if (CompletionCallback
)
1617 co_IntCallSentMessageCallback(CompletionCallback
,
1620 CompletionCallbackContext
,
1625 if (Window
->head
.pti
== Win32Thread
)
1627 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1629 ERR("Failed to unpack message parameters\n");
1634 if(!(Message
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
1636 ERR("MsqSendMessage(): Not enough memory to allocate a message");
1640 Message
->Msg
.hwnd
= hWnd
;
1641 Message
->Msg
.message
= Msg
;
1642 Message
->Msg
.wParam
= wParam
;
1643 Message
->Msg
.lParam
= lParamPacked
;
1644 Message
->CompletionEvent
= NULL
;
1645 Message
->Result
= 0;
1646 Message
->lResult
= 0;
1647 Message
->QS_Flags
= 0;
1648 Message
->ptiReceiver
= Window
->head
.pti
;
1649 Message
->ptiSender
= NULL
; // mjmartin, you are right! This is null.
1650 Message
->ptiCallBackSender
= Win32Thread
;
1651 Message
->DispatchingListEntry
.Flink
= NULL
;
1652 Message
->CompletionCallback
= CompletionCallback
;
1653 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1654 Message
->HookMessage
= MSQ_NORMAL
;
1655 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1656 Message
->QS_Flags
= QS_SENDMESSAGE
;
1658 if (Msg
& 0x80000000) // Higher priority event message!
1659 InsertHeadList(&Window
->head
.pti
->SentMessagesListHead
, &Message
->ListEntry
);
1661 InsertTailList(&Window
->head
.pti
->SentMessagesListHead
, &Message
->ListEntry
);
1662 MsqWakeQueue(Window
->head
.pti
, QS_SENDMESSAGE
, TRUE
);
1667 if (Window
) UserDerefObjectCo(Window
);
1673 This HACK function posts a message if the destination's message queue belongs to
1674 another thread, otherwise it sends the message. It does not support broadcast
1678 co_IntPostOrSendMessage( HWND hWnd
,
1687 if ( hWnd
== HWND_BROADCAST
)
1692 if(!(Window
= UserGetWindowObject(hWnd
)))
1694 TRACE("PostOrSendMessage: Invalid handle 0x%p!\n",hWnd
);
1698 pti
= PsGetCurrentThreadWin32Thread();
1700 if ( Window
->head
.pti
->MessageQueue
!= pti
->MessageQueue
&&
1701 FindMsgMemory(Msg
) == 0 )
1703 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1707 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1713 return (LRESULT
)Result
;
1717 co_IntDoSendMessage( HWND hWnd
,
1724 LRESULT Result
= TRUE
;
1729 PMSGMEMORY MsgMemoryEntry
;
1731 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1733 Window
= UserGetWindowObject(hWnd
);
1740 /* Check for an exiting window. */
1741 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1743 ERR("co_IntDoSendMessage Window Exiting!\n");
1746 /* See if the current thread can handle the message */
1747 //pti = PsGetCurrentThreadWin32Thread();
1749 UserModeMsg
.hwnd
= hWnd
;
1750 UserModeMsg
.message
= Msg
;
1751 UserModeMsg
.wParam
= wParam
;
1752 UserModeMsg
.lParam
= lParam
;
1753 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1755 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1756 if (! NT_SUCCESS(Status
))
1758 EngSetLastError(ERROR_INVALID_PARAMETER
);
1759 return (dsm
? 0 : -1);
1764 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1765 KernelModeMsg
.message
,
1766 KernelModeMsg
.wParam
,
1767 KernelModeMsg
.lParam
);
1771 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1772 KernelModeMsg
.message
,
1773 KernelModeMsg
.wParam
,
1774 KernelModeMsg
.lParam
,
1780 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1781 if (! NT_SUCCESS(Status
))
1783 EngSetLastError(ERROR_INVALID_PARAMETER
);
1784 return(dsm
? 0 : -1);
1787 return (LRESULT
)Result
;
1791 UserSendNotifyMessage( HWND hWnd
,
1798 if (is_pointer_message(Msg
))
1800 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1804 // Basicly the same as IntPostOrSendMessage
1805 if (hWnd
== HWND_BROADCAST
) // Handle Broadcast
1811 DesktopWindow
= UserGetDesktopWindow();
1812 List
= IntWinListChildren(DesktopWindow
);
1816 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1817 for (i
= 0; List
[i
]; i
++)
1819 PWND pwnd
= UserGetWindowObject(List
[i
]);
1820 if (!pwnd
) continue;
1822 if ( pwnd
->fnid
== FNID_MENU
||
1823 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1826 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1833 Ret
= co_IntSendMessageNoWait( hWnd
, Msg
, wParam
, lParam
);
1840 IntGetQueueStatus(DWORD Changes
)
1845 pti
= PsGetCurrentThreadWin32Thread();
1847 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1849 /* High word, types of messages currently in the queue.
1850 Low word, types of messages that have been added to the queue and that
1851 are still in the queue
1853 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1855 pti
->pcti
->fsChangeBits
&= ~Changes
;
1861 IntInitMessagePumpHook()
1863 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1867 pti
->pcti
->dwcPumpHook
++;
1874 IntUninitMessagePumpHook()
1876 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1880 if (pti
->pcti
->dwcPumpHook
<= 0)
1884 pti
->pcti
->dwcPumpHook
--;
1890 /** Functions ******************************************************************/
1896 POINT pt
) // Just like the User call.
1900 ULONG wDragWidth
, wDragHeight
;
1901 DECLARE_RETURN(BOOL
);
1903 TRACE("Enter NtUserDragDetect(%p)\n", hWnd
);
1904 UserEnterExclusive();
1906 wDragWidth
= UserGetSystemMetrics(SM_CXDRAG
);
1907 wDragHeight
= UserGetSystemMetrics(SM_CYDRAG
);
1909 rect
.left
= pt
.x
- wDragWidth
;
1910 rect
.right
= pt
.x
+ wDragWidth
;
1912 rect
.top
= pt
.y
- wDragHeight
;
1913 rect
.bottom
= pt
.y
+ wDragHeight
;
1915 co_UserSetCapture(hWnd
);
1919 while (co_IntGetPeekMessage( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, FALSE
) ||
1920 co_IntGetPeekMessage( &msg
, 0, WM_QUEUESYNC
, WM_QUEUESYNC
, PM_REMOVE
, FALSE
) ||
1921 co_IntGetPeekMessage( &msg
, 0, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
, FALSE
) )
1923 if ( msg
.message
== WM_LBUTTONUP
)
1925 co_UserSetCapture(NULL
);
1928 if ( msg
.message
== WM_MOUSEMOVE
)
1931 tmp
.x
= (short)LOWORD(msg
.lParam
);
1932 tmp
.y
= (short)HIWORD(msg
.lParam
);
1933 if( !RECTL_bPointInRect( &rect
, tmp
.x
, tmp
.y
) )
1935 co_UserSetCapture(NULL
);
1939 if ( msg
.message
== WM_KEYDOWN
)
1941 if ( msg
.wParam
== VK_ESCAPE
)
1943 co_UserSetCapture(NULL
);
1947 if ( msg
.message
== WM_QUEUESYNC
)
1949 co_HOOK_CallHooks( WH_CBT
, HCBT_QS
, 0, 0 );
1952 co_IntWaitMessage(NULL
, 0, 0);
1957 TRACE("Leave NtUserDragDetect, ret=%i\n",_ret_
);
1963 NtUserPostMessage(HWND hWnd
,
1970 UserEnterExclusive();
1972 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1980 NtUserPostThreadMessage(DWORD idThread
,
1987 UserEnterExclusive();
1989 ret
= UserPostThreadMessage( idThread
, Msg
, wParam
, lParam
);
1997 NtUserWaitMessage(VOID
)
2001 UserEnterExclusive();
2002 TRACE("NtUserWaitMessage Enter\n");
2003 ret
= co_IntWaitMessage(NULL
, 0, 0);
2004 TRACE("NtUserWaitMessage Leave\n");
2011 NtUserGetMessage(PMSG pMsg
,
2019 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
2021 EngSetLastError(ERROR_INVALID_PARAMETER
);
2025 UserEnterExclusive();
2027 RtlZeroMemory(&Msg
, sizeof(MSG
));
2029 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
2037 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2038 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2040 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2042 SetLastNtError(_SEH2_GetExceptionCode());
2049 Ret
= Ret
? (WM_QUIT
!= pMsg
->message
) : FALSE
;
2055 NtUserPeekMessage( PMSG pMsg
,
2064 if ( RemoveMsg
& PM_BADMSGFLAGS
)
2066 EngSetLastError(ERROR_INVALID_FLAGS
);
2070 UserEnterExclusive();
2072 RtlZeroMemory(&Msg
, sizeof(MSG
));
2074 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
2082 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2083 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2085 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2087 SetLastNtError(_SEH2_GetExceptionCode());
2097 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
2104 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
2105 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
2107 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2109 _SEH2_YIELD(return FALSE
);
2113 UserEnterExclusive();
2115 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
2121 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
2128 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
2129 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
2131 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2141 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
2148 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
2149 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
2151 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2153 SetLastNtError(_SEH2_GetExceptionCode());
2154 _SEH2_YIELD(return FALSE
);
2158 UserEnterExclusive();
2160 Res
= IntDispatchMessage(&SafeMsg
);
2167 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
2175 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
2176 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
2178 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2180 SetLastNtError(_SEH2_GetExceptionCode());
2181 _SEH2_YIELD(return FALSE
);
2185 UserEnterExclusive();
2186 pWnd
= UserGetWindowObject(SafeMsg
.hwnd
);
2187 if (pWnd
) // Must have a window!
2189 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
2193 TRACE("No Window for Translate. hwnd 0x%p Msg %u\n", SafeMsg
.hwnd
, SafeMsg
.message
);
2201 LRESULT APIENTRY
ScrollBarWndProc(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
);
2204 NtUserMessageCall( HWND hWnd
,
2208 ULONG_PTR ResultInfo
,
2209 DWORD dwType
, // fnID?
2212 LRESULT lResult
= 0;
2215 USER_REFERENCE_ENTRY Ref
;
2217 UserEnterExclusive();
2221 case FNID_SCROLLBAR
:
2223 lResult
= ScrollBarWndProc(hWnd
, Msg
, wParam
, lParam
);
2228 Window
= UserGetWindowObject(hWnd
);
2231 //ERR("FNID_DESKTOP IN\n");
2232 Ret
= DesktopWindowProc(Window
, Msg
, wParam
, lParam
, &lResult
);
2233 //ERR("FNID_DESKTOP OUT\n");
2238 case FNID_MESSAGEWND
:
2240 Window
= UserGetWindowObject(hWnd
);
2243 Ret
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,&lResult
);
2247 case FNID_DEFWINDOWPROC
:
2248 /* Validate input */
2251 Window
= UserGetWindowObject(hWnd
);
2257 UserRefObjectCo(Window
, &Ref
);
2259 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2262 UserDerefObjectCo(Window
);
2264 case FNID_SENDNOTIFYMESSAGE
:
2265 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2267 case FNID_BROADCASTSYSTEMMESSAGE
:
2269 BROADCASTPARM parm
, *retparam
;
2270 DWORD_PTR RetVal
= 0;
2276 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2277 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2279 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2288 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2289 parm
.recipients
== BSM_ALLCOMPONENTS
)
2291 PLIST_ENTRY DesktopEntry
;
2293 HWND
*List
, hwndDenied
= NULL
;
2295 PWND pwnd
, pwndDesk
;
2299 for (DesktopEntry
= InputWindowStation
->DesktopListHead
.Flink
;
2300 DesktopEntry
!= &InputWindowStation
->DesktopListHead
;
2301 DesktopEntry
= DesktopEntry
->Flink
)
2303 rpdesk
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
2304 pwndDesk
= rpdesk
->pDeskInfo
->spwnd
;
2305 List
= IntWinListChildren(pwndDesk
);
2307 if (parm
.flags
& BSF_QUERY
)
2311 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2313 fuFlags
= SMTO_ABORTIFHUNG
;
2315 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2317 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2321 fuFlags
= SMTO_NORMAL
;
2323 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2331 for (i
= 0; List
[i
]; i
++)
2333 pwnd
= UserGetWindowObject(List
[i
]);
2334 if (!pwnd
) continue;
2336 if ( pwnd
->fnid
== FNID_MENU
||
2337 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2340 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2342 if ( pwnd
->head
.pti
== gptiCurrent
)
2345 co_IntSendMessageTimeout( List
[i
],
2353 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2355 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2358 if (RetVal
== BROADCAST_QUERY_DENY
)
2360 hwndDenied
= List
[i
];
2361 hDesk
= UserHMGetHandle(pwndDesk
);
2365 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2368 retparam
= (PBROADCASTPARM
) ResultInfo
;
2369 retparam
->hDesk
= hDesk
;
2370 retparam
->hWnd
= hwndDenied
;
2372 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2377 if (!Ret
) break; // Have a hit! Let everyone know!
2380 else if (parm
.flags
& BSF_POSTMESSAGE
)
2384 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2386 for (i
= 0; List
[i
]; i
++)
2388 pwnd
= UserGetWindowObject(List
[i
]);
2389 if (!pwnd
) continue;
2391 if ( pwnd
->fnid
== FNID_MENU
||
2392 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2395 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2397 if ( pwnd
->head
.pti
== gptiCurrent
)
2400 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2402 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2410 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2412 for (i
= 0; List
[i
]; i
++)
2414 pwnd
= UserGetWindowObject(List
[i
]);
2415 if (!pwnd
) continue;
2417 if ( pwnd
->fnid
== FNID_MENU
||
2418 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2421 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2423 if ( pwnd
->head
.pti
== gptiCurrent
)
2426 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2428 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2434 else if (parm
.recipients
& BSM_APPLICATIONS
)
2436 HWND
*List
, hwndDenied
= NULL
;
2438 PWND pwnd
, pwndDesk
;
2442 pwndDesk
= UserGetDesktopWindow();
2443 List
= IntWinListChildren(pwndDesk
);
2445 if (parm
.flags
& BSF_QUERY
)
2449 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2451 fuFlags
= SMTO_ABORTIFHUNG
;
2453 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2455 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2459 fuFlags
= SMTO_NORMAL
;
2461 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2469 for (i
= 0; List
[i
]; i
++)
2471 pwnd
= UserGetWindowObject(List
[i
]);
2472 if (!pwnd
) continue;
2474 if ( pwnd
->fnid
== FNID_MENU
||
2475 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2478 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2480 if ( pwnd
->head
.pti
== gptiCurrent
)
2483 co_IntSendMessageTimeout( List
[i
],
2491 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2493 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2496 if (RetVal
== BROADCAST_QUERY_DENY
)
2498 hwndDenied
= List
[i
];
2499 hDesk
= UserHMGetHandle(pwndDesk
);
2503 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2506 retparam
= (PBROADCASTPARM
) ResultInfo
;
2507 retparam
->hDesk
= hDesk
;
2508 retparam
->hWnd
= hwndDenied
;
2510 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2517 else if (parm
.flags
& BSF_POSTMESSAGE
)
2521 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2523 for (i
= 0; List
[i
]; i
++)
2525 pwnd
= UserGetWindowObject(List
[i
]);
2526 if (!pwnd
) continue;
2528 if ( pwnd
->fnid
== FNID_MENU
||
2529 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2532 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2534 if ( pwnd
->head
.pti
== gptiCurrent
)
2537 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2539 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2547 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2549 for (i
= 0; List
[i
]; i
++)
2551 pwnd
= UserGetWindowObject(List
[i
]);
2552 if (!pwnd
) continue;
2554 if ( pwnd
->fnid
== FNID_MENU
||
2555 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2558 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2560 if ( pwnd
->head
.pti
== gptiCurrent
)
2563 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2565 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2572 case FNID_SENDMESSAGECALLBACK
:
2574 CALL_BACK_INFO CallBackInfo
;
2579 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2580 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2582 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2588 if (is_pointer_message(Msg
))
2590 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
2594 if (!(Ret
= co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2595 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
)))
2597 ERR("Callback failure!\n");
2601 case FNID_SENDMESSAGE
:
2603 Ret
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2609 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2610 RtlCopyMemory((PVOID
)ResultInfo
, &Ret
, sizeof(ULONG_PTR
));
2612 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2621 case FNID_SENDMESSAGEFF
:
2622 case FNID_SENDMESSAGEWTOOPTION
:
2624 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2629 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2630 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2632 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2639 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, &dsm
);
2645 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2646 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2648 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2657 // CallNextHook bypass.
2658 case FNID_CALLWNDPROC
:
2659 case FNID_CALLWNDPROCRET
:
2662 PCLIENTINFO ClientInfo
;
2663 PHOOK NextObj
, Hook
;
2665 pti
= GetW32ThreadInfo();
2667 Hook
= pti
->sphkCurrent
;
2671 NextObj
= Hook
->phkNext
;
2672 ClientInfo
= pti
->pClientInfo
;
2675 ClientInfo
->phkCurrent
= NextObj
;
2677 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2683 if (!ClientInfo
|| !NextObj
) break;
2685 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2687 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2692 CWP
.wParam
= wParam
;
2693 CWP
.lParam
= lParam
;
2694 TRACE("WH_CALLWNDPROC: Hook %p NextHook %p\n", Hook
, NextObj
);
2696 lResult
= co_IntCallHookProc( Hook
->HookId
,
2698 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2709 CWPR
.wParam
= wParam
;
2710 CWPR
.lParam
= lParam
;
2711 CWPR
.lResult
= ClientInfo
->dwHookData
;
2713 lResult
= co_IntCallHookProc( Hook
->HookId
,
2715 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2727 case FNID_DEFWINDOWPROC
:
2728 case FNID_CALLWNDPROC
:
2729 case FNID_CALLWNDPROCRET
:
2730 case FNID_SCROLLBAR
:
2736 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2737 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2739 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2755 #define INFINITE 0xFFFFFFFF
2756 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2760 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2761 IN DWORD dwMilliseconds
,
2765 PPROCESSINFO W32Process
;
2769 LARGE_INTEGER Timeout
;
2771 UserEnterExclusive();
2773 Status
= ObReferenceObjectByHandle(hProcess
,
2774 PROCESS_QUERY_INFORMATION
,
2780 if (!NT_SUCCESS(Status
))
2783 SetLastNtError(Status
);
2787 pti
= PsGetCurrentThreadWin32Thread();
2789 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2791 if ( PsGetProcessExitProcessCalled(Process
) ||
2793 pti
->ppi
== W32Process
)
2795 ObDereferenceObject(Process
);
2797 EngSetLastError(ERROR_INVALID_PARAMETER
);
2801 Handles
[0] = Process
;
2802 Handles
[1] = W32Process
->InputIdleEvent
;
2803 Handles
[2] = pti
->pEventQueueServer
; // IntMsqSetWakeMask returns hEventQueueClient
2807 ObDereferenceObject(Process
);
2809 return STATUS_SUCCESS
; /* no event to wait on */
2812 if (dwMilliseconds
!= INFINITE
)
2813 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2815 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2816 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2818 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2819 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2822 TRACE("WFII: ppi %p\n", W32Process
);
2823 TRACE("WFII: waiting for %p\n", Handles
[1] );
2827 Status
= KeWaitForMultipleObjects( 3,
2833 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2835 UserEnterExclusive();
2837 if (!NT_SUCCESS(Status
))
2839 SetLastNtError(Status
);
2840 Status
= WAIT_FAILED
;
2852 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2853 ERR("WFII: WAIT 2\n");
2857 case STATUS_TIMEOUT
:
2858 ERR("WFII: timeout\n");
2863 ERR("WFII: finished\n");
2864 Status
= STATUS_SUCCESS
;
2871 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2873 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
2874 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2876 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
2877 ObDereferenceObject(Process
);