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(((PTHREADINFO
)PsGetCurrentThreadWin32Thread())->MessageQueue
,
1265 Window
->head
.pti
->MessageQueue
,
1274 (uFlags
& SMTO_BLOCK
),
1278 while ((STATUS_TIMEOUT
== Status
) &&
1279 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1280 !MsqIsHung(Window
->head
.pti
->MessageQueue
)); // FIXME - Set window hung and add to a list.
1282 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1284 if (STATUS_TIMEOUT
== Status
)
1288 Microsoft Windows 2000: If GetLastError returns zero, then the function
1290 XP+ : If the function fails or times out, the return value is zero.
1291 To get extended error information, call GetLastError. If GetLastError
1292 returns ERROR_TIMEOUT, then the function timed out.
1294 EngSetLastError(ERROR_TIMEOUT
);
1297 else if (! NT_SUCCESS(Status
))
1299 SetLastNtError(Status
);
1306 if (Window
) UserDerefObjectCo(Window
);
1311 co_IntSendMessageTimeout( HWND hWnd
,
1317 ULONG_PTR
*uResult
)
1323 if (HWND_BROADCAST
!= hWnd
)
1325 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1328 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1329 if (NULL
== DesktopWindow
)
1331 EngSetLastError(ERROR_INTERNAL_ERROR
);
1335 /* Send message to the desktop window too! */
1336 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1338 Children
= IntWinListChildren(DesktopWindow
);
1339 if (NULL
== Children
)
1344 for (Child
= Children
; NULL
!= *Child
; Child
++)
1346 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1349 ExFreePool(Children
);
1351 return (LRESULT
) TRUE
;
1355 co_IntSendMessageNoWait(HWND hWnd
,
1360 ULONG_PTR Result
= 0;
1361 /* Piggyback off CallBack */
1362 co_IntSendMessageWithCallBack(hWnd
,
1372 If you send a message in the range below WM_USER to the asynchronous message
1373 functions (PostMessage, SendNotifyMessage, and SendMessageCallback), its
1374 message parameters cannot include pointers. Otherwise, the operation will fail.
1375 The functions will return before the receiving thread has had a chance to
1376 process the message and the sender will free the memory before it is used.
1379 co_IntSendMessageWithCallBack( HWND hWnd
,
1383 SENDASYNCPROC CompletionCallback
,
1384 ULONG_PTR CompletionCallbackContext
,
1389 PMSGMEMORY MsgMemoryEntry
;
1390 INT lParamBufferSize
;
1391 LPARAM lParamPacked
;
1392 PTHREADINFO Win32Thread
;
1393 DECLARE_RETURN(LRESULT
);
1394 USER_REFERENCE_ENTRY Ref
;
1395 PUSER_SENT_MESSAGE Message
;
1397 if (!(Window
= UserGetWindowObject(hWnd
)))
1402 UserRefObjectCo(Window
, &Ref
);
1404 if (Window
->state
& WNDS_DESTROYED
)
1406 /* FIXME - last error? */
1407 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1411 Win32Thread
= PsGetCurrentThreadWin32Thread();
1413 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1415 if (Win32Thread
== NULL
)
1421 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1423 /* Never send messages to exiting threads */
1427 /* See if this message type is present in the table */
1428 MsgMemoryEntry
= FindMsgMemory(Msg
);
1429 if (NULL
== MsgMemoryEntry
)
1431 lParamBufferSize
= -1;
1435 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1438 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, Window
->head
.pti
->MessageQueue
!= Win32Thread
->MessageQueue
)))
1440 DPRINT1("Failed to pack message parameters\n");
1444 /* If this is not a callback and it can be sent now, then send it. */
1445 if (Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1447 ObReferenceObject(Win32Thread
->pEThread
);
1448 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1459 ObDereferenceObject(Win32Thread
->pEThread
);
1461 if (CompletionCallback
)
1463 co_IntCallSentMessageCallback(CompletionCallback
,
1466 CompletionCallbackContext
,
1471 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1473 if (Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1475 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1477 DPRINT1("Failed to unpack message parameters\n");
1482 if(!(Message
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
1484 DPRINT1("MsqSendMessage(): Not enough memory to allocate a message");
1488 Message
->Msg
.hwnd
= hWnd
;
1489 Message
->Msg
.message
= Msg
;
1490 Message
->Msg
.wParam
= wParam
;
1491 Message
->Msg
.lParam
= lParamPacked
;
1492 Message
->CompletionEvent
= NULL
;
1493 Message
->Result
= 0;
1494 Message
->lResult
= 0;
1495 Message
->QS_Flags
= 0;
1496 Message
->SenderQueue
= NULL
; // mjmartin, you are right! This is null.
1497 if (CompletionCallback
)
1498 Message
->CallBackSenderQueue
= Win32Thread
->MessageQueue
;
1500 Message
->CallBackSenderQueue
= NULL
;
1501 IntReferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1502 Message
->CompletionCallback
= CompletionCallback
;
1503 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1504 Message
->HookMessage
= MSQ_NORMAL
;
1505 Message
->HasPackedLParam
= (lParamBufferSize
> -1);
1507 Message
->QS_Flags
= QS_SENDMESSAGE
;
1508 if (CompletionCallback
)
1509 InsertTailList(&Win32Thread
->MessageQueue
->DispatchingMessagesHead
, &Message
->DispatchingListEntry
);
1510 InsertTailList(&Window
->head
.pti
->MessageQueue
->SentMessagesListHead
, &Message
->ListEntry
);
1511 MsqWakeQueue(Window
->head
.pti
->MessageQueue
, QS_SENDMESSAGE
, FALSE
);
1512 IntDereferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1517 if (Window
) UserDerefObjectCo(Window
);
1521 /* This function posts a message if the destination's message queue belongs to
1522 another thread, otherwise it sends the message. It does not support broadcast
1525 co_IntPostOrSendMessage( HWND hWnd
,
1534 if ( hWnd
== HWND_BROADCAST
)
1539 if(!(Window
= UserGetWindowObject(hWnd
)))
1544 pti
= PsGetCurrentThreadWin32Thread();
1546 if ( Window
->head
.pti
->MessageQueue
!= pti
->MessageQueue
&&
1547 FindMsgMemory(Msg
) == 0 )
1549 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1553 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1559 return (LRESULT
)Result
;
1563 co_IntDoSendMessage( HWND hWnd
,
1570 LRESULT Result
= TRUE
;
1575 PMSGMEMORY MsgMemoryEntry
;
1577 if (HWND_BROADCAST
!= hWnd
)
1579 Window
= UserGetWindowObject(hWnd
);
1586 /* Check for an exiting window. */
1587 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1589 DPRINT1("co_IntDoSendMessage Window Exiting!\n");
1592 /* See if the current thread can handle the message */
1593 pti
= PsGetCurrentThreadWin32Thread();
1595 UserModeMsg
.hwnd
= hWnd
;
1596 UserModeMsg
.message
= Msg
;
1597 UserModeMsg
.wParam
= wParam
;
1598 UserModeMsg
.lParam
= lParam
;
1599 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1601 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1602 if (! NT_SUCCESS(Status
))
1604 EngSetLastError(ERROR_INVALID_PARAMETER
);
1605 return (dsm
? 0 : -1);
1610 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1611 KernelModeMsg
.message
,
1612 KernelModeMsg
.wParam
,
1613 KernelModeMsg
.lParam
);
1617 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1618 KernelModeMsg
.message
,
1619 KernelModeMsg
.wParam
,
1620 KernelModeMsg
.lParam
,
1626 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1627 if (! NT_SUCCESS(Status
))
1629 EngSetLastError(ERROR_INVALID_PARAMETER
);
1630 return(dsm
? 0 : -1);
1633 return (LRESULT
)Result
;
1637 UserSendNotifyMessage( HWND hWnd
,
1644 if (is_pointer_message(Msg
))
1646 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1650 // Basicly the same as IntPostOrSendMessage
1651 if (hWnd
== HWND_BROADCAST
) //Handle Broadcast
1657 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1658 List
= IntWinListChildren(DesktopWindow
);
1662 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1663 for (i
= 0; List
[i
]; i
++)
1665 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1672 ULONG_PTR lResult
= 0;
1673 Ret
= co_IntSendMessageWithCallBack( hWnd
,
1686 IntGetQueueStatus(DWORD Changes
)
1689 PUSER_MESSAGE_QUEUE Queue
;
1692 pti
= PsGetCurrentThreadWin32Thread();
1693 Queue
= pti
->MessageQueue
;
1695 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1697 /* High word, types of messages currently in the queue.
1698 Low word, types of messages that have been added to the queue and that
1699 are still in the queue
1701 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1703 pti
->pcti
->fsChangeBits
&= ~Changes
;
1709 IntInitMessagePumpHook()
1711 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1715 pti
->pcti
->dwcPumpHook
++;
1722 IntUninitMessagePumpHook()
1724 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1728 if (pti
->pcti
->dwcPumpHook
<= 0)
1732 pti
->pcti
->dwcPumpHook
--;
1738 /** Functions ******************************************************************/
1744 POINT pt
) // Just like the User call.
1748 WORD wDragWidth
, wDragHeight
;
1749 DECLARE_RETURN(BOOL
);
1751 DPRINT("Enter NtUserDragDetect(%x)\n", hWnd
);
1752 UserEnterExclusive();
1754 wDragWidth
= UserGetSystemMetrics(SM_CXDRAG
);
1755 wDragHeight
= UserGetSystemMetrics(SM_CYDRAG
);
1757 rect
.left
= pt
.x
- wDragWidth
;
1758 rect
.right
= pt
.x
+ wDragWidth
;
1760 rect
.top
= pt
.y
- wDragHeight
;
1761 rect
.bottom
= pt
.y
+ wDragHeight
;
1763 co_UserSetCapture(hWnd
);
1767 while (co_IntGetPeekMessage( &msg
, 0, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
, FALSE
) ||
1768 co_IntGetPeekMessage( &msg
, 0, WM_QUEUESYNC
, WM_QUEUESYNC
, PM_REMOVE
, FALSE
) ||
1769 co_IntGetPeekMessage( &msg
, 0, WM_KEYFIRST
, WM_KEYLAST
, PM_REMOVE
, FALSE
) )
1771 if ( msg
.message
== WM_LBUTTONUP
)
1773 co_UserSetCapture(NULL
);
1776 if ( msg
.message
== WM_MOUSEMOVE
)
1779 tmp
.x
= (short)LOWORD(msg
.lParam
);
1780 tmp
.y
= (short)HIWORD(msg
.lParam
);
1781 if( !IntPtInRect( &rect
, tmp
) )
1783 co_UserSetCapture(NULL
);
1787 if ( msg
.message
== WM_KEYDOWN
)
1789 if ( msg
.wParam
== VK_ESCAPE
)
1791 co_UserSetCapture(NULL
);
1795 if ( msg
.message
== WM_QUEUESYNC
)
1797 co_HOOK_CallHooks( WH_CBT
, HCBT_QS
, 0, 0 );
1800 co_IntWaitMessage(NULL
, 0, 0);
1805 DPRINT("Leave NtUserDragDetect, ret=%i\n",_ret_
);
1811 NtUserPostMessage(HWND hWnd
,
1818 UserEnterExclusive();
1820 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1828 NtUserPostThreadMessage(DWORD idThread
,
1835 UserEnterExclusive();
1837 ret
= UserPostThreadMessage( idThread
, Msg
, wParam
, lParam
);
1845 NtUserWaitMessage(VOID
)
1849 UserEnterExclusive();
1850 DPRINT("NtUserWaitMessage Enter\n");
1851 ret
= co_IntWaitMessage(NULL
, 0, 0);
1852 DPRINT("NtUserWaitMessage Leave\n");
1859 NtUserGetMessage(PMSG pMsg
,
1867 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
1869 EngSetLastError(ERROR_INVALID_PARAMETER
);
1873 UserEnterExclusive();
1875 RtlZeroMemory(&Msg
, sizeof(MSG
));
1877 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
1885 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
1886 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
1888 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1890 SetLastNtError(_SEH2_GetExceptionCode());
1897 Ret
= Ret
? (WM_QUIT
!= pMsg
->message
) : FALSE
;
1903 NtUserPeekMessage( PMSG pMsg
,
1912 if ( RemoveMsg
& PM_BADMSGFLAGS
)
1914 EngSetLastError(ERROR_INVALID_FLAGS
);
1918 UserEnterExclusive();
1920 RtlZeroMemory(&Msg
, sizeof(MSG
));
1922 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
1930 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
1931 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
1933 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1935 SetLastNtError(_SEH2_GetExceptionCode());
1945 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
1952 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
1953 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
1955 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1957 _SEH2_YIELD(return FALSE
);
1961 UserEnterExclusive();
1963 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
1969 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
1976 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
1977 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
1979 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1989 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
1996 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
1997 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
1999 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2001 SetLastNtError(_SEH2_GetExceptionCode());
2002 _SEH2_YIELD(return FALSE
);
2006 UserEnterExclusive();
2008 Res
= IntDispatchMessage(&SafeMsg
);
2016 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
2023 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
2024 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
2026 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2028 SetLastNtError(_SEH2_GetExceptionCode());
2029 _SEH2_YIELD(return FALSE
);
2033 UserEnterExclusive();
2035 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
2043 NtUserMessageCall( HWND hWnd
,
2047 ULONG_PTR ResultInfo
,
2048 DWORD dwType
, // fnID?
2051 LRESULT lResult
= 0;
2054 USER_REFERENCE_ENTRY Ref
;
2056 UserEnterExclusive();
2060 case FNID_DEFWINDOWPROC
:
2061 /* Validate input */
2062 if (hWnd
&& (hWnd
!= INVALID_HANDLE_VALUE
))
2064 Window
= UserGetWindowObject(hWnd
);
2071 UserRefObjectCo(Window
, &Ref
);
2072 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2074 UserDerefObjectCo(Window
);
2076 case FNID_SENDNOTIFYMESSAGE
:
2077 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2079 case FNID_BROADCASTSYSTEMMESSAGE
:
2082 DWORD_PTR RetVal
= 0;
2088 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2089 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2091 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2100 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2101 parm
.recipients
== BSM_ALLCOMPONENTS
)
2104 else if (parm
.recipients
& BSM_APPLICATIONS
)
2106 if (parm
.flags
& BSF_QUERY
)
2108 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2110 co_IntSendMessageTimeout( HWND_BROADCAST
,
2118 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2120 co_IntSendMessageTimeout( HWND_BROADCAST
,
2124 SMTO_NOTIMEOUTIFNOTHUNG
,
2130 co_IntSendMessageTimeout( HWND_BROADCAST
,
2140 else if (parm
.flags
& BSF_POSTMESSAGE
)
2142 Ret
= UserPostMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2144 else //Everything else,,,, if ( parm.flags & BSF_SENDNOTIFYMESSAGE)
2146 Ret
= UserSendNotifyMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2151 case FNID_SENDMESSAGECALLBACK
:
2153 CALL_BACK_INFO CallBackInfo
;
2158 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2159 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2161 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2167 if (is_pointer_message(Msg
))
2169 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
2173 if (!(Ret
= co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2174 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
)))
2176 DPRINT1("Callback failure!\n");
2180 case FNID_SENDMESSAGE
:
2182 Ret
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2188 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2189 RtlCopyMemory((PVOID
)ResultInfo
, &Ret
, sizeof(ULONG_PTR
));
2191 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2200 case FNID_SENDMESSAGETIMEOUT
:
2202 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2207 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2208 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2210 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2217 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, &dsm
);
2223 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2224 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2226 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2235 // CallNextHook bypass.
2236 case FNID_CALLWNDPROC
:
2237 case FNID_CALLWNDPROCRET
:
2240 PCLIENTINFO ClientInfo
;
2241 PHOOK NextObj
, Hook
;
2243 pti
= GetW32ThreadInfo();
2245 Hook
= pti
->sphkCurrent
;
2249 NextObj
= Hook
->phkNext
;
2250 ClientInfo
= pti
->pClientInfo
;
2253 ClientInfo
->phkCurrent
= NextObj
;
2255 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2261 if (!ClientInfo
|| !NextObj
) break;
2263 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2265 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2270 CWP
.wParam
= wParam
;
2271 CWP
.lParam
= lParam
;
2272 DPRINT("WH_CALLWNDPROC: Hook %x NextHook %x\n", Hook
, NextObj
);
2274 lResult
= co_IntCallHookProc( Hook
->HookId
,
2276 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2287 CWPR
.wParam
= wParam
;
2288 CWPR
.lParam
= lParam
;
2289 CWPR
.lResult
= ClientInfo
->dwHookData
;
2291 lResult
= co_IntCallHookProc( Hook
->HookId
,
2293 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2305 case FNID_DEFWINDOWPROC
:
2306 case FNID_CALLWNDPROC
:
2307 case FNID_CALLWNDPROCRET
:
2312 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2313 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2315 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2331 #define INFINITE 0xFFFFFFFF
2332 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2336 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2337 IN DWORD dwMilliseconds
,
2341 PPROCESSINFO W32Process
;
2345 LARGE_INTEGER Timeout
;
2347 UserEnterExclusive();
2349 Status
= ObReferenceObjectByHandle(hProcess
,
2350 PROCESS_QUERY_INFORMATION
,
2356 if (!NT_SUCCESS(Status
))
2359 SetLastNtError(Status
);
2363 pti
= PsGetCurrentThreadWin32Thread();
2365 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2367 if ( PsGetProcessExitProcessCalled(Process
) ||
2369 pti
->ppi
== W32Process
)
2371 ObDereferenceObject(Process
);
2373 EngSetLastError(ERROR_INVALID_PARAMETER
);
2377 Handles
[0] = Process
;
2378 Handles
[1] = W32Process
->InputIdleEvent
;
2379 Handles
[2] = pti
->MessageQueue
->NewMessages
; // pEventQueueServer; IntMsqSetWakeMask returns hEventQueueClient
2383 ObDereferenceObject(Process
);
2385 return STATUS_SUCCESS
; /* no event to wait on */
2388 if (dwMilliseconds
!= INFINITE
)
2389 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2391 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2392 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2394 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2395 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2398 DPRINT("WFII: ppi 0x%x\n",W32Process
);
2399 DPRINT("WFII: waiting for %p\n", Handles
[1] );
2403 Status
= KeWaitForMultipleObjects( 3,
2409 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2411 UserEnterExclusive();
2413 if (!NT_SUCCESS(Status
))
2415 SetLastNtError(Status
);
2416 Status
= WAIT_FAILED
;
2428 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2429 DPRINT1("WFII: WAIT 2\n");
2433 case STATUS_TIMEOUT
:
2434 DPRINT1("WFII: timeout\n");
2439 DPRINT1("WFII: finished\n");
2440 Status
= STATUS_SUCCESS
;
2447 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2449 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
2450 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2452 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
2453 ObDereferenceObject(Process
);