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
;
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 DPRINT1("No size for lParamPacked\n");
335 return STATUS_SUCCESS
;
337 PackedData
= ExAllocatePoolWithTag(NonPagedPool
, size
, TAG_MSG
);
338 RtlCopyMemory(PackedData
, (PVOID
)lParam
, MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
));
339 *lParamPacked
= (LPARAM
)PackedData
;
342 return STATUS_SUCCESS
;
346 UnpackParam(LPARAM lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolUsed
)
348 NCCALCSIZE_PARAMS
*UnpackedParams
;
349 NCCALCSIZE_PARAMS
*PackedParams
;
350 PWINDOWPOS UnpackedWindowPos
;
352 if (lParamPacked
== lParam
)
354 return STATUS_SUCCESS
;
357 if (WM_NCCALCSIZE
== Msg
&& wParam
)
359 PackedParams
= (NCCALCSIZE_PARAMS
*) lParamPacked
;
360 UnpackedParams
= (NCCALCSIZE_PARAMS
*) lParam
;
361 UnpackedWindowPos
= UnpackedParams
->lppos
;
362 RtlCopyMemory(UnpackedParams
, PackedParams
, sizeof(NCCALCSIZE_PARAMS
));
363 UnpackedParams
->lppos
= UnpackedWindowPos
;
364 RtlCopyMemory(UnpackedWindowPos
, PackedParams
+ 1, sizeof(WINDOWPOS
));
365 ExFreePool((PVOID
) lParamPacked
);
367 return STATUS_SUCCESS
;
369 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
371 ExFreePool((PVOID
) lParamPacked
);
373 return STATUS_SUCCESS
;
375 else if (NonPagedPoolUsed
)
377 PMSGMEMORY MsgMemoryEntry
;
378 MsgMemoryEntry
= FindMsgMemory(Msg
);
379 if (MsgMemoryEntry
->Size
< 0)
381 /* Keep previous behavior */
382 return STATUS_INVALID_PARAMETER
;
385 if (MsgMemory
->Flags
== MMS_FLAG_READWRITE
)
387 //RtlCopyMemory((PVOID)lParam, (PVOID)lParamPacked, MsgMemory->Size);
389 ExFreePool((PVOID
) lParamPacked
);
390 return STATUS_SUCCESS
;
395 return STATUS_INVALID_PARAMETER
;
398 static NTSTATUS FASTCALL
399 CopyMsgToKernelMem(MSG
*KernelModeMsg
, MSG
*UserModeMsg
, PMSGMEMORY MsgMemoryEntry
)
406 *KernelModeMsg
= *UserModeMsg
;
408 /* See if this message type is present in the table */
409 if (NULL
== MsgMemoryEntry
)
411 /* Not present, no copying needed */
412 return STATUS_SUCCESS
;
415 /* Determine required size */
416 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
420 /* Allocate kernel mem */
421 KernelMem
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
422 if (NULL
== KernelMem
)
424 DPRINT1("Not enough memory to copy message to kernel mem\n");
425 return STATUS_NO_MEMORY
;
427 KernelModeMsg
->lParam
= (LPARAM
) KernelMem
;
429 /* Copy data if required */
430 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_READ
))
432 Status
= MmCopyFromCaller(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
433 if (! NT_SUCCESS(Status
))
435 DPRINT1("Failed to copy message to kernel: invalid usermode buffer\n");
436 ExFreePoolWithTag(KernelMem
, TAG_MSG
);
442 /* Make sure we don't pass any secrets to usermode */
443 RtlZeroMemory(KernelMem
, Size
);
448 KernelModeMsg
->lParam
= 0;
451 return STATUS_SUCCESS
;
454 static NTSTATUS FASTCALL
455 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
458 PMSGMEMORY MsgMemoryEntry
;
461 /* See if this message type is present in the table */
462 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
463 if (NULL
== MsgMemoryEntry
)
465 /* Not present, no copying needed */
466 return STATUS_SUCCESS
;
469 /* Determine required size */
470 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
474 /* Copy data if required */
475 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
477 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
478 if (! NT_SUCCESS(Status
))
480 DPRINT1("Failed to copy message from kernel: invalid usermode buffer\n");
481 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
486 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
489 return STATUS_SUCCESS
;
493 // Wakeup any thread/process waiting on idle input.
498 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
499 PUSER_MESSAGE_QUEUE ForegroundQueue
;
500 PTHREADINFO pti
, ptiForeground
= NULL
;
502 ForegroundQueue
= IntGetFocusMessageQueue();
505 ptiForeground
= ForegroundQueue
->Thread
->Tcb
.Win32Thread
;
507 pti
= PsGetCurrentThreadWin32Thread();
511 pti
->pClientInfo
->cSpins
= 0; // Reset spins.
513 if ( pti
->pDeskInfo
&& pti
== ptiForeground
)
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 DPRINT("IdlePing ppi 0x%x\n",ppi
);
524 if ( ppi
&& ppi
->InputIdleEvent
)
526 DPRINT("InputIdleEvent\n");
527 KeSetEvent( ppi
->InputIdleEvent
, IO_NO_INCREMENT
, FALSE
);
534 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
536 DPRINT("IdlePong ppi 0x%x\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
;
592 co_HOOK_CallHooks( WH_CALLWNDPROCRET
, HC_ACTION
, SameThread
, (LPARAM
)&CWPR
);
596 IntDispatchMessage(PMSG pMsg
)
598 LARGE_INTEGER TickCount
;
606 Window
= UserGetWindowObject(pMsg
->hwnd
);
607 if (!Window
) return 0;
610 pti
= PsGetCurrentThreadWin32Thread();
612 if ( Window
->head
.pti
!= pti
)
614 EngSetLastError( ERROR_MESSAGE_SYNC_ONLY
);
618 if (((pMsg
->message
== WM_SYSTIMER
) ||
619 (pMsg
->message
== WM_TIMER
)) &&
622 if (pMsg
->message
== WM_TIMER
)
624 if (ValidateTimerCallback(pti
,pMsg
->lParam
))
626 KeQueryTickCount(&TickCount
);
627 Time
= MsqCalculateMessageTime(&TickCount
);
628 retval
= co_IntCallWindowProc((WNDPROC
)pMsg
->lParam
,
640 PTIMER pTimer
= FindSystemTimer(pMsg
);
641 if (pTimer
&& pTimer
->pfn
)
643 KeQueryTickCount(&TickCount
);
644 Time
= MsqCalculateMessageTime(&TickCount
);
645 pTimer
->pfn(pMsg
->hwnd
, WM_SYSTIMER
, (UINT
)pMsg
->wParam
, Time
);
651 if ( !Window
) return 0;
653 /* Since we are doing a callback on the same thread right away, there is
654 no need to copy the lparam to kernel mode and then back to usermode.
655 We just pretend it isn't a pointer */
657 retval
= co_IntCallWindowProc( Window
->lpfnWndProc
,
665 if (pMsg
->message
== WM_PAINT
)
667 /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
668 HRGN hrgn
= IntSysCreateRectRgn( 0, 0, 0, 0 );
669 co_UserGetUpdateRgn( Window
, hrgn
, TRUE
);
670 REGION_FreeRgnByHandle( hrgn
);
677 * Internal version of PeekMessage() doing all the work
680 co_IntPeekMessage( PMSG Msg
,
689 LARGE_INTEGER LargeTickCount
;
690 PUSER_MESSAGE_QUEUE ThreadQueue
;
695 pti
= PsGetCurrentThreadWin32Thread();
696 ThreadQueue
= pti
->MessageQueue
;
697 pci
= pti
->pClientInfo
;
699 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
700 ProcessMask
= HIWORD(RemoveMsg
);
702 /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns
703 all available messages (that is, no range filtering is performed)". */
704 if (!ProcessMask
) ProcessMask
= (QS_ALLPOSTMESSAGE
|QS_ALLINPUT
);
710 KeQueryTickCount(&LargeTickCount
);
711 ThreadQueue
->LastMsgRead
= LargeTickCount
.u
.LowPart
;
712 pti
->pcti
->tickLastMsgChecked
= LargeTickCount
.u
.LowPart
;
714 /* Dispatch sent messages here. */
715 while ( co_MsqDispatchOneSentMessage(ThreadQueue
) )
717 /* if some PM_QS* flags were specified, only handle sent messages from now on */
718 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
; // wine does this; ProcessMask = QS_SENDMESSAGE;
720 if (Hit
) return FALSE
;
722 /* Clear changed bits so we can wait on them if we don't find a message */
723 if (ProcessMask
& QS_POSTMESSAGE
)
725 pti
->pcti
->fsChangeBits
&= ~(QS_POSTMESSAGE
| QS_HOTKEY
| QS_TIMER
);
726 if (MsgFilterMin
== 0 && MsgFilterMax
== 0) // wine hack does this; ~0U)
728 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
732 if (ProcessMask
& QS_INPUT
)
734 pti
->pcti
->fsChangeBits
&= ~QS_INPUT
;
737 /* Now check for normal messages. */
738 if ((ProcessMask
& QS_POSTMESSAGE
) &&
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 DPRINT1("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 DPRINT1("Attempted to post message to window 0x%x when the thread is in cleanup!\n", Wnd
);
1130 if ( Window
->state
& WNDS_DESTROYED
)
1132 DPRINT1("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
)))
1188 UserRefObjectCo(Window
, &Ref
);
1190 Win32Thread
= PsGetCurrentThreadWin32Thread();
1192 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1194 if ( NULL
!= Win32Thread
&&
1195 Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1197 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1199 /* Never send messages to exiting threads */
1203 /* See if this message type is present in the table */
1204 MsgMemoryEntry
= FindMsgMemory(Msg
);
1205 if (NULL
== MsgMemoryEntry
)
1207 lParamBufferSize
= -1;
1211 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1214 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1216 DPRINT1("Failed to pack message parameters\n");
1220 ObReferenceObject(Win32Thread
->pEThread
);
1221 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1233 ObDereferenceObject(Win32Thread
->pEThread
);
1235 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1237 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1239 DPRINT1("Failed to unpack message parameters\n");
1246 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->head
.pti
->MessageQueue
))
1248 // FIXME - Set window hung and add to a list.
1249 /* FIXME - Set a LastError? */
1253 if (Window
->state
& WNDS_DESTROYED
)
1255 /* FIXME - last error? */
1256 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1262 Status
= co_MsqSendMessage( Window
->head
.pti
->MessageQueue
,
1268 (uFlags
& SMTO_BLOCK
),
1272 while ((STATUS_TIMEOUT
== Status
) &&
1273 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1274 !MsqIsHung(Window
->head
.pti
->MessageQueue
)); // FIXME - Set window hung and add to a list.
1276 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1278 if (STATUS_TIMEOUT
== Status
)
1282 Microsoft Windows 2000: If GetLastError returns zero, then the function
1284 XP+ : If the function fails or times out, the return value is zero.
1285 To get extended error information, call GetLastError. If GetLastError
1286 returns ERROR_TIMEOUT, then the function timed out.
1288 EngSetLastError(ERROR_TIMEOUT
);
1291 else if (! NT_SUCCESS(Status
))
1293 SetLastNtError(Status
);
1300 if (Window
) UserDerefObjectCo(Window
);
1305 co_IntSendMessageTimeout( HWND hWnd
,
1311 ULONG_PTR
*uResult
)
1317 if (HWND_BROADCAST
!= hWnd
)
1319 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1322 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1323 if (NULL
== DesktopWindow
)
1325 EngSetLastError(ERROR_INTERNAL_ERROR
);
1329 /* Send message to the desktop window too! */
1330 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1332 Children
= IntWinListChildren(DesktopWindow
);
1333 if (NULL
== Children
)
1338 for (Child
= Children
; NULL
!= *Child
; Child
++)
1340 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1343 ExFreePool(Children
);
1345 return (LRESULT
) TRUE
;
1349 co_IntSendMessageNoWait(HWND hWnd
,
1354 ULONG_PTR Result
= 0;
1355 co_IntSendMessageWithCallBack(hWnd
,
1365 If you send a message in the range below WM_USER to the asynchronous message
1366 functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its
1367 message parameters cannot include pointers. Otherwise, the operation will fail.
1368 The functions will return before the receiving thread has had a chance to
1369 process the message and the sender will free the memory before it is used.
1372 co_IntSendMessageWithCallBack( HWND hWnd
,
1376 SENDASYNCPROC CompletionCallback
,
1377 ULONG_PTR CompletionCallbackContext
,
1382 PMSGMEMORY MsgMemoryEntry
;
1383 INT lParamBufferSize
;
1384 LPARAM lParamPacked
;
1385 PTHREADINFO Win32Thread
;
1386 DECLARE_RETURN(LRESULT
);
1387 USER_REFERENCE_ENTRY Ref
;
1388 PUSER_SENT_MESSAGE Message
;
1390 if (!(Window
= UserGetWindowObject(hWnd
)))
1395 UserRefObjectCo(Window
, &Ref
);
1397 if (Window
->state
& WNDS_DESTROYED
)
1399 /* FIXME - last error? */
1400 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1404 Win32Thread
= PsGetCurrentThreadWin32Thread();
1406 if (Win32Thread
== NULL
)
1411 /* See if this message type is present in the table */
1412 MsgMemoryEntry
= FindMsgMemory(Msg
);
1413 if (NULL
== MsgMemoryEntry
)
1415 lParamBufferSize
= -1;
1419 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1422 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, Window
->head
.pti
->MessageQueue
!= Win32Thread
->MessageQueue
)))
1424 DPRINT1("Failed to pack message parameters\n");
1428 /* If it can be sent now, then send it. */
1429 if (Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1431 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1433 UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
);
1434 /* Never send messages to exiting threads */
1438 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1440 ObReferenceObject(Win32Thread
->pEThread
);
1441 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1452 ObDereferenceObject(Win32Thread
->pEThread
);
1454 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1456 if (CompletionCallback
)
1458 co_IntCallSentMessageCallback(CompletionCallback
,
1461 CompletionCallbackContext
,
1468 if (Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1470 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1472 DPRINT1("Failed to unpack message parameters\n");
1477 if(!(Message
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
1479 DPRINT1("MsqSendMessage(): Not enough memory to allocate a message");
1483 IntReferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1484 /* Take reference on this MessageQueue if its a callback. It will be released
1485 when message is processed or removed from target hwnd MessageQueue */
1486 if (CompletionCallback
)
1487 IntReferenceMessageQueue(Win32Thread
->MessageQueue
);
1489 Message
->Msg
.hwnd
= hWnd
;
1490 Message
->Msg
.message
= Msg
;
1491 Message
->Msg
.wParam
= wParam
;
1492 Message
->Msg
.lParam
= lParamPacked
;
1493 Message
->CompletionEvent
= NULL
;
1494 Message
->Result
= 0;
1495 Message
->lResult
= 0;
1496 Message
->QS_Flags
= 0;
1497 Message
->SenderQueue
= NULL
; // mjmartin, you are right! This is null.
1498 Message
->CallBackSenderQueue
= Win32Thread
->MessageQueue
;
1499 Message
->DispatchingListEntry
.Flink
= NULL
;
1500 Message
->CompletionCallback
= CompletionCallback
;
1501 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1502 Message
->HookMessage
= MSQ_NORMAL
;
1503 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1504 Message
->QS_Flags
= QS_SENDMESSAGE
;
1506 InsertTailList(&Window
->head
.pti
->MessageQueue
->SentMessagesListHead
, &Message
->ListEntry
);
1507 MsqWakeQueue(Window
->head
.pti
->MessageQueue
, QS_SENDMESSAGE
, TRUE
);
1508 IntDereferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1513 if (Window
) UserDerefObjectCo(Window
);
1517 /* This function posts a message if the destination's message queue belongs to
1518 another thread, otherwise it sends the message. It does not support broadcast
1521 co_IntPostOrSendMessage( HWND hWnd
,
1530 if ( hWnd
== HWND_BROADCAST
)
1535 if(!(Window
= UserGetWindowObject(hWnd
)))
1540 pti
= PsGetCurrentThreadWin32Thread();
1542 if ( Window
->head
.pti
->MessageQueue
!= pti
->MessageQueue
&&
1543 FindMsgMemory(Msg
) == 0 )
1545 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1549 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1555 return (LRESULT
)Result
;
1559 co_IntDoSendMessage( HWND hWnd
,
1566 LRESULT Result
= TRUE
;
1571 PMSGMEMORY MsgMemoryEntry
;
1573 if (HWND_BROADCAST
!= hWnd
)
1575 Window
= UserGetWindowObject(hWnd
);
1582 /* Check for an exiting window. */
1583 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1585 DPRINT1("co_IntDoSendMessage Window Exiting!\n");
1588 /* See if the current thread can handle the message */
1589 pti
= PsGetCurrentThreadWin32Thread();
1591 UserModeMsg
.hwnd
= hWnd
;
1592 UserModeMsg
.message
= Msg
;
1593 UserModeMsg
.wParam
= wParam
;
1594 UserModeMsg
.lParam
= lParam
;
1595 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1597 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1598 if (! NT_SUCCESS(Status
))
1600 EngSetLastError(ERROR_INVALID_PARAMETER
);
1601 return (dsm
? 0 : -1);
1606 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1607 KernelModeMsg
.message
,
1608 KernelModeMsg
.wParam
,
1609 KernelModeMsg
.lParam
);
1613 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1614 KernelModeMsg
.message
,
1615 KernelModeMsg
.wParam
,
1616 KernelModeMsg
.lParam
,
1622 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1623 if (! NT_SUCCESS(Status
))
1625 EngSetLastError(ERROR_INVALID_PARAMETER
);
1626 return(dsm
? 0 : -1);
1629 return (LRESULT
)Result
;
1633 UserSendNotifyMessage( HWND hWnd
,
1640 if (is_pointer_message(Msg
))
1642 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1646 // Basicly the same as IntPostOrSendMessage
1647 if (hWnd
== HWND_BROADCAST
) //Handle Broadcast
1653 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1654 List
= IntWinListChildren(DesktopWindow
);
1658 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1659 for (i
= 0; List
[i
]; i
++)
1661 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1668 ULONG_PTR lResult
= 0;
1669 Ret
= co_IntSendMessageWithCallBack( hWnd
,
1682 IntGetQueueStatus(DWORD Changes
)
1685 PUSER_MESSAGE_QUEUE Queue
;
1688 pti
= PsGetCurrentThreadWin32Thread();
1689 Queue
= pti
->MessageQueue
;
1691 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1693 /* High word, types of messages currently in the queue.
1694 Low word, types of messages that have been added to the queue and that
1695 are still in the queue
1697 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1699 pti
->pcti
->fsChangeBits
&= ~Changes
;
1705 IntInitMessagePumpHook()
1707 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1711 pti
->pcti
->dwcPumpHook
++;
1718 IntUninitMessagePumpHook()
1720 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1724 if (pti
->pcti
->dwcPumpHook
<= 0)
1728 pti
->pcti
->dwcPumpHook
--;
1734 /** Functions ******************************************************************/
1740 POINT pt
) // Just like the User call.
1744 WORD wDragWidth
, wDragHeight
;
1745 DECLARE_RETURN(BOOL
);
1747 DPRINT("Enter NtUserDragDetect(%x)\n", hWnd
);
1748 UserEnterExclusive();
1750 wDragWidth
= UserGetSystemMetrics(SM_CXDRAG
);
1751 wDragHeight
= UserGetSystemMetrics(SM_CYDRAG
);
1753 rect
.left
= pt
.x
- wDragWidth
;
1754 rect
.right
= pt
.x
+ wDragWidth
;
1756 rect
.top
= pt
.y
- wDragHeight
;
1757 rect
.bottom
= pt
.y
+ wDragHeight
;
1759 co_UserSetCapture(hWnd
);
1763 while (co_IntGetPeekMessage( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, FALSE
) ||
1764 co_IntGetPeekMessage( &msg
, 0, WM_QUEUESYNC
, WM_QUEUESYNC
, PM_REMOVE
, FALSE
) ||
1765 co_IntGetPeekMessage( &msg
, 0, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
, FALSE
) )
1767 if ( msg
.message
== WM_LBUTTONUP
)
1769 co_UserSetCapture(NULL
);
1772 if ( msg
.message
== WM_MOUSEMOVE
)
1775 tmp
.x
= (short)LOWORD(msg
.lParam
);
1776 tmp
.y
= (short)HIWORD(msg
.lParam
);
1777 if( !IntPtInRect( &rect
, tmp
) )
1779 co_UserSetCapture(NULL
);
1783 if ( msg
.message
== WM_KEYDOWN
)
1785 if ( msg
.wParam
== VK_ESCAPE
)
1787 co_UserSetCapture(NULL
);
1791 if ( msg
.message
== WM_QUEUESYNC
)
1793 co_HOOK_CallHooks( WH_CBT
, HCBT_QS
, 0, 0 );
1796 co_IntWaitMessage(NULL
, 0, 0);
1801 DPRINT("Leave NtUserDragDetect, ret=%i\n",_ret_
);
1807 NtUserPostMessage(HWND hWnd
,
1814 UserEnterExclusive();
1816 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1824 NtUserPostThreadMessage(DWORD idThread
,
1831 UserEnterExclusive();
1833 ret
= UserPostThreadMessage( idThread
, Msg
, wParam
, lParam
);
1841 NtUserWaitMessage(VOID
)
1845 UserEnterExclusive();
1846 DPRINT("NtUserWaitMessage Enter\n");
1847 ret
= co_IntWaitMessage(NULL
, 0, 0);
1848 DPRINT("NtUserWaitMessage Leave\n");
1855 NtUserGetMessage(PMSG pMsg
,
1863 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
1865 EngSetLastError(ERROR_INVALID_PARAMETER
);
1869 UserEnterExclusive();
1871 RtlZeroMemory(&Msg
, sizeof(MSG
));
1873 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
1881 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
1882 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
1884 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1886 SetLastNtError(_SEH2_GetExceptionCode());
1893 Ret
= Ret
? (WM_QUIT
!= pMsg
->message
) : FALSE
;
1899 NtUserPeekMessage( PMSG pMsg
,
1908 if ( RemoveMsg
& PM_BADMSGFLAGS
)
1910 EngSetLastError(ERROR_INVALID_FLAGS
);
1914 UserEnterExclusive();
1916 RtlZeroMemory(&Msg
, sizeof(MSG
));
1918 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
1926 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
1927 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
1929 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1931 SetLastNtError(_SEH2_GetExceptionCode());
1941 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
1948 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
1949 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
1951 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1953 _SEH2_YIELD(return FALSE
);
1957 UserEnterExclusive();
1959 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
1965 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
1972 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
1973 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
1975 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1985 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
1992 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
1993 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
1995 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1997 SetLastNtError(_SEH2_GetExceptionCode());
1998 _SEH2_YIELD(return FALSE
);
2002 UserEnterExclusive();
2004 Res
= IntDispatchMessage(&SafeMsg
);
2012 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
2019 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
2020 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
2022 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2024 SetLastNtError(_SEH2_GetExceptionCode());
2025 _SEH2_YIELD(return FALSE
);
2029 UserEnterExclusive();
2031 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
2039 NtUserMessageCall( HWND hWnd
,
2043 ULONG_PTR ResultInfo
,
2044 DWORD dwType
, // fnID?
2047 LRESULT lResult
= 0;
2050 USER_REFERENCE_ENTRY Ref
;
2052 UserEnterExclusive();
2056 case FNID_DEFWINDOWPROC
:
2057 /* Validate input */
2058 if (hWnd
&& (hWnd
!= INVALID_HANDLE_VALUE
))
2060 Window
= UserGetWindowObject(hWnd
);
2067 UserRefObjectCo(Window
, &Ref
);
2068 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2070 UserDerefObjectCo(Window
);
2072 case FNID_SENDNOTIFYMESSAGE
:
2073 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2075 case FNID_BROADCASTSYSTEMMESSAGE
:
2078 DWORD_PTR RetVal
= 0;
2084 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2085 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2087 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2096 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2097 parm
.recipients
== BSM_ALLCOMPONENTS
)
2100 else if (parm
.recipients
& BSM_APPLICATIONS
)
2102 if (parm
.flags
& BSF_QUERY
)
2104 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2106 co_IntSendMessageTimeout( HWND_BROADCAST
,
2114 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2116 co_IntSendMessageTimeout( HWND_BROADCAST
,
2120 SMTO_NOTIMEOUTIFNOTHUNG
,
2126 co_IntSendMessageTimeout( HWND_BROADCAST
,
2136 else if (parm
.flags
& BSF_POSTMESSAGE
)
2138 Ret
= UserPostMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2140 else //Everything else,,,, if ( parm.flags & BSF_SENDNOTIFYMESSAGE)
2142 Ret
= UserSendNotifyMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2147 case FNID_SENDMESSAGECALLBACK
:
2149 CALL_BACK_INFO CallBackInfo
;
2154 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2155 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2157 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2163 if (is_pointer_message(Msg
))
2165 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
2169 if (!(Ret
= co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2170 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
)))
2172 DPRINT1("Callback failure!\n");
2176 case FNID_SENDMESSAGE
:
2178 Ret
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2184 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2185 RtlCopyMemory((PVOID
)ResultInfo
, &Ret
, sizeof(ULONG_PTR
));
2187 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2196 case FNID_SENDMESSAGETIMEOUT
:
2198 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2203 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2204 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2206 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2213 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, &dsm
);
2219 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2220 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2222 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2231 // CallNextHook bypass.
2232 case FNID_CALLWNDPROC
:
2233 case FNID_CALLWNDPROCRET
:
2236 PCLIENTINFO ClientInfo
;
2237 PHOOK NextObj
, Hook
;
2239 pti
= GetW32ThreadInfo();
2241 Hook
= pti
->sphkCurrent
;
2245 NextObj
= Hook
->phkNext
;
2246 ClientInfo
= pti
->pClientInfo
;
2249 ClientInfo
->phkCurrent
= NextObj
;
2251 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2257 if (!ClientInfo
|| !NextObj
) break;
2259 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2261 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2266 CWP
.wParam
= wParam
;
2267 CWP
.lParam
= lParam
;
2268 DPRINT("WH_CALLWNDPROC: Hook %x NextHook %x\n", Hook
, NextObj
);
2270 lResult
= co_IntCallHookProc( Hook
->HookId
,
2272 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2283 CWPR
.wParam
= wParam
;
2284 CWPR
.lParam
= lParam
;
2285 CWPR
.lResult
= ClientInfo
->dwHookData
;
2287 lResult
= co_IntCallHookProc( Hook
->HookId
,
2289 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2301 case FNID_DEFWINDOWPROC
:
2302 case FNID_CALLWNDPROC
:
2303 case FNID_CALLWNDPROCRET
:
2308 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2309 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2311 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2327 #define INFINITE 0xFFFFFFFF
2328 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2332 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2333 IN DWORD dwMilliseconds
,
2337 PPROCESSINFO W32Process
;
2341 LARGE_INTEGER Timeout
;
2343 UserEnterExclusive();
2345 Status
= ObReferenceObjectByHandle(hProcess
,
2346 PROCESS_QUERY_INFORMATION
,
2352 if (!NT_SUCCESS(Status
))
2355 SetLastNtError(Status
);
2359 pti
= PsGetCurrentThreadWin32Thread();
2361 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2363 if ( PsGetProcessExitProcessCalled(Process
) ||
2365 pti
->ppi
== W32Process
)
2367 ObDereferenceObject(Process
);
2369 EngSetLastError(ERROR_INVALID_PARAMETER
);
2373 Handles
[0] = Process
;
2374 Handles
[1] = W32Process
->InputIdleEvent
;
2375 Handles
[2] = pti
->MessageQueue
->NewMessages
; // pEventQueueServer; IntMsqSetWakeMask returns hEventQueueClient
2379 ObDereferenceObject(Process
);
2381 return STATUS_SUCCESS
; /* no event to wait on */
2384 if (dwMilliseconds
!= INFINITE
)
2385 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2387 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2388 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2390 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2391 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2394 DPRINT("WFII: ppi 0x%x\n",W32Process
);
2395 DPRINT("WFII: waiting for %p\n", Handles
[1] );
2399 Status
= KeWaitForMultipleObjects( 3,
2405 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2407 UserEnterExclusive();
2409 if (!NT_SUCCESS(Status
))
2411 SetLastNtError(Status
);
2412 Status
= WAIT_FAILED
;
2424 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2425 DPRINT1("WFII: WAIT 2\n");
2429 case STATUS_TIMEOUT
:
2430 DPRINT1("WFII: timeout\n");
2435 DPRINT1("WFII: finished\n");
2436 Status
= STATUS_SUCCESS
;
2443 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2445 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
2446 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2448 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
2449 ObDereferenceObject(Process
);