2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
5 * FILE: subsystems/win32/win32k/ntuser/message.c
6 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * 06-06-2001 CSH Created
11 /* INCLUDES ******************************************************************/
18 BOOLEAN NTAPI
PsGetProcessExitProcessCalled(PEPROCESS Process
);
20 #define PM_BADMSGFLAGS ~((QS_RAWINPUT << 16)|PM_QS_SENDMESSAGE|PM_QS_PAINT|PM_QS_POSTMESSAGE|PM_QS_INPUT|PM_NOYIELD|PM_REMOVE)
22 /* FUNCTIONS *****************************************************************/
25 IntInitMessageImpl(VOID
)
27 return STATUS_SUCCESS
;
31 IntCleanupMessageImpl(VOID
)
33 return STATUS_SUCCESS
;
37 /* flag for messages that contain pointers */
38 /* 32 messages per entry, messages 0..31 map to bits 0..31 */
40 #define SET(msg) (1 << ((msg) & 31))
42 static const unsigned int message_pointer_flags
[] =
45 SET(WM_CREATE
) | SET(WM_SETTEXT
) | SET(WM_GETTEXT
) |
46 SET(WM_WININICHANGE
) | SET(WM_DEVMODECHANGE
),
48 SET(WM_GETMINMAXINFO
) | SET(WM_DRAWITEM
) | SET(WM_MEASUREITEM
) | SET(WM_DELETEITEM
) |
51 SET(WM_WINDOWPOSCHANGING
) | SET(WM_WINDOWPOSCHANGED
) | SET(WM_COPYDATA
) |
52 SET(WM_COPYGLOBALDATA
) | SET(WM_NOTIFY
) | SET(WM_HELP
),
54 SET(WM_STYLECHANGING
) | SET(WM_STYLECHANGED
),
56 SET(WM_NCCREATE
) | SET(WM_NCCALCSIZE
) | SET(WM_GETDLGCODE
),
58 SET(EM_GETSEL
) | SET(EM_GETRECT
) | SET(EM_SETRECT
) | SET(EM_SETRECTNP
),
60 SET(EM_REPLACESEL
) | SET(EM_GETLINE
) | SET(EM_SETTABSTOPS
),
62 SET(SBM_GETRANGE
) | SET(SBM_SETSCROLLINFO
) | SET(SBM_GETSCROLLINFO
) | SET(SBM_GETSCROLLBARINFO
),
68 SET(CB_GETEDITSEL
) | SET(CB_ADDSTRING
) | SET(CB_DIR
) | SET(CB_GETLBTEXT
) |
69 SET(CB_INSERTSTRING
) | SET(CB_FINDSTRING
) | SET(CB_SELECTSTRING
) |
70 SET(CB_GETDROPPEDCONTROLRECT
) | SET(CB_FINDSTRINGEXACT
),
74 SET(LB_ADDSTRING
) | SET(LB_INSERTSTRING
) | SET(LB_GETTEXT
) | SET(LB_SELECTSTRING
) |
75 SET(LB_DIR
) | SET(LB_FINDSTRING
) |
76 SET(LB_GETSELITEMS
) | SET(LB_SETTABSTOPS
) | SET(LB_ADDFILE
) | SET(LB_GETITEMRECT
),
78 SET(LB_FINDSTRINGEXACT
),
84 SET(WM_NEXTMENU
) | SET(WM_SIZING
) | SET(WM_MOVING
) | SET(WM_DEVICECHANGE
),
86 SET(WM_MDICREATE
) | SET(WM_MDIGETACTIVE
) | SET(WM_DROPOBJECT
) |
87 SET(WM_QUERYDROPOBJECT
) | SET(WM_DRAGLOOP
) | SET(WM_DRAGSELECT
) | SET(WM_DRAGMOVE
),
101 SET(WM_ASKCBFORMATNAME
)
104 /* check whether a given message type includes pointers */
105 static inline int is_pointer_message( UINT message
)
107 if (message
>= 8*sizeof(message_pointer_flags
)) return FALSE
;
108 return (message_pointer_flags
[message
/ 32] & SET(message
)) != 0;
111 #define MMS_SIZE_WPARAM -1
112 #define MMS_SIZE_WPARAMWCHAR -2
113 #define MMS_SIZE_LPARAMSZ -3
114 #define MMS_SIZE_SPECIAL -4
115 #define MMS_FLAG_READ 0x01
116 #define MMS_FLAG_WRITE 0x02
117 #define MMS_FLAG_READWRITE (MMS_FLAG_READ | MMS_FLAG_WRITE)
118 typedef struct tagMSGMEMORY
124 MSGMEMORY
, *PMSGMEMORY
;
126 static MSGMEMORY MsgMemory
[] =
128 { WM_CREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
129 { WM_DDE_ACK
, sizeof(KMDDELPARAM
), MMS_FLAG_READ
},
130 { WM_DDE_EXECUTE
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
131 { WM_GETMINMAXINFO
, sizeof(MINMAXINFO
), MMS_FLAG_READWRITE
},
132 { WM_GETTEXT
, MMS_SIZE_WPARAMWCHAR
, MMS_FLAG_WRITE
},
133 { WM_NCCALCSIZE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
134 { WM_NCCREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
135 { WM_SETTEXT
, MMS_SIZE_LPARAMSZ
, MMS_FLAG_READ
},
136 { WM_STYLECHANGED
, sizeof(STYLESTRUCT
), MMS_FLAG_READ
},
137 { WM_STYLECHANGING
, sizeof(STYLESTRUCT
), MMS_FLAG_READWRITE
},
138 { WM_COPYDATA
, MMS_SIZE_SPECIAL
, MMS_FLAG_READ
},
139 { WM_COPYGLOBALDATA
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
140 { WM_WINDOWPOSCHANGED
, sizeof(WINDOWPOS
), MMS_FLAG_READ
},
141 { WM_WINDOWPOSCHANGING
, sizeof(WINDOWPOS
), MMS_FLAG_READWRITE
},
144 static PMSGMEMORY FASTCALL
145 FindMsgMemory(UINT Msg
)
147 PMSGMEMORY MsgMemoryEntry
;
149 /* See if this message type is present in the table */
150 for (MsgMemoryEntry
= MsgMemory
;
151 MsgMemoryEntry
< MsgMemory
+ sizeof(MsgMemory
) / sizeof(MSGMEMORY
);
154 if (Msg
== MsgMemoryEntry
->Message
)
156 return MsgMemoryEntry
;
164 MsgMemorySize(PMSGMEMORY MsgMemoryEntry
, WPARAM wParam
, LPARAM lParam
)
167 PUNICODE_STRING WindowName
;
168 PUNICODE_STRING ClassName
;
173 if (MMS_SIZE_WPARAM
== MsgMemoryEntry
->Size
)
177 else if (MMS_SIZE_WPARAMWCHAR
== MsgMemoryEntry
->Size
)
179 Size
= (UINT
) (wParam
* sizeof(WCHAR
));
181 else if (MMS_SIZE_LPARAMSZ
== MsgMemoryEntry
->Size
)
183 Size
= (UINT
) ((wcslen((PWSTR
) lParam
) + 1) * sizeof(WCHAR
));
185 else if (MMS_SIZE_SPECIAL
== MsgMemoryEntry
->Size
)
187 switch(MsgMemoryEntry
->Message
)
191 Cs
= (CREATESTRUCTW
*) lParam
;
192 WindowName
= (PUNICODE_STRING
) Cs
->lpszName
;
193 ClassName
= (PUNICODE_STRING
) Cs
->lpszClass
;
194 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
195 if (IS_ATOM(ClassName
->Buffer
))
197 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
201 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
206 Size
= wParam
? sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
) : sizeof(RECT
);
210 Size
= sizeof(COPYDATASTRUCT
) + ((PCOPYDATASTRUCT
)lParam
)->cbData
;
221 Size
= MsgMemoryEntry
->Size
;
224 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
226 DPRINT1("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH2_GetExceptionCode());
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 DPRINT1("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 DPRINT1("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
;
323 MsgMemoryEntry
= FindMsgMemory(Msg
);
325 if ((!MsgMemoryEntry
) || (MsgMemoryEntry
->Size
< 0))
327 /* Keep previous behavior */
328 return STATUS_SUCCESS
;
330 PackedData
= ExAllocatePoolWithTag(NonPagedPool
, MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
), TAG_MSG
);
331 RtlCopyMemory(PackedData
, (PVOID
)lParam
, MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
));
332 *lParamPacked
= (LPARAM
)PackedData
;
335 return STATUS_SUCCESS
;
339 UnpackParam(LPARAM lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolUsed
)
341 NCCALCSIZE_PARAMS
*UnpackedParams
;
342 NCCALCSIZE_PARAMS
*PackedParams
;
343 PWINDOWPOS UnpackedWindowPos
;
345 if (lParamPacked
== lParam
)
347 return STATUS_SUCCESS
;
350 if (WM_NCCALCSIZE
== Msg
&& wParam
)
352 PackedParams
= (NCCALCSIZE_PARAMS
*) lParamPacked
;
353 UnpackedParams
= (NCCALCSIZE_PARAMS
*) lParam
;
354 UnpackedWindowPos
= UnpackedParams
->lppos
;
355 RtlCopyMemory(UnpackedParams
, PackedParams
, sizeof(NCCALCSIZE_PARAMS
));
356 UnpackedParams
->lppos
= UnpackedWindowPos
;
357 RtlCopyMemory(UnpackedWindowPos
, PackedParams
+ 1, sizeof(WINDOWPOS
));
358 ExFreePool((PVOID
) lParamPacked
);
360 return STATUS_SUCCESS
;
362 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
364 ExFreePool((PVOID
) lParamPacked
);
366 return STATUS_SUCCESS
;
368 else if (NonPagedPoolUsed
)
370 PMSGMEMORY MsgMemoryEntry
;
371 MsgMemoryEntry
= FindMsgMemory(Msg
);
372 if (MsgMemoryEntry
->Size
< 0)
374 /* Keep previous behavior */
375 return STATUS_INVALID_PARAMETER
;
378 if (MsgMemory
->Flags
== MMS_FLAG_READWRITE
)
380 //RtlCopyMemory((PVOID)lParam, (PVOID)lParamPacked, MsgMemory->Size);
382 ExFreePool((PVOID
) lParamPacked
);
383 return STATUS_SUCCESS
;
388 return STATUS_INVALID_PARAMETER
;
391 static NTSTATUS FASTCALL
392 CopyMsgToKernelMem(MSG
*KernelModeMsg
, MSG
*UserModeMsg
, PMSGMEMORY MsgMemoryEntry
)
399 *KernelModeMsg
= *UserModeMsg
;
401 /* See if this message type is present in the table */
402 if (NULL
== MsgMemoryEntry
)
404 /* Not present, no copying needed */
405 return STATUS_SUCCESS
;
408 /* Determine required size */
409 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
413 /* Allocate kernel mem */
414 KernelMem
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
415 if (NULL
== KernelMem
)
417 DPRINT1("Not enough memory to copy message to kernel mem\n");
418 return STATUS_NO_MEMORY
;
420 KernelModeMsg
->lParam
= (LPARAM
) KernelMem
;
422 /* Copy data if required */
423 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_READ
))
425 Status
= MmCopyFromCaller(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
426 if (! NT_SUCCESS(Status
))
428 DPRINT1("Failed to copy message to kernel: invalid usermode buffer\n");
429 ExFreePoolWithTag(KernelMem
, TAG_MSG
);
435 /* Make sure we don't pass any secrets to usermode */
436 RtlZeroMemory(KernelMem
, Size
);
441 KernelModeMsg
->lParam
= 0;
444 return STATUS_SUCCESS
;
447 static NTSTATUS FASTCALL
448 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
451 PMSGMEMORY MsgMemoryEntry
;
454 /* See if this message type is present in the table */
455 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
456 if (NULL
== MsgMemoryEntry
)
458 /* Not present, no copying needed */
459 return STATUS_SUCCESS
;
462 /* Determine required size */
463 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
467 /* Copy data if required */
468 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
470 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
471 if (! NT_SUCCESS(Status
))
473 DPRINT1("Failed to copy message from kernel: invalid usermode buffer\n");
474 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
479 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
482 return STATUS_SUCCESS
;
486 // Wakeup any thread/process waiting on idle input.
491 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
492 PUSER_MESSAGE_QUEUE ForegroundQueue
;
493 PTHREADINFO pti
, ptiForeground
= NULL
;
495 ForegroundQueue
= IntGetFocusMessageQueue();
498 ptiForeground
= ForegroundQueue
->Thread
->Tcb
.Win32Thread
;
500 pti
= PsGetCurrentThreadWin32Thread();
504 pti
->pClientInfo
->cSpins
= 0; // Reset spins.
506 if ( pti
->pDeskInfo
&& pti
== ptiForeground
)
508 if ( pti
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) ||
509 pti
->pDeskInfo
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) )
511 co_HOOK_CallHooks(WH_FOREGROUNDIDLE
,HC_ACTION
,0,0);
516 DPRINT("IdlePing ppi 0x%x\n",ppi
);
517 if ( ppi
&& ppi
->InputIdleEvent
)
519 DPRINT("InputIdleEvent\n");
520 KeSetEvent( ppi
->InputIdleEvent
, IO_NO_INCREMENT
, FALSE
);
527 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
529 DPRINT("IdlePong ppi 0x%x\n",ppi
);
530 if ( ppi
&& ppi
->InputIdleEvent
)
532 KeClearEvent(ppi
->InputIdleEvent
);
537 GetWakeMask(UINT first
, UINT last
)
539 UINT mask
= QS_POSTMESSAGE
| QS_SENDMESSAGE
; /* Always selected */
543 if ((first
<= WM_KEYLAST
) && (last
>= WM_KEYFIRST
)) mask
|= QS_KEY
;
544 if ( ((first
<= WM_MOUSELAST
) && (last
>= WM_MOUSEFIRST
)) ||
545 ((first
<= WM_NCMOUSELAST
) && (last
>= WM_NCMOUSEFIRST
)) ) mask
|= QS_MOUSE
;
546 if ((first
<= WM_TIMER
) && (last
>= WM_TIMER
)) mask
|= QS_TIMER
;
547 if ((first
<= WM_SYSTIMER
) && (last
>= WM_SYSTIMER
)) mask
|= QS_TIMER
;
548 if ((first
<= WM_PAINT
) && (last
>= WM_PAINT
)) mask
|= QS_PAINT
;
550 else mask
= QS_ALLINPUT
;
556 IntCallWndProc( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
558 BOOL SameThread
= FALSE
;
561 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
568 co_HOOK_CallHooks( WH_CALLWNDPROC
, HC_ACTION
, SameThread
, (LPARAM
)&CWP
);
572 IntCallWndProcRet ( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*uResult
)
574 BOOL SameThread
= FALSE
;
577 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
582 CWPR
.wParam
= wParam
;
583 CWPR
.lParam
= lParam
;
584 CWPR
.lResult
= *uResult
;
585 co_HOOK_CallHooks( WH_CALLWNDPROCRET
, HC_ACTION
, SameThread
, (LPARAM
)&CWPR
);
589 IntDispatchMessage(PMSG pMsg
)
591 LARGE_INTEGER TickCount
;
599 Window
= UserGetWindowObject(pMsg
->hwnd
);
600 if (!Window
) return 0;
603 pti
= PsGetCurrentThreadWin32Thread();
605 if ( Window
->head
.pti
!= pti
)
607 EngSetLastError( ERROR_MESSAGE_SYNC_ONLY
);
611 if (((pMsg
->message
== WM_SYSTIMER
) ||
612 (pMsg
->message
== WM_TIMER
)) &&
615 if (pMsg
->message
== WM_TIMER
)
617 if (ValidateTimerCallback(pti
,pMsg
->lParam
))
619 KeQueryTickCount(&TickCount
);
620 Time
= MsqCalculateMessageTime(&TickCount
);
621 retval
= co_IntCallWindowProc((WNDPROC
)pMsg
->lParam
,
633 PTIMER pTimer
= FindSystemTimer(pMsg
);
634 if (pTimer
&& pTimer
->pfn
)
636 KeQueryTickCount(&TickCount
);
637 Time
= MsqCalculateMessageTime(&TickCount
);
638 pTimer
->pfn(pMsg
->hwnd
, WM_SYSTIMER
, (UINT
)pMsg
->wParam
, Time
);
644 if ( !Window
) return 0;
646 /* Since we are doing a callback on the same thread right away, there is
647 no need to copy the lparam to kernel mode and then back to usermode.
648 We just pretend it isn't a pointer */
650 retval
= co_IntCallWindowProc( Window
->lpfnWndProc
,
658 if (pMsg
->message
== WM_PAINT
)
660 /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
661 HRGN hrgn
= IntSysCreateRectRgn( 0, 0, 0, 0 );
662 co_UserGetUpdateRgn( Window
, hrgn
, TRUE
);
663 REGION_FreeRgnByHandle( hrgn
);
670 * Internal version of PeekMessage() doing all the work
673 co_IntPeekMessage( PMSG Msg
,
682 LARGE_INTEGER LargeTickCount
;
683 PUSER_MESSAGE_QUEUE ThreadQueue
;
688 pti
= PsGetCurrentThreadWin32Thread();
689 ThreadQueue
= pti
->MessageQueue
;
690 pci
= pti
->pClientInfo
;
692 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
693 ProcessMask
= HIWORD(RemoveMsg
);
695 /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns
696 all available messages (that is, no range filtering is performed)". */
697 if (!ProcessMask
) ProcessMask
= (QS_ALLPOSTMESSAGE
|QS_ALLINPUT
);
703 KeQueryTickCount(&LargeTickCount
);
704 ThreadQueue
->LastMsgRead
= LargeTickCount
.u
.LowPart
;
705 pti
->pcti
->tickLastMsgChecked
= LargeTickCount
.u
.LowPart
;
707 /* Dispatch sent messages here. */
708 while ( co_MsqDispatchOneSentMessage(ThreadQueue
) )
710 /* if some PM_QS* flags were specified, only handle sent messages from now on */
711 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
; // wine does this; ProcessMask = QS_SENDMESSAGE;
713 if (Hit
) return FALSE
;
715 /* Clear changed bits so we can wait on them if we don't find a message */
716 if (ProcessMask
& QS_POSTMESSAGE
)
718 pti
->pcti
->fsChangeBits
&= ~(QS_POSTMESSAGE
| QS_HOTKEY
| QS_TIMER
);
719 if (MsgFilterMin
== 0 && MsgFilterMax
== 0) // wine hack does this; ~0U)
721 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
725 if (ProcessMask
& QS_INPUT
)
727 pti
->pcti
->fsChangeBits
&= ~QS_INPUT
;
730 /* Now check for normal messages. */
731 if ((ProcessMask
& QS_POSTMESSAGE
) &&
732 MsqPeekMessage( ThreadQueue
,
743 /* Now look for a quit message. */
744 if (ThreadQueue
->QuitPosted
)
746 /* According to the PSDK, WM_QUIT messages are always returned, regardless
747 of the filter specified */
749 Msg
->message
= WM_QUIT
;
750 Msg
->wParam
= ThreadQueue
->QuitExitCode
;
754 ThreadQueue
->QuitPosted
= FALSE
;
755 ClearMsgBitsMask(ThreadQueue
, QS_POSTMESSAGE
);
756 pti
->pcti
->fsWakeBits
&= ~QS_ALLPOSTMESSAGE
;
757 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
762 /* Check for hardware events. */
763 if ((ProcessMask
& QS_MOUSE
) &&
764 co_MsqPeekMouseMove( ThreadQueue
,
774 if ((ProcessMask
& QS_INPUT
) &&
775 co_MsqPeekHardwareMessage( ThreadQueue
,
786 /* Check for sent messages again. */
787 while ( co_MsqDispatchOneSentMessage(ThreadQueue
) )
789 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
;
791 if (Hit
) return FALSE
;
793 /* Check for paint messages. */
794 if ((ProcessMask
& QS_PAINT
) &&
796 IntGetPaintMessage( Window
,
806 /* This is correct, check for the current threads timers waiting to be
807 posted to this threads message queue. If any we loop again.
809 if ((ProcessMask
& QS_TIMER
) &&
810 PostTimerMessages(Window
))
823 co_IntWaitMessage( PWND Window
,
828 PUSER_MESSAGE_QUEUE ThreadQueue
;
829 NTSTATUS Status
= STATUS_SUCCESS
;
832 pti
= PsGetCurrentThreadWin32Thread();
833 ThreadQueue
= pti
->MessageQueue
;
837 if ( co_IntPeekMessage( &Msg
, // Dont reenter!
841 MAKELONG( PM_NOREMOVE
, GetWakeMask( MsgFilterMin
, MsgFilterMax
)),
842 TRUE
) ) // act like GetMessage.
847 /* Nothing found. Wait for new messages. */
848 Status
= co_MsqWaitForNewMessages( ThreadQueue
,
853 while ( (STATUS_WAIT_0
<= Status
&& Status
<= STATUS_WAIT_63
) ||
854 STATUS_TIMEOUT
== Status
);
856 if (!NT_SUCCESS(Status
))
858 SetLastNtError(Status
);
859 DPRINT1("Exit co_IntWaitMessage on error!\n");
866 co_IntGetPeekMessage( PMSG pMsg
,
875 BOOL Present
= FALSE
;
877 if ( hWnd
== HWND_TOPMOST
|| hWnd
== HWND_BROADCAST
)
881 if (hWnd
&& hWnd
!= HWND_BOTTOM
)
883 if (!(Window
= UserGetWindowObject(hWnd
)))
896 if (MsgFilterMax
< MsgFilterMin
)
904 RemoveMsg
|= ((GetWakeMask( MsgFilterMin
, MsgFilterMax
))<< 16);
907 pti
= PsGetCurrentThreadWin32Thread();
908 pti
->pClientInfo
->cSpins
++; // Bump up the spin count.
912 Present
= co_IntPeekMessage( pMsg
,
920 /* GetMessage or PostMessage must never get messages that contain pointers */
921 ASSERT(FindMsgMemory(pMsg
->message
) == NULL
);
923 if (pMsg
->message
!= WM_PAINT
&& pMsg
->message
!= WM_QUIT
)
925 pti
->timeLast
= pMsg
->time
;
926 pti
->ptLast
= pMsg
->pt
;
929 // The WH_GETMESSAGE hook enables an application to monitor messages about to
930 // be returned by the GetMessage or PeekMessage function.
932 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)pMsg
);
936 Present
= (WM_QUIT
!= pMsg
->message
);
943 if ( !co_IntWaitMessage(Window
, MsgFilterMin
, MsgFilterMax
) )
951 if (!(RemoveMsg
& PM_NOYIELD
))
954 // Yield this thread!
957 UserEnterExclusive();
958 // Fall through to exit.
964 while( bGMSG
&& !Present
);
966 // Been spinning, time to swap vinyl...
967 if (pti
->pClientInfo
->cSpins
>= 100)
969 // Clear the spin cycle to fix the mix.
970 pti
->pClientInfo
->cSpins
= 0;
971 //if (!(pti->TIF_flags & TIF_SPINNING)) FIXME need to swap vinyl..
977 UserPostThreadMessage( DWORD idThread
,
985 LARGE_INTEGER LargeTickCount
;
988 if (is_pointer_message(Msg
))
990 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
994 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
996 if( Status
== STATUS_SUCCESS
)
998 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
1000 !pThread
->MessageQueue
||
1001 (pThread
->TIF_flags
& TIF_INCLEANUP
))
1003 ObDereferenceObject( peThread
);
1007 Message
.hwnd
= NULL
;
1008 Message
.message
= Msg
;
1009 Message
.wParam
= wParam
;
1010 Message
.lParam
= lParam
;
1011 Message
.pt
= gpsi
->ptCursor
;
1013 KeQueryTickCount(&LargeTickCount
);
1014 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1015 MsqPostMessage(pThread
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
);
1016 ObDereferenceObject( peThread
);
1021 SetLastNtError( Status
);
1027 UserPostMessage( HWND Wnd
,
1033 MSG Message
, KernelModeMsg
;
1034 LARGE_INTEGER LargeTickCount
;
1035 PMSGMEMORY MsgMemoryEntry
;
1038 Message
.message
= Msg
;
1039 Message
.wParam
= wParam
;
1040 Message
.lParam
= lParam
;
1041 Message
.pt
= gpsi
->ptCursor
;
1042 KeQueryTickCount(&LargeTickCount
);
1043 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1045 MsgMemoryEntry
= FindMsgMemory(Message
.message
);
1047 if( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1051 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &Message
, MsgMemoryEntry
);
1052 if (! NT_SUCCESS(Status
))
1054 EngSetLastError(ERROR_INVALID_PARAMETER
);
1057 co_IntSendMessageNoWait(KernelModeMsg
.hwnd
,
1058 KernelModeMsg
.message
,
1059 KernelModeMsg
.wParam
,
1060 KernelModeMsg
.lParam
);
1062 if (MsgMemoryEntry
&& KernelModeMsg
.lParam
)
1063 ExFreePool((PVOID
) KernelModeMsg
.lParam
);
1068 if (is_pointer_message(Message
.message
))
1070 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1076 return UserPostThreadMessage( PtrToInt(PsGetCurrentThreadId()),
1081 if (Wnd
== HWND_BROADCAST
)
1087 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1088 List
= IntWinListChildren(DesktopWindow
);
1092 UserPostMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1093 for (i
= 0; List
[i
]; i
++)
1095 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1097 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1104 Window
= UserGetWindowObject(Wnd
);
1110 pti
= Window
->head
.pti
;
1111 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1113 DPRINT1("Attempted to post message to window 0x%x when the thread is in cleanup!\n", Wnd
);
1117 if ( Window
->state
& WNDS_DESTROYED
)
1119 DPRINT1("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd
);
1120 /* FIXME - last error code? */
1126 MsqPostQuitMessage(Window
->head
.pti
->MessageQueue
, wParam
);
1130 MsqPostMessage(Window
->head
.pti
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
);
1138 co_IntSendMessage( HWND hWnd
,
1143 ULONG_PTR Result
= 0;
1144 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1146 return (LRESULT
)Result
;
1151 static LRESULT FASTCALL
1152 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1158 ULONG_PTR
*uResult
)
1162 PMSGMEMORY MsgMemoryEntry
;
1163 INT lParamBufferSize
;
1164 LPARAM lParamPacked
;
1165 PTHREADINFO Win32Thread
;
1166 ULONG_PTR Result
= 0;
1167 DECLARE_RETURN(LRESULT
);
1168 USER_REFERENCE_ENTRY Ref
;
1170 if (!(Window
= UserGetWindowObject(hWnd
)))
1175 UserRefObjectCo(Window
, &Ref
);
1177 Win32Thread
= PsGetCurrentThreadWin32Thread();
1179 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1181 if ( NULL
!= Win32Thread
&&
1182 Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1184 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1186 /* Never send messages to exiting threads */
1190 /* See if this message type is present in the table */
1191 MsgMemoryEntry
= FindMsgMemory(Msg
);
1192 if (NULL
== MsgMemoryEntry
)
1194 lParamBufferSize
= -1;
1198 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1201 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1203 DPRINT1("Failed to pack message parameters\n");
1207 ObReferenceObject(Win32Thread
->pEThread
);
1208 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1220 ObDereferenceObject(Win32Thread
->pEThread
);
1222 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1224 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1226 DPRINT1("Failed to unpack message parameters\n");
1233 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->head
.pti
->MessageQueue
))
1235 /* FIXME - Set a LastError? */
1239 if (Window
->state
& WNDS_DESTROYED
)
1241 /* FIXME - last error? */
1242 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1248 Status
= co_MsqSendMessage( Window
->head
.pti
->MessageQueue
,
1254 (uFlags
& SMTO_BLOCK
),
1258 while ((STATUS_TIMEOUT
== Status
) &&
1259 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1260 !MsqIsHung(Window
->head
.pti
->MessageQueue
));
1262 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1264 if (STATUS_TIMEOUT
== Status
)
1268 Microsoft Windows 2000: If GetLastError returns zero, then the function
1270 XP+ : If the function fails or times out, the return value is zero.
1271 To get extended error information, call GetLastError. If GetLastError
1272 returns ERROR_TIMEOUT, then the function timed out.
1274 EngSetLastError(ERROR_TIMEOUT
);
1277 else if (! NT_SUCCESS(Status
))
1279 SetLastNtError(Status
);
1286 if (Window
) UserDerefObjectCo(Window
);
1291 co_IntSendMessageTimeout( HWND hWnd
,
1297 ULONG_PTR
*uResult
)
1303 if (HWND_BROADCAST
!= hWnd
)
1305 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1308 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1309 if (NULL
== DesktopWindow
)
1311 EngSetLastError(ERROR_INTERNAL_ERROR
);
1315 /* Send message to the desktop window too! */
1316 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1318 Children
= IntWinListChildren(DesktopWindow
);
1319 if (NULL
== Children
)
1324 for (Child
= Children
; NULL
!= *Child
; Child
++)
1326 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1329 ExFreePool(Children
);
1331 return (LRESULT
) TRUE
;
1335 co_IntSendMessageNoWait(HWND hWnd
,
1340 ULONG_PTR Result
= 0;
1341 co_IntSendMessageWithCallBack(hWnd
,
1352 co_IntSendMessageWithCallBack( HWND hWnd
,
1356 SENDASYNCPROC CompletionCallback
,
1357 ULONG_PTR CompletionCallbackContext
,
1362 PMSGMEMORY MsgMemoryEntry
;
1363 INT lParamBufferSize
;
1364 LPARAM lParamPacked
;
1365 PTHREADINFO Win32Thread
;
1366 DECLARE_RETURN(LRESULT
);
1367 USER_REFERENCE_ENTRY Ref
;
1368 PUSER_SENT_MESSAGE Message
;
1370 if (!(Window
= UserGetWindowObject(hWnd
)))
1375 UserRefObjectCo(Window
, &Ref
);
1377 if (Window
->state
& WNDS_DESTROYED
)
1379 /* FIXME - last error? */
1380 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1384 Win32Thread
= PsGetCurrentThreadWin32Thread();
1386 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1388 if (Win32Thread
== NULL
)
1394 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1396 /* Never send messages to exiting threads */
1400 /* See if this message type is present in the table */
1401 MsgMemoryEntry
= FindMsgMemory(Msg
);
1402 if (NULL
== MsgMemoryEntry
)
1404 lParamBufferSize
= -1;
1408 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1411 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, Window
->head
.pti
->MessageQueue
!= Win32Thread
->MessageQueue
)))
1413 DPRINT1("Failed to pack message parameters\n");
1417 /* If this is not a callback and it can be sent now, then send it. */
1418 if ((Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
) && (CompletionCallback
== NULL
))
1420 ObReferenceObject(Win32Thread
->pEThread
);
1421 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1432 ObDereferenceObject(Win32Thread
->pEThread
);
1435 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1437 if ((Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
) && (CompletionCallback
== NULL
))
1439 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1441 DPRINT1("Failed to unpack message parameters\n");
1446 if(!(Message
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
1448 DPRINT1("MsqSendMessage(): Not enough memory to allocate a message");
1449 return STATUS_INSUFFICIENT_RESOURCES
;
1452 Message
->Msg
.hwnd
= hWnd
;
1453 Message
->Msg
.message
= Msg
;
1454 Message
->Msg
.wParam
= wParam
;
1455 Message
->Msg
.lParam
= lParamPacked
;
1456 Message
->CompletionEvent
= NULL
;
1457 Message
->Result
= 0;
1458 Message
->lResult
= 0;
1459 Message
->QS_Flags
= 0;
1460 Message
->SenderQueue
= NULL
; // mjmartin, you are right! This is null.
1461 Message
->CallBackSenderQueue
= Win32Thread
->MessageQueue
;
1463 IntReferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1464 Message
->CompletionCallback
= CompletionCallback
;
1465 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1466 Message
->HookMessage
= MSQ_NORMAL
| MSQ_SENTNOWAIT
;
1467 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1469 Message
->QS_Flags
= QS_SENDMESSAGE
;
1470 MsqWakeQueue(Window
->head
.pti
->MessageQueue
, QS_SENDMESSAGE
, FALSE
);
1472 InsertTailList(&Window
->head
.pti
->MessageQueue
->SentMessagesListHead
, &Message
->ListEntry
);
1473 IntDereferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1478 if (Window
) UserDerefObjectCo(Window
);
1482 /* This function posts a message if the destination's message queue belongs to
1483 another thread, otherwise it sends the message. It does not support broadcast
1486 co_IntPostOrSendMessage( HWND hWnd
,
1495 if ( hWnd
== HWND_BROADCAST
)
1500 if(!(Window
= UserGetWindowObject(hWnd
)))
1505 pti
= PsGetCurrentThreadWin32Thread();
1507 if ( Window
->head
.pti
->MessageQueue
!= pti
->MessageQueue
&&
1508 FindMsgMemory(Msg
) == 0 )
1510 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1514 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1520 return (LRESULT
)Result
;
1524 co_IntDoSendMessage( HWND hWnd
,
1531 LRESULT Result
= TRUE
;
1536 PMSGMEMORY MsgMemoryEntry
;
1538 if (HWND_BROADCAST
!= hWnd
)
1540 Window
= UserGetWindowObject(hWnd
);
1547 /* Check for an exiting window. */
1548 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1550 DPRINT1("co_IntDoSendMessage Window Exiting!\n");
1553 /* See if the current thread can handle the message */
1554 pti
= PsGetCurrentThreadWin32Thread();
1556 UserModeMsg
.hwnd
= hWnd
;
1557 UserModeMsg
.message
= Msg
;
1558 UserModeMsg
.wParam
= wParam
;
1559 UserModeMsg
.lParam
= lParam
;
1560 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1562 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1563 if (! NT_SUCCESS(Status
))
1565 EngSetLastError(ERROR_INVALID_PARAMETER
);
1566 return (dsm
? 0 : -1);
1571 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1572 KernelModeMsg
.message
,
1573 KernelModeMsg
.wParam
,
1574 KernelModeMsg
.lParam
);
1578 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1579 KernelModeMsg
.message
,
1580 KernelModeMsg
.wParam
,
1581 KernelModeMsg
.lParam
,
1587 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1588 if (! NT_SUCCESS(Status
))
1590 EngSetLastError(ERROR_INVALID_PARAMETER
);
1591 return(dsm
? 0 : -1);
1594 return (LRESULT
)Result
;
1598 UserSendNotifyMessage( HWND hWnd
,
1605 if (is_pointer_message(Msg
))
1607 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1611 // Basicly the same as IntPostOrSendMessage
1612 if (hWnd
== HWND_BROADCAST
) //Handle Broadcast
1618 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1619 List
= IntWinListChildren(DesktopWindow
);
1623 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1624 for (i
= 0; List
[i
]; i
++)
1626 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1633 ULONG_PTR lResult
= 0;
1634 Ret
= co_IntSendMessageWithCallBack( hWnd
,
1647 IntGetQueueStatus(DWORD Changes
)
1650 PUSER_MESSAGE_QUEUE Queue
;
1653 pti
= PsGetCurrentThreadWin32Thread();
1654 Queue
= pti
->MessageQueue
;
1656 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1658 /* High word, types of messages currently in the queue.
1659 Low word, types of messages that have been added to the queue and that
1660 are still in the queue
1662 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1664 pti
->pcti
->fsChangeBits
&= ~Changes
;
1670 IntInitMessagePumpHook()
1672 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1676 pti
->pcti
->dwcPumpHook
++;
1683 IntUninitMessagePumpHook()
1685 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1689 if (pti
->pcti
->dwcPumpHook
<= 0)
1693 pti
->pcti
->dwcPumpHook
--;
1699 /** Functions ******************************************************************/
1702 NtUserPostMessage(HWND hWnd
,
1709 UserEnterExclusive();
1711 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1719 NtUserPostThreadMessage(DWORD idThread
,
1726 UserEnterExclusive();
1728 ret
= UserPostThreadMessage( idThread
, Msg
, wParam
, lParam
);
1736 NtUserWaitMessage(VOID
)
1740 UserEnterExclusive();
1741 DPRINT("NtUserWaitMessage Enter\n");
1742 ret
= co_IntWaitMessage(NULL
, 0, 0);
1743 DPRINT("NtUserWaitMessage Leave\n");
1750 NtUserGetMessage(PMSG pMsg
,
1758 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
1760 EngSetLastError(ERROR_INVALID_PARAMETER
);
1764 UserEnterExclusive();
1766 RtlZeroMemory(&Msg
, sizeof(MSG
));
1768 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
1776 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
1777 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
1779 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1781 SetLastNtError(_SEH2_GetExceptionCode());
1791 NtUserPeekMessage( PMSG pMsg
,
1800 if ( RemoveMsg
& PM_BADMSGFLAGS
)
1802 EngSetLastError(ERROR_INVALID_FLAGS
);
1806 UserEnterExclusive();
1808 RtlZeroMemory(&Msg
, sizeof(MSG
));
1810 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
1818 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
1819 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
1821 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1823 SetLastNtError(_SEH2_GetExceptionCode());
1833 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
1840 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
1841 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
1843 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1845 _SEH2_YIELD(return FALSE
);
1849 UserEnterExclusive();
1851 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
1857 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
1864 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
1865 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
1867 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1877 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
1884 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
1885 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
1887 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1889 SetLastNtError(_SEH2_GetExceptionCode());
1890 _SEH2_YIELD(return FALSE
);
1894 UserEnterExclusive();
1896 Res
= IntDispatchMessage(&SafeMsg
);
1904 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
1911 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
1912 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
1914 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1916 SetLastNtError(_SEH2_GetExceptionCode());
1917 _SEH2_YIELD(return FALSE
);
1921 UserEnterExclusive();
1923 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
1931 NtUserMessageCall( HWND hWnd
,
1935 ULONG_PTR ResultInfo
,
1936 DWORD dwType
, // fnID?
1939 LRESULT lResult
= 0;
1942 USER_REFERENCE_ENTRY Ref
;
1944 UserEnterExclusive();
1946 /* Validate input */
1947 if (hWnd
&& (hWnd
!= INVALID_HANDLE_VALUE
))
1949 Window
= UserGetWindowObject(hWnd
);
1959 case FNID_DEFWINDOWPROC
:
1960 if (Window
) UserRefObjectCo(Window
, &Ref
);
1961 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
1963 if (Window
) UserDerefObjectCo(Window
);
1965 case FNID_SENDNOTIFYMESSAGE
:
1966 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
1968 case FNID_BROADCASTSYSTEMMESSAGE
:
1971 DWORD_PTR RetVal
= 0;
1977 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
1978 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
1980 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1990 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
1991 parm
.recipients
== BSM_ALLCOMPONENTS
)
1994 else if (parm
.recipients
& BSM_APPLICATIONS
)
1996 if (parm
.flags
& BSF_QUERY
)
1998 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2000 co_IntSendMessageTimeout( HWND_BROADCAST
,
2008 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2010 co_IntSendMessageTimeout( HWND_BROADCAST
,
2014 SMTO_NOTIMEOUTIFNOTHUNG
,
2020 co_IntSendMessageTimeout( HWND_BROADCAST
,
2030 else if (parm
.flags
& BSF_POSTMESSAGE
)
2032 Ret
= UserPostMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2034 else //Everything else,,,, if ( parm.flags & BSF_SENDNOTIFYMESSAGE)
2036 Ret
= UserSendNotifyMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2041 case FNID_SENDMESSAGECALLBACK
:
2043 CALL_BACK_INFO CallBackInfo
;
2048 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2049 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2051 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2058 if (!co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2059 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
))
2061 DPRINT1("Callback failure!\n");
2065 case FNID_SENDMESSAGE
:
2067 Ret
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2073 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2074 RtlCopyMemory((PVOID
)ResultInfo
, &Ret
, sizeof(ULONG_PTR
));
2076 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2085 case FNID_SENDMESSAGETIMEOUT
:
2087 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2092 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2093 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2095 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2103 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, &dsm
);
2109 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2110 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2112 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2121 // CallNextHook bypass.
2122 case FNID_CALLWNDPROC
:
2123 case FNID_CALLWNDPROCRET
:
2126 PCLIENTINFO ClientInfo
;
2127 PHOOK NextObj
, Hook
;
2129 pti
= GetW32ThreadInfo();
2131 Hook
= pti
->sphkCurrent
;
2135 NextObj
= Hook
->phkNext
;
2136 ClientInfo
= pti
->pClientInfo
;
2139 ClientInfo
->phkCurrent
= NextObj
;
2141 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2147 if (!ClientInfo
|| !NextObj
) break;
2149 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2151 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2156 CWP
.wParam
= wParam
;
2157 CWP
.lParam
= lParam
;
2158 DPRINT("WH_CALLWNDPROC: Hook %x NextHook %x\n", Hook
, NextObj
);
2160 lResult
= co_IntCallHookProc( Hook
->HookId
,
2162 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2173 CWPR
.wParam
= wParam
;
2174 CWPR
.lParam
= lParam
;
2175 CWPR
.lResult
= ClientInfo
->dwHookData
;
2177 lResult
= co_IntCallHookProc( Hook
->HookId
,
2179 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2191 case FNID_DEFWINDOWPROC
:
2192 case FNID_CALLWNDPROC
:
2193 case FNID_CALLWNDPROCRET
:
2198 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2199 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2201 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2217 #define INFINITE 0xFFFFFFFF
2218 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2222 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2223 IN DWORD dwMilliseconds
,
2227 PPROCESSINFO W32Process
;
2231 LARGE_INTEGER Timeout
;
2233 UserEnterExclusive();
2235 Status
= ObReferenceObjectByHandle(hProcess
,
2236 PROCESS_QUERY_INFORMATION
,
2242 if (!NT_SUCCESS(Status
))
2245 SetLastNtError(Status
);
2249 pti
= PsGetCurrentThreadWin32Thread();
2251 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2253 if ( PsGetProcessExitProcessCalled(Process
) ||
2255 pti
->ppi
== W32Process
)
2257 ObDereferenceObject(Process
);
2259 EngSetLastError(ERROR_INVALID_PARAMETER
);
2263 Handles
[0] = Process
;
2264 Handles
[1] = W32Process
->InputIdleEvent
;
2265 Handles
[2] = pti
->MessageQueue
->NewMessages
; // pEventQueueServer; IntMsqSetWakeMask returns hEventQueueClient
2269 ObDereferenceObject(Process
);
2271 return STATUS_SUCCESS
; /* no event to wait on */
2274 if (dwMilliseconds
!= INFINITE
)
2275 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2277 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2278 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2280 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2281 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2284 DPRINT("WFII: ppi 0x%x\n",W32Process
);
2285 DPRINT("WFII: waiting for %p\n", Handles
[1] );
2289 Status
= KeWaitForMultipleObjects( 3,
2295 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2297 UserEnterExclusive();
2299 if (!NT_SUCCESS(Status
))
2301 SetLastNtError(Status
);
2302 Status
= WAIT_FAILED
;
2314 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2315 DPRINT1("WFII: WAIT 2\n");
2319 case STATUS_TIMEOUT
:
2320 DPRINT1("WFII: timeout\n");
2325 DPRINT1("WFII: finished\n");
2326 Status
= STATUS_SUCCESS
;
2333 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2335 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
2336 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2338 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
2339 ObDereferenceObject(Process
);