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
);
19 HWND FASTCALL
co_UserSetCapture(HWND hWnd
);
21 #define PM_BADMSGFLAGS ~((QS_RAWINPUT << 16)|PM_QS_SENDMESSAGE|PM_QS_PAINT|PM_QS_POSTMESSAGE|PM_QS_INPUT|PM_NOYIELD|PM_REMOVE)
23 /* FUNCTIONS *****************************************************************/
26 IntInitMessageImpl(VOID
)
28 return STATUS_SUCCESS
;
32 IntCleanupMessageImpl(VOID
)
34 return STATUS_SUCCESS
;
38 /* flag for messages that contain pointers */
39 /* 32 messages per entry, messages 0..31 map to bits 0..31 */
41 #define SET(msg) (1 << ((msg) & 31))
43 static const unsigned int message_pointer_flags
[] =
46 SET(WM_CREATE
) | SET(WM_SETTEXT
) | SET(WM_GETTEXT
) |
47 SET(WM_WININICHANGE
) | SET(WM_DEVMODECHANGE
),
49 SET(WM_GETMINMAXINFO
) | SET(WM_DRAWITEM
) | SET(WM_MEASUREITEM
) | SET(WM_DELETEITEM
) |
52 SET(WM_WINDOWPOSCHANGING
) | SET(WM_WINDOWPOSCHANGED
) | SET(WM_COPYDATA
) |
53 SET(WM_COPYGLOBALDATA
) | SET(WM_NOTIFY
) | SET(WM_HELP
),
55 SET(WM_STYLECHANGING
) | SET(WM_STYLECHANGED
),
57 SET(WM_NCCREATE
) | SET(WM_NCCALCSIZE
) | SET(WM_GETDLGCODE
),
59 SET(EM_GETSEL
) | SET(EM_GETRECT
) | SET(EM_SETRECT
) | SET(EM_SETRECTNP
),
61 SET(EM_REPLACESEL
) | SET(EM_GETLINE
) | SET(EM_SETTABSTOPS
),
63 SET(SBM_GETRANGE
) | SET(SBM_SETSCROLLINFO
) | SET(SBM_GETSCROLLINFO
) | SET(SBM_GETSCROLLBARINFO
),
69 SET(CB_GETEDITSEL
) | SET(CB_ADDSTRING
) | SET(CB_DIR
) | SET(CB_GETLBTEXT
) |
70 SET(CB_INSERTSTRING
) | SET(CB_FINDSTRING
) | SET(CB_SELECTSTRING
) |
71 SET(CB_GETDROPPEDCONTROLRECT
) | SET(CB_FINDSTRINGEXACT
),
75 SET(LB_ADDSTRING
) | SET(LB_INSERTSTRING
) | SET(LB_GETTEXT
) | SET(LB_SELECTSTRING
) |
76 SET(LB_DIR
) | SET(LB_FINDSTRING
) |
77 SET(LB_GETSELITEMS
) | SET(LB_SETTABSTOPS
) | SET(LB_ADDFILE
) | SET(LB_GETITEMRECT
),
79 SET(LB_FINDSTRINGEXACT
),
85 SET(WM_NEXTMENU
) | SET(WM_SIZING
) | SET(WM_MOVING
) | SET(WM_DEVICECHANGE
),
87 SET(WM_MDICREATE
) | SET(WM_MDIGETACTIVE
) | SET(WM_DROPOBJECT
) |
88 SET(WM_QUERYDROPOBJECT
) | SET(WM_DRAGLOOP
) | SET(WM_DRAGSELECT
) | SET(WM_DRAGMOVE
),
102 SET(WM_ASKCBFORMATNAME
)
105 /* check whether a given message type includes pointers */
106 static inline int is_pointer_message( UINT message
)
108 if (message
>= 8*sizeof(message_pointer_flags
)) return FALSE
;
109 return (message_pointer_flags
[message
/ 32] & SET(message
)) != 0;
112 #define MMS_SIZE_WPARAM -1
113 #define MMS_SIZE_WPARAMWCHAR -2
114 #define MMS_SIZE_LPARAMSZ -3
115 #define MMS_SIZE_SPECIAL -4
116 #define MMS_FLAG_READ 0x01
117 #define MMS_FLAG_WRITE 0x02
118 #define MMS_FLAG_READWRITE (MMS_FLAG_READ | MMS_FLAG_WRITE)
119 typedef struct tagMSGMEMORY
125 MSGMEMORY
, *PMSGMEMORY
;
127 static MSGMEMORY MsgMemory
[] =
129 { WM_CREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
130 { WM_DDE_ACK
, sizeof(KMDDELPARAM
), MMS_FLAG_READ
},
131 { WM_DDE_EXECUTE
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
132 { WM_GETMINMAXINFO
, sizeof(MINMAXINFO
), MMS_FLAG_READWRITE
},
133 { WM_GETTEXT
, MMS_SIZE_WPARAMWCHAR
, MMS_FLAG_WRITE
},
134 { WM_NCCALCSIZE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
135 { WM_NCCREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
136 { WM_SETTEXT
, MMS_SIZE_LPARAMSZ
, MMS_FLAG_READ
},
137 { WM_STYLECHANGED
, sizeof(STYLESTRUCT
), MMS_FLAG_READ
},
138 { WM_STYLECHANGING
, sizeof(STYLESTRUCT
), MMS_FLAG_READWRITE
},
139 { WM_COPYDATA
, MMS_SIZE_SPECIAL
, MMS_FLAG_READ
},
140 { WM_COPYGLOBALDATA
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
141 { WM_WINDOWPOSCHANGED
, sizeof(WINDOWPOS
), MMS_FLAG_READ
},
142 { WM_WINDOWPOSCHANGING
, sizeof(WINDOWPOS
), MMS_FLAG_READWRITE
},
145 static PMSGMEMORY FASTCALL
146 FindMsgMemory(UINT Msg
)
148 PMSGMEMORY MsgMemoryEntry
;
150 /* See if this message type is present in the table */
151 for (MsgMemoryEntry
= MsgMemory
;
152 MsgMemoryEntry
< MsgMemory
+ sizeof(MsgMemory
) / sizeof(MSGMEMORY
);
155 if (Msg
== MsgMemoryEntry
->Message
)
157 return MsgMemoryEntry
;
165 MsgMemorySize(PMSGMEMORY MsgMemoryEntry
, WPARAM wParam
, LPARAM lParam
)
168 PUNICODE_STRING WindowName
;
169 PUNICODE_STRING ClassName
;
174 if (MMS_SIZE_WPARAM
== MsgMemoryEntry
->Size
)
178 else if (MMS_SIZE_WPARAMWCHAR
== MsgMemoryEntry
->Size
)
180 Size
= (UINT
) (wParam
* sizeof(WCHAR
));
182 else if (MMS_SIZE_LPARAMSZ
== MsgMemoryEntry
->Size
)
184 Size
= (UINT
) ((wcslen((PWSTR
) lParam
) + 1) * sizeof(WCHAR
));
186 else if (MMS_SIZE_SPECIAL
== MsgMemoryEntry
->Size
)
188 switch(MsgMemoryEntry
->Message
)
192 Cs
= (CREATESTRUCTW
*) lParam
;
193 WindowName
= (PUNICODE_STRING
) Cs
->lpszName
;
194 ClassName
= (PUNICODE_STRING
) Cs
->lpszClass
;
195 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
196 if (IS_ATOM(ClassName
->Buffer
))
198 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
202 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
207 Size
= wParam
? sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
) : sizeof(RECT
);
211 Size
= sizeof(COPYDATASTRUCT
) + ((PCOPYDATASTRUCT
)lParam
)->cbData
;
222 Size
= MsgMemoryEntry
->Size
;
225 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
227 DPRINT1("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH2_GetExceptionCode());
235 PackParam(LPARAM
*lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolNeeded
)
237 NCCALCSIZE_PARAMS
*UnpackedNcCalcsize
;
238 NCCALCSIZE_PARAMS
*PackedNcCalcsize
;
239 CREATESTRUCTW
*UnpackedCs
;
240 CREATESTRUCTW
*PackedCs
;
241 PLARGE_STRING WindowName
;
242 PUNICODE_STRING ClassName
;
247 *lParamPacked
= lParam
;
249 if (NonPagedPoolNeeded
)
250 PoolType
= NonPagedPool
;
252 PoolType
= PagedPool
;
254 if (WM_NCCALCSIZE
== Msg
&& wParam
)
257 UnpackedNcCalcsize
= (NCCALCSIZE_PARAMS
*) lParam
;
258 PackedNcCalcsize
= ExAllocatePoolWithTag(PoolType
,
259 sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
),
262 if (NULL
== PackedNcCalcsize
)
264 DPRINT1("Not enough memory to pack lParam\n");
265 return STATUS_NO_MEMORY
;
267 RtlCopyMemory(PackedNcCalcsize
, UnpackedNcCalcsize
, sizeof(NCCALCSIZE_PARAMS
));
268 PackedNcCalcsize
->lppos
= (PWINDOWPOS
) (PackedNcCalcsize
+ 1);
269 RtlCopyMemory(PackedNcCalcsize
->lppos
, UnpackedNcCalcsize
->lppos
, sizeof(WINDOWPOS
));
270 *lParamPacked
= (LPARAM
) PackedNcCalcsize
;
272 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
274 UnpackedCs
= (CREATESTRUCTW
*) lParam
;
275 WindowName
= (PLARGE_STRING
) UnpackedCs
->lpszName
;
276 ClassName
= (PUNICODE_STRING
) UnpackedCs
->lpszClass
;
277 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
278 if (IS_ATOM(ClassName
->Buffer
))
280 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
284 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
286 PackedCs
= ExAllocatePoolWithTag(PoolType
, Size
, TAG_MSG
);
287 if (NULL
== PackedCs
)
289 DPRINT1("Not enough memory to pack lParam\n");
290 return STATUS_NO_MEMORY
;
292 RtlCopyMemory(PackedCs
, UnpackedCs
, sizeof(CREATESTRUCTW
));
293 CsData
= (PCHAR
) (PackedCs
+ 1);
294 PackedCs
->lpszName
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
295 RtlCopyMemory(CsData
, WindowName
->Buffer
, WindowName
->Length
);
296 CsData
+= WindowName
->Length
;
297 *((WCHAR
*) CsData
) = L
'\0';
298 CsData
+= sizeof(WCHAR
);
299 PackedCs
->lpszClass
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
300 if (IS_ATOM(ClassName
->Buffer
))
302 *((WCHAR
*) CsData
) = L
'A';
303 CsData
+= sizeof(WCHAR
);
304 *((ATOM
*) CsData
) = (ATOM
)(DWORD_PTR
) ClassName
->Buffer
;
305 CsData
+= sizeof(ATOM
);
309 *((WCHAR
*) CsData
) = L
'S';
310 CsData
+= sizeof(WCHAR
);
311 RtlCopyMemory(CsData
, ClassName
->Buffer
, ClassName
->Length
);
312 CsData
+= ClassName
->Length
;
313 *((WCHAR
*) CsData
) = L
'\0';
314 CsData
+= sizeof(WCHAR
);
316 ASSERT(CsData
== (PCHAR
) PackedCs
+ Size
);
317 *lParamPacked
= (LPARAM
) PackedCs
;
319 else if (PoolType
== NonPagedPool
)
321 PMSGMEMORY MsgMemoryEntry
;
325 MsgMemoryEntry
= FindMsgMemory(Msg
);
327 if ((!MsgMemoryEntry
) || (MsgMemoryEntry
->Size
< 0))
329 /* Keep previous behavior */
330 return STATUS_SUCCESS
;
332 size
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
335 DPRINT1("No size for lParamPacked\n");
336 return STATUS_SUCCESS
;
338 PackedData
= ExAllocatePoolWithTag(NonPagedPool
, size
, TAG_MSG
);
339 RtlCopyMemory(PackedData
, (PVOID
)lParam
, MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
));
340 *lParamPacked
= (LPARAM
)PackedData
;
343 return STATUS_SUCCESS
;
347 UnpackParam(LPARAM lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolUsed
)
349 NCCALCSIZE_PARAMS
*UnpackedParams
;
350 NCCALCSIZE_PARAMS
*PackedParams
;
351 PWINDOWPOS UnpackedWindowPos
;
353 if (lParamPacked
== lParam
)
355 return STATUS_SUCCESS
;
358 if (WM_NCCALCSIZE
== Msg
&& wParam
)
360 PackedParams
= (NCCALCSIZE_PARAMS
*) lParamPacked
;
361 UnpackedParams
= (NCCALCSIZE_PARAMS
*) lParam
;
362 UnpackedWindowPos
= UnpackedParams
->lppos
;
363 RtlCopyMemory(UnpackedParams
, PackedParams
, sizeof(NCCALCSIZE_PARAMS
));
364 UnpackedParams
->lppos
= UnpackedWindowPos
;
365 RtlCopyMemory(UnpackedWindowPos
, PackedParams
+ 1, sizeof(WINDOWPOS
));
366 ExFreePool((PVOID
) lParamPacked
);
368 return STATUS_SUCCESS
;
370 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
372 ExFreePool((PVOID
) lParamPacked
);
374 return STATUS_SUCCESS
;
376 else if (NonPagedPoolUsed
)
378 PMSGMEMORY MsgMemoryEntry
;
379 MsgMemoryEntry
= FindMsgMemory(Msg
);
380 if (MsgMemoryEntry
->Size
< 0)
382 /* Keep previous behavior */
383 return STATUS_INVALID_PARAMETER
;
386 if (MsgMemory
->Flags
== MMS_FLAG_READWRITE
)
388 //RtlCopyMemory((PVOID)lParam, (PVOID)lParamPacked, MsgMemory->Size);
390 ExFreePool((PVOID
) lParamPacked
);
391 return STATUS_SUCCESS
;
396 return STATUS_INVALID_PARAMETER
;
399 static NTSTATUS FASTCALL
400 CopyMsgToKernelMem(MSG
*KernelModeMsg
, MSG
*UserModeMsg
, PMSGMEMORY MsgMemoryEntry
)
407 *KernelModeMsg
= *UserModeMsg
;
409 /* See if this message type is present in the table */
410 if (NULL
== MsgMemoryEntry
)
412 /* Not present, no copying needed */
413 return STATUS_SUCCESS
;
416 /* Determine required size */
417 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
421 /* Allocate kernel mem */
422 KernelMem
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
423 if (NULL
== KernelMem
)
425 DPRINT1("Not enough memory to copy message to kernel mem\n");
426 return STATUS_NO_MEMORY
;
428 KernelModeMsg
->lParam
= (LPARAM
) KernelMem
;
430 /* Copy data if required */
431 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_READ
))
433 Status
= MmCopyFromCaller(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
434 if (! NT_SUCCESS(Status
))
436 DPRINT1("Failed to copy message to kernel: invalid usermode buffer\n");
437 ExFreePoolWithTag(KernelMem
, TAG_MSG
);
443 /* Make sure we don't pass any secrets to usermode */
444 RtlZeroMemory(KernelMem
, Size
);
449 KernelModeMsg
->lParam
= 0;
452 return STATUS_SUCCESS
;
455 static NTSTATUS FASTCALL
456 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
459 PMSGMEMORY MsgMemoryEntry
;
462 /* See if this message type is present in the table */
463 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
464 if (NULL
== MsgMemoryEntry
)
466 /* Not present, no copying needed */
467 return STATUS_SUCCESS
;
470 /* Determine required size */
471 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
475 /* Copy data if required */
476 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
478 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
479 if (! NT_SUCCESS(Status
))
481 DPRINT1("Failed to copy message from kernel: invalid usermode buffer\n");
482 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
487 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
490 return STATUS_SUCCESS
;
494 // Wakeup any thread/process waiting on idle input.
499 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
500 PUSER_MESSAGE_QUEUE ForegroundQueue
;
501 PTHREADINFO pti
, ptiForeground
= NULL
;
503 ForegroundQueue
= IntGetFocusMessageQueue();
506 ptiForeground
= ForegroundQueue
->Thread
->Tcb
.Win32Thread
;
508 pti
= PsGetCurrentThreadWin32Thread();
512 pti
->pClientInfo
->cSpins
= 0; // Reset spins.
514 if ( pti
->pDeskInfo
&& pti
== ptiForeground
)
516 if ( pti
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) ||
517 pti
->pDeskInfo
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) )
519 co_HOOK_CallHooks(WH_FOREGROUNDIDLE
,HC_ACTION
,0,0);
524 DPRINT("IdlePing ppi 0x%x\n",ppi
);
525 if ( ppi
&& ppi
->InputIdleEvent
)
527 DPRINT("InputIdleEvent\n");
528 KeSetEvent( ppi
->InputIdleEvent
, IO_NO_INCREMENT
, FALSE
);
535 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
537 DPRINT("IdlePong ppi 0x%x\n",ppi
);
538 if ( ppi
&& ppi
->InputIdleEvent
)
540 KeClearEvent(ppi
->InputIdleEvent
);
545 GetWakeMask(UINT first
, UINT last
)
547 UINT mask
= QS_POSTMESSAGE
| QS_SENDMESSAGE
; /* Always selected */
551 if ((first
<= WM_KEYLAST
) && (last
>= WM_KEYFIRST
)) mask
|= QS_KEY
;
552 if ( ((first
<= WM_MOUSELAST
) && (last
>= WM_MOUSEFIRST
)) ||
553 ((first
<= WM_NCMOUSELAST
) && (last
>= WM_NCMOUSEFIRST
)) ) mask
|= QS_MOUSE
;
554 if ((first
<= WM_TIMER
) && (last
>= WM_TIMER
)) mask
|= QS_TIMER
;
555 if ((first
<= WM_SYSTIMER
) && (last
>= WM_SYSTIMER
)) mask
|= QS_TIMER
;
556 if ((first
<= WM_PAINT
) && (last
>= WM_PAINT
)) mask
|= QS_PAINT
;
558 else mask
= QS_ALLINPUT
;
564 IntCallWndProc( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
566 BOOL SameThread
= FALSE
;
569 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
576 co_HOOK_CallHooks( WH_CALLWNDPROC
, HC_ACTION
, SameThread
, (LPARAM
)&CWP
);
580 IntCallWndProcRet ( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*uResult
)
582 BOOL SameThread
= FALSE
;
585 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
590 CWPR
.wParam
= wParam
;
591 CWPR
.lParam
= lParam
;
592 CWPR
.lResult
= *uResult
;
593 co_HOOK_CallHooks( WH_CALLWNDPROCRET
, HC_ACTION
, SameThread
, (LPARAM
)&CWPR
);
597 IntDispatchMessage(PMSG pMsg
)
599 LARGE_INTEGER TickCount
;
607 Window
= UserGetWindowObject(pMsg
->hwnd
);
608 if (!Window
) return 0;
611 pti
= PsGetCurrentThreadWin32Thread();
613 if ( Window
->head
.pti
!= pti
)
615 EngSetLastError( ERROR_MESSAGE_SYNC_ONLY
);
619 if (((pMsg
->message
== WM_SYSTIMER
) ||
620 (pMsg
->message
== WM_TIMER
)) &&
623 if (pMsg
->message
== WM_TIMER
)
625 if (ValidateTimerCallback(pti
,pMsg
->lParam
))
627 KeQueryTickCount(&TickCount
);
628 Time
= MsqCalculateMessageTime(&TickCount
);
629 retval
= co_IntCallWindowProc((WNDPROC
)pMsg
->lParam
,
641 PTIMER pTimer
= FindSystemTimer(pMsg
);
642 if (pTimer
&& pTimer
->pfn
)
644 KeQueryTickCount(&TickCount
);
645 Time
= MsqCalculateMessageTime(&TickCount
);
646 pTimer
->pfn(pMsg
->hwnd
, WM_SYSTIMER
, (UINT
)pMsg
->wParam
, Time
);
652 if ( !Window
) return 0;
654 /* Since we are doing a callback on the same thread right away, there is
655 no need to copy the lparam to kernel mode and then back to usermode.
656 We just pretend it isn't a pointer */
658 retval
= co_IntCallWindowProc( Window
->lpfnWndProc
,
666 if (pMsg
->message
== WM_PAINT
)
668 /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
669 HRGN hrgn
= IntSysCreateRectRgn( 0, 0, 0, 0 );
670 co_UserGetUpdateRgn( Window
, hrgn
, TRUE
);
671 REGION_FreeRgnByHandle( hrgn
);
678 * Internal version of PeekMessage() doing all the work
681 co_IntPeekMessage( PMSG Msg
,
690 LARGE_INTEGER LargeTickCount
;
691 PUSER_MESSAGE_QUEUE ThreadQueue
;
696 pti
= PsGetCurrentThreadWin32Thread();
697 ThreadQueue
= pti
->MessageQueue
;
698 pci
= pti
->pClientInfo
;
700 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
701 ProcessMask
= HIWORD(RemoveMsg
);
703 /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns
704 all available messages (that is, no range filtering is performed)". */
705 if (!ProcessMask
) ProcessMask
= (QS_ALLPOSTMESSAGE
|QS_ALLINPUT
);
711 KeQueryTickCount(&LargeTickCount
);
712 ThreadQueue
->LastMsgRead
= LargeTickCount
.u
.LowPart
;
713 pti
->pcti
->tickLastMsgChecked
= LargeTickCount
.u
.LowPart
;
715 /* Dispatch sent messages here. */
716 while ( co_MsqDispatchOneSentMessage(ThreadQueue
) )
718 /* if some PM_QS* flags were specified, only handle sent messages from now on */
719 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
; // wine does this; ProcessMask = QS_SENDMESSAGE;
721 if (Hit
) return FALSE
;
723 /* Clear changed bits so we can wait on them if we don't find a message */
724 if (ProcessMask
& QS_POSTMESSAGE
)
726 pti
->pcti
->fsChangeBits
&= ~(QS_POSTMESSAGE
| QS_HOTKEY
| QS_TIMER
);
727 if (MsgFilterMin
== 0 && MsgFilterMax
== 0) // wine hack does this; ~0U)
729 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
733 if (ProcessMask
& QS_INPUT
)
735 pti
->pcti
->fsChangeBits
&= ~QS_INPUT
;
738 /* Now check for normal messages. */
739 if ((ProcessMask
& QS_POSTMESSAGE
) &&
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");
867 if (Status
== STATUS_USER_APC
|| Status
== STATUS_TIMEOUT
)
878 co_IntGetPeekMessage( PMSG pMsg
,
887 BOOL Present
= FALSE
;
890 if ( hWnd
== HWND_TOPMOST
|| hWnd
== HWND_BROADCAST
)
894 if (hWnd
&& hWnd
!= HWND_BOTTOM
)
896 if (!(Window
= UserGetWindowObject(hWnd
)))
909 if (MsgFilterMax
< MsgFilterMin
)
917 RemoveMsg
|= ((GetWakeMask( MsgFilterMin
, MsgFilterMax
))<< 16);
920 pti
= PsGetCurrentThreadWin32Thread();
921 pti
->pClientInfo
->cSpins
++; // Bump up the spin count.
925 Present
= co_IntPeekMessage( pMsg
,
933 /* GetMessage or PostMessage must never get messages that contain pointers */
934 ASSERT(FindMsgMemory(pMsg
->message
) == NULL
);
936 if (pMsg
->message
!= WM_PAINT
&& pMsg
->message
!= WM_QUIT
)
938 pti
->timeLast
= pMsg
->time
;
939 pti
->ptLast
= pMsg
->pt
;
942 // The WH_GETMESSAGE hook enables an application to monitor messages about to
943 // be returned by the GetMessage or PeekMessage function.
945 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)pMsg
);
952 Status
= co_MsqWaitForNewMessages( pti
->MessageQueue
,
956 if ( !NT_SUCCESS(Status
) ||
957 Status
== STATUS_USER_APC
||
958 Status
== STATUS_TIMEOUT
)
966 if (!(RemoveMsg
& PM_NOYIELD
))
969 // Yield this thread!
972 UserEnterExclusive();
973 // Fall through to exit.
979 while( bGMSG
&& !Present
);
981 // Been spinning, time to swap vinyl...
982 if (pti
->pClientInfo
->cSpins
>= 100)
984 // Clear the spin cycle to fix the mix.
985 pti
->pClientInfo
->cSpins
= 0;
986 //if (!(pti->TIF_flags & TIF_SPINNING)) FIXME need to swap vinyl..
992 UserPostThreadMessage( DWORD idThread
,
1000 LARGE_INTEGER LargeTickCount
;
1003 if (is_pointer_message(Msg
))
1005 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1009 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
1011 if( Status
== STATUS_SUCCESS
)
1013 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
1015 !pThread
->MessageQueue
||
1016 (pThread
->TIF_flags
& TIF_INCLEANUP
))
1018 ObDereferenceObject( peThread
);
1022 Message
.hwnd
= NULL
;
1023 Message
.message
= Msg
;
1024 Message
.wParam
= wParam
;
1025 Message
.lParam
= lParam
;
1026 Message
.pt
= gpsi
->ptCursor
;
1028 KeQueryTickCount(&LargeTickCount
);
1029 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1030 MsqPostMessage(pThread
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
);
1031 ObDereferenceObject( peThread
);
1036 SetLastNtError( Status
);
1042 UserPostMessage( HWND Wnd
,
1048 MSG Message
, KernelModeMsg
;
1049 LARGE_INTEGER LargeTickCount
;
1052 Message
.message
= Msg
;
1053 Message
.wParam
= wParam
;
1054 Message
.lParam
= lParam
;
1055 Message
.pt
= gpsi
->ptCursor
;
1056 KeQueryTickCount(&LargeTickCount
);
1057 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1059 if (is_pointer_message(Message
.message
))
1061 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1065 if( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1068 PMSGMEMORY MsgMemoryEntry
;
1070 MsgMemoryEntry
= FindMsgMemory(Message
.message
);
1072 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &Message
, MsgMemoryEntry
);
1073 if (! NT_SUCCESS(Status
))
1075 EngSetLastError(ERROR_INVALID_PARAMETER
);
1078 co_IntSendMessageNoWait(KernelModeMsg
.hwnd
,
1079 KernelModeMsg
.message
,
1080 KernelModeMsg
.wParam
,
1081 KernelModeMsg
.lParam
);
1083 if (MsgMemoryEntry
&& KernelModeMsg
.lParam
)
1084 ExFreePool((PVOID
) KernelModeMsg
.lParam
);
1091 return UserPostThreadMessage( PtrToInt(PsGetCurrentThreadId()),
1096 if (Wnd
== HWND_BROADCAST
)
1102 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1103 List
= IntWinListChildren(DesktopWindow
);
1107 UserPostMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1108 for (i
= 0; List
[i
]; i
++)
1110 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1112 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1119 Window
= UserGetWindowObject(Wnd
);
1125 pti
= Window
->head
.pti
;
1126 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1128 DPRINT1("Attempted to post message to window 0x%x when the thread is in cleanup!\n", Wnd
);
1132 if ( Window
->state
& WNDS_DESTROYED
)
1134 DPRINT1("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd
);
1135 /* FIXME - last error code? */
1141 MsqPostQuitMessage(Window
->head
.pti
->MessageQueue
, wParam
);
1145 MsqPostMessage(Window
->head
.pti
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
);
1153 co_IntSendMessage( HWND hWnd
,
1158 ULONG_PTR Result
= 0;
1159 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1161 return (LRESULT
)Result
;
1166 static LRESULT FASTCALL
1167 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1173 ULONG_PTR
*uResult
)
1177 PMSGMEMORY MsgMemoryEntry
;
1178 INT lParamBufferSize
;
1179 LPARAM lParamPacked
;
1180 PTHREADINFO Win32Thread
;
1181 ULONG_PTR Result
= 0;
1182 DECLARE_RETURN(LRESULT
);
1183 USER_REFERENCE_ENTRY Ref
;
1185 if (!(Window
= UserGetWindowObject(hWnd
)))
1190 UserRefObjectCo(Window
, &Ref
);
1192 Win32Thread
= PsGetCurrentThreadWin32Thread();
1194 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1196 if ( NULL
!= Win32Thread
&&
1197 Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1199 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
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 DPRINT1("Failed to pack message parameters\n");
1222 ObReferenceObject(Win32Thread
->pEThread
);
1223 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1235 ObDereferenceObject(Win32Thread
->pEThread
);
1237 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1239 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1241 DPRINT1("Failed to unpack message parameters\n");
1248 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->head
.pti
->MessageQueue
))
1250 // FIXME - Set window hung and add to a list.
1251 /* FIXME - Set a LastError? */
1255 if (Window
->state
& WNDS_DESTROYED
)
1257 /* FIXME - last error? */
1258 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1264 Status
= co_MsqSendMessage( Window
->head
.pti
->MessageQueue
,
1270 (uFlags
& SMTO_BLOCK
),
1274 while ((STATUS_TIMEOUT
== Status
) &&
1275 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1276 !MsqIsHung(Window
->head
.pti
->MessageQueue
)); // FIXME - Set window hung and add to a list.
1278 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1280 if (STATUS_TIMEOUT
== Status
)
1284 Microsoft Windows 2000: If GetLastError returns zero, then the function
1286 XP+ : If the function fails or times out, the return value is zero.
1287 To get extended error information, call GetLastError. If GetLastError
1288 returns ERROR_TIMEOUT, then the function timed out.
1290 EngSetLastError(ERROR_TIMEOUT
);
1293 else if (! NT_SUCCESS(Status
))
1295 SetLastNtError(Status
);
1302 if (Window
) UserDerefObjectCo(Window
);
1307 co_IntSendMessageTimeout( HWND hWnd
,
1313 ULONG_PTR
*uResult
)
1319 if (HWND_BROADCAST
!= hWnd
)
1321 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1324 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1325 if (NULL
== DesktopWindow
)
1327 EngSetLastError(ERROR_INTERNAL_ERROR
);
1331 /* Send message to the desktop window too! */
1332 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1334 Children
= IntWinListChildren(DesktopWindow
);
1335 if (NULL
== Children
)
1340 for (Child
= Children
; NULL
!= *Child
; Child
++)
1342 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1345 ExFreePool(Children
);
1347 return (LRESULT
) TRUE
;
1351 co_IntSendMessageNoWait(HWND hWnd
,
1356 ULONG_PTR Result
= 0;
1357 co_IntSendMessageWithCallBack(hWnd
,
1367 If you send a message in the range below WM_USER to the asynchronous message
1368 functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its
1369 message parameters cannot include pointers. Otherwise, the operation will fail.
1370 The functions will return before the receiving thread has had a chance to
1371 process the message and the sender will free the memory before it is used.
1374 co_IntSendMessageWithCallBack( HWND hWnd
,
1378 SENDASYNCPROC CompletionCallback
,
1379 ULONG_PTR CompletionCallbackContext
,
1384 PMSGMEMORY MsgMemoryEntry
;
1385 INT lParamBufferSize
;
1386 LPARAM lParamPacked
;
1387 PTHREADINFO Win32Thread
;
1388 DECLARE_RETURN(LRESULT
);
1389 USER_REFERENCE_ENTRY Ref
;
1390 PUSER_SENT_MESSAGE Message
;
1392 if (!(Window
= UserGetWindowObject(hWnd
)))
1397 UserRefObjectCo(Window
, &Ref
);
1399 if (Window
->state
& WNDS_DESTROYED
)
1401 /* FIXME - last error? */
1402 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1406 Win32Thread
= PsGetCurrentThreadWin32Thread();
1408 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1410 if (Win32Thread
== NULL
)
1416 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1418 /* Never send messages to exiting threads */
1422 /* See if this message type is present in the table */
1423 MsgMemoryEntry
= FindMsgMemory(Msg
);
1424 if (NULL
== MsgMemoryEntry
)
1426 lParamBufferSize
= -1;
1430 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1433 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, Window
->head
.pti
->MessageQueue
!= Win32Thread
->MessageQueue
)))
1435 DPRINT1("Failed to pack message parameters\n");
1439 /* If this is not a callback and it can be sent now, then send it. */
1440 if ((Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
) && (CompletionCallback
== NULL
))
1442 ObReferenceObject(Win32Thread
->pEThread
);
1443 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1454 ObDereferenceObject(Win32Thread
->pEThread
);
1457 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1459 if ((Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
) && (CompletionCallback
== NULL
))
1461 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1463 DPRINT1("Failed to unpack message parameters\n");
1468 if(!(Message
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
1470 DPRINT1("MsqSendMessage(): Not enough memory to allocate a message");
1474 Message
->Msg
.hwnd
= hWnd
;
1475 Message
->Msg
.message
= Msg
;
1476 Message
->Msg
.wParam
= wParam
;
1477 Message
->Msg
.lParam
= lParamPacked
;
1478 Message
->CompletionEvent
= NULL
;
1479 Message
->Result
= 0;
1480 Message
->lResult
= 0;
1481 Message
->QS_Flags
= 0;
1482 Message
->SenderQueue
= NULL
; // mjmartin, you are right! This is null.
1483 Message
->CallBackSenderQueue
= Win32Thread
->MessageQueue
;
1485 IntReferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1486 Message
->CompletionCallback
= CompletionCallback
;
1487 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1488 Message
->HookMessage
= MSQ_NORMAL
| MSQ_SENTNOWAIT
;
1489 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1491 Message
->QS_Flags
= QS_SENDMESSAGE
;
1492 MsqWakeQueue(Window
->head
.pti
->MessageQueue
, QS_SENDMESSAGE
, FALSE
);
1494 InsertTailList(&Window
->head
.pti
->MessageQueue
->SentMessagesListHead
, &Message
->ListEntry
);
1495 IntDereferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1500 if (Window
) UserDerefObjectCo(Window
);
1504 /* This function posts a message if the destination's message queue belongs to
1505 another thread, otherwise it sends the message. It does not support broadcast
1508 co_IntPostOrSendMessage( HWND hWnd
,
1517 if ( hWnd
== HWND_BROADCAST
)
1522 if(!(Window
= UserGetWindowObject(hWnd
)))
1527 pti
= PsGetCurrentThreadWin32Thread();
1529 if ( Window
->head
.pti
->MessageQueue
!= pti
->MessageQueue
&&
1530 FindMsgMemory(Msg
) == 0 )
1532 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1536 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1542 return (LRESULT
)Result
;
1546 co_IntDoSendMessage( HWND hWnd
,
1553 LRESULT Result
= TRUE
;
1558 PMSGMEMORY MsgMemoryEntry
;
1560 if (HWND_BROADCAST
!= hWnd
)
1562 Window
= UserGetWindowObject(hWnd
);
1569 /* Check for an exiting window. */
1570 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1572 DPRINT1("co_IntDoSendMessage Window Exiting!\n");
1575 /* See if the current thread can handle the message */
1576 pti
= PsGetCurrentThreadWin32Thread();
1578 UserModeMsg
.hwnd
= hWnd
;
1579 UserModeMsg
.message
= Msg
;
1580 UserModeMsg
.wParam
= wParam
;
1581 UserModeMsg
.lParam
= lParam
;
1582 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1584 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1585 if (! NT_SUCCESS(Status
))
1587 EngSetLastError(ERROR_INVALID_PARAMETER
);
1588 return (dsm
? 0 : -1);
1593 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1594 KernelModeMsg
.message
,
1595 KernelModeMsg
.wParam
,
1596 KernelModeMsg
.lParam
);
1600 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1601 KernelModeMsg
.message
,
1602 KernelModeMsg
.wParam
,
1603 KernelModeMsg
.lParam
,
1609 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1610 if (! NT_SUCCESS(Status
))
1612 EngSetLastError(ERROR_INVALID_PARAMETER
);
1613 return(dsm
? 0 : -1);
1616 return (LRESULT
)Result
;
1620 UserSendNotifyMessage( HWND hWnd
,
1627 if (is_pointer_message(Msg
))
1629 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1633 // Basicly the same as IntPostOrSendMessage
1634 if (hWnd
== HWND_BROADCAST
) //Handle Broadcast
1640 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1641 List
= IntWinListChildren(DesktopWindow
);
1645 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1646 for (i
= 0; List
[i
]; i
++)
1648 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1655 ULONG_PTR lResult
= 0;
1656 Ret
= co_IntSendMessageWithCallBack( hWnd
,
1669 IntGetQueueStatus(DWORD Changes
)
1672 PUSER_MESSAGE_QUEUE Queue
;
1675 pti
= PsGetCurrentThreadWin32Thread();
1676 Queue
= pti
->MessageQueue
;
1678 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1680 /* High word, types of messages currently in the queue.
1681 Low word, types of messages that have been added to the queue and that
1682 are still in the queue
1684 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1686 pti
->pcti
->fsChangeBits
&= ~Changes
;
1692 IntInitMessagePumpHook()
1694 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1698 pti
->pcti
->dwcPumpHook
++;
1705 IntUninitMessagePumpHook()
1707 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1711 if (pti
->pcti
->dwcPumpHook
<= 0)
1715 pti
->pcti
->dwcPumpHook
--;
1721 /** Functions ******************************************************************/
1727 POINT pt
) // Just like the User call.
1731 WORD wDragWidth
, wDragHeight
;
1732 DECLARE_RETURN(BOOL
);
1734 DPRINT("Enter NtUserDragDetect(%x)\n", hWnd
);
1735 UserEnterExclusive();
1737 wDragWidth
= UserGetSystemMetrics(SM_CXDRAG
);
1738 wDragHeight
= UserGetSystemMetrics(SM_CYDRAG
);
1740 rect
.left
= pt
.x
- wDragWidth
;
1741 rect
.right
= pt
.x
+ wDragWidth
;
1743 rect
.top
= pt
.y
- wDragHeight
;
1744 rect
.bottom
= pt
.y
+ wDragHeight
;
1746 co_UserSetCapture(hWnd
);
1750 while (co_IntGetPeekMessage( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, FALSE
) ||
1751 co_IntGetPeekMessage( &msg
, 0, WM_QUEUESYNC
, WM_QUEUESYNC
, PM_REMOVE
, FALSE
) ||
1752 co_IntGetPeekMessage( &msg
, 0, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
, FALSE
) )
1754 if ( msg
.message
== WM_LBUTTONUP
)
1756 co_UserSetCapture(NULL
);
1759 if ( msg
.message
== WM_MOUSEMOVE
)
1762 tmp
.x
= (short)LOWORD(msg
.lParam
);
1763 tmp
.y
= (short)HIWORD(msg
.lParam
);
1764 if( !IntPtInRect( &rect
, tmp
) )
1766 co_UserSetCapture(NULL
);
1770 if ( msg
.message
== WM_KEYDOWN
)
1772 if ( msg
.wParam
== VK_ESCAPE
)
1774 co_UserSetCapture(NULL
);
1778 if ( msg
.message
== WM_QUEUESYNC
)
1780 co_HOOK_CallHooks( WH_CBT
, HCBT_QS
, 0, 0 );
1783 co_IntWaitMessage(NULL
, 0, 0);
1788 DPRINT("Leave NtUserDragDetect, ret=%i\n",_ret_
);
1794 NtUserPostMessage(HWND hWnd
,
1801 UserEnterExclusive();
1803 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1811 NtUserPostThreadMessage(DWORD idThread
,
1818 UserEnterExclusive();
1820 ret
= UserPostThreadMessage( idThread
, Msg
, wParam
, lParam
);
1828 NtUserWaitMessage(VOID
)
1832 UserEnterExclusive();
1833 DPRINT("NtUserWaitMessage Enter\n");
1834 ret
= co_IntWaitMessage(NULL
, 0, 0);
1835 DPRINT("NtUserWaitMessage Leave\n");
1842 NtUserGetMessage(PMSG pMsg
,
1850 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
1852 EngSetLastError(ERROR_INVALID_PARAMETER
);
1856 UserEnterExclusive();
1858 RtlZeroMemory(&Msg
, sizeof(MSG
));
1860 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
1868 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
1869 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
1871 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1873 SetLastNtError(_SEH2_GetExceptionCode());
1880 Ret
= Ret
? (WM_QUIT
!= pMsg
->message
) : FALSE
;
1886 NtUserPeekMessage( PMSG pMsg
,
1895 if ( RemoveMsg
& PM_BADMSGFLAGS
)
1897 EngSetLastError(ERROR_INVALID_FLAGS
);
1901 UserEnterExclusive();
1903 RtlZeroMemory(&Msg
, sizeof(MSG
));
1905 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
1913 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
1914 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
1916 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1918 SetLastNtError(_SEH2_GetExceptionCode());
1928 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
1935 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
1936 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
1938 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1940 _SEH2_YIELD(return FALSE
);
1944 UserEnterExclusive();
1946 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
1952 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
1959 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
1960 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
1962 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1972 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
1979 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
1980 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
1982 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1984 SetLastNtError(_SEH2_GetExceptionCode());
1985 _SEH2_YIELD(return FALSE
);
1989 UserEnterExclusive();
1991 Res
= IntDispatchMessage(&SafeMsg
);
1999 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
2006 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
2007 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
2009 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2011 SetLastNtError(_SEH2_GetExceptionCode());
2012 _SEH2_YIELD(return FALSE
);
2016 UserEnterExclusive();
2018 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
2026 NtUserMessageCall( HWND hWnd
,
2030 ULONG_PTR ResultInfo
,
2031 DWORD dwType
, // fnID?
2034 LRESULT lResult
= 0;
2037 USER_REFERENCE_ENTRY Ref
;
2039 UserEnterExclusive();
2043 case FNID_DEFWINDOWPROC
:
2044 /* Validate input */
2045 if (hWnd
&& (hWnd
!= INVALID_HANDLE_VALUE
))
2047 Window
= UserGetWindowObject(hWnd
);
2054 UserRefObjectCo(Window
, &Ref
);
2055 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2057 UserDerefObjectCo(Window
);
2059 case FNID_SENDNOTIFYMESSAGE
:
2060 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2062 case FNID_BROADCASTSYSTEMMESSAGE
:
2065 DWORD_PTR RetVal
= 0;
2071 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2072 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2074 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2083 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2084 parm
.recipients
== BSM_ALLCOMPONENTS
)
2087 else if (parm
.recipients
& BSM_APPLICATIONS
)
2089 if (parm
.flags
& BSF_QUERY
)
2091 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2093 co_IntSendMessageTimeout( HWND_BROADCAST
,
2101 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2103 co_IntSendMessageTimeout( HWND_BROADCAST
,
2107 SMTO_NOTIMEOUTIFNOTHUNG
,
2113 co_IntSendMessageTimeout( HWND_BROADCAST
,
2123 else if (parm
.flags
& BSF_POSTMESSAGE
)
2125 Ret
= UserPostMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2127 else //Everything else,,,, if ( parm.flags & BSF_SENDNOTIFYMESSAGE)
2129 Ret
= UserSendNotifyMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2134 case FNID_SENDMESSAGECALLBACK
:
2136 CALL_BACK_INFO CallBackInfo
;
2141 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2142 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2144 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2150 if (is_pointer_message(Msg
))
2152 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
2156 if (!(Ret
= co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2157 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
)))
2159 DPRINT1("Callback failure!\n");
2163 case FNID_SENDMESSAGE
:
2165 Ret
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2171 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2172 RtlCopyMemory((PVOID
)ResultInfo
, &Ret
, sizeof(ULONG_PTR
));
2174 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2183 case FNID_SENDMESSAGETIMEOUT
:
2185 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2190 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2191 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2193 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2200 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, &dsm
);
2206 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2207 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2209 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2218 // CallNextHook bypass.
2219 case FNID_CALLWNDPROC
:
2220 case FNID_CALLWNDPROCRET
:
2223 PCLIENTINFO ClientInfo
;
2224 PHOOK NextObj
, Hook
;
2226 pti
= GetW32ThreadInfo();
2228 Hook
= pti
->sphkCurrent
;
2232 NextObj
= Hook
->phkNext
;
2233 ClientInfo
= pti
->pClientInfo
;
2236 ClientInfo
->phkCurrent
= NextObj
;
2238 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2244 if (!ClientInfo
|| !NextObj
) break;
2246 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2248 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2253 CWP
.wParam
= wParam
;
2254 CWP
.lParam
= lParam
;
2255 DPRINT("WH_CALLWNDPROC: Hook %x NextHook %x\n", Hook
, NextObj
);
2257 lResult
= co_IntCallHookProc( Hook
->HookId
,
2259 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2270 CWPR
.wParam
= wParam
;
2271 CWPR
.lParam
= lParam
;
2272 CWPR
.lResult
= ClientInfo
->dwHookData
;
2274 lResult
= co_IntCallHookProc( Hook
->HookId
,
2276 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2288 case FNID_DEFWINDOWPROC
:
2289 case FNID_CALLWNDPROC
:
2290 case FNID_CALLWNDPROCRET
:
2295 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2296 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2298 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2314 #define INFINITE 0xFFFFFFFF
2315 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2319 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2320 IN DWORD dwMilliseconds
,
2324 PPROCESSINFO W32Process
;
2328 LARGE_INTEGER Timeout
;
2330 UserEnterExclusive();
2332 Status
= ObReferenceObjectByHandle(hProcess
,
2333 PROCESS_QUERY_INFORMATION
,
2339 if (!NT_SUCCESS(Status
))
2342 SetLastNtError(Status
);
2346 pti
= PsGetCurrentThreadWin32Thread();
2348 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2350 if ( PsGetProcessExitProcessCalled(Process
) ||
2352 pti
->ppi
== W32Process
)
2354 ObDereferenceObject(Process
);
2356 EngSetLastError(ERROR_INVALID_PARAMETER
);
2360 Handles
[0] = Process
;
2361 Handles
[1] = W32Process
->InputIdleEvent
;
2362 Handles
[2] = pti
->MessageQueue
->NewMessages
; // pEventQueueServer; IntMsqSetWakeMask returns hEventQueueClient
2366 ObDereferenceObject(Process
);
2368 return STATUS_SUCCESS
; /* no event to wait on */
2371 if (dwMilliseconds
!= INFINITE
)
2372 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2374 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2375 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2377 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2378 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2381 DPRINT("WFII: ppi 0x%x\n",W32Process
);
2382 DPRINT("WFII: waiting for %p\n", Handles
[1] );
2386 Status
= KeWaitForMultipleObjects( 3,
2392 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2394 UserEnterExclusive();
2396 if (!NT_SUCCESS(Status
))
2398 SetLastNtError(Status
);
2399 Status
= WAIT_FAILED
;
2411 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2412 DPRINT1("WFII: WAIT 2\n");
2416 case STATUS_TIMEOUT
:
2417 DPRINT1("WFII: timeout\n");
2422 DPRINT1("WFII: finished\n");
2423 Status
= STATUS_SUCCESS
;
2430 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2432 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
2433 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2435 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
2436 ObDereferenceObject(Process
);