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 ******************************************************************/
15 DBG_DEFAULT_CHANNEL(UserMsg
);
17 BOOLEAN NTAPI
PsGetProcessExitProcessCalled(PEPROCESS Process
);
19 #define PM_BADMSGFLAGS ~((QS_RAWINPUT << 16)|PM_QS_SENDMESSAGE|PM_QS_PAINT|PM_QS_POSTMESSAGE|PM_QS_INPUT|PM_NOYIELD|PM_REMOVE)
21 /* FUNCTIONS *****************************************************************/
24 IntInitMessageImpl(VOID
)
26 return STATUS_SUCCESS
;
30 IntCleanupMessageImpl(VOID
)
32 return STATUS_SUCCESS
;
36 /* flag for messages that contain pointers */
37 /* 32 messages per entry, messages 0..31 map to bits 0..31 */
39 #define SET(msg) (1 << ((msg) & 31))
41 static const unsigned int message_pointer_flags
[] =
44 SET(WM_CREATE
) | SET(WM_SETTEXT
) | SET(WM_GETTEXT
) |
45 SET(WM_WININICHANGE
) | SET(WM_DEVMODECHANGE
),
47 SET(WM_GETMINMAXINFO
) | SET(WM_DRAWITEM
) | SET(WM_MEASUREITEM
) | SET(WM_DELETEITEM
) |
50 SET(WM_WINDOWPOSCHANGING
) | SET(WM_WINDOWPOSCHANGED
) | SET(WM_COPYDATA
) |
51 SET(WM_COPYGLOBALDATA
) | SET(WM_NOTIFY
) | SET(WM_HELP
),
53 SET(WM_STYLECHANGING
) | SET(WM_STYLECHANGED
),
55 SET(WM_NCCREATE
) | SET(WM_NCCALCSIZE
) | SET(WM_GETDLGCODE
),
57 SET(EM_GETSEL
) | SET(EM_GETRECT
) | SET(EM_SETRECT
) | SET(EM_SETRECTNP
),
59 SET(EM_REPLACESEL
) | SET(EM_GETLINE
) | SET(EM_SETTABSTOPS
),
61 SET(SBM_GETRANGE
) | SET(SBM_SETSCROLLINFO
) | SET(SBM_GETSCROLLINFO
) | SET(SBM_GETSCROLLBARINFO
),
67 SET(CB_GETEDITSEL
) | SET(CB_ADDSTRING
) | SET(CB_DIR
) | SET(CB_GETLBTEXT
) |
68 SET(CB_INSERTSTRING
) | SET(CB_FINDSTRING
) | SET(CB_SELECTSTRING
) |
69 SET(CB_GETDROPPEDCONTROLRECT
) | SET(CB_FINDSTRINGEXACT
),
73 SET(LB_ADDSTRING
) | SET(LB_INSERTSTRING
) | SET(LB_GETTEXT
) | SET(LB_SELECTSTRING
) |
74 SET(LB_DIR
) | SET(LB_FINDSTRING
) |
75 SET(LB_GETSELITEMS
) | SET(LB_SETTABSTOPS
) | SET(LB_ADDFILE
) | SET(LB_GETITEMRECT
),
77 SET(LB_FINDSTRINGEXACT
),
83 SET(WM_NEXTMENU
) | SET(WM_SIZING
) | SET(WM_MOVING
) | SET(WM_DEVICECHANGE
),
85 SET(WM_MDICREATE
) | SET(WM_MDIGETACTIVE
) | SET(WM_DROPOBJECT
) |
86 SET(WM_QUERYDROPOBJECT
) | SET(WM_DRAGLOOP
) | SET(WM_DRAGSELECT
) | SET(WM_DRAGMOVE
),
100 SET(WM_ASKCBFORMATNAME
)
103 /* check whether a given message type includes pointers */
104 static inline int is_pointer_message( UINT message
)
106 if (message
>= 8*sizeof(message_pointer_flags
)) return FALSE
;
107 return (message_pointer_flags
[message
/ 32] & SET(message
)) != 0;
110 #define MMS_SIZE_WPARAM -1
111 #define MMS_SIZE_WPARAMWCHAR -2
112 #define MMS_SIZE_LPARAMSZ -3
113 #define MMS_SIZE_SPECIAL -4
114 #define MMS_FLAG_READ 0x01
115 #define MMS_FLAG_WRITE 0x02
116 #define MMS_FLAG_READWRITE (MMS_FLAG_READ | MMS_FLAG_WRITE)
117 typedef struct tagMSGMEMORY
123 MSGMEMORY
, *PMSGMEMORY
;
125 static MSGMEMORY MsgMemory
[] =
127 { WM_CREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
128 { WM_DDE_ACK
, sizeof(KMDDELPARAM
), MMS_FLAG_READ
},
129 { WM_DDE_EXECUTE
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
130 { WM_GETMINMAXINFO
, sizeof(MINMAXINFO
), MMS_FLAG_READWRITE
},
131 { WM_GETTEXT
, MMS_SIZE_WPARAMWCHAR
, MMS_FLAG_WRITE
},
132 { WM_NCCALCSIZE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
133 { WM_NCCREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
134 { WM_SETTEXT
, MMS_SIZE_LPARAMSZ
, MMS_FLAG_READ
},
135 { WM_STYLECHANGED
, sizeof(STYLESTRUCT
), MMS_FLAG_READ
},
136 { WM_STYLECHANGING
, sizeof(STYLESTRUCT
), MMS_FLAG_READWRITE
},
137 { WM_COPYDATA
, MMS_SIZE_SPECIAL
, MMS_FLAG_READ
},
138 { WM_COPYGLOBALDATA
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
139 { WM_WINDOWPOSCHANGED
, sizeof(WINDOWPOS
), MMS_FLAG_READ
},
140 { WM_WINDOWPOSCHANGING
, sizeof(WINDOWPOS
), MMS_FLAG_READWRITE
},
143 static PMSGMEMORY FASTCALL
144 FindMsgMemory(UINT Msg
)
146 PMSGMEMORY MsgMemoryEntry
;
148 /* See if this message type is present in the table */
149 for (MsgMemoryEntry
= MsgMemory
;
150 MsgMemoryEntry
< MsgMemory
+ sizeof(MsgMemory
) / sizeof(MSGMEMORY
);
153 if (Msg
== MsgMemoryEntry
->Message
)
155 return MsgMemoryEntry
;
163 MsgMemorySize(PMSGMEMORY MsgMemoryEntry
, WPARAM wParam
, LPARAM lParam
)
166 PUNICODE_STRING WindowName
;
167 PUNICODE_STRING ClassName
;
172 if (MMS_SIZE_WPARAM
== MsgMemoryEntry
->Size
)
176 else if (MMS_SIZE_WPARAMWCHAR
== MsgMemoryEntry
->Size
)
178 Size
= (UINT
) (wParam
* sizeof(WCHAR
));
180 else if (MMS_SIZE_LPARAMSZ
== MsgMemoryEntry
->Size
)
182 Size
= (UINT
) ((wcslen((PWSTR
) lParam
) + 1) * sizeof(WCHAR
));
184 else if (MMS_SIZE_SPECIAL
== MsgMemoryEntry
->Size
)
186 switch(MsgMemoryEntry
->Message
)
190 Cs
= (CREATESTRUCTW
*) lParam
;
191 WindowName
= (PUNICODE_STRING
) Cs
->lpszName
;
192 ClassName
= (PUNICODE_STRING
) Cs
->lpszClass
;
193 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
194 if (IS_ATOM(ClassName
->Buffer
))
196 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
200 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
205 Size
= wParam
? sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
) : sizeof(RECT
);
209 Size
= sizeof(COPYDATASTRUCT
) + ((PCOPYDATASTRUCT
)lParam
)->cbData
;
220 Size
= MsgMemoryEntry
->Size
;
223 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
225 ERR("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH2_GetExceptionCode());
233 PackParam(LPARAM
*lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolNeeded
)
235 NCCALCSIZE_PARAMS
*UnpackedNcCalcsize
;
236 NCCALCSIZE_PARAMS
*PackedNcCalcsize
;
237 CREATESTRUCTW
*UnpackedCs
;
238 CREATESTRUCTW
*PackedCs
;
239 PLARGE_STRING WindowName
;
240 PUNICODE_STRING ClassName
;
245 *lParamPacked
= lParam
;
247 if (NonPagedPoolNeeded
)
248 PoolType
= NonPagedPool
;
250 PoolType
= PagedPool
;
252 if (WM_NCCALCSIZE
== Msg
&& wParam
)
255 UnpackedNcCalcsize
= (NCCALCSIZE_PARAMS
*) lParam
;
256 PackedNcCalcsize
= ExAllocatePoolWithTag(PoolType
,
257 sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
),
260 if (NULL
== PackedNcCalcsize
)
262 ERR("Not enough memory to pack lParam\n");
263 return STATUS_NO_MEMORY
;
265 RtlCopyMemory(PackedNcCalcsize
, UnpackedNcCalcsize
, sizeof(NCCALCSIZE_PARAMS
));
266 PackedNcCalcsize
->lppos
= (PWINDOWPOS
) (PackedNcCalcsize
+ 1);
267 RtlCopyMemory(PackedNcCalcsize
->lppos
, UnpackedNcCalcsize
->lppos
, sizeof(WINDOWPOS
));
268 *lParamPacked
= (LPARAM
) PackedNcCalcsize
;
270 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
272 UnpackedCs
= (CREATESTRUCTW
*) lParam
;
273 WindowName
= (PLARGE_STRING
) UnpackedCs
->lpszName
;
274 ClassName
= (PUNICODE_STRING
) UnpackedCs
->lpszClass
;
275 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
276 if (IS_ATOM(ClassName
->Buffer
))
278 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
282 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
284 PackedCs
= ExAllocatePoolWithTag(PoolType
, Size
, TAG_MSG
);
285 if (NULL
== PackedCs
)
287 ERR("Not enough memory to pack lParam\n");
288 return STATUS_NO_MEMORY
;
290 RtlCopyMemory(PackedCs
, UnpackedCs
, sizeof(CREATESTRUCTW
));
291 CsData
= (PCHAR
) (PackedCs
+ 1);
292 PackedCs
->lpszName
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
293 RtlCopyMemory(CsData
, WindowName
->Buffer
, WindowName
->Length
);
294 CsData
+= WindowName
->Length
;
295 *((WCHAR
*) CsData
) = L
'\0';
296 CsData
+= sizeof(WCHAR
);
297 PackedCs
->lpszClass
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
298 if (IS_ATOM(ClassName
->Buffer
))
300 *((WCHAR
*) CsData
) = L
'A';
301 CsData
+= sizeof(WCHAR
);
302 *((ATOM
*) CsData
) = (ATOM
)(DWORD_PTR
) ClassName
->Buffer
;
303 CsData
+= sizeof(ATOM
);
307 *((WCHAR
*) CsData
) = L
'S';
308 CsData
+= sizeof(WCHAR
);
309 RtlCopyMemory(CsData
, ClassName
->Buffer
, ClassName
->Length
);
310 CsData
+= ClassName
->Length
;
311 *((WCHAR
*) CsData
) = L
'\0';
312 CsData
+= sizeof(WCHAR
);
314 ASSERT(CsData
== (PCHAR
) PackedCs
+ Size
);
315 *lParamPacked
= (LPARAM
) PackedCs
;
317 else if (PoolType
== NonPagedPool
)
319 PMSGMEMORY MsgMemoryEntry
;
323 MsgMemoryEntry
= FindMsgMemory(Msg
);
325 if ((!MsgMemoryEntry
) || (MsgMemoryEntry
->Size
< 0))
327 /* Keep previous behavior */
328 return STATUS_SUCCESS
;
330 size
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
333 ERR("No size for lParamPacked\n");
334 return STATUS_SUCCESS
;
336 PackedData
= ExAllocatePoolWithTag(NonPagedPool
, size
, TAG_MSG
);
337 RtlCopyMemory(PackedData
, (PVOID
)lParam
, MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
));
338 *lParamPacked
= (LPARAM
)PackedData
;
341 return STATUS_SUCCESS
;
345 UnpackParam(LPARAM lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolUsed
)
347 NCCALCSIZE_PARAMS
*UnpackedParams
;
348 NCCALCSIZE_PARAMS
*PackedParams
;
349 PWINDOWPOS UnpackedWindowPos
;
351 if (lParamPacked
== lParam
)
353 return STATUS_SUCCESS
;
356 if (WM_NCCALCSIZE
== Msg
&& wParam
)
358 PackedParams
= (NCCALCSIZE_PARAMS
*) lParamPacked
;
359 UnpackedParams
= (NCCALCSIZE_PARAMS
*) lParam
;
360 UnpackedWindowPos
= UnpackedParams
->lppos
;
361 RtlCopyMemory(UnpackedParams
, PackedParams
, sizeof(NCCALCSIZE_PARAMS
));
362 UnpackedParams
->lppos
= UnpackedWindowPos
;
363 RtlCopyMemory(UnpackedWindowPos
, PackedParams
+ 1, sizeof(WINDOWPOS
));
364 ExFreePool((PVOID
) lParamPacked
);
366 return STATUS_SUCCESS
;
368 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
370 ExFreePool((PVOID
) lParamPacked
);
372 return STATUS_SUCCESS
;
374 else if (NonPagedPoolUsed
)
376 PMSGMEMORY MsgMemoryEntry
;
377 MsgMemoryEntry
= FindMsgMemory(Msg
);
378 if (MsgMemoryEntry
->Size
< 0)
380 /* Keep previous behavior */
381 return STATUS_INVALID_PARAMETER
;
384 if (MsgMemory
->Flags
== MMS_FLAG_READWRITE
)
386 //RtlCopyMemory((PVOID)lParam, (PVOID)lParamPacked, MsgMemory->Size);
388 ExFreePool((PVOID
) lParamPacked
);
389 return STATUS_SUCCESS
;
394 return STATUS_INVALID_PARAMETER
;
397 static NTSTATUS FASTCALL
398 CopyMsgToKernelMem(MSG
*KernelModeMsg
, MSG
*UserModeMsg
, PMSGMEMORY MsgMemoryEntry
)
405 *KernelModeMsg
= *UserModeMsg
;
407 /* See if this message type is present in the table */
408 if (NULL
== MsgMemoryEntry
)
410 /* Not present, no copying needed */
411 return STATUS_SUCCESS
;
414 /* Determine required size */
415 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
419 /* Allocate kernel mem */
420 KernelMem
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
421 if (NULL
== KernelMem
)
423 ERR("Not enough memory to copy message to kernel mem\n");
424 return STATUS_NO_MEMORY
;
426 KernelModeMsg
->lParam
= (LPARAM
) KernelMem
;
428 /* Copy data if required */
429 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_READ
))
431 Status
= MmCopyFromCaller(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
432 if (! NT_SUCCESS(Status
))
434 ERR("Failed to copy message to kernel: invalid usermode buffer\n");
435 ExFreePoolWithTag(KernelMem
, TAG_MSG
);
441 /* Make sure we don't pass any secrets to usermode */
442 RtlZeroMemory(KernelMem
, Size
);
447 KernelModeMsg
->lParam
= 0;
450 return STATUS_SUCCESS
;
453 static NTSTATUS FASTCALL
454 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
457 PMSGMEMORY MsgMemoryEntry
;
460 /* See if this message type is present in the table */
461 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
462 if (NULL
== MsgMemoryEntry
)
464 /* Not present, no copying needed */
465 return STATUS_SUCCESS
;
468 /* Determine required size */
469 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
473 /* Copy data if required */
474 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
476 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
477 if (! NT_SUCCESS(Status
))
479 ERR("Failed to copy message from kernel: invalid usermode buffer\n");
480 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
485 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
488 return STATUS_SUCCESS
;
492 // Wakeup any thread/process waiting on idle input.
497 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
498 PUSER_MESSAGE_QUEUE ForegroundQueue
;
499 PTHREADINFO pti
, ptiForeground
= NULL
;
501 ForegroundQueue
= IntGetFocusMessageQueue();
504 ptiForeground
= ForegroundQueue
->Thread
->Tcb
.Win32Thread
;
506 pti
= PsGetCurrentThreadWin32Thread();
510 pti
->pClientInfo
->cSpins
= 0; // Reset spins.
512 if ( pti
->pDeskInfo
&& pti
== ptiForeground
)
514 if ( pti
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) ||
515 pti
->pDeskInfo
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) )
517 co_HOOK_CallHooks(WH_FOREGROUNDIDLE
,HC_ACTION
,0,0);
522 TRACE("IdlePing ppi 0x%x\n",ppi
);
523 if ( ppi
&& ppi
->InputIdleEvent
)
525 TRACE("InputIdleEvent\n");
526 KeSetEvent( ppi
->InputIdleEvent
, IO_NO_INCREMENT
, FALSE
);
533 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
535 TRACE("IdlePong ppi 0x%x\n",ppi
);
536 if ( ppi
&& ppi
->InputIdleEvent
)
538 KeClearEvent(ppi
->InputIdleEvent
);
543 GetWakeMask(UINT first
, UINT last
)
545 UINT mask
= QS_POSTMESSAGE
| QS_SENDMESSAGE
; /* Always selected */
549 if ((first
<= WM_KEYLAST
) && (last
>= WM_KEYFIRST
)) mask
|= QS_KEY
;
550 if ( ((first
<= WM_MOUSELAST
) && (last
>= WM_MOUSEFIRST
)) ||
551 ((first
<= WM_NCMOUSELAST
) && (last
>= WM_NCMOUSEFIRST
)) ) mask
|= QS_MOUSE
;
552 if ((first
<= WM_TIMER
) && (last
>= WM_TIMER
)) mask
|= QS_TIMER
;
553 if ((first
<= WM_SYSTIMER
) && (last
>= WM_SYSTIMER
)) mask
|= QS_TIMER
;
554 if ((first
<= WM_PAINT
) && (last
>= WM_PAINT
)) mask
|= QS_PAINT
;
556 else mask
= QS_ALLINPUT
;
562 IntCallWndProc( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
564 BOOL SameThread
= FALSE
;
567 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
574 co_HOOK_CallHooks( WH_CALLWNDPROC
, HC_ACTION
, SameThread
, (LPARAM
)&CWP
);
578 IntCallWndProcRet ( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*uResult
)
580 BOOL SameThread
= FALSE
;
583 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
588 CWPR
.wParam
= wParam
;
589 CWPR
.lParam
= lParam
;
590 CWPR
.lResult
= *uResult
;
591 co_HOOK_CallHooks( WH_CALLWNDPROCRET
, HC_ACTION
, SameThread
, (LPARAM
)&CWPR
);
595 IntDispatchMessage(PMSG pMsg
)
597 LARGE_INTEGER TickCount
;
605 Window
= UserGetWindowObject(pMsg
->hwnd
);
606 if (!Window
) return 0;
609 pti
= PsGetCurrentThreadWin32Thread();
611 if ( Window
->head
.pti
!= pti
)
613 EngSetLastError( ERROR_MESSAGE_SYNC_ONLY
);
617 if (((pMsg
->message
== WM_SYSTIMER
) ||
618 (pMsg
->message
== WM_TIMER
)) &&
621 if (pMsg
->message
== WM_TIMER
)
623 if (ValidateTimerCallback(pti
,pMsg
->lParam
))
625 KeQueryTickCount(&TickCount
);
626 Time
= MsqCalculateMessageTime(&TickCount
);
627 retval
= co_IntCallWindowProc((WNDPROC
)pMsg
->lParam
,
639 PTIMER pTimer
= FindSystemTimer(pMsg
);
640 if (pTimer
&& pTimer
->pfn
)
642 KeQueryTickCount(&TickCount
);
643 Time
= MsqCalculateMessageTime(&TickCount
);
644 pTimer
->pfn(pMsg
->hwnd
, WM_SYSTIMER
, (UINT
)pMsg
->wParam
, Time
);
650 if ( !Window
) return 0;
652 /* Since we are doing a callback on the same thread right away, there is
653 no need to copy the lparam to kernel mode and then back to usermode.
654 We just pretend it isn't a pointer */
656 retval
= co_IntCallWindowProc( Window
->lpfnWndProc
,
664 if (pMsg
->message
== WM_PAINT
)
666 /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
667 HRGN hrgn
= IntSysCreateRectRgn( 0, 0, 0, 0 );
668 co_UserGetUpdateRgn( Window
, hrgn
, TRUE
);
669 GreDeleteObject(hrgn
);
676 * Internal version of PeekMessage() doing all the work
679 co_IntPeekMessage( PMSG Msg
,
688 LARGE_INTEGER LargeTickCount
;
689 PUSER_MESSAGE_QUEUE ThreadQueue
;
694 pti
= PsGetCurrentThreadWin32Thread();
695 ThreadQueue
= pti
->MessageQueue
;
696 pci
= pti
->pClientInfo
;
698 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
699 ProcessMask
= HIWORD(RemoveMsg
);
701 /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns
702 all available messages (that is, no range filtering is performed)". */
703 if (!ProcessMask
) ProcessMask
= (QS_ALLPOSTMESSAGE
|QS_ALLINPUT
);
709 KeQueryTickCount(&LargeTickCount
);
710 ThreadQueue
->LastMsgRead
= LargeTickCount
.u
.LowPart
;
711 pti
->pcti
->tickLastMsgChecked
= LargeTickCount
.u
.LowPart
;
713 /* Dispatch sent messages here. */
714 while ( co_MsqDispatchOneSentMessage(ThreadQueue
) )
716 /* if some PM_QS* flags were specified, only handle sent messages from now on */
717 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
; // wine does this; ProcessMask = QS_SENDMESSAGE;
719 if (Hit
) return FALSE
;
721 /* Clear changed bits so we can wait on them if we don't find a message */
722 if (ProcessMask
& QS_POSTMESSAGE
)
724 pti
->pcti
->fsChangeBits
&= ~(QS_POSTMESSAGE
| QS_HOTKEY
| QS_TIMER
);
725 if (MsgFilterMin
== 0 && MsgFilterMax
== 0) // wine hack does this; ~0U)
727 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
731 if (ProcessMask
& QS_INPUT
)
733 pti
->pcti
->fsChangeBits
&= ~QS_INPUT
;
736 /* Now check for normal messages. */
737 if (( (ProcessMask
& QS_POSTMESSAGE
) ||
738 (ProcessMask
& QS_HOTKEY
) ) &&
739 MsqPeekMessage( ThreadQueue
,
750 /* Now look for a quit message. */
751 if (ThreadQueue
->QuitPosted
)
753 /* According to the PSDK, WM_QUIT messages are always returned, regardless
754 of the filter specified */
756 Msg
->message
= WM_QUIT
;
757 Msg
->wParam
= ThreadQueue
->QuitExitCode
;
761 ThreadQueue
->QuitPosted
= FALSE
;
762 ClearMsgBitsMask(ThreadQueue
, QS_POSTMESSAGE
);
763 pti
->pcti
->fsWakeBits
&= ~QS_ALLPOSTMESSAGE
;
764 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
769 /* Check for hardware events. */
770 if ((ProcessMask
& QS_MOUSE
) &&
771 co_MsqPeekMouseMove( ThreadQueue
,
781 if ((ProcessMask
& QS_INPUT
) &&
782 co_MsqPeekHardwareMessage( ThreadQueue
,
793 /* Check for sent messages again. */
794 while ( co_MsqDispatchOneSentMessage(ThreadQueue
) )
796 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
;
798 if (Hit
) return FALSE
;
800 /* Check for paint messages. */
801 if ((ProcessMask
& QS_PAINT
) &&
803 IntGetPaintMessage( Window
,
813 /* This is correct, check for the current threads timers waiting to be
814 posted to this threads message queue. If any we loop again.
816 if ((ProcessMask
& QS_TIMER
) &&
817 PostTimerMessages(Window
))
830 co_IntWaitMessage( PWND Window
,
835 PUSER_MESSAGE_QUEUE ThreadQueue
;
836 NTSTATUS Status
= STATUS_SUCCESS
;
839 pti
= PsGetCurrentThreadWin32Thread();
840 ThreadQueue
= pti
->MessageQueue
;
844 if ( co_IntPeekMessage( &Msg
, // Dont reenter!
848 MAKELONG( PM_NOREMOVE
, GetWakeMask( MsgFilterMin
, MsgFilterMax
)),
849 TRUE
) ) // act like GetMessage.
854 /* Nothing found. Wait for new messages. */
855 Status
= co_MsqWaitForNewMessages( ThreadQueue
,
859 if (!NT_SUCCESS(Status
))
861 SetLastNtError(Status
);
862 ERR("Exit co_IntWaitMessage on error!\n");
865 if (Status
== STATUS_USER_APC
|| Status
== STATUS_TIMEOUT
)
876 co_IntGetPeekMessage( PMSG pMsg
,
885 BOOL Present
= FALSE
;
888 if ( hWnd
== HWND_TOPMOST
|| hWnd
== HWND_BROADCAST
)
892 if (hWnd
&& hWnd
!= HWND_BOTTOM
)
894 if (!(Window
= UserGetWindowObject(hWnd
)))
907 if (MsgFilterMax
< MsgFilterMin
)
915 RemoveMsg
|= ((GetWakeMask( MsgFilterMin
, MsgFilterMax
))<< 16);
918 pti
= PsGetCurrentThreadWin32Thread();
919 pti
->pClientInfo
->cSpins
++; // Bump up the spin count.
923 Present
= co_IntPeekMessage( pMsg
,
931 /* GetMessage or PostMessage must never get messages that contain pointers */
932 ASSERT(FindMsgMemory(pMsg
->message
) == NULL
);
934 if (pMsg
->message
!= WM_PAINT
&& pMsg
->message
!= WM_QUIT
)
936 pti
->timeLast
= pMsg
->time
;
937 pti
->ptLast
= pMsg
->pt
;
940 // The WH_GETMESSAGE hook enables an application to monitor messages about to
941 // be returned by the GetMessage or PeekMessage function.
943 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)pMsg
);
950 Status
= co_MsqWaitForNewMessages( pti
->MessageQueue
,
954 if ( !NT_SUCCESS(Status
) ||
955 Status
== STATUS_USER_APC
||
956 Status
== STATUS_TIMEOUT
)
964 if (!(RemoveMsg
& PM_NOYIELD
))
967 // Yield this thread!
970 UserEnterExclusive();
971 // Fall through to exit.
977 while( bGMSG
&& !Present
);
979 // Been spinning, time to swap vinyl...
980 if (pti
->pClientInfo
->cSpins
>= 100)
982 // Clear the spin cycle to fix the mix.
983 pti
->pClientInfo
->cSpins
= 0;
984 //if (!(pti->TIF_flags & TIF_SPINNING)) FIXME need to swap vinyl..
990 UserPostThreadMessage( DWORD idThread
,
998 LARGE_INTEGER LargeTickCount
;
1001 if (is_pointer_message(Msg
))
1003 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1007 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
1009 if( Status
== STATUS_SUCCESS
)
1011 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
1013 !pThread
->MessageQueue
||
1014 (pThread
->TIF_flags
& TIF_INCLEANUP
))
1016 ObDereferenceObject( peThread
);
1020 Message
.hwnd
= NULL
;
1021 Message
.message
= Msg
;
1022 Message
.wParam
= wParam
;
1023 Message
.lParam
= lParam
;
1024 Message
.pt
= gpsi
->ptCursor
;
1026 KeQueryTickCount(&LargeTickCount
);
1027 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1028 MsqPostMessage(pThread
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
);
1029 ObDereferenceObject( peThread
);
1034 SetLastNtError( Status
);
1040 UserPostMessage( HWND Wnd
,
1046 MSG Message
, KernelModeMsg
;
1047 LARGE_INTEGER LargeTickCount
;
1050 Message
.message
= Msg
;
1051 Message
.wParam
= wParam
;
1052 Message
.lParam
= lParam
;
1053 Message
.pt
= gpsi
->ptCursor
;
1054 KeQueryTickCount(&LargeTickCount
);
1055 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1057 if (is_pointer_message(Message
.message
))
1059 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1063 if( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1066 PMSGMEMORY MsgMemoryEntry
;
1068 MsgMemoryEntry
= FindMsgMemory(Message
.message
);
1070 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &Message
, MsgMemoryEntry
);
1071 if (! NT_SUCCESS(Status
))
1073 EngSetLastError(ERROR_INVALID_PARAMETER
);
1076 co_IntSendMessageNoWait(KernelModeMsg
.hwnd
,
1077 KernelModeMsg
.message
,
1078 KernelModeMsg
.wParam
,
1079 KernelModeMsg
.lParam
);
1081 if (MsgMemoryEntry
&& KernelModeMsg
.lParam
)
1082 ExFreePool((PVOID
) KernelModeMsg
.lParam
);
1089 return UserPostThreadMessage( PtrToInt(PsGetCurrentThreadId()),
1094 if (Wnd
== HWND_BROADCAST
)
1100 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1101 List
= IntWinListChildren(DesktopWindow
);
1105 UserPostMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1106 for (i
= 0; List
[i
]; i
++)
1108 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1110 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1117 Window
= UserGetWindowObject(Wnd
);
1123 pti
= Window
->head
.pti
;
1124 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1126 ERR("Attempted to post message to window 0x%x when the thread is in cleanup!\n", Wnd
);
1130 if ( Window
->state
& WNDS_DESTROYED
)
1132 ERR("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd
);
1133 /* FIXME - last error code? */
1139 MsqPostQuitMessage(Window
->head
.pti
->MessageQueue
, wParam
);
1143 MsqPostMessage(Window
->head
.pti
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
);
1151 co_IntSendMessage( HWND hWnd
,
1156 ULONG_PTR Result
= 0;
1157 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1159 return (LRESULT
)Result
;
1164 static LRESULT FASTCALL
1165 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1171 ULONG_PTR
*uResult
)
1175 PMSGMEMORY MsgMemoryEntry
;
1176 INT lParamBufferSize
;
1177 LPARAM lParamPacked
;
1178 PTHREADINFO Win32Thread
;
1179 ULONG_PTR Result
= 0;
1180 DECLARE_RETURN(LRESULT
);
1181 USER_REFERENCE_ENTRY Ref
;
1183 if (!(Window
= UserGetWindowObject(hWnd
)))
1185 ERR("UserGetWindowObject filed!\n");
1189 UserRefObjectCo(Window
, &Ref
);
1191 Win32Thread
= PsGetCurrentThreadWin32Thread();
1193 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1195 if ( NULL
!= Win32Thread
&&
1196 Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1198 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1200 ERR("Trying to send message to a thread in cleanup\n");
1201 /* Never send messages to exiting threads */
1205 /* See if this message type is present in the table */
1206 MsgMemoryEntry
= FindMsgMemory(Msg
);
1207 if (NULL
== MsgMemoryEntry
)
1209 lParamBufferSize
= -1;
1213 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1216 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1218 ERR("Failed to pack message parameters\n");
1222 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1234 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1236 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1238 ERR("Failed to unpack message parameters\n");
1245 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->head
.pti
->MessageQueue
))
1247 // FIXME - Set window hung and add to a list.
1248 /* FIXME - Set a LastError? */
1252 if (Window
->state
& WNDS_DESTROYED
)
1254 /* FIXME - last error? */
1255 ERR("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1261 Status
= co_MsqSendMessage( Window
->head
.pti
->MessageQueue
,
1267 (uFlags
& SMTO_BLOCK
),
1271 while ((STATUS_TIMEOUT
== Status
) &&
1272 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1273 !MsqIsHung(Window
->head
.pti
->MessageQueue
)); // FIXME - Set window hung and add to a list.
1275 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1277 if (STATUS_TIMEOUT
== Status
)
1281 Microsoft Windows 2000: If GetLastError returns zero, then the function
1283 XP+ : If the function fails or times out, the return value is zero.
1284 To get extended error information, call GetLastError. If GetLastError
1285 returns ERROR_TIMEOUT, then the function timed out.
1287 EngSetLastError(ERROR_TIMEOUT
);
1290 else if (! NT_SUCCESS(Status
))
1292 SetLastNtError(Status
);
1299 if (Window
) UserDerefObjectCo(Window
);
1304 co_IntSendMessageTimeout( HWND hWnd
,
1310 ULONG_PTR
*uResult
)
1316 if (HWND_BROADCAST
!= hWnd
)
1318 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1321 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1322 if (NULL
== DesktopWindow
)
1324 EngSetLastError(ERROR_INTERNAL_ERROR
);
1328 /* Send message to the desktop window too! */
1329 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1331 Children
= IntWinListChildren(DesktopWindow
);
1332 if (NULL
== Children
)
1337 for (Child
= Children
; NULL
!= *Child
; Child
++)
1339 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1342 ExFreePool(Children
);
1344 return (LRESULT
) TRUE
;
1348 co_IntSendMessageNoWait(HWND hWnd
,
1353 ULONG_PTR Result
= 0;
1354 co_IntSendMessageWithCallBack(hWnd
,
1364 If you send a message in the range below WM_USER to the asynchronous message
1365 functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its
1366 message parameters cannot include pointers. Otherwise, the operation will fail.
1367 The functions will return before the receiving thread has had a chance to
1368 process the message and the sender will free the memory before it is used.
1371 co_IntSendMessageWithCallBack( HWND hWnd
,
1375 SENDASYNCPROC CompletionCallback
,
1376 ULONG_PTR CompletionCallbackContext
,
1381 PMSGMEMORY MsgMemoryEntry
;
1382 INT lParamBufferSize
;
1383 LPARAM lParamPacked
;
1384 PTHREADINFO Win32Thread
;
1385 DECLARE_RETURN(LRESULT
);
1386 USER_REFERENCE_ENTRY Ref
;
1387 PUSER_SENT_MESSAGE Message
;
1389 if (!(Window
= UserGetWindowObject(hWnd
)))
1394 UserRefObjectCo(Window
, &Ref
);
1396 if (Window
->state
& WNDS_DESTROYED
)
1398 /* FIXME - last error? */
1399 ERR("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1403 Win32Thread
= PsGetCurrentThreadWin32Thread();
1405 if (Win32Thread
== NULL
)
1410 /* See if this message type is present in the table */
1411 MsgMemoryEntry
= FindMsgMemory(Msg
);
1412 if (NULL
== MsgMemoryEntry
)
1414 lParamBufferSize
= -1;
1418 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1421 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, Window
->head
.pti
->MessageQueue
!= Win32Thread
->MessageQueue
)))
1423 ERR("Failed to pack message parameters\n");
1427 /* If it can be sent now, then send it. */
1428 if (Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1430 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1432 UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
);
1433 /* Never send messages to exiting threads */
1437 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1439 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1451 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1453 if (CompletionCallback
)
1455 co_IntCallSentMessageCallback(CompletionCallback
,
1458 CompletionCallbackContext
,
1465 if (Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1467 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1469 ERR("Failed to unpack message parameters\n");
1474 if(!(Message
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
1476 ERR("MsqSendMessage(): Not enough memory to allocate a message");
1480 IntReferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1481 /* Take reference on this MessageQueue if its a callback. It will be released
1482 when message is processed or removed from target hwnd MessageQueue */
1483 if (CompletionCallback
)
1484 IntReferenceMessageQueue(Win32Thread
->MessageQueue
);
1486 Message
->Msg
.hwnd
= hWnd
;
1487 Message
->Msg
.message
= Msg
;
1488 Message
->Msg
.wParam
= wParam
;
1489 Message
->Msg
.lParam
= lParamPacked
;
1490 Message
->CompletionEvent
= NULL
;
1491 Message
->Result
= 0;
1492 Message
->lResult
= 0;
1493 Message
->QS_Flags
= 0;
1494 Message
->SenderQueue
= NULL
; // mjmartin, you are right! This is null.
1495 Message
->CallBackSenderQueue
= Win32Thread
->MessageQueue
;
1496 Message
->DispatchingListEntry
.Flink
= NULL
;
1497 Message
->CompletionCallback
= CompletionCallback
;
1498 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1499 Message
->HookMessage
= MSQ_NORMAL
;
1500 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1501 Message
->QS_Flags
= QS_SENDMESSAGE
;
1503 InsertTailList(&Window
->head
.pti
->MessageQueue
->SentMessagesListHead
, &Message
->ListEntry
);
1504 MsqWakeQueue(Window
->head
.pti
->MessageQueue
, QS_SENDMESSAGE
, TRUE
);
1505 IntDereferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1510 if (Window
) UserDerefObjectCo(Window
);
1514 /* This function posts a message if the destination's message queue belongs to
1515 another thread, otherwise it sends the message. It does not support broadcast
1518 co_IntPostOrSendMessage( HWND hWnd
,
1527 if ( hWnd
== HWND_BROADCAST
)
1532 if(!(Window
= UserGetWindowObject(hWnd
)))
1537 pti
= PsGetCurrentThreadWin32Thread();
1539 if ( Window
->head
.pti
->MessageQueue
!= pti
->MessageQueue
&&
1540 FindMsgMemory(Msg
) == 0 )
1542 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1546 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1552 return (LRESULT
)Result
;
1556 co_IntDoSendMessage( HWND hWnd
,
1563 LRESULT Result
= TRUE
;
1568 PMSGMEMORY MsgMemoryEntry
;
1570 if (HWND_BROADCAST
!= hWnd
)
1572 Window
= UserGetWindowObject(hWnd
);
1579 /* Check for an exiting window. */
1580 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1582 ERR("co_IntDoSendMessage Window Exiting!\n");
1585 /* See if the current thread can handle the message */
1586 pti
= PsGetCurrentThreadWin32Thread();
1588 UserModeMsg
.hwnd
= hWnd
;
1589 UserModeMsg
.message
= Msg
;
1590 UserModeMsg
.wParam
= wParam
;
1591 UserModeMsg
.lParam
= lParam
;
1592 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1594 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1595 if (! NT_SUCCESS(Status
))
1597 EngSetLastError(ERROR_INVALID_PARAMETER
);
1598 return (dsm
? 0 : -1);
1603 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1604 KernelModeMsg
.message
,
1605 KernelModeMsg
.wParam
,
1606 KernelModeMsg
.lParam
);
1610 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1611 KernelModeMsg
.message
,
1612 KernelModeMsg
.wParam
,
1613 KernelModeMsg
.lParam
,
1619 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1620 if (! NT_SUCCESS(Status
))
1622 EngSetLastError(ERROR_INVALID_PARAMETER
);
1623 return(dsm
? 0 : -1);
1626 return (LRESULT
)Result
;
1630 UserSendNotifyMessage( HWND hWnd
,
1637 if (is_pointer_message(Msg
))
1639 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1643 // Basicly the same as IntPostOrSendMessage
1644 if (hWnd
== HWND_BROADCAST
) //Handle Broadcast
1650 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1651 List
= IntWinListChildren(DesktopWindow
);
1655 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1656 for (i
= 0; List
[i
]; i
++)
1658 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1665 ULONG_PTR lResult
= 0;
1666 Ret
= co_IntSendMessageWithCallBack( hWnd
,
1679 IntGetQueueStatus(DWORD Changes
)
1682 PUSER_MESSAGE_QUEUE Queue
;
1685 pti
= PsGetCurrentThreadWin32Thread();
1686 Queue
= pti
->MessageQueue
;
1688 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1690 /* High word, types of messages currently in the queue.
1691 Low word, types of messages that have been added to the queue and that
1692 are still in the queue
1694 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1696 pti
->pcti
->fsChangeBits
&= ~Changes
;
1702 IntInitMessagePumpHook()
1704 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1708 pti
->pcti
->dwcPumpHook
++;
1715 IntUninitMessagePumpHook()
1717 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1721 if (pti
->pcti
->dwcPumpHook
<= 0)
1725 pti
->pcti
->dwcPumpHook
--;
1731 /** Functions ******************************************************************/
1737 POINT pt
) // Just like the User call.
1741 WORD wDragWidth
, wDragHeight
;
1742 DECLARE_RETURN(BOOL
);
1744 TRACE("Enter NtUserDragDetect(%x)\n", hWnd
);
1745 UserEnterExclusive();
1747 wDragWidth
= UserGetSystemMetrics(SM_CXDRAG
);
1748 wDragHeight
= UserGetSystemMetrics(SM_CYDRAG
);
1750 rect
.left
= pt
.x
- wDragWidth
;
1751 rect
.right
= pt
.x
+ wDragWidth
;
1753 rect
.top
= pt
.y
- wDragHeight
;
1754 rect
.bottom
= pt
.y
+ wDragHeight
;
1756 co_UserSetCapture(hWnd
);
1760 while (co_IntGetPeekMessage( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, FALSE
) ||
1761 co_IntGetPeekMessage( &msg
, 0, WM_QUEUESYNC
, WM_QUEUESYNC
, PM_REMOVE
, FALSE
) ||
1762 co_IntGetPeekMessage( &msg
, 0, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
, FALSE
) )
1764 if ( msg
.message
== WM_LBUTTONUP
)
1766 co_UserSetCapture(NULL
);
1769 if ( msg
.message
== WM_MOUSEMOVE
)
1772 tmp
.x
= (short)LOWORD(msg
.lParam
);
1773 tmp
.y
= (short)HIWORD(msg
.lParam
);
1774 if( !IntPtInRect( &rect
, tmp
) )
1776 co_UserSetCapture(NULL
);
1780 if ( msg
.message
== WM_KEYDOWN
)
1782 if ( msg
.wParam
== VK_ESCAPE
)
1784 co_UserSetCapture(NULL
);
1788 if ( msg
.message
== WM_QUEUESYNC
)
1790 co_HOOK_CallHooks( WH_CBT
, HCBT_QS
, 0, 0 );
1793 co_IntWaitMessage(NULL
, 0, 0);
1798 TRACE("Leave NtUserDragDetect, ret=%i\n",_ret_
);
1804 NtUserPostMessage(HWND hWnd
,
1811 UserEnterExclusive();
1813 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1821 NtUserPostThreadMessage(DWORD idThread
,
1828 UserEnterExclusive();
1830 ret
= UserPostThreadMessage( idThread
, Msg
, wParam
, lParam
);
1838 NtUserWaitMessage(VOID
)
1842 UserEnterExclusive();
1843 TRACE("NtUserWaitMessage Enter\n");
1844 ret
= co_IntWaitMessage(NULL
, 0, 0);
1845 TRACE("NtUserWaitMessage Leave\n");
1852 NtUserGetMessage(PMSG pMsg
,
1860 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
1862 EngSetLastError(ERROR_INVALID_PARAMETER
);
1866 UserEnterExclusive();
1868 RtlZeroMemory(&Msg
, sizeof(MSG
));
1870 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
1878 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
1879 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
1881 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1883 SetLastNtError(_SEH2_GetExceptionCode());
1890 Ret
= Ret
? (WM_QUIT
!= pMsg
->message
) : FALSE
;
1896 NtUserPeekMessage( PMSG pMsg
,
1905 if ( RemoveMsg
& PM_BADMSGFLAGS
)
1907 EngSetLastError(ERROR_INVALID_FLAGS
);
1911 UserEnterExclusive();
1913 RtlZeroMemory(&Msg
, sizeof(MSG
));
1915 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
1923 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
1924 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
1926 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1928 SetLastNtError(_SEH2_GetExceptionCode());
1938 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
1945 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
1946 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
1948 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1950 _SEH2_YIELD(return FALSE
);
1954 UserEnterExclusive();
1956 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
1962 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
1969 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
1970 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
1972 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1982 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
1989 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
1990 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
1992 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1994 SetLastNtError(_SEH2_GetExceptionCode());
1995 _SEH2_YIELD(return FALSE
);
1999 UserEnterExclusive();
2001 Res
= IntDispatchMessage(&SafeMsg
);
2009 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
2016 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
2017 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
2019 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2021 SetLastNtError(_SEH2_GetExceptionCode());
2022 _SEH2_YIELD(return FALSE
);
2026 UserEnterExclusive();
2028 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
2036 NtUserMessageCall( HWND hWnd
,
2040 ULONG_PTR ResultInfo
,
2041 DWORD dwType
, // fnID?
2044 LRESULT lResult
= 0;
2047 USER_REFERENCE_ENTRY Ref
;
2049 UserEnterExclusive();
2053 case FNID_DEFWINDOWPROC
:
2054 /* Validate input */
2055 if (hWnd
&& (hWnd
!= INVALID_HANDLE_VALUE
))
2057 Window
= UserGetWindowObject(hWnd
);
2064 UserRefObjectCo(Window
, &Ref
);
2065 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2067 UserDerefObjectCo(Window
);
2069 case FNID_SENDNOTIFYMESSAGE
:
2070 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2072 case FNID_BROADCASTSYSTEMMESSAGE
:
2075 DWORD_PTR RetVal
= 0;
2081 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2082 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2084 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2093 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2094 parm
.recipients
== BSM_ALLCOMPONENTS
)
2097 else if (parm
.recipients
& BSM_APPLICATIONS
)
2099 if (parm
.flags
& BSF_QUERY
)
2101 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2103 co_IntSendMessageTimeout( HWND_BROADCAST
,
2111 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2113 co_IntSendMessageTimeout( HWND_BROADCAST
,
2117 SMTO_NOTIMEOUTIFNOTHUNG
,
2123 co_IntSendMessageTimeout( HWND_BROADCAST
,
2133 else if (parm
.flags
& BSF_POSTMESSAGE
)
2135 Ret
= UserPostMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2137 else //Everything else,,,, if ( parm.flags & BSF_SENDNOTIFYMESSAGE)
2139 Ret
= UserSendNotifyMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2144 case FNID_SENDMESSAGECALLBACK
:
2146 CALL_BACK_INFO CallBackInfo
;
2151 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2152 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2154 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2160 if (is_pointer_message(Msg
))
2162 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
2166 if (!(Ret
= co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2167 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
)))
2169 ERR("Callback failure!\n");
2173 case FNID_SENDMESSAGE
:
2175 Ret
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2181 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2182 RtlCopyMemory((PVOID
)ResultInfo
, &Ret
, sizeof(ULONG_PTR
));
2184 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2193 case FNID_SENDMESSAGETIMEOUT
:
2195 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2200 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2201 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2203 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2210 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, &dsm
);
2216 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2217 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2219 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2228 // CallNextHook bypass.
2229 case FNID_CALLWNDPROC
:
2230 case FNID_CALLWNDPROCRET
:
2233 PCLIENTINFO ClientInfo
;
2234 PHOOK NextObj
, Hook
;
2236 pti
= GetW32ThreadInfo();
2238 Hook
= pti
->sphkCurrent
;
2242 NextObj
= Hook
->phkNext
;
2243 ClientInfo
= pti
->pClientInfo
;
2246 ClientInfo
->phkCurrent
= NextObj
;
2248 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2254 if (!ClientInfo
|| !NextObj
) break;
2256 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2258 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2263 CWP
.wParam
= wParam
;
2264 CWP
.lParam
= lParam
;
2265 TRACE("WH_CALLWNDPROC: Hook %x NextHook %x\n", Hook
, NextObj
);
2267 lResult
= co_IntCallHookProc( Hook
->HookId
,
2269 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2280 CWPR
.wParam
= wParam
;
2281 CWPR
.lParam
= lParam
;
2282 CWPR
.lResult
= ClientInfo
->dwHookData
;
2284 lResult
= co_IntCallHookProc( Hook
->HookId
,
2286 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2298 case FNID_DEFWINDOWPROC
:
2299 case FNID_CALLWNDPROC
:
2300 case FNID_CALLWNDPROCRET
:
2305 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2306 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2308 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2324 #define INFINITE 0xFFFFFFFF
2325 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2329 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2330 IN DWORD dwMilliseconds
,
2334 PPROCESSINFO W32Process
;
2338 LARGE_INTEGER Timeout
;
2340 UserEnterExclusive();
2342 Status
= ObReferenceObjectByHandle(hProcess
,
2343 PROCESS_QUERY_INFORMATION
,
2349 if (!NT_SUCCESS(Status
))
2352 SetLastNtError(Status
);
2356 pti
= PsGetCurrentThreadWin32Thread();
2358 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2360 if ( PsGetProcessExitProcessCalled(Process
) ||
2362 pti
->ppi
== W32Process
)
2364 ObDereferenceObject(Process
);
2366 EngSetLastError(ERROR_INVALID_PARAMETER
);
2370 Handles
[0] = Process
;
2371 Handles
[1] = W32Process
->InputIdleEvent
;
2372 Handles
[2] = pti
->MessageQueue
->NewMessages
; // pEventQueueServer; IntMsqSetWakeMask returns hEventQueueClient
2376 ObDereferenceObject(Process
);
2378 return STATUS_SUCCESS
; /* no event to wait on */
2381 if (dwMilliseconds
!= INFINITE
)
2382 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2384 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2385 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2387 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2388 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2391 TRACE("WFII: ppi 0x%x\n",W32Process
);
2392 TRACE("WFII: waiting for %p\n", Handles
[1] );
2396 Status
= KeWaitForMultipleObjects( 3,
2402 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2404 UserEnterExclusive();
2406 if (!NT_SUCCESS(Status
))
2408 SetLastNtError(Status
);
2409 Status
= WAIT_FAILED
;
2421 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2422 ERR("WFII: WAIT 2\n");
2426 case STATUS_TIMEOUT
:
2427 ERR("WFII: timeout\n");
2432 ERR("WFII: finished\n");
2433 Status
= STATUS_SUCCESS
;
2440 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2442 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
2443 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2445 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
2446 ObDereferenceObject(Process
);