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 GreDeleteObject(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 (ProcessMask
& QS_HOTKEY
) ) &&
740 MsqPeekMessage( ThreadQueue
,
751 /* Now look for a quit message. */
752 if (ThreadQueue
->QuitPosted
)
754 /* According to the PSDK, WM_QUIT messages are always returned, regardless
755 of the filter specified */
757 Msg
->message
= WM_QUIT
;
758 Msg
->wParam
= ThreadQueue
->QuitExitCode
;
762 ThreadQueue
->QuitPosted
= FALSE
;
763 ClearMsgBitsMask(ThreadQueue
, QS_POSTMESSAGE
);
764 pti
->pcti
->fsWakeBits
&= ~QS_ALLPOSTMESSAGE
;
765 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
770 /* Check for hardware events. */
771 if ((ProcessMask
& QS_MOUSE
) &&
772 co_MsqPeekMouseMove( ThreadQueue
,
782 if ((ProcessMask
& QS_INPUT
) &&
783 co_MsqPeekHardwareMessage( ThreadQueue
,
794 /* Check for sent messages again. */
795 while ( co_MsqDispatchOneSentMessage(ThreadQueue
) )
797 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
;
799 if (Hit
) return FALSE
;
801 /* Check for paint messages. */
802 if ((ProcessMask
& QS_PAINT
) &&
804 IntGetPaintMessage( Window
,
814 /* This is correct, check for the current threads timers waiting to be
815 posted to this threads message queue. If any we loop again.
817 if ((ProcessMask
& QS_TIMER
) &&
818 PostTimerMessages(Window
))
831 co_IntWaitMessage( PWND Window
,
836 PUSER_MESSAGE_QUEUE ThreadQueue
;
837 NTSTATUS Status
= STATUS_SUCCESS
;
840 pti
= PsGetCurrentThreadWin32Thread();
841 ThreadQueue
= pti
->MessageQueue
;
845 if ( co_IntPeekMessage( &Msg
, // Dont reenter!
849 MAKELONG( PM_NOREMOVE
, GetWakeMask( MsgFilterMin
, MsgFilterMax
)),
850 TRUE
) ) // act like GetMessage.
855 /* Nothing found. Wait for new messages. */
856 Status
= co_MsqWaitForNewMessages( ThreadQueue
,
860 if (!NT_SUCCESS(Status
))
862 SetLastNtError(Status
);
863 DPRINT1("Exit co_IntWaitMessage on error!\n");
866 if (Status
== STATUS_USER_APC
|| Status
== STATUS_TIMEOUT
)
877 co_IntGetPeekMessage( PMSG pMsg
,
886 BOOL Present
= FALSE
;
889 if ( hWnd
== HWND_TOPMOST
|| hWnd
== HWND_BROADCAST
)
893 if (hWnd
&& hWnd
!= HWND_BOTTOM
)
895 if (!(Window
= UserGetWindowObject(hWnd
)))
908 if (MsgFilterMax
< MsgFilterMin
)
916 RemoveMsg
|= ((GetWakeMask( MsgFilterMin
, MsgFilterMax
))<< 16);
919 pti
= PsGetCurrentThreadWin32Thread();
920 pti
->pClientInfo
->cSpins
++; // Bump up the spin count.
924 Present
= co_IntPeekMessage( pMsg
,
932 /* GetMessage or PostMessage must never get messages that contain pointers */
933 ASSERT(FindMsgMemory(pMsg
->message
) == NULL
);
935 if (pMsg
->message
!= WM_PAINT
&& pMsg
->message
!= WM_QUIT
)
937 pti
->timeLast
= pMsg
->time
;
938 pti
->ptLast
= pMsg
->pt
;
941 // The WH_GETMESSAGE hook enables an application to monitor messages about to
942 // be returned by the GetMessage or PeekMessage function.
944 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)pMsg
);
951 Status
= co_MsqWaitForNewMessages( pti
->MessageQueue
,
955 if ( !NT_SUCCESS(Status
) ||
956 Status
== STATUS_USER_APC
||
957 Status
== STATUS_TIMEOUT
)
965 if (!(RemoveMsg
& PM_NOYIELD
))
968 // Yield this thread!
971 UserEnterExclusive();
972 // Fall through to exit.
978 while( bGMSG
&& !Present
);
980 // Been spinning, time to swap vinyl...
981 if (pti
->pClientInfo
->cSpins
>= 100)
983 // Clear the spin cycle to fix the mix.
984 pti
->pClientInfo
->cSpins
= 0;
985 //if (!(pti->TIF_flags & TIF_SPINNING)) FIXME need to swap vinyl..
991 UserPostThreadMessage( DWORD idThread
,
999 LARGE_INTEGER LargeTickCount
;
1002 if (is_pointer_message(Msg
))
1004 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1008 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
1010 if( Status
== STATUS_SUCCESS
)
1012 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
1014 !pThread
->MessageQueue
||
1015 (pThread
->TIF_flags
& TIF_INCLEANUP
))
1017 ObDereferenceObject( peThread
);
1021 Message
.hwnd
= NULL
;
1022 Message
.message
= Msg
;
1023 Message
.wParam
= wParam
;
1024 Message
.lParam
= lParam
;
1025 Message
.pt
= gpsi
->ptCursor
;
1027 KeQueryTickCount(&LargeTickCount
);
1028 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1029 MsqPostMessage(pThread
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
);
1030 ObDereferenceObject( peThread
);
1035 SetLastNtError( Status
);
1041 UserPostMessage( HWND Wnd
,
1047 MSG Message
, KernelModeMsg
;
1048 LARGE_INTEGER LargeTickCount
;
1051 Message
.message
= Msg
;
1052 Message
.wParam
= wParam
;
1053 Message
.lParam
= lParam
;
1054 Message
.pt
= gpsi
->ptCursor
;
1055 KeQueryTickCount(&LargeTickCount
);
1056 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1058 if (is_pointer_message(Message
.message
))
1060 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1064 if( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1067 PMSGMEMORY MsgMemoryEntry
;
1069 MsgMemoryEntry
= FindMsgMemory(Message
.message
);
1071 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &Message
, MsgMemoryEntry
);
1072 if (! NT_SUCCESS(Status
))
1074 EngSetLastError(ERROR_INVALID_PARAMETER
);
1077 co_IntSendMessageNoWait(KernelModeMsg
.hwnd
,
1078 KernelModeMsg
.message
,
1079 KernelModeMsg
.wParam
,
1080 KernelModeMsg
.lParam
);
1082 if (MsgMemoryEntry
&& KernelModeMsg
.lParam
)
1083 ExFreePool((PVOID
) KernelModeMsg
.lParam
);
1090 return UserPostThreadMessage( PtrToInt(PsGetCurrentThreadId()),
1095 if (Wnd
== HWND_BROADCAST
)
1101 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1102 List
= IntWinListChildren(DesktopWindow
);
1106 UserPostMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1107 for (i
= 0; List
[i
]; i
++)
1109 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1111 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1118 Window
= UserGetWindowObject(Wnd
);
1124 pti
= Window
->head
.pti
;
1125 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1127 DPRINT1("Attempted to post message to window 0x%x when the thread is in cleanup!\n", Wnd
);
1131 if ( Window
->state
& WNDS_DESTROYED
)
1133 DPRINT1("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd
);
1134 /* FIXME - last error code? */
1140 MsqPostQuitMessage(Window
->head
.pti
->MessageQueue
, wParam
);
1144 MsqPostMessage(Window
->head
.pti
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
);
1152 co_IntSendMessage( HWND hWnd
,
1157 ULONG_PTR Result
= 0;
1158 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1160 return (LRESULT
)Result
;
1165 static LRESULT FASTCALL
1166 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1172 ULONG_PTR
*uResult
)
1176 PMSGMEMORY MsgMemoryEntry
;
1177 INT lParamBufferSize
;
1178 LPARAM lParamPacked
;
1179 PTHREADINFO Win32Thread
;
1180 ULONG_PTR Result
= 0;
1181 DECLARE_RETURN(LRESULT
);
1182 USER_REFERENCE_ENTRY Ref
;
1184 if (!(Window
= UserGetWindowObject(hWnd
)))
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 /* Never send messages to exiting threads */
1204 /* See if this message type is present in the table */
1205 MsgMemoryEntry
= FindMsgMemory(Msg
);
1206 if (NULL
== MsgMemoryEntry
)
1208 lParamBufferSize
= -1;
1212 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1215 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1217 DPRINT1("Failed to pack message parameters\n");
1221 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1233 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1235 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1237 DPRINT1("Failed to unpack message parameters\n");
1244 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->head
.pti
->MessageQueue
))
1246 // FIXME - Set window hung and add to a list.
1247 /* FIXME - Set a LastError? */
1251 if (Window
->state
& WNDS_DESTROYED
)
1253 /* FIXME - last error? */
1254 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1260 Status
= co_MsqSendMessage( Window
->head
.pti
->MessageQueue
,
1266 (uFlags
& SMTO_BLOCK
),
1270 while ((STATUS_TIMEOUT
== Status
) &&
1271 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1272 !MsqIsHung(Window
->head
.pti
->MessageQueue
)); // FIXME - Set window hung and add to a list.
1274 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1276 if (STATUS_TIMEOUT
== Status
)
1280 Microsoft Windows 2000: If GetLastError returns zero, then the function
1282 XP+ : If the function fails or times out, the return value is zero.
1283 To get extended error information, call GetLastError. If GetLastError
1284 returns ERROR_TIMEOUT, then the function timed out.
1286 EngSetLastError(ERROR_TIMEOUT
);
1289 else if (! NT_SUCCESS(Status
))
1291 SetLastNtError(Status
);
1298 if (Window
) UserDerefObjectCo(Window
);
1303 co_IntSendMessageTimeout( HWND hWnd
,
1309 ULONG_PTR
*uResult
)
1315 if (HWND_BROADCAST
!= hWnd
)
1317 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1320 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1321 if (NULL
== DesktopWindow
)
1323 EngSetLastError(ERROR_INTERNAL_ERROR
);
1327 /* Send message to the desktop window too! */
1328 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1330 Children
= IntWinListChildren(DesktopWindow
);
1331 if (NULL
== Children
)
1336 for (Child
= Children
; NULL
!= *Child
; Child
++)
1338 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1341 ExFreePool(Children
);
1343 return (LRESULT
) TRUE
;
1347 co_IntSendMessageNoWait(HWND hWnd
,
1352 ULONG_PTR Result
= 0;
1353 co_IntSendMessageWithCallBack(hWnd
,
1363 If you send a message in the range below WM_USER to the asynchronous message
1364 functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its
1365 message parameters cannot include pointers. Otherwise, the operation will fail.
1366 The functions will return before the receiving thread has had a chance to
1367 process the message and the sender will free the memory before it is used.
1370 co_IntSendMessageWithCallBack( HWND hWnd
,
1374 SENDASYNCPROC CompletionCallback
,
1375 ULONG_PTR CompletionCallbackContext
,
1380 PMSGMEMORY MsgMemoryEntry
;
1381 INT lParamBufferSize
;
1382 LPARAM lParamPacked
;
1383 PTHREADINFO Win32Thread
;
1384 DECLARE_RETURN(LRESULT
);
1385 USER_REFERENCE_ENTRY Ref
;
1386 PUSER_SENT_MESSAGE Message
;
1388 if (!(Window
= UserGetWindowObject(hWnd
)))
1393 UserRefObjectCo(Window
, &Ref
);
1395 if (Window
->state
& WNDS_DESTROYED
)
1397 /* FIXME - last error? */
1398 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1402 Win32Thread
= PsGetCurrentThreadWin32Thread();
1404 if (Win32Thread
== NULL
)
1409 /* See if this message type is present in the table */
1410 MsgMemoryEntry
= FindMsgMemory(Msg
);
1411 if (NULL
== MsgMemoryEntry
)
1413 lParamBufferSize
= -1;
1417 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1420 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, Window
->head
.pti
->MessageQueue
!= Win32Thread
->MessageQueue
)))
1422 DPRINT1("Failed to pack message parameters\n");
1426 /* If it can be sent now, then send it. */
1427 if (Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1429 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1431 UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
);
1432 /* Never send messages to exiting threads */
1436 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1438 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1450 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1452 if (CompletionCallback
)
1454 co_IntCallSentMessageCallback(CompletionCallback
,
1457 CompletionCallbackContext
,
1464 if (Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1466 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1468 DPRINT1("Failed to unpack message parameters\n");
1473 if(!(Message
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
1475 DPRINT1("MsqSendMessage(): Not enough memory to allocate a message");
1479 IntReferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1480 /* Take reference on this MessageQueue if its a callback. It will be released
1481 when message is processed or removed from target hwnd MessageQueue */
1482 if (CompletionCallback
)
1483 IntReferenceMessageQueue(Win32Thread
->MessageQueue
);
1485 Message
->Msg
.hwnd
= hWnd
;
1486 Message
->Msg
.message
= Msg
;
1487 Message
->Msg
.wParam
= wParam
;
1488 Message
->Msg
.lParam
= lParamPacked
;
1489 Message
->CompletionEvent
= NULL
;
1490 Message
->Result
= 0;
1491 Message
->lResult
= 0;
1492 Message
->QS_Flags
= 0;
1493 Message
->SenderQueue
= NULL
; // mjmartin, you are right! This is null.
1494 Message
->CallBackSenderQueue
= Win32Thread
->MessageQueue
;
1495 Message
->DispatchingListEntry
.Flink
= NULL
;
1496 Message
->CompletionCallback
= CompletionCallback
;
1497 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1498 Message
->HookMessage
= MSQ_NORMAL
;
1499 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1500 Message
->QS_Flags
= QS_SENDMESSAGE
;
1502 InsertTailList(&Window
->head
.pti
->MessageQueue
->SentMessagesListHead
, &Message
->ListEntry
);
1503 MsqWakeQueue(Window
->head
.pti
->MessageQueue
, QS_SENDMESSAGE
, TRUE
);
1504 IntDereferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1509 if (Window
) UserDerefObjectCo(Window
);
1513 /* This function posts a message if the destination's message queue belongs to
1514 another thread, otherwise it sends the message. It does not support broadcast
1517 co_IntPostOrSendMessage( HWND hWnd
,
1526 if ( hWnd
== HWND_BROADCAST
)
1531 if(!(Window
= UserGetWindowObject(hWnd
)))
1536 pti
= PsGetCurrentThreadWin32Thread();
1538 if ( Window
->head
.pti
->MessageQueue
!= pti
->MessageQueue
&&
1539 FindMsgMemory(Msg
) == 0 )
1541 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1545 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1551 return (LRESULT
)Result
;
1555 co_IntDoSendMessage( HWND hWnd
,
1562 LRESULT Result
= TRUE
;
1567 PMSGMEMORY MsgMemoryEntry
;
1569 if (HWND_BROADCAST
!= hWnd
)
1571 Window
= UserGetWindowObject(hWnd
);
1578 /* Check for an exiting window. */
1579 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1581 DPRINT1("co_IntDoSendMessage Window Exiting!\n");
1584 /* See if the current thread can handle the message */
1585 pti
= PsGetCurrentThreadWin32Thread();
1587 UserModeMsg
.hwnd
= hWnd
;
1588 UserModeMsg
.message
= Msg
;
1589 UserModeMsg
.wParam
= wParam
;
1590 UserModeMsg
.lParam
= lParam
;
1591 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1593 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1594 if (! NT_SUCCESS(Status
))
1596 EngSetLastError(ERROR_INVALID_PARAMETER
);
1597 return (dsm
? 0 : -1);
1602 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1603 KernelModeMsg
.message
,
1604 KernelModeMsg
.wParam
,
1605 KernelModeMsg
.lParam
);
1609 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1610 KernelModeMsg
.message
,
1611 KernelModeMsg
.wParam
,
1612 KernelModeMsg
.lParam
,
1618 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1619 if (! NT_SUCCESS(Status
))
1621 EngSetLastError(ERROR_INVALID_PARAMETER
);
1622 return(dsm
? 0 : -1);
1625 return (LRESULT
)Result
;
1629 UserSendNotifyMessage( HWND hWnd
,
1636 if (is_pointer_message(Msg
))
1638 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1642 // Basicly the same as IntPostOrSendMessage
1643 if (hWnd
== HWND_BROADCAST
) //Handle Broadcast
1649 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1650 List
= IntWinListChildren(DesktopWindow
);
1654 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1655 for (i
= 0; List
[i
]; i
++)
1657 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1664 ULONG_PTR lResult
= 0;
1665 Ret
= co_IntSendMessageWithCallBack( hWnd
,
1678 IntGetQueueStatus(DWORD Changes
)
1681 PUSER_MESSAGE_QUEUE Queue
;
1684 pti
= PsGetCurrentThreadWin32Thread();
1685 Queue
= pti
->MessageQueue
;
1687 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1689 /* High word, types of messages currently in the queue.
1690 Low word, types of messages that have been added to the queue and that
1691 are still in the queue
1693 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1695 pti
->pcti
->fsChangeBits
&= ~Changes
;
1701 IntInitMessagePumpHook()
1703 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1707 pti
->pcti
->dwcPumpHook
++;
1714 IntUninitMessagePumpHook()
1716 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1720 if (pti
->pcti
->dwcPumpHook
<= 0)
1724 pti
->pcti
->dwcPumpHook
--;
1730 /** Functions ******************************************************************/
1736 POINT pt
) // Just like the User call.
1740 WORD wDragWidth
, wDragHeight
;
1741 DECLARE_RETURN(BOOL
);
1743 DPRINT("Enter NtUserDragDetect(%x)\n", hWnd
);
1744 UserEnterExclusive();
1746 wDragWidth
= UserGetSystemMetrics(SM_CXDRAG
);
1747 wDragHeight
= UserGetSystemMetrics(SM_CYDRAG
);
1749 rect
.left
= pt
.x
- wDragWidth
;
1750 rect
.right
= pt
.x
+ wDragWidth
;
1752 rect
.top
= pt
.y
- wDragHeight
;
1753 rect
.bottom
= pt
.y
+ wDragHeight
;
1755 co_UserSetCapture(hWnd
);
1759 while (co_IntGetPeekMessage( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, FALSE
) ||
1760 co_IntGetPeekMessage( &msg
, 0, WM_QUEUESYNC
, WM_QUEUESYNC
, PM_REMOVE
, FALSE
) ||
1761 co_IntGetPeekMessage( &msg
, 0, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
, FALSE
) )
1763 if ( msg
.message
== WM_LBUTTONUP
)
1765 co_UserSetCapture(NULL
);
1768 if ( msg
.message
== WM_MOUSEMOVE
)
1771 tmp
.x
= (short)LOWORD(msg
.lParam
);
1772 tmp
.y
= (short)HIWORD(msg
.lParam
);
1773 if( !IntPtInRect( &rect
, tmp
) )
1775 co_UserSetCapture(NULL
);
1779 if ( msg
.message
== WM_KEYDOWN
)
1781 if ( msg
.wParam
== VK_ESCAPE
)
1783 co_UserSetCapture(NULL
);
1787 if ( msg
.message
== WM_QUEUESYNC
)
1789 co_HOOK_CallHooks( WH_CBT
, HCBT_QS
, 0, 0 );
1792 co_IntWaitMessage(NULL
, 0, 0);
1797 DPRINT("Leave NtUserDragDetect, ret=%i\n",_ret_
);
1803 NtUserPostMessage(HWND hWnd
,
1810 UserEnterExclusive();
1812 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1820 NtUserPostThreadMessage(DWORD idThread
,
1827 UserEnterExclusive();
1829 ret
= UserPostThreadMessage( idThread
, Msg
, wParam
, lParam
);
1837 NtUserWaitMessage(VOID
)
1841 UserEnterExclusive();
1842 DPRINT("NtUserWaitMessage Enter\n");
1843 ret
= co_IntWaitMessage(NULL
, 0, 0);
1844 DPRINT("NtUserWaitMessage Leave\n");
1851 NtUserGetMessage(PMSG pMsg
,
1859 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
1861 EngSetLastError(ERROR_INVALID_PARAMETER
);
1865 UserEnterExclusive();
1867 RtlZeroMemory(&Msg
, sizeof(MSG
));
1869 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
1877 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
1878 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
1880 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1882 SetLastNtError(_SEH2_GetExceptionCode());
1889 Ret
= Ret
? (WM_QUIT
!= pMsg
->message
) : FALSE
;
1895 NtUserPeekMessage( PMSG pMsg
,
1904 if ( RemoveMsg
& PM_BADMSGFLAGS
)
1906 EngSetLastError(ERROR_INVALID_FLAGS
);
1910 UserEnterExclusive();
1912 RtlZeroMemory(&Msg
, sizeof(MSG
));
1914 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
1922 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
1923 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
1925 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1927 SetLastNtError(_SEH2_GetExceptionCode());
1937 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
1944 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
1945 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
1947 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1949 _SEH2_YIELD(return FALSE
);
1953 UserEnterExclusive();
1955 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
1961 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
1968 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
1969 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
1971 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1981 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
1988 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
1989 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
1991 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1993 SetLastNtError(_SEH2_GetExceptionCode());
1994 _SEH2_YIELD(return FALSE
);
1998 UserEnterExclusive();
2000 Res
= IntDispatchMessage(&SafeMsg
);
2008 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
2015 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
2016 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
2018 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2020 SetLastNtError(_SEH2_GetExceptionCode());
2021 _SEH2_YIELD(return FALSE
);
2025 UserEnterExclusive();
2027 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
2035 NtUserMessageCall( HWND hWnd
,
2039 ULONG_PTR ResultInfo
,
2040 DWORD dwType
, // fnID?
2043 LRESULT lResult
= 0;
2046 USER_REFERENCE_ENTRY Ref
;
2048 UserEnterExclusive();
2052 case FNID_DEFWINDOWPROC
:
2053 /* Validate input */
2054 if (hWnd
&& (hWnd
!= INVALID_HANDLE_VALUE
))
2056 Window
= UserGetWindowObject(hWnd
);
2063 UserRefObjectCo(Window
, &Ref
);
2064 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2066 UserDerefObjectCo(Window
);
2068 case FNID_SENDNOTIFYMESSAGE
:
2069 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2071 case FNID_BROADCASTSYSTEMMESSAGE
:
2074 DWORD_PTR RetVal
= 0;
2080 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2081 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2083 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2092 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2093 parm
.recipients
== BSM_ALLCOMPONENTS
)
2096 else if (parm
.recipients
& BSM_APPLICATIONS
)
2098 if (parm
.flags
& BSF_QUERY
)
2100 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2102 co_IntSendMessageTimeout( HWND_BROADCAST
,
2110 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2112 co_IntSendMessageTimeout( HWND_BROADCAST
,
2116 SMTO_NOTIMEOUTIFNOTHUNG
,
2122 co_IntSendMessageTimeout( HWND_BROADCAST
,
2132 else if (parm
.flags
& BSF_POSTMESSAGE
)
2134 Ret
= UserPostMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2136 else //Everything else,,,, if ( parm.flags & BSF_SENDNOTIFYMESSAGE)
2138 Ret
= UserSendNotifyMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2143 case FNID_SENDMESSAGECALLBACK
:
2145 CALL_BACK_INFO CallBackInfo
;
2150 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2151 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2153 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2159 if (is_pointer_message(Msg
))
2161 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
2165 if (!(Ret
= co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2166 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
)))
2168 DPRINT1("Callback failure!\n");
2172 case FNID_SENDMESSAGE
:
2174 Ret
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2180 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2181 RtlCopyMemory((PVOID
)ResultInfo
, &Ret
, sizeof(ULONG_PTR
));
2183 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2192 case FNID_SENDMESSAGETIMEOUT
:
2194 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2199 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2200 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2202 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2209 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, &dsm
);
2215 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2216 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2218 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2227 // CallNextHook bypass.
2228 case FNID_CALLWNDPROC
:
2229 case FNID_CALLWNDPROCRET
:
2232 PCLIENTINFO ClientInfo
;
2233 PHOOK NextObj
, Hook
;
2235 pti
= GetW32ThreadInfo();
2237 Hook
= pti
->sphkCurrent
;
2241 NextObj
= Hook
->phkNext
;
2242 ClientInfo
= pti
->pClientInfo
;
2245 ClientInfo
->phkCurrent
= NextObj
;
2247 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2253 if (!ClientInfo
|| !NextObj
) break;
2255 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2257 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2262 CWP
.wParam
= wParam
;
2263 CWP
.lParam
= lParam
;
2264 DPRINT("WH_CALLWNDPROC: Hook %x NextHook %x\n", Hook
, NextObj
);
2266 lResult
= co_IntCallHookProc( Hook
->HookId
,
2268 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2279 CWPR
.wParam
= wParam
;
2280 CWPR
.lParam
= lParam
;
2281 CWPR
.lResult
= ClientInfo
->dwHookData
;
2283 lResult
= co_IntCallHookProc( Hook
->HookId
,
2285 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2297 case FNID_DEFWINDOWPROC
:
2298 case FNID_CALLWNDPROC
:
2299 case FNID_CALLWNDPROCRET
:
2304 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2305 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2307 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2323 #define INFINITE 0xFFFFFFFF
2324 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2328 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2329 IN DWORD dwMilliseconds
,
2333 PPROCESSINFO W32Process
;
2337 LARGE_INTEGER Timeout
;
2339 UserEnterExclusive();
2341 Status
= ObReferenceObjectByHandle(hProcess
,
2342 PROCESS_QUERY_INFORMATION
,
2348 if (!NT_SUCCESS(Status
))
2351 SetLastNtError(Status
);
2355 pti
= PsGetCurrentThreadWin32Thread();
2357 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2359 if ( PsGetProcessExitProcessCalled(Process
) ||
2361 pti
->ppi
== W32Process
)
2363 ObDereferenceObject(Process
);
2365 EngSetLastError(ERROR_INVALID_PARAMETER
);
2369 Handles
[0] = Process
;
2370 Handles
[1] = W32Process
->InputIdleEvent
;
2371 Handles
[2] = pti
->MessageQueue
->NewMessages
; // pEventQueueServer; IntMsqSetWakeMask returns hEventQueueClient
2375 ObDereferenceObject(Process
);
2377 return STATUS_SUCCESS
; /* no event to wait on */
2380 if (dwMilliseconds
!= INFINITE
)
2381 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2383 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2384 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2386 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2387 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2390 DPRINT("WFII: ppi 0x%x\n",W32Process
);
2391 DPRINT("WFII: waiting for %p\n", Handles
[1] );
2395 Status
= KeWaitForMultipleObjects( 3,
2401 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2403 UserEnterExclusive();
2405 if (!NT_SUCCESS(Status
))
2407 SetLastNtError(Status
);
2408 Status
= WAIT_FAILED
;
2420 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2421 DPRINT1("WFII: WAIT 2\n");
2425 case STATUS_TIMEOUT
:
2426 DPRINT1("WFII: timeout\n");
2431 DPRINT1("WFII: finished\n");
2432 Status
= STATUS_SUCCESS
;
2439 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2441 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
2442 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2444 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
2445 ObDereferenceObject(Process
);