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();
507 pti
= PsGetCurrentThreadWin32Thread();
511 pti
->pClientInfo
->cSpins
= 0; // Reset spins.
513 if ( pti
->pDeskInfo
&& pti
== gptiForeground
)
515 if ( pti
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) ||
516 pti
->pDeskInfo
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) )
518 co_HOOK_CallHooks(WH_FOREGROUNDIDLE
,HC_ACTION
,0,0);
523 TRACE("IdlePing ppi %p\n", ppi
);
524 if ( ppi
&& ppi
->InputIdleEvent
)
526 TRACE("InputIdleEvent\n");
527 KeSetEvent( ppi
->InputIdleEvent
, IO_NO_INCREMENT
, FALSE
);
534 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
536 TRACE("IdlePong ppi %p\n", ppi
);
537 if ( ppi
&& ppi
->InputIdleEvent
)
539 KeClearEvent(ppi
->InputIdleEvent
);
544 GetWakeMask(UINT first
, UINT last
)
546 UINT mask
= QS_POSTMESSAGE
| QS_SENDMESSAGE
; /* Always selected */
550 if ((first
<= WM_KEYLAST
) && (last
>= WM_KEYFIRST
)) mask
|= QS_KEY
;
551 if ( ((first
<= WM_MOUSELAST
) && (last
>= WM_MOUSEFIRST
)) ||
552 ((first
<= WM_NCMOUSELAST
) && (last
>= WM_NCMOUSEFIRST
)) ) mask
|= QS_MOUSE
;
553 if ((first
<= WM_TIMER
) && (last
>= WM_TIMER
)) mask
|= QS_TIMER
;
554 if ((first
<= WM_SYSTIMER
) && (last
>= WM_SYSTIMER
)) mask
|= QS_TIMER
;
555 if ((first
<= WM_PAINT
) && (last
>= WM_PAINT
)) mask
|= QS_PAINT
;
557 else mask
= QS_ALLINPUT
;
563 IntCallWndProc( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
565 BOOL SameThread
= FALSE
;
568 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
575 co_HOOK_CallHooks( WH_CALLWNDPROC
, HC_ACTION
, SameThread
, (LPARAM
)&CWP
);
579 IntCallWndProcRet ( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*uResult
)
581 BOOL SameThread
= FALSE
;
584 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
589 CWPR
.wParam
= wParam
;
590 CWPR
.lParam
= lParam
;
591 CWPR
.lResult
= uResult
? (*uResult
) : 0;
592 co_HOOK_CallHooks( WH_CALLWNDPROCRET
, HC_ACTION
, SameThread
, (LPARAM
)&CWPR
);
595 static LRESULT
handle_internal_message( PWND pWnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
598 USER_REFERENCE_ENTRY Ref
;
599 // PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
602 pWnd
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
603 pWnd
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
606 TRACE("Internal Event Msg %p hWnd 0x%x\n",msg
,pWnd
->head
.h
);
610 case WM_ASYNC_SHOWWINDOW
:
611 return co_WinPosShowWindow( pWnd
, wparam
);
612 case WM_ASYNC_SETWINDOWPOS
:
614 PWINDOWPOS winpos
= (PWINDOWPOS
)lparam
;
615 if (!winpos
) return 0;
616 lRes
= co_WinPosSetWindowPos( pWnd
,
617 winpos
->hwndInsertAfter
,
623 ExFreePoolWithTag(winpos
, USERTAG_SWP
);
626 case WM_ASYNC_SETACTIVEWINDOW
:
628 PWND Window
= (PWND
)wparam
;
629 if (wparam
) UserRefObjectCo(Window
, &Ref
);
630 lRes
= (LRESULT
)co_IntSetActiveWindow(Window
,(BOOL
)lparam
,TRUE
,TRUE
);
631 if (wparam
) UserDerefObjectCo(Window
);
639 IntDispatchMessage(PMSG pMsg
)
641 LARGE_INTEGER TickCount
;
647 BOOL DoCallBack
= TRUE
;
651 Window
= UserGetWindowObject(pMsg
->hwnd
);
652 if (!Window
) return 0;
655 pti
= PsGetCurrentThreadWin32Thread();
657 if ( Window
&& Window
->head
.pti
!= pti
)
659 EngSetLastError( ERROR_MESSAGE_SYNC_ONLY
);
663 if (((pMsg
->message
== WM_SYSTIMER
) ||
664 (pMsg
->message
== WM_TIMER
)) &&
667 if (pMsg
->message
== WM_TIMER
)
669 if (ValidateTimerCallback(pti
,pMsg
->lParam
))
671 KeQueryTickCount(&TickCount
);
672 Time
= MsqCalculateMessageTime(&TickCount
);
673 retval
= co_IntCallWindowProc((WNDPROC
)pMsg
->lParam
,
685 PTIMER pTimer
= FindSystemTimer(pMsg
);
686 if (pTimer
&& pTimer
->pfn
)
688 KeQueryTickCount(&TickCount
);
689 Time
= MsqCalculateMessageTime(&TickCount
);
690 pTimer
->pfn(pMsg
->hwnd
, WM_SYSTIMER
, (UINT
)pMsg
->wParam
, Time
);
696 if ( !Window
) return 0;
698 if (pMsg
->message
== WM_PAINT
) Window
->state
|= WNDS_PAINTNOTPROCESSED
;
700 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
702 TRACE("Dispatch: Server Side Window Procedure\n");
706 DoCallBack
= !DesktopWindowProc( Window
,
712 case FNID_MESSAGEWND
:
713 DoCallBack
= !UserMessageWindowProc( Window
,
722 /* Since we are doing a callback on the same thread right away, there is
723 no need to copy the lparam to kernel mode and then back to usermode.
724 We just pretend it isn't a pointer */
727 retval
= co_IntCallWindowProc( Window
->lpfnWndProc
,
735 if (pMsg
->message
== WM_PAINT
)
737 Window
->state2
&= ~WNDS2_WMPAINTSENT
;
738 /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
739 hrgn
= IntSysCreateRectRgn( 0, 0, 0, 0 );
740 co_UserGetUpdateRgn( Window
, hrgn
, TRUE
);
741 GreDeleteObject(hrgn
);
748 * Internal version of PeekMessage() doing all the work
753 * Input (hardware) messages and system internal events
754 * Sent messages (again)
759 co_IntPeekMessage( PMSG Msg
,
767 LARGE_INTEGER LargeTickCount
;
772 pti
= PsGetCurrentThreadWin32Thread();
774 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
775 ProcessMask
= HIWORD(RemoveMsg
);
777 /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns
778 all available messages (that is, no range filtering is performed)". */
779 if (!ProcessMask
) ProcessMask
= (QS_ALLPOSTMESSAGE
|QS_ALLINPUT
);
785 KeQueryTickCount(&LargeTickCount
);
786 pti
->timeLast
= LargeTickCount
.u
.LowPart
;
787 pti
->pcti
->tickLastMsgChecked
= LargeTickCount
.u
.LowPart
;
789 /* Dispatch sent messages here. */
790 while ( co_MsqDispatchOneSentMessage(pti
) )
792 /* if some PM_QS* flags were specified, only handle sent messages from now on */
793 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
; // wine does this; ProcessMask = QS_SENDMESSAGE;
795 if (Hit
) return FALSE
;
797 /* Clear changed bits so we can wait on them if we don't find a message */
798 if (ProcessMask
& QS_POSTMESSAGE
)
800 pti
->pcti
->fsChangeBits
&= ~(QS_POSTMESSAGE
| QS_HOTKEY
| QS_TIMER
);
801 if (MsgFilterMin
== 0 && MsgFilterMax
== 0) // Wine hack does this; ~0U)
803 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
807 if (ProcessMask
& QS_INPUT
)
809 pti
->pcti
->fsChangeBits
&= ~QS_INPUT
;
812 /* Now check for normal messages. */
813 if (( (ProcessMask
& QS_POSTMESSAGE
) ||
814 (ProcessMask
& QS_HOTKEY
) ) &&
826 /* Now look for a quit message. */
829 /* According to the PSDK, WM_QUIT messages are always returned, regardless
830 of the filter specified */
832 Msg
->message
= WM_QUIT
;
833 Msg
->wParam
= pti
->exitCode
;
837 pti
->QuitPosted
= FALSE
;
838 ClearMsgBitsMask(pti
, QS_POSTMESSAGE
);
839 pti
->pcti
->fsWakeBits
&= ~QS_ALLPOSTMESSAGE
;
840 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
845 /* Check for hardware events. */
846 if ((ProcessMask
& QS_MOUSE
) &&
847 co_MsqPeekMouseMove( pti
,
857 if ((ProcessMask
& QS_INPUT
) &&
858 co_MsqPeekHardwareMessage( pti
,
869 /* Check for sent messages again. */
870 while ( co_MsqDispatchOneSentMessage(pti
) )
872 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
;
874 if (Hit
) return FALSE
;
876 /* Check for paint messages. */
877 if ((ProcessMask
& QS_PAINT
) &&
879 IntGetPaintMessage( Window
,
889 /* This is correct, check for the current threads timers waiting to be
890 posted to this threads message queue. If any we loop again.
892 if ((ProcessMask
& QS_TIMER
) &&
893 PostTimerMessages(Window
))
906 co_IntWaitMessage( PWND Window
,
911 NTSTATUS Status
= STATUS_SUCCESS
;
914 pti
= PsGetCurrentThreadWin32Thread();
918 if ( co_IntPeekMessage( &Msg
, // Dont reenter!
922 MAKELONG( PM_NOREMOVE
, GetWakeMask( MsgFilterMin
, MsgFilterMax
)),
923 TRUE
) ) // act like GetMessage.
928 /* Nothing found. Wait for new messages. */
929 Status
= co_MsqWaitForNewMessages( pti
,
933 if (!NT_SUCCESS(Status
))
935 SetLastNtError(Status
);
936 ERR("Exit co_IntWaitMessage on error!\n");
939 if (Status
== STATUS_USER_APC
|| Status
== STATUS_TIMEOUT
)
950 co_IntGetPeekMessage( PMSG pMsg
,
959 BOOL Present
= FALSE
;
962 if ( hWnd
== HWND_TOPMOST
|| hWnd
== HWND_BROADCAST
)
966 if (hWnd
&& hWnd
!= HWND_BOTTOM
)
968 if (!(Window
= UserGetWindowObject(hWnd
)))
981 if (MsgFilterMax
< MsgFilterMin
)
989 RemoveMsg
|= ((GetWakeMask( MsgFilterMin
, MsgFilterMax
))<< 16);
992 pti
= PsGetCurrentThreadWin32Thread();
993 pti
->pClientInfo
->cSpins
++; // Bump up the spin count.
997 Present
= co_IntPeekMessage( pMsg
,
1005 /* GetMessage or PostMessage must never get messages that contain pointers */
1006 ASSERT(FindMsgMemory(pMsg
->message
) == NULL
);
1008 if (pMsg
->message
!= WM_PAINT
&& pMsg
->message
!= WM_QUIT
)
1010 pti
->timeLast
= pMsg
->time
;
1011 pti
->ptLast
= pMsg
->pt
;
1014 // The WH_GETMESSAGE hook enables an application to monitor messages about to
1015 // be returned by the GetMessage or PeekMessage function.
1017 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)pMsg
);
1024 Status
= co_MsqWaitForNewMessages( pti
,
1028 if ( !NT_SUCCESS(Status
) ||
1029 Status
== STATUS_USER_APC
||
1030 Status
== STATUS_TIMEOUT
)
1038 if (!(RemoveMsg
& PM_NOYIELD
))
1041 // Yield this thread!
1044 UserEnterExclusive();
1045 // Fall through to exit.
1051 while( bGMSG
&& !Present
);
1053 // Been spinning, time to swap vinyl...
1054 if (pti
->pClientInfo
->cSpins
>= 100)
1056 // Clear the spin cycle to fix the mix.
1057 pti
->pClientInfo
->cSpins
= 0;
1058 //if (!(pti->TIF_flags & TIF_SPINNING)) // FIXME: Need to swap vinyl...
1064 UserPostThreadMessage( PTHREADINFO pti
,
1070 LARGE_INTEGER LargeTickCount
;
1072 if (is_pointer_message(Msg
))
1074 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1077 Message
.hwnd
= NULL
;
1078 Message
.message
= Msg
;
1079 Message
.wParam
= wParam
;
1080 Message
.lParam
= lParam
;
1081 Message
.pt
= gpsi
->ptCursor
;
1083 KeQueryTickCount(&LargeTickCount
);
1084 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1085 MsqPostMessage(pti
, &Message
, FALSE
, QS_POSTMESSAGE
, 0);
1089 PTHREADINFO FASTCALL
1090 IntSendTo(PWND Window
, PTHREADINFO ptiCur
, UINT Msg
)
1094 if ( Window
->head
.pti
->MessageQueue
== ptiCur
->MessageQueue
)
1099 return Window
->head
.pti
;
1103 UserPostMessage( HWND Wnd
,
1109 MSG Message
, KernelModeMsg
;
1110 LARGE_INTEGER LargeTickCount
;
1113 Message
.message
= Msg
;
1114 Message
.wParam
= wParam
;
1115 Message
.lParam
= lParam
;
1116 Message
.pt
= gpsi
->ptCursor
;
1117 KeQueryTickCount(&LargeTickCount
);
1118 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1120 if (is_pointer_message(Message
.message
))
1122 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1126 if( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1129 PMSGMEMORY MsgMemoryEntry
;
1131 MsgMemoryEntry
= FindMsgMemory(Message
.message
);
1133 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &Message
, MsgMemoryEntry
);
1134 if (! NT_SUCCESS(Status
))
1136 EngSetLastError(ERROR_INVALID_PARAMETER
);
1139 co_IntSendMessageNoWait(KernelModeMsg
.hwnd
,
1140 KernelModeMsg
.message
,
1141 KernelModeMsg
.wParam
,
1142 KernelModeMsg
.lParam
);
1144 if (MsgMemoryEntry
&& KernelModeMsg
.lParam
)
1145 ExFreePool((PVOID
) KernelModeMsg
.lParam
);
1152 pti
= PsGetCurrentThreadWin32Thread();
1153 return UserPostThreadMessage( pti
,
1158 if (Wnd
== HWND_BROADCAST
)
1164 DesktopWindow
= UserGetDesktopWindow();
1165 List
= IntWinListChildren(DesktopWindow
);
1169 UserPostMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1170 for (i
= 0; List
[i
]; i
++)
1172 PWND pwnd
= UserGetWindowObject(List
[i
]);
1173 if (!pwnd
) continue;
1175 if ( pwnd
->fnid
== FNID_MENU
|| // Also need pwnd->pcls->atomClassName == gaOleMainThreadWndClass
1176 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1179 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1181 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1188 Window
= UserGetWindowObject(Wnd
);
1191 ERR("UserPostMessage: Invalid handle 0x%p!\n",Wnd
);
1195 pti
= Window
->head
.pti
;
1196 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1198 ERR("Attempted to post message to window %p when the thread is in cleanup!\n", Wnd
);
1202 if ( Window
->state
& WNDS_DESTROYED
)
1204 ERR("Attempted to post message to window %p that is being destroyed!\n", Wnd
);
1205 /* FIXME: Last error code? */
1211 MsqPostQuitMessage(pti
, wParam
);
1215 MsqPostMessage(pti
, &Message
, FALSE
, QS_POSTMESSAGE
, 0);
1222 co_IntSendMessage( HWND hWnd
,
1227 ULONG_PTR Result
= 0;
1228 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1230 return (LRESULT
)Result
;
1235 static LRESULT FASTCALL
1236 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1242 ULONG_PTR
*uResult
)
1246 PMSGMEMORY MsgMemoryEntry
;
1247 INT lParamBufferSize
;
1248 LPARAM lParamPacked
;
1249 PTHREADINFO Win32Thread
, ptiSendTo
= NULL
;
1250 ULONG_PTR Hi
, Lo
, Result
= 0;
1251 DECLARE_RETURN(LRESULT
);
1252 USER_REFERENCE_ENTRY Ref
;
1253 BOOL DoCallBack
= TRUE
;
1255 if (!(Window
= UserGetWindowObject(hWnd
)))
1257 TRACE("SendMessageTimeoutSingle: Invalid handle 0x%p!\n",hWnd
);
1261 UserRefObjectCo(Window
, &Ref
);
1263 Win32Thread
= PsGetCurrentThreadWin32Thread();
1265 ptiSendTo
= IntSendTo(Window
, Win32Thread
, Msg
);
1269 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1271 /* Never send messages to exiting threads */
1275 if (Msg
& 0x80000000)
1277 TRACE("SMTS: Internal Message!\n");
1278 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1279 if (uResult
) *uResult
= Result
;
1283 // Only happens when calling the client!
1284 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1286 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1288 TRACE("SMT: Server Side Window Procedure\n");
1289 IoGetStackLimits(&Lo
, &Hi
);
1290 // Handle it here. Safeguard against excessive recursions.
1291 if (((ULONG_PTR
)&uResult
- Lo
) < 4096 )
1293 ERR("Server Callback Exceeded Stack!\n");
1296 /* Return after server side call, IntCallWndProcRet will not be called. */
1297 switch(Window
->fnid
)
1300 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1302 case FNID_MESSAGEWND
:
1303 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1308 if (uResult
) *uResult
= Result
;
1312 /* See if this message type is present in the table */
1313 MsgMemoryEntry
= FindMsgMemory(Msg
);
1314 if (NULL
== MsgMemoryEntry
)
1316 lParamBufferSize
= -1;
1320 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1323 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1325 ERR("Failed to pack message parameters\n");
1329 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1341 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1343 ERR("Failed to unpack message parameters\n");
1347 // Only happens when calling the client!
1348 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1353 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(ptiSendTo
/*Window->head.pti*/))
1355 // FIXME: Set window hung and add to a list.
1356 /* FIXME: Set a LastError? */
1360 if (Window
->state
& WNDS_DESTROYED
)
1362 /* FIXME: Last error? */
1363 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1369 Status
= co_MsqSendMessage( ptiSendTo
, //Window->head.pti,
1375 (uFlags
& SMTO_BLOCK
),
1379 while ((STATUS_TIMEOUT
== Status
) &&
1380 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1381 !MsqIsHung(ptiSendTo
/*Window->head.pti*/)); // FIXME: Set window hung and add to a list.
1383 if (STATUS_TIMEOUT
== Status
)
1387 * Microsoft Windows 2000: If GetLastError returns zero, then the function
1389 * XP+ : If the function fails or times out, the return value is zero.
1390 * To get extended error information, call GetLastError. If GetLastError
1391 * returns ERROR_TIMEOUT, then the function timed out.
1393 EngSetLastError(ERROR_TIMEOUT
);
1396 else if (!NT_SUCCESS(Status
))
1398 SetLastNtError(Status
);
1405 if (Window
) UserDerefObjectCo(Window
);
1410 co_IntSendMessageTimeout( HWND hWnd
,
1416 ULONG_PTR
*uResult
)
1422 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1424 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1427 DesktopWindow
= UserGetDesktopWindow();
1428 if (NULL
== DesktopWindow
)
1430 EngSetLastError(ERROR_INTERNAL_ERROR
);
1434 if (hWnd
!= HWND_TOPMOST
)
1436 /* Send message to the desktop window too! */
1437 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1440 Children
= IntWinListChildren(DesktopWindow
);
1441 if (NULL
== Children
)
1446 for (Child
= Children
; NULL
!= *Child
; Child
++)
1448 if (hWnd
== HWND_TOPMOST
)
1450 DesktopWindow
= UserGetWindowObject(*Child
);
1451 if (DesktopWindow
&& DesktopWindow
->ExStyle
& WS_EX_TOPMOST
)
1453 ERR("HWND_TOPMOST Found\n");
1454 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1459 PWND pwnd
= UserGetWindowObject(*Child
);
1460 if (!pwnd
) continue;
1462 if ( pwnd
->fnid
== FNID_MENU
||
1463 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1466 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1470 ExFreePool(Children
);
1472 return (LRESULT
) TRUE
;
1476 co_IntSendMessageNoWait(HWND hWnd
,
1481 ULONG_PTR Result
= 0;
1482 return co_IntSendMessageWithCallBack( hWnd
,
1491 If you send a message in the range below WM_USER to the asynchronous message
1492 functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its
1493 message parameters cannot include pointers. Otherwise, the operation will fail.
1494 The functions will return before the receiving thread has had a chance to
1495 process the message and the sender will free the memory before it is used.
1498 co_IntSendMessageWithCallBack( HWND hWnd
,
1502 SENDASYNCPROC CompletionCallback
,
1503 ULONG_PTR CompletionCallbackContext
,
1508 PMSGMEMORY MsgMemoryEntry
;
1509 INT lParamBufferSize
;
1510 LPARAM lParamPacked
;
1511 PTHREADINFO Win32Thread
, ptiSendTo
= NULL
;
1512 DECLARE_RETURN(LRESULT
);
1513 USER_REFERENCE_ENTRY Ref
;
1514 PUSER_SENT_MESSAGE Message
;
1515 BOOL DoCallBack
= TRUE
;
1517 if (!(Window
= UserGetWindowObject(hWnd
)))
1519 TRACE("SendMessageWithCallBack: Invalid handle 0x%p!\n",hWnd
);
1523 UserRefObjectCo(Window
, &Ref
);
1525 if (Window
->state
& WNDS_DESTROYED
)
1527 /* FIXME: last error? */
1528 ERR("Attempted to send message to window %p that is being destroyed!\n", hWnd
);
1532 Win32Thread
= PsGetCurrentThreadWin32Thread();
1534 if (Win32Thread
== NULL
||
1535 Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1540 ptiSendTo
= IntSendTo(Window
, Win32Thread
, Msg
);
1542 if (Msg
& 0x80000000 &&
1545 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
) RETURN( FALSE
);
1547 TRACE("SMWCB: Internal Message!\n");
1548 Result
= (ULONG_PTR
)handle_internal_message( Window
, Msg
, wParam
, lParam
);
1549 if (uResult
) *uResult
= Result
;
1553 /* See if this message type is present in the table */
1554 MsgMemoryEntry
= FindMsgMemory(Msg
);
1555 if (NULL
== MsgMemoryEntry
)
1557 lParamBufferSize
= -1;
1561 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1564 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, !!ptiSendTo
)))
1566 ERR("Failed to pack message parameters\n");
1570 /* If it can be sent now, then send it. */
1573 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1575 UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
);
1576 /* Never send messages to exiting threads */
1580 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1582 if ( Window
->state
& WNDS_SERVERSIDEWINDOWPROC
)
1584 TRACE("SMWCB: Server Side Window Procedure\n");
1585 switch(Window
->fnid
)
1588 DoCallBack
= !DesktopWindowProc(Window
, Msg
, wParam
, lParamPacked
, (LRESULT
*)&Result
);
1590 case FNID_MESSAGEWND
:
1591 DoCallBack
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,(LRESULT
*)&Result
);
1597 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1609 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1611 if (CompletionCallback
)
1613 co_IntCallSentMessageCallback(CompletionCallback
,
1616 CompletionCallbackContext
,
1623 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1625 ERR("Failed to unpack message parameters\n");
1630 if(!(Message
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
1632 ERR("MsqSendMessage(): Not enough memory to allocate a message");
1636 Message
->Msg
.hwnd
= hWnd
;
1637 Message
->Msg
.message
= Msg
;
1638 Message
->Msg
.wParam
= wParam
;
1639 Message
->Msg
.lParam
= lParamPacked
;
1640 Message
->CompletionEvent
= NULL
;
1641 Message
->Result
= 0;
1642 Message
->lResult
= 0;
1643 Message
->QS_Flags
= 0;
1644 Message
->ptiReceiver
= ptiSendTo
; //Window->head.pti;
1645 Message
->ptiSender
= NULL
; // mjmartin, you are right! This is null.
1646 Message
->ptiCallBackSender
= Win32Thread
;
1647 Message
->DispatchingListEntry
.Flink
= NULL
;
1648 Message
->CompletionCallback
= CompletionCallback
;
1649 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1650 Message
->HookMessage
= MSQ_NORMAL
;
1651 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1652 Message
->QS_Flags
= QS_SENDMESSAGE
;
1654 if (Msg
& 0x80000000) // Higher priority event message!
1655 InsertHeadList(&ptiSendTo
->SentMessagesListHead
/*&Window->head.pti->SentMessagesListHead*/, &Message
->ListEntry
);
1657 InsertTailList(&ptiSendTo
->SentMessagesListHead
/*&Window->head.pti->SentMessagesListHead*/, &Message
->ListEntry
);
1658 MsqWakeQueue(ptiSendTo
/*Window->head.pti*/, QS_SENDMESSAGE
, TRUE
);
1663 if (Window
) UserDerefObjectCo(Window
);
1669 This HACK function posts a message if the destination's message queue belongs to
1670 another thread, otherwise it sends the message. It does not support broadcast
1674 co_IntPostOrSendMessage( HWND hWnd
,
1683 if ( hWnd
== HWND_BROADCAST
)
1688 if(!(Window
= UserGetWindowObject(hWnd
)))
1690 TRACE("PostOrSendMessage: Invalid handle 0x%p!\n",hWnd
);
1694 pti
= PsGetCurrentThreadWin32Thread();
1696 if ( IntSendTo(Window
, pti
, Msg
) &&
1697 FindMsgMemory(Msg
) == 0 )
1699 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1703 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1709 return (LRESULT
)Result
;
1713 co_IntDoSendMessage( HWND hWnd
,
1720 LRESULT Result
= TRUE
;
1725 PMSGMEMORY MsgMemoryEntry
;
1727 if (hWnd
!= HWND_BROADCAST
&& hWnd
!= HWND_TOPMOST
)
1729 Window
= UserGetWindowObject(hWnd
);
1736 /* Check for an exiting window. */
1737 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1739 ERR("co_IntDoSendMessage Window Exiting!\n");
1742 /* See if the current thread can handle the message */
1743 //pti = PsGetCurrentThreadWin32Thread();
1745 UserModeMsg
.hwnd
= hWnd
;
1746 UserModeMsg
.message
= Msg
;
1747 UserModeMsg
.wParam
= wParam
;
1748 UserModeMsg
.lParam
= lParam
;
1749 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1751 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1752 if (! NT_SUCCESS(Status
))
1754 EngSetLastError(ERROR_INVALID_PARAMETER
);
1755 return (dsm
? 0 : -1);
1760 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1761 KernelModeMsg
.message
,
1762 KernelModeMsg
.wParam
,
1763 KernelModeMsg
.lParam
);
1767 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1768 KernelModeMsg
.message
,
1769 KernelModeMsg
.wParam
,
1770 KernelModeMsg
.lParam
,
1776 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1777 if (! NT_SUCCESS(Status
))
1779 EngSetLastError(ERROR_INVALID_PARAMETER
);
1780 return(dsm
? 0 : -1);
1783 return (LRESULT
)Result
;
1787 UserSendNotifyMessage( HWND hWnd
,
1794 if (is_pointer_message(Msg
))
1796 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1800 // Basicly the same as IntPostOrSendMessage
1801 if (hWnd
== HWND_BROADCAST
) // Handle Broadcast
1807 DesktopWindow
= UserGetDesktopWindow();
1808 List
= IntWinListChildren(DesktopWindow
);
1812 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1813 for (i
= 0; List
[i
]; i
++)
1815 PWND pwnd
= UserGetWindowObject(List
[i
]);
1816 if (!pwnd
) continue;
1818 if ( pwnd
->fnid
== FNID_MENU
||
1819 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
1822 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1829 Ret
= co_IntSendMessageNoWait( hWnd
, Msg
, wParam
, lParam
);
1836 IntGetQueueStatus(DWORD Changes
)
1841 pti
= PsGetCurrentThreadWin32Thread();
1843 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1845 /* High word, types of messages currently in the queue.
1846 Low word, types of messages that have been added to the queue and that
1847 are still in the queue
1849 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1851 pti
->pcti
->fsChangeBits
&= ~Changes
;
1857 IntInitMessagePumpHook()
1859 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1863 pti
->pcti
->dwcPumpHook
++;
1870 IntUninitMessagePumpHook()
1872 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1876 if (pti
->pcti
->dwcPumpHook
<= 0)
1880 pti
->pcti
->dwcPumpHook
--;
1886 /** Functions ******************************************************************/
1892 POINT pt
) // Just like the User call.
1896 ULONG wDragWidth
, wDragHeight
;
1897 DECLARE_RETURN(BOOL
);
1899 TRACE("Enter NtUserDragDetect(%p)\n", hWnd
);
1900 UserEnterExclusive();
1902 wDragWidth
= UserGetSystemMetrics(SM_CXDRAG
);
1903 wDragHeight
= UserGetSystemMetrics(SM_CYDRAG
);
1905 rect
.left
= pt
.x
- wDragWidth
;
1906 rect
.right
= pt
.x
+ wDragWidth
;
1908 rect
.top
= pt
.y
- wDragHeight
;
1909 rect
.bottom
= pt
.y
+ wDragHeight
;
1911 co_UserSetCapture(hWnd
);
1915 while (co_IntGetPeekMessage( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, FALSE
) ||
1916 co_IntGetPeekMessage( &msg
, 0, WM_QUEUESYNC
, WM_QUEUESYNC
, PM_REMOVE
, FALSE
) ||
1917 co_IntGetPeekMessage( &msg
, 0, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
, FALSE
) )
1919 if ( msg
.message
== WM_LBUTTONUP
)
1921 co_UserSetCapture(NULL
);
1924 if ( msg
.message
== WM_MOUSEMOVE
)
1927 tmp
.x
= (short)LOWORD(msg
.lParam
);
1928 tmp
.y
= (short)HIWORD(msg
.lParam
);
1929 if( !RECTL_bPointInRect( &rect
, tmp
.x
, tmp
.y
) )
1931 co_UserSetCapture(NULL
);
1935 if ( msg
.message
== WM_KEYDOWN
)
1937 if ( msg
.wParam
== VK_ESCAPE
)
1939 co_UserSetCapture(NULL
);
1943 if ( msg
.message
== WM_QUEUESYNC
)
1945 co_HOOK_CallHooks( WH_CBT
, HCBT_QS
, 0, 0 );
1948 co_IntWaitMessage(NULL
, 0, 0);
1953 TRACE("Leave NtUserDragDetect, ret=%i\n",_ret_
);
1959 NtUserPostMessage(HWND hWnd
,
1966 UserEnterExclusive();
1968 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1976 NtUserPostThreadMessage(DWORD idThread
,
1983 PTHREADINFO pThread
;
1986 UserEnterExclusive();
1988 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
1990 if ( Status
== STATUS_SUCCESS
)
1992 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
1994 !pThread
->MessageQueue
||
1995 (pThread
->TIF_flags
& TIF_INCLEANUP
))
1997 ObDereferenceObject( peThread
);
2000 ret
= UserPostThreadMessage( pThread
, Msg
, wParam
, lParam
);
2001 ObDereferenceObject( peThread
);
2005 SetLastNtError( Status
);
2013 NtUserWaitMessage(VOID
)
2017 UserEnterExclusive();
2018 TRACE("NtUserWaitMessage Enter\n");
2019 ret
= co_IntWaitMessage(NULL
, 0, 0);
2020 TRACE("NtUserWaitMessage Leave\n");
2027 NtUserGetMessage(PMSG pMsg
,
2035 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
2037 EngSetLastError(ERROR_INVALID_PARAMETER
);
2041 UserEnterExclusive();
2043 RtlZeroMemory(&Msg
, sizeof(MSG
));
2045 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
2053 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2054 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2056 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2058 SetLastNtError(_SEH2_GetExceptionCode());
2065 Ret
= Ret
? (WM_QUIT
!= pMsg
->message
) : FALSE
;
2071 NtUserPeekMessage( PMSG pMsg
,
2080 if ( RemoveMsg
& PM_BADMSGFLAGS
)
2082 EngSetLastError(ERROR_INVALID_FLAGS
);
2086 UserEnterExclusive();
2088 RtlZeroMemory(&Msg
, sizeof(MSG
));
2090 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
2098 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
2099 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
2101 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2103 SetLastNtError(_SEH2_GetExceptionCode());
2113 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
2120 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
2121 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
2123 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2125 _SEH2_YIELD(return FALSE
);
2129 UserEnterExclusive();
2131 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
2137 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
2144 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
2145 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
2147 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2157 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
2164 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
2165 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
2167 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2169 SetLastNtError(_SEH2_GetExceptionCode());
2170 _SEH2_YIELD(return FALSE
);
2174 UserEnterExclusive();
2176 Res
= IntDispatchMessage(&SafeMsg
);
2183 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
2191 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
2192 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
2194 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2196 SetLastNtError(_SEH2_GetExceptionCode());
2197 _SEH2_YIELD(return FALSE
);
2201 UserEnterExclusive();
2202 pWnd
= UserGetWindowObject(SafeMsg
.hwnd
);
2203 if (pWnd
) // Must have a window!
2205 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
2209 TRACE("No Window for Translate. hwnd 0x%p Msg %u\n", SafeMsg
.hwnd
, SafeMsg
.message
);
2217 LRESULT APIENTRY
ScrollBarWndProc(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
);
2220 NtUserMessageCall( HWND hWnd
,
2224 ULONG_PTR ResultInfo
,
2225 DWORD dwType
, // fnID?
2228 LRESULT lResult
= 0;
2231 USER_REFERENCE_ENTRY Ref
;
2233 UserEnterExclusive();
2237 case FNID_SCROLLBAR
:
2239 lResult
= ScrollBarWndProc(hWnd
, Msg
, wParam
, lParam
);
2244 Window
= UserGetWindowObject(hWnd
);
2247 //ERR("FNID_DESKTOP IN\n");
2248 Ret
= DesktopWindowProc(Window
, Msg
, wParam
, lParam
, &lResult
);
2249 //ERR("FNID_DESKTOP OUT\n");
2254 case FNID_MESSAGEWND
:
2256 Window
= UserGetWindowObject(hWnd
);
2259 Ret
= !UserMessageWindowProc(Window
, Msg
, wParam
, lParam
,&lResult
);
2263 case FNID_DEFWINDOWPROC
:
2264 /* Validate input */
2267 Window
= UserGetWindowObject(hWnd
);
2273 UserRefObjectCo(Window
, &Ref
);
2275 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2278 UserDerefObjectCo(Window
);
2280 case FNID_SENDNOTIFYMESSAGE
:
2281 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2283 case FNID_BROADCASTSYSTEMMESSAGE
:
2285 BROADCASTPARM parm
, *retparam
;
2286 DWORD_PTR RetVal
= 0;
2292 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2293 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2295 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2304 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2305 parm
.recipients
== BSM_ALLCOMPONENTS
)
2307 PLIST_ENTRY DesktopEntry
;
2309 HWND
*List
, hwndDenied
= NULL
;
2311 PWND pwnd
, pwndDesk
;
2315 for (DesktopEntry
= InputWindowStation
->DesktopListHead
.Flink
;
2316 DesktopEntry
!= &InputWindowStation
->DesktopListHead
;
2317 DesktopEntry
= DesktopEntry
->Flink
)
2319 rpdesk
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
2320 pwndDesk
= rpdesk
->pDeskInfo
->spwnd
;
2321 List
= IntWinListChildren(pwndDesk
);
2323 if (parm
.flags
& BSF_QUERY
)
2327 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2329 fuFlags
= SMTO_ABORTIFHUNG
;
2331 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2333 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2337 fuFlags
= SMTO_NORMAL
;
2339 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2347 for (i
= 0; List
[i
]; i
++)
2349 pwnd
= UserGetWindowObject(List
[i
]);
2350 if (!pwnd
) continue;
2352 if ( pwnd
->fnid
== FNID_MENU
||
2353 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2356 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2358 if ( pwnd
->head
.pti
== gptiCurrent
)
2361 co_IntSendMessageTimeout( List
[i
],
2369 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2371 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2374 if (RetVal
== BROADCAST_QUERY_DENY
)
2376 hwndDenied
= List
[i
];
2377 hDesk
= UserHMGetHandle(pwndDesk
);
2381 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2384 retparam
= (PBROADCASTPARM
) ResultInfo
;
2385 retparam
->hDesk
= hDesk
;
2386 retparam
->hWnd
= hwndDenied
;
2388 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2393 if (!Ret
) break; // Have a hit! Let everyone know!
2396 else if (parm
.flags
& BSF_POSTMESSAGE
)
2400 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2402 for (i
= 0; List
[i
]; i
++)
2404 pwnd
= UserGetWindowObject(List
[i
]);
2405 if (!pwnd
) continue;
2407 if ( pwnd
->fnid
== FNID_MENU
||
2408 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2411 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2413 if ( pwnd
->head
.pti
== gptiCurrent
)
2416 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2418 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2426 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2428 for (i
= 0; List
[i
]; i
++)
2430 pwnd
= UserGetWindowObject(List
[i
]);
2431 if (!pwnd
) continue;
2433 if ( pwnd
->fnid
== FNID_MENU
||
2434 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2437 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2439 if ( pwnd
->head
.pti
== gptiCurrent
)
2442 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2444 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2450 else if (parm
.recipients
& BSM_APPLICATIONS
)
2452 HWND
*List
, hwndDenied
= NULL
;
2454 PWND pwnd
, pwndDesk
;
2458 pwndDesk
= UserGetDesktopWindow();
2459 List
= IntWinListChildren(pwndDesk
);
2461 if (parm
.flags
& BSF_QUERY
)
2465 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2467 fuFlags
= SMTO_ABORTIFHUNG
;
2469 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2471 fuFlags
= SMTO_NOTIMEOUTIFNOTHUNG
;
2475 fuFlags
= SMTO_NORMAL
;
2477 co_IntSendMessageTimeout( UserHMGetHandle(pwndDesk
),
2485 for (i
= 0; List
[i
]; i
++)
2487 pwnd
= UserGetWindowObject(List
[i
]);
2488 if (!pwnd
) continue;
2490 if ( pwnd
->fnid
== FNID_MENU
||
2491 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2494 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2496 if ( pwnd
->head
.pti
== gptiCurrent
)
2499 co_IntSendMessageTimeout( List
[i
],
2507 if (!RetVal
&& EngGetLastError() == ERROR_TIMEOUT
)
2509 if (!(parm
.flags
& BSF_FORCEIFHUNG
))
2512 if (RetVal
== BROADCAST_QUERY_DENY
)
2514 hwndDenied
= List
[i
];
2515 hDesk
= UserHMGetHandle(pwndDesk
);
2519 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2522 retparam
= (PBROADCASTPARM
) ResultInfo
;
2523 retparam
->hDesk
= hDesk
;
2524 retparam
->hWnd
= hwndDenied
;
2526 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2533 else if (parm
.flags
& BSF_POSTMESSAGE
)
2537 UserPostMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2539 for (i
= 0; List
[i
]; i
++)
2541 pwnd
= UserGetWindowObject(List
[i
]);
2542 if (!pwnd
) continue;
2544 if ( pwnd
->fnid
== FNID_MENU
||
2545 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2548 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2550 if ( pwnd
->head
.pti
== gptiCurrent
)
2553 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
2555 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2563 UserSendNotifyMessage(UserHMGetHandle(pwndDesk
), Msg
, wParam
, lParam
);
2565 for (i
= 0; List
[i
]; i
++)
2567 pwnd
= UserGetWindowObject(List
[i
]);
2568 if (!pwnd
) continue;
2570 if ( pwnd
->fnid
== FNID_MENU
||
2571 pwnd
->pcls
->atomClassName
== gpsi
->atomSysClass
[ICLS_SWITCH
] )
2574 if ( parm
.flags
& BSF_IGNORECURRENTTASK
)
2576 if ( pwnd
->head
.pti
== gptiCurrent
)
2579 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
2581 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
2588 case FNID_SENDMESSAGECALLBACK
:
2590 CALL_BACK_INFO CallBackInfo
;
2595 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2596 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2598 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2604 if (is_pointer_message(Msg
))
2606 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
2610 if (!(Ret
= co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2611 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
)))
2613 ERR("Callback failure!\n");
2617 case FNID_SENDMESSAGE
:
2619 Ret
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2625 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2626 RtlCopyMemory((PVOID
)ResultInfo
, &Ret
, sizeof(ULONG_PTR
));
2628 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2637 case FNID_SENDMESSAGEFF
:
2638 case FNID_SENDMESSAGEWTOOPTION
:
2640 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2645 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2646 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2648 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2655 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, &dsm
);
2661 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2662 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2664 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2673 // CallNextHook bypass.
2674 case FNID_CALLWNDPROC
:
2675 case FNID_CALLWNDPROCRET
:
2678 PCLIENTINFO ClientInfo
;
2679 PHOOK NextObj
, Hook
;
2681 pti
= GetW32ThreadInfo();
2683 Hook
= pti
->sphkCurrent
;
2687 NextObj
= Hook
->phkNext
;
2688 ClientInfo
= pti
->pClientInfo
;
2691 ClientInfo
->phkCurrent
= NextObj
;
2693 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2699 if (!ClientInfo
|| !NextObj
) break;
2701 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2703 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2708 CWP
.wParam
= wParam
;
2709 CWP
.lParam
= lParam
;
2710 TRACE("WH_CALLWNDPROC: Hook %p NextHook %p\n", Hook
, NextObj
);
2712 lResult
= co_IntCallHookProc( Hook
->HookId
,
2714 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2727 CWPR
.wParam
= wParam
;
2728 CWPR
.lParam
= lParam
;
2729 CWPR
.lResult
= ClientInfo
->dwHookData
;
2731 lResult
= co_IntCallHookProc( Hook
->HookId
,
2733 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2747 case FNID_DEFWINDOWPROC
:
2748 case FNID_CALLWNDPROC
:
2749 case FNID_CALLWNDPROCRET
:
2750 case FNID_SCROLLBAR
:
2756 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2757 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2759 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2775 #define INFINITE 0xFFFFFFFF
2776 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2780 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2781 IN DWORD dwMilliseconds
,
2785 PPROCESSINFO W32Process
;
2789 LARGE_INTEGER Timeout
;
2791 UserEnterExclusive();
2793 Status
= ObReferenceObjectByHandle(hProcess
,
2794 PROCESS_QUERY_INFORMATION
,
2800 if (!NT_SUCCESS(Status
))
2803 SetLastNtError(Status
);
2807 pti
= PsGetCurrentThreadWin32Thread();
2809 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2811 if ( PsGetProcessExitProcessCalled(Process
) ||
2813 pti
->ppi
== W32Process
)
2815 ObDereferenceObject(Process
);
2817 EngSetLastError(ERROR_INVALID_PARAMETER
);
2821 Handles
[0] = Process
;
2822 Handles
[1] = W32Process
->InputIdleEvent
;
2823 Handles
[2] = pti
->pEventQueueServer
; // IntMsqSetWakeMask returns hEventQueueClient
2827 ObDereferenceObject(Process
);
2829 return STATUS_SUCCESS
; /* no event to wait on */
2832 if (dwMilliseconds
!= INFINITE
)
2833 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2835 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2836 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2838 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2839 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2842 TRACE("WFII: ppi %p\n", W32Process
);
2843 TRACE("WFII: waiting for %p\n", Handles
[1] );
2847 Status
= KeWaitForMultipleObjects( 3,
2853 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2855 UserEnterExclusive();
2857 if (!NT_SUCCESS(Status
))
2859 SetLastNtError(Status
);
2860 Status
= WAIT_FAILED
;
2872 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2873 ERR("WFII: WAIT 2\n");
2877 case STATUS_TIMEOUT
:
2878 ERR("WFII: timeout\n");
2883 ERR("WFII: finished\n");
2884 Status
= STATUS_SUCCESS
;
2891 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2893 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
2894 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2896 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
2897 ObDereferenceObject(Process
);