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
},
142 { WM_MDICREATE
, MMS_SIZE_SPECIAL
, 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 MDICREATESTRUCTW
*mCs
;
169 PUNICODE_STRING WindowName
;
170 PUNICODE_STRING ClassName
;
175 if (MMS_SIZE_WPARAM
== MsgMemoryEntry
->Size
)
179 else if (MMS_SIZE_WPARAMWCHAR
== MsgMemoryEntry
->Size
)
181 Size
= (UINT
) (wParam
* sizeof(WCHAR
));
183 else if (MMS_SIZE_LPARAMSZ
== MsgMemoryEntry
->Size
)
185 Size
= (UINT
) ((wcslen((PWSTR
) lParam
) + 1) * sizeof(WCHAR
));
187 else if (MMS_SIZE_SPECIAL
== MsgMemoryEntry
->Size
)
189 switch(MsgMemoryEntry
->Message
)
193 Cs
= (CREATESTRUCTW
*) lParam
;
194 WindowName
= (PUNICODE_STRING
) Cs
->lpszName
;
195 ClassName
= (PUNICODE_STRING
) Cs
->lpszClass
;
196 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
197 if (IS_ATOM(ClassName
->Buffer
))
199 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
203 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
208 mCs
= (MDICREATESTRUCTW
*)lParam
;
209 WindowName
= (PUNICODE_STRING
) mCs
->szTitle
;
210 ClassName
= (PUNICODE_STRING
) mCs
->szClass
;
211 Size
= sizeof(MDICREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
212 if (IS_ATOM(ClassName
->Buffer
))
214 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
218 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
223 Size
= wParam
? sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
) : sizeof(RECT
);
227 Size
= sizeof(COPYDATASTRUCT
) + ((PCOPYDATASTRUCT
)lParam
)->cbData
;
238 Size
= MsgMemoryEntry
->Size
;
241 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
243 DPRINT1("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH2_GetExceptionCode());
251 PackParam(LPARAM
*lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolNeeded
)
253 NCCALCSIZE_PARAMS
*UnpackedNcCalcsize
;
254 NCCALCSIZE_PARAMS
*PackedNcCalcsize
;
255 CREATESTRUCTW
*UnpackedCs
;
256 CREATESTRUCTW
*PackedCs
;
257 MDICREATESTRUCTW
*UnpackedmCs
, *PackedmCs
;
258 PLARGE_STRING WindowName
;
259 PUNICODE_STRING ClassName
;
264 *lParamPacked
= lParam
;
266 if (NonPagedPoolNeeded
)
267 PoolType
= NonPagedPool
;
269 PoolType
= PagedPool
;
271 if (WM_NCCALCSIZE
== Msg
&& wParam
)
274 UnpackedNcCalcsize
= (NCCALCSIZE_PARAMS
*) lParam
;
275 PackedNcCalcsize
= ExAllocatePoolWithTag(PoolType
,
276 sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
),
279 if (NULL
== PackedNcCalcsize
)
281 DPRINT1("Not enough memory to pack lParam\n");
282 return STATUS_NO_MEMORY
;
284 RtlCopyMemory(PackedNcCalcsize
, UnpackedNcCalcsize
, sizeof(NCCALCSIZE_PARAMS
));
285 PackedNcCalcsize
->lppos
= (PWINDOWPOS
) (PackedNcCalcsize
+ 1);
286 RtlCopyMemory(PackedNcCalcsize
->lppos
, UnpackedNcCalcsize
->lppos
, sizeof(WINDOWPOS
));
287 *lParamPacked
= (LPARAM
) PackedNcCalcsize
;
289 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
291 UnpackedCs
= (CREATESTRUCTW
*) lParam
;
292 WindowName
= (PLARGE_STRING
) UnpackedCs
->lpszName
;
293 ClassName
= (PUNICODE_STRING
) UnpackedCs
->lpszClass
;
294 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
295 if (IS_ATOM(ClassName
->Buffer
))
297 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
301 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
303 PackedCs
= ExAllocatePoolWithTag(PoolType
, Size
, TAG_MSG
);
304 if (NULL
== PackedCs
)
306 DPRINT1("Not enough memory to pack lParam\n");
307 return STATUS_NO_MEMORY
;
309 RtlCopyMemory(PackedCs
, UnpackedCs
, sizeof(CREATESTRUCTW
));
310 CsData
= (PCHAR
) (PackedCs
+ 1);
311 PackedCs
->lpszName
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
312 RtlCopyMemory(CsData
, WindowName
->Buffer
, WindowName
->Length
);
313 CsData
+= WindowName
->Length
;
314 *((WCHAR
*) CsData
) = L
'\0';
315 CsData
+= sizeof(WCHAR
);
316 PackedCs
->lpszClass
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
317 if (IS_ATOM(ClassName
->Buffer
))
319 *((WCHAR
*) CsData
) = L
'A';
320 CsData
+= sizeof(WCHAR
);
321 *((ATOM
*) CsData
) = (ATOM
)(DWORD_PTR
) ClassName
->Buffer
;
322 CsData
+= sizeof(ATOM
);
326 *((WCHAR
*) CsData
) = L
'S';
327 CsData
+= sizeof(WCHAR
);
328 RtlCopyMemory(CsData
, ClassName
->Buffer
, ClassName
->Length
);
329 CsData
+= ClassName
->Length
;
330 *((WCHAR
*) CsData
) = L
'\0';
331 CsData
+= sizeof(WCHAR
);
333 ASSERT(CsData
== (PCHAR
) PackedCs
+ Size
);
334 *lParamPacked
= (LPARAM
) PackedCs
;
336 else if (WM_MDICREATE
== Msg
)
338 UnpackedmCs
= (MDICREATESTRUCTW
*) lParam
;
339 WindowName
= (PLARGE_STRING
) UnpackedmCs
->szTitle
;
340 ClassName
= (PUNICODE_STRING
) UnpackedmCs
->szClass
;
341 Size
= sizeof(MDICREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
342 if (IS_ATOM(ClassName
->Buffer
))
344 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
348 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
350 PackedmCs
= ExAllocatePoolWithTag(PoolType
, Size
, TAG_MSG
);
351 if (NULL
== PackedmCs
)
353 DPRINT1("Not enough memory to pack lParam\n");
354 return STATUS_NO_MEMORY
;
356 RtlCopyMemory(PackedmCs
, UnpackedmCs
, sizeof(MDICREATESTRUCTW
));
357 CsData
= (PCHAR
) (PackedmCs
+ 1);
358 PackedmCs
->szTitle
= (LPCWSTR
) (CsData
- (PCHAR
) PackedmCs
);
359 RtlCopyMemory(CsData
, WindowName
->Buffer
, WindowName
->Length
);
360 CsData
+= WindowName
->Length
;
361 *((WCHAR
*) CsData
) = L
'\0';
362 CsData
+= sizeof(WCHAR
);
363 PackedmCs
->szClass
= (LPCWSTR
) (CsData
- (PCHAR
) PackedmCs
);
364 if (IS_ATOM(ClassName
->Buffer
))
366 *((WCHAR
*) CsData
) = L
'A';
367 CsData
+= sizeof(WCHAR
);
368 *((ATOM
*) CsData
) = (ATOM
)(DWORD_PTR
) ClassName
->Buffer
;
369 CsData
+= sizeof(ATOM
);
373 *((WCHAR
*) CsData
) = L
'S';
374 CsData
+= sizeof(WCHAR
);
375 RtlCopyMemory(CsData
, ClassName
->Buffer
, ClassName
->Length
);
376 CsData
+= ClassName
->Length
;
377 *((WCHAR
*) CsData
) = L
'\0';
378 CsData
+= sizeof(WCHAR
);
380 ASSERT(CsData
== (PCHAR
) PackedmCs
+ Size
);
381 *lParamPacked
= (LPARAM
) PackedmCs
;
383 else if (PoolType
== NonPagedPool
)
385 PMSGMEMORY MsgMemoryEntry
;
388 MsgMemoryEntry
= FindMsgMemory(Msg
);
390 if ((!MsgMemoryEntry
) || (MsgMemoryEntry
->Size
< 0))
392 /* Keep previous behavior */
393 return STATUS_SUCCESS
;
395 PackedData
= ExAllocatePoolWithTag(NonPagedPool
, MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
), TAG_MSG
);
396 RtlCopyMemory(PackedData
, (PVOID
)lParam
, MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
));
397 *lParamPacked
= (LPARAM
)PackedData
;
400 return STATUS_SUCCESS
;
404 UnpackParam(LPARAM lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL NonPagedPoolUsed
)
406 NCCALCSIZE_PARAMS
*UnpackedParams
;
407 NCCALCSIZE_PARAMS
*PackedParams
;
408 PWINDOWPOS UnpackedWindowPos
;
410 if (lParamPacked
== lParam
)
412 return STATUS_SUCCESS
;
415 if (WM_NCCALCSIZE
== Msg
&& wParam
)
417 PackedParams
= (NCCALCSIZE_PARAMS
*) lParamPacked
;
418 UnpackedParams
= (NCCALCSIZE_PARAMS
*) lParam
;
419 UnpackedWindowPos
= UnpackedParams
->lppos
;
420 RtlCopyMemory(UnpackedParams
, PackedParams
, sizeof(NCCALCSIZE_PARAMS
));
421 UnpackedParams
->lppos
= UnpackedWindowPos
;
422 RtlCopyMemory(UnpackedWindowPos
, PackedParams
+ 1, sizeof(WINDOWPOS
));
423 ExFreePool((PVOID
) lParamPacked
);
425 return STATUS_SUCCESS
;
427 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
429 ExFreePool((PVOID
) lParamPacked
);
431 return STATUS_SUCCESS
;
433 else if (WM_MDICREATE
== Msg
)
435 ExFreePool((PVOID
) lParamPacked
);
436 return STATUS_SUCCESS
;
438 else if (NonPagedPoolUsed
)
440 PMSGMEMORY MsgMemoryEntry
;
441 MsgMemoryEntry
= FindMsgMemory(Msg
);
442 if (MsgMemoryEntry
->Size
< 0)
444 /* Keep previous behavior */
445 return STATUS_INVALID_PARAMETER
;
448 if (MsgMemory
->Flags
== MMS_FLAG_READWRITE
)
450 //RtlCopyMemory((PVOID)lParam, (PVOID)lParamPacked, MsgMemory->Size);
452 ExFreePool((PVOID
) lParamPacked
);
453 return STATUS_SUCCESS
;
458 return STATUS_INVALID_PARAMETER
;
461 static NTSTATUS FASTCALL
462 CopyMsgToKernelMem(MSG
*KernelModeMsg
, MSG
*UserModeMsg
, PMSGMEMORY MsgMemoryEntry
)
469 *KernelModeMsg
= *UserModeMsg
;
471 /* See if this message type is present in the table */
472 if (NULL
== MsgMemoryEntry
)
474 /* Not present, no copying needed */
475 return STATUS_SUCCESS
;
478 /* Determine required size */
479 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
483 /* Allocate kernel mem */
484 KernelMem
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
485 if (NULL
== KernelMem
)
487 DPRINT1("Not enough memory to copy message to kernel mem\n");
488 return STATUS_NO_MEMORY
;
490 KernelModeMsg
->lParam
= (LPARAM
) KernelMem
;
492 /* Copy data if required */
493 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_READ
))
495 Status
= MmCopyFromCaller(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
496 if (! NT_SUCCESS(Status
))
498 DPRINT1("Failed to copy message to kernel: invalid usermode buffer\n");
499 ExFreePoolWithTag(KernelMem
, TAG_MSG
);
505 /* Make sure we don't pass any secrets to usermode */
506 RtlZeroMemory(KernelMem
, Size
);
511 KernelModeMsg
->lParam
= 0;
514 return STATUS_SUCCESS
;
517 static NTSTATUS FASTCALL
518 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
521 PMSGMEMORY MsgMemoryEntry
;
524 /* See if this message type is present in the table */
525 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
526 if (NULL
== MsgMemoryEntry
)
528 /* Not present, no copying needed */
529 return STATUS_SUCCESS
;
532 /* Determine required size */
533 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
537 /* Copy data if required */
538 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
540 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
541 if (! NT_SUCCESS(Status
))
543 DPRINT1("Failed to copy message from kernel: invalid usermode buffer\n");
544 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
549 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
552 return STATUS_SUCCESS
;
556 // Wakeup any thread/process waiting on idle input.
561 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
562 PUSER_MESSAGE_QUEUE ForegroundQueue
;
563 PTHREADINFO pti
, ptiForeground
= NULL
;
565 ForegroundQueue
= IntGetFocusMessageQueue();
568 ptiForeground
= ForegroundQueue
->Thread
->Tcb
.Win32Thread
;
570 pti
= PsGetCurrentThreadWin32Thread();
574 pti
->pClientInfo
->cSpins
= 0; // Reset spins.
576 if ( pti
->pDeskInfo
&& pti
== ptiForeground
)
578 if ( pti
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) ||
579 pti
->pDeskInfo
->fsHooks
& HOOKID_TO_FLAG(WH_FOREGROUNDIDLE
) )
581 co_HOOK_CallHooks(WH_FOREGROUNDIDLE
,HC_ACTION
,0,0);
586 DPRINT("IdlePing ppi 0x%x\n",ppi
);
587 if ( ppi
&& ppi
->InputIdleEvent
)
589 DPRINT("InputIdleEvent\n");
590 KeSetEvent( ppi
->InputIdleEvent
, IO_NO_INCREMENT
, FALSE
);
597 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
599 DPRINT("IdlePong ppi 0x%x\n",ppi
);
600 if ( ppi
&& ppi
->InputIdleEvent
)
602 KeClearEvent(ppi
->InputIdleEvent
);
607 GetWakeMask(UINT first
, UINT last
)
609 UINT mask
= QS_POSTMESSAGE
| QS_SENDMESSAGE
; /* Always selected */
613 if ((first
<= WM_KEYLAST
) && (last
>= WM_KEYFIRST
)) mask
|= QS_KEY
;
614 if ( ((first
<= WM_MOUSELAST
) && (last
>= WM_MOUSEFIRST
)) ||
615 ((first
<= WM_NCMOUSELAST
) && (last
>= WM_NCMOUSEFIRST
)) ) mask
|= QS_MOUSE
;
616 if ((first
<= WM_TIMER
) && (last
>= WM_TIMER
)) mask
|= QS_TIMER
;
617 if ((first
<= WM_SYSTIMER
) && (last
>= WM_SYSTIMER
)) mask
|= QS_TIMER
;
618 if ((first
<= WM_PAINT
) && (last
>= WM_PAINT
)) mask
|= QS_PAINT
;
620 else mask
= QS_ALLINPUT
;
626 IntCallWndProc( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
628 BOOL SameThread
= FALSE
;
631 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
638 co_HOOK_CallHooks( WH_CALLWNDPROC
, HC_ACTION
, SameThread
, (LPARAM
)&CWP
);
642 IntCallWndProcRet ( PWND Window
, HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, LRESULT
*uResult
)
644 BOOL SameThread
= FALSE
;
647 if (Window
->head
.pti
== ((PTHREADINFO
)PsGetCurrentThreadWin32Thread()))
652 CWPR
.wParam
= wParam
;
653 CWPR
.lParam
= lParam
;
654 CWPR
.lResult
= *uResult
;
655 co_HOOK_CallHooks( WH_CALLWNDPROCRET
, HC_ACTION
, SameThread
, (LPARAM
)&CWPR
);
659 IntDispatchMessage(PMSG pMsg
)
661 LARGE_INTEGER TickCount
;
669 Window
= UserGetWindowObject(pMsg
->hwnd
);
670 if (!Window
) return 0;
673 pti
= PsGetCurrentThreadWin32Thread();
675 if ( Window
->head
.pti
!= pti
)
677 EngSetLastError( ERROR_MESSAGE_SYNC_ONLY
);
681 if (((pMsg
->message
== WM_SYSTIMER
) ||
682 (pMsg
->message
== WM_TIMER
)) &&
685 if (pMsg
->message
== WM_TIMER
)
687 if (ValidateTimerCallback(pti
,pMsg
->lParam
))
689 KeQueryTickCount(&TickCount
);
690 Time
= MsqCalculateMessageTime(&TickCount
);
691 retval
= co_IntCallWindowProc((WNDPROC
)pMsg
->lParam
,
703 PTIMER pTimer
= FindSystemTimer(pMsg
);
704 if (pTimer
&& pTimer
->pfn
)
706 KeQueryTickCount(&TickCount
);
707 Time
= MsqCalculateMessageTime(&TickCount
);
708 pTimer
->pfn(pMsg
->hwnd
, WM_SYSTIMER
, (UINT
)pMsg
->wParam
, Time
);
714 if ( !Window
) return 0;
716 /* Since we are doing a callback on the same thread right away, there is
717 no need to copy the lparam to kernel mode and then back to usermode.
718 We just pretend it isn't a pointer */
720 retval
= co_IntCallWindowProc( Window
->lpfnWndProc
,
728 if (pMsg
->message
== WM_PAINT
)
730 /* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
731 HRGN hrgn
= IntSysCreateRectRgn( 0, 0, 0, 0 );
732 co_UserGetUpdateRgn( Window
, hrgn
, TRUE
);
733 REGION_FreeRgnByHandle( hrgn
);
740 * Internal version of PeekMessage() doing all the work
743 co_IntPeekMessage( PMSG Msg
,
752 LARGE_INTEGER LargeTickCount
;
753 PUSER_MESSAGE_QUEUE ThreadQueue
;
758 pti
= PsGetCurrentThreadWin32Thread();
759 ThreadQueue
= pti
->MessageQueue
;
760 pci
= pti
->pClientInfo
;
762 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
763 ProcessMask
= HIWORD(RemoveMsg
);
765 /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns
766 all available messages (that is, no range filtering is performed)". */
767 if (!ProcessMask
) ProcessMask
= (QS_ALLPOSTMESSAGE
|QS_ALLINPUT
);
773 KeQueryTickCount(&LargeTickCount
);
774 ThreadQueue
->LastMsgRead
= LargeTickCount
.u
.LowPart
;
775 pti
->pcti
->tickLastMsgChecked
= LargeTickCount
.u
.LowPart
;
777 /* Dispatch sent messages here. */
778 while ( co_MsqDispatchOneSentMessage(ThreadQueue
) )
780 /* if some PM_QS* flags were specified, only handle sent messages from now on */
781 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
; // wine does this; ProcessMask = QS_SENDMESSAGE;
783 if (Hit
) return FALSE
;
785 /* Clear changed bits so we can wait on them if we don't find a message */
786 if (ProcessMask
& QS_POSTMESSAGE
)
788 pti
->pcti
->fsChangeBits
&= ~(QS_POSTMESSAGE
| QS_HOTKEY
| QS_TIMER
);
789 if (MsgFilterMin
== 0 && MsgFilterMax
== 0) // wine hack does this; ~0U)
791 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
795 if (ProcessMask
& QS_INPUT
)
797 pti
->pcti
->fsChangeBits
&= ~QS_INPUT
;
800 /* Now check for normal messages. */
801 if ((ProcessMask
& QS_POSTMESSAGE
) &&
802 MsqPeekMessage( ThreadQueue
,
813 /* Now look for a quit message. */
814 if (ThreadQueue
->QuitPosted
)
816 /* According to the PSDK, WM_QUIT messages are always returned, regardless
817 of the filter specified */
819 Msg
->message
= WM_QUIT
;
820 Msg
->wParam
= ThreadQueue
->QuitExitCode
;
824 ThreadQueue
->QuitPosted
= FALSE
;
825 ClearMsgBitsMask(ThreadQueue
, QS_POSTMESSAGE
);
826 pti
->pcti
->fsWakeBits
&= ~QS_ALLPOSTMESSAGE
;
827 pti
->pcti
->fsChangeBits
&= ~QS_ALLPOSTMESSAGE
;
832 /* Check for hardware events. */
833 if ((ProcessMask
& QS_MOUSE
) &&
834 co_MsqPeekMouseMove( ThreadQueue
,
844 if ((ProcessMask
& QS_INPUT
) &&
845 co_MsqPeekHardwareMessage( ThreadQueue
,
856 /* Check for sent messages again. */
857 while ( co_MsqDispatchOneSentMessage(ThreadQueue
) )
859 if (HIWORD(RemoveMsg
) && !bGMSG
) Hit
= TRUE
;
861 if (Hit
) return FALSE
;
863 /* Check for paint messages. */
864 if ((ProcessMask
& QS_PAINT
) &&
866 IntGetPaintMessage( Window
,
876 /* This is correct, check for the current threads timers waiting to be
877 posted to this threads message queue. If any we loop again.
879 if ((ProcessMask
& QS_TIMER
) &&
880 PostTimerMessages(Window
))
893 co_IntWaitMessage( PWND Window
,
898 PUSER_MESSAGE_QUEUE ThreadQueue
;
899 NTSTATUS Status
= STATUS_SUCCESS
;
902 pti
= PsGetCurrentThreadWin32Thread();
903 ThreadQueue
= pti
->MessageQueue
;
907 if ( co_IntPeekMessage( &Msg
, // Dont reenter!
911 MAKELONG( PM_NOREMOVE
, GetWakeMask( MsgFilterMin
, MsgFilterMax
)),
912 TRUE
) ) // act like GetMessage.
917 /* Nothing found. Wait for new messages. */
918 Status
= co_MsqWaitForNewMessages( ThreadQueue
,
923 while ( (STATUS_WAIT_0
<= Status
&& Status
<= STATUS_WAIT_63
) ||
924 STATUS_TIMEOUT
== Status
);
926 if (!NT_SUCCESS(Status
))
928 SetLastNtError(Status
);
929 DPRINT1("Exit co_IntWaitMessage on error!\n");
936 co_IntGetPeekMessage( PMSG pMsg
,
945 BOOL Present
= FALSE
;
947 if ( hWnd
== HWND_TOPMOST
|| hWnd
== HWND_BROADCAST
)
951 if (hWnd
&& hWnd
!= HWND_BOTTOM
)
953 if (!(Window
= UserGetWindowObject(hWnd
)))
966 if (MsgFilterMax
< MsgFilterMin
)
974 RemoveMsg
|= ((GetWakeMask( MsgFilterMin
, MsgFilterMax
))<< 16);
977 pti
= PsGetCurrentThreadWin32Thread();
978 pti
->pClientInfo
->cSpins
++; // Bump up the spin count.
982 Present
= co_IntPeekMessage( pMsg
,
990 /* GetMessage or PostMessage must never get messages that contain pointers */
991 ASSERT(FindMsgMemory(pMsg
->message
) == NULL
);
993 if (pMsg
->message
!= WM_PAINT
&& pMsg
->message
!= WM_QUIT
)
995 pti
->timeLast
= pMsg
->time
;
996 pti
->ptLast
= pMsg
->pt
;
999 // The WH_GETMESSAGE hook enables an application to monitor messages about to
1000 // be returned by the GetMessage or PeekMessage function.
1002 co_HOOK_CallHooks( WH_GETMESSAGE
, HC_ACTION
, RemoveMsg
& PM_REMOVE
, (LPARAM
)pMsg
);
1006 Present
= (WM_QUIT
!= pMsg
->message
);
1013 if ( !co_IntWaitMessage(Window
, MsgFilterMin
, MsgFilterMax
) )
1021 if (!(RemoveMsg
& PM_NOYIELD
))
1024 // Yield this thread!
1027 UserEnterExclusive();
1028 // Fall through to exit.
1034 while( bGMSG
&& !Present
);
1036 // Been spinning, time to swap vinyl...
1037 if (pti
->pClientInfo
->cSpins
>= 100)
1039 // Clear the spin cycle to fix the mix.
1040 pti
->pClientInfo
->cSpins
= 0;
1041 //if (!(pti->TIF_flags & TIF_SPINNING)) FIXME need to swap vinyl..
1047 UserPostThreadMessage( DWORD idThread
,
1054 PTHREADINFO pThread
;
1055 LARGE_INTEGER LargeTickCount
;
1058 if (is_pointer_message(Msg
))
1060 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1064 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
1066 if( Status
== STATUS_SUCCESS
)
1068 pThread
= (PTHREADINFO
)peThread
->Tcb
.Win32Thread
;
1070 !pThread
->MessageQueue
||
1071 (pThread
->TIF_flags
& TIF_INCLEANUP
))
1073 ObDereferenceObject( peThread
);
1077 Message
.hwnd
= NULL
;
1078 Message
.message
= Msg
;
1079 Message
.wParam
= wParam
;
1080 Message
.lParam
= lParam
;
1081 Message
.pt
= gpsi
->ptCursor
;
1083 KeQueryTickCount(&LargeTickCount
);
1084 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1085 MsqPostMessage(pThread
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
);
1086 ObDereferenceObject( peThread
);
1091 SetLastNtError( Status
);
1097 UserPostMessage( HWND Wnd
,
1103 MSG Message
, KernelModeMsg
;
1104 LARGE_INTEGER LargeTickCount
;
1105 PMSGMEMORY MsgMemoryEntry
;
1108 Message
.message
= Msg
;
1109 Message
.wParam
= wParam
;
1110 Message
.lParam
= lParam
;
1111 Message
.pt
= gpsi
->ptCursor
;
1112 KeQueryTickCount(&LargeTickCount
);
1113 Message
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1115 MsgMemoryEntry
= FindMsgMemory(Message
.message
);
1117 if( Msg
>= WM_DDE_FIRST
&& Msg
<= WM_DDE_LAST
)
1121 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &Message
, MsgMemoryEntry
);
1122 if (! NT_SUCCESS(Status
))
1124 EngSetLastError(ERROR_INVALID_PARAMETER
);
1127 co_IntSendMessageNoWait(KernelModeMsg
.hwnd
,
1128 KernelModeMsg
.message
,
1129 KernelModeMsg
.wParam
,
1130 KernelModeMsg
.lParam
);
1132 if (MsgMemoryEntry
&& KernelModeMsg
.lParam
)
1133 ExFreePool((PVOID
) KernelModeMsg
.lParam
);
1138 if (is_pointer_message(Message
.message
))
1140 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1146 return UserPostThreadMessage( PtrToInt(PsGetCurrentThreadId()),
1151 if (Wnd
== HWND_BROADCAST
)
1157 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1158 List
= IntWinListChildren(DesktopWindow
);
1162 UserPostMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1163 for (i
= 0; List
[i
]; i
++)
1165 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1167 ExFreePoolWithTag(List
, USERTAG_WINDOWLIST
);
1174 Window
= UserGetWindowObject(Wnd
);
1180 pti
= Window
->head
.pti
;
1181 if ( pti
->TIF_flags
& TIF_INCLEANUP
)
1183 DPRINT1("Attempted to post message to window 0x%x when the thread is in cleanup!\n", Wnd
);
1187 if ( Window
->state
& WNDS_DESTROYED
)
1189 DPRINT1("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd
);
1190 /* FIXME - last error code? */
1196 MsqPostQuitMessage(Window
->head
.pti
->MessageQueue
, wParam
);
1200 MsqPostMessage(Window
->head
.pti
->MessageQueue
, &Message
, FALSE
, QS_POSTMESSAGE
);
1208 co_IntSendMessage( HWND hWnd
,
1213 ULONG_PTR Result
= 0;
1214 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1216 return (LRESULT
)Result
;
1221 static LRESULT FASTCALL
1222 co_IntSendMessageTimeoutSingle( HWND hWnd
,
1228 ULONG_PTR
*uResult
)
1232 PMSGMEMORY MsgMemoryEntry
;
1233 INT lParamBufferSize
;
1234 LPARAM lParamPacked
;
1235 PTHREADINFO Win32Thread
;
1236 ULONG_PTR Result
= 0;
1237 DECLARE_RETURN(LRESULT
);
1238 USER_REFERENCE_ENTRY Ref
;
1240 if (!(Window
= UserGetWindowObject(hWnd
)))
1245 UserRefObjectCo(Window
, &Ref
);
1247 Win32Thread
= PsGetCurrentThreadWin32Thread();
1249 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1251 if ( NULL
!= Win32Thread
&&
1252 Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
)
1254 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1256 /* Never send messages to exiting threads */
1260 /* See if this message type is present in the table */
1261 MsgMemoryEntry
= FindMsgMemory(Msg
);
1262 if (NULL
== MsgMemoryEntry
)
1264 lParamBufferSize
= -1;
1268 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1271 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1273 DPRINT1("Failed to pack message parameters\n");
1277 ObReferenceObject(Win32Thread
->pEThread
);
1278 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1290 ObDereferenceObject(Win32Thread
->pEThread
);
1292 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1294 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1296 DPRINT1("Failed to unpack message parameters\n");
1303 if (uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->head
.pti
->MessageQueue
))
1305 /* FIXME - Set a LastError? */
1309 if (Window
->state
& WNDS_DESTROYED
)
1311 /* FIXME - last error? */
1312 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1318 Status
= co_MsqSendMessage( Window
->head
.pti
->MessageQueue
,
1324 (uFlags
& SMTO_BLOCK
),
1328 while ((STATUS_TIMEOUT
== Status
) &&
1329 (uFlags
& SMTO_NOTIMEOUTIFNOTHUNG
) &&
1330 !MsqIsHung(Window
->head
.pti
->MessageQueue
));
1332 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1334 if (STATUS_TIMEOUT
== Status
)
1338 Microsoft Windows 2000: If GetLastError returns zero, then the function
1340 XP+ : If the function fails or times out, the return value is zero.
1341 To get extended error information, call GetLastError. If GetLastError
1342 returns ERROR_TIMEOUT, then the function timed out.
1344 EngSetLastError(ERROR_TIMEOUT
);
1347 else if (! NT_SUCCESS(Status
))
1349 SetLastNtError(Status
);
1356 if (Window
) UserDerefObjectCo(Window
);
1361 co_IntSendMessageTimeout( HWND hWnd
,
1367 ULONG_PTR
*uResult
)
1373 if (HWND_BROADCAST
!= hWnd
)
1375 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1378 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1379 if (NULL
== DesktopWindow
)
1381 EngSetLastError(ERROR_INTERNAL_ERROR
);
1385 /* Send message to the desktop window too! */
1386 co_IntSendMessageTimeoutSingle(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1388 Children
= IntWinListChildren(DesktopWindow
);
1389 if (NULL
== Children
)
1394 for (Child
= Children
; NULL
!= *Child
; Child
++)
1396 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1399 ExFreePool(Children
);
1401 return (LRESULT
) TRUE
;
1405 co_IntSendMessageNoWait(HWND hWnd
,
1410 ULONG_PTR Result
= 0;
1411 co_IntSendMessageWithCallBack(hWnd
,
1422 co_IntSendMessageWithCallBack( HWND hWnd
,
1426 SENDASYNCPROC CompletionCallback
,
1427 ULONG_PTR CompletionCallbackContext
,
1432 PMSGMEMORY MsgMemoryEntry
;
1433 INT lParamBufferSize
;
1434 LPARAM lParamPacked
;
1435 PTHREADINFO Win32Thread
;
1436 DECLARE_RETURN(LRESULT
);
1437 USER_REFERENCE_ENTRY Ref
;
1438 PUSER_SENT_MESSAGE Message
;
1440 if (!(Window
= UserGetWindowObject(hWnd
)))
1445 UserRefObjectCo(Window
, &Ref
);
1447 if (Window
->state
& WNDS_DESTROYED
)
1449 /* FIXME - last error? */
1450 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1454 Win32Thread
= PsGetCurrentThreadWin32Thread();
1456 IntCallWndProc( Window
, hWnd
, Msg
, wParam
, lParam
);
1458 if (Win32Thread
== NULL
)
1464 if (Win32Thread
->TIF_flags
& TIF_INCLEANUP
)
1466 /* Never send messages to exiting threads */
1470 /* See if this message type is present in the table */
1471 MsgMemoryEntry
= FindMsgMemory(Msg
);
1472 if (NULL
== MsgMemoryEntry
)
1474 lParamBufferSize
= -1;
1478 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1481 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
, Window
->head
.pti
->MessageQueue
!= Win32Thread
->MessageQueue
)))
1483 DPRINT1("Failed to pack message parameters\n");
1487 /* If this is not a callback and it can be sent now, then send it. */
1488 if ((Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
) && (CompletionCallback
== NULL
))
1490 ObReferenceObject(Win32Thread
->pEThread
);
1491 Result
= (ULONG_PTR
)co_IntCallWindowProc( Window
->lpfnWndProc
,
1502 ObDereferenceObject(Win32Thread
->pEThread
);
1505 IntCallWndProcRet( Window
, hWnd
, Msg
, wParam
, lParam
, (LRESULT
*)uResult
);
1507 if ((Window
->head
.pti
->MessageQueue
== Win32Thread
->MessageQueue
) && (CompletionCallback
== NULL
))
1509 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
, FALSE
)))
1511 DPRINT1("Failed to unpack message parameters\n");
1516 if(!(Message
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(USER_SENT_MESSAGE
), TAG_USRMSG
)))
1518 DPRINT1("MsqSendMessage(): Not enough memory to allocate a message");
1519 return STATUS_INSUFFICIENT_RESOURCES
;
1522 Message
->Msg
.hwnd
= hWnd
;
1523 Message
->Msg
.message
= Msg
;
1524 Message
->Msg
.wParam
= wParam
;
1525 Message
->Msg
.lParam
= lParamPacked
;
1526 Message
->CompletionEvent
= NULL
;
1527 Message
->Result
= 0;
1528 Message
->lResult
= 0;
1529 Message
->QS_Flags
= 0;
1530 Message
->SenderQueue
= NULL
; // mjmartin, you are right! This is null.
1531 Message
->CallBackSenderQueue
= Win32Thread
->MessageQueue
;
1533 IntReferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1534 Message
->CompletionCallback
= CompletionCallback
;
1535 Message
->CompletionCallbackContext
= CompletionCallbackContext
;
1536 Message
->HookMessage
= MSQ_NORMAL
| MSQ_SENTNOWAIT
;
1537 Message
->HasPackedLParam
= (lParamBufferSize
> 0);
1539 Message
->QS_Flags
= QS_SENDMESSAGE
;
1540 MsqWakeQueue(Window
->head
.pti
->MessageQueue
, QS_SENDMESSAGE
, FALSE
);
1542 InsertTailList(&Window
->head
.pti
->MessageQueue
->SentMessagesListHead
, &Message
->ListEntry
);
1543 IntDereferenceMessageQueue(Window
->head
.pti
->MessageQueue
);
1548 if (Window
) UserDerefObjectCo(Window
);
1552 /* This function posts a message if the destination's message queue belongs to
1553 another thread, otherwise it sends the message. It does not support broadcast
1556 co_IntPostOrSendMessage( HWND hWnd
,
1565 if ( hWnd
== HWND_BROADCAST
)
1570 if(!(Window
= UserGetWindowObject(hWnd
)))
1575 pti
= PsGetCurrentThreadWin32Thread();
1577 if ( Window
->head
.pti
->MessageQueue
!= pti
->MessageQueue
&&
1578 FindMsgMemory(Msg
) == 0 )
1580 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1584 if ( !co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
) )
1590 return (LRESULT
)Result
;
1594 co_IntDoSendMessage( HWND hWnd
,
1601 LRESULT Result
= TRUE
;
1606 PMSGMEMORY MsgMemoryEntry
;
1608 if (HWND_BROADCAST
!= hWnd
)
1610 Window
= UserGetWindowObject(hWnd
);
1617 /* Check for an exiting window. */
1618 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1620 DPRINT1("co_IntDoSendMessage Window Exiting!\n");
1623 /* See if the current thread can handle the message */
1624 pti
= PsGetCurrentThreadWin32Thread();
1626 UserModeMsg
.hwnd
= hWnd
;
1627 UserModeMsg
.message
= Msg
;
1628 UserModeMsg
.wParam
= wParam
;
1629 UserModeMsg
.lParam
= lParam
;
1630 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1632 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1633 if (! NT_SUCCESS(Status
))
1635 EngSetLastError(ERROR_INVALID_PARAMETER
);
1636 return (dsm
? 0 : -1);
1641 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1642 KernelModeMsg
.message
,
1643 KernelModeMsg
.wParam
,
1644 KernelModeMsg
.lParam
);
1648 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1649 KernelModeMsg
.message
,
1650 KernelModeMsg
.wParam
,
1651 KernelModeMsg
.lParam
,
1657 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1658 if (! NT_SUCCESS(Status
))
1660 EngSetLastError(ERROR_INVALID_PARAMETER
);
1661 return(dsm
? 0 : -1);
1664 return (LRESULT
)Result
;
1668 UserSendNotifyMessage( HWND hWnd
,
1675 if (is_pointer_message(Msg
))
1677 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1681 // Basicly the same as IntPostOrSendMessage
1682 if (hWnd
== HWND_BROADCAST
) //Handle Broadcast
1688 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1689 List
= IntWinListChildren(DesktopWindow
);
1693 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1694 for (i
= 0; List
[i
]; i
++)
1696 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1699 DPRINT1("SendNotifyMessage: Failed in Broadcast!\n");
1708 ULONG_PTR lResult
= 0;
1709 Ret
= co_IntSendMessageWithCallBack( hWnd
,
1722 IntGetQueueStatus(DWORD Changes
)
1725 PUSER_MESSAGE_QUEUE Queue
;
1728 pti
= PsGetCurrentThreadWin32Thread();
1729 Queue
= pti
->MessageQueue
;
1731 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1733 /* High word, types of messages currently in the queue.
1734 Low word, types of messages that have been added to the queue and that
1735 are still in the queue
1737 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1739 pti
->pcti
->fsChangeBits
&= ~Changes
;
1745 IntInitMessagePumpHook()
1747 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1751 pti
->pcti
->dwcPumpHook
++;
1758 IntUninitMessagePumpHook()
1760 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1764 if (pti
->pcti
->dwcPumpHook
<= 0)
1768 pti
->pcti
->dwcPumpHook
--;
1774 /** Functions ******************************************************************/
1777 NtUserPostMessage(HWND hWnd
,
1784 UserEnterExclusive();
1786 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1794 NtUserPostThreadMessage(DWORD idThread
,
1801 UserEnterExclusive();
1803 ret
= UserPostThreadMessage( idThread
, Msg
, wParam
, lParam
);
1811 NtUserWaitMessage(VOID
)
1815 UserEnterExclusive();
1816 DPRINT("NtUserWaitMessage Enter\n");
1817 ret
= co_IntWaitMessage(NULL
, 0, 0);
1818 DPRINT("NtUserWaitMessage Leave\n");
1825 NtUserGetMessage(PMSG pMsg
,
1833 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
1835 EngSetLastError(ERROR_INVALID_PARAMETER
);
1839 UserEnterExclusive();
1841 RtlZeroMemory(&Msg
, sizeof(MSG
));
1843 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
1851 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
1852 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
1854 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1856 SetLastNtError(_SEH2_GetExceptionCode());
1866 NtUserPeekMessage( PMSG pMsg
,
1875 if ( RemoveMsg
& PM_BADMSGFLAGS
)
1877 EngSetLastError(ERROR_INVALID_FLAGS
);
1881 UserEnterExclusive();
1883 RtlZeroMemory(&Msg
, sizeof(MSG
));
1885 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
1893 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
1894 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
1896 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1898 SetLastNtError(_SEH2_GetExceptionCode());
1908 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
1915 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
1916 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
1918 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1920 _SEH2_YIELD(return FALSE
);
1924 UserEnterExclusive();
1926 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
1932 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
1939 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
1940 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
1942 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1952 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
1959 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
1960 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
1962 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1964 SetLastNtError(_SEH2_GetExceptionCode());
1965 _SEH2_YIELD(return FALSE
);
1969 UserEnterExclusive();
1971 Res
= IntDispatchMessage(&SafeMsg
);
1979 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
1986 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
1987 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
1989 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1991 SetLastNtError(_SEH2_GetExceptionCode());
1992 _SEH2_YIELD(return FALSE
);
1996 UserEnterExclusive();
1998 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
2006 NtUserMessageCall( HWND hWnd
,
2010 ULONG_PTR ResultInfo
,
2011 DWORD dwType
, // fnID?
2014 LRESULT lResult
= 0;
2017 USER_REFERENCE_ENTRY Ref
;
2019 UserEnterExclusive();
2021 /* Validate input */
2022 if (hWnd
&& (hWnd
!= INVALID_HANDLE_VALUE
))
2024 Window
= UserGetWindowObject(hWnd
);
2034 case FNID_DEFWINDOWPROC
:
2035 if (Window
) UserRefObjectCo(Window
, &Ref
);
2036 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
2038 if (Window
) UserDerefObjectCo(Window
);
2040 case FNID_SENDNOTIFYMESSAGE
:
2041 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2043 case FNID_BROADCASTSYSTEMMESSAGE
:
2046 DWORD_PTR RetVal
= 0;
2052 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2053 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2055 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2065 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2066 parm
.recipients
== BSM_ALLCOMPONENTS
)
2069 else if (parm
.recipients
& BSM_APPLICATIONS
)
2071 if (parm
.flags
& BSF_QUERY
)
2073 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2075 co_IntSendMessageTimeout( HWND_BROADCAST
,
2083 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2085 co_IntSendMessageTimeout( HWND_BROADCAST
,
2089 SMTO_NOTIMEOUTIFNOTHUNG
,
2095 co_IntSendMessageTimeout( HWND_BROADCAST
,
2105 else if (parm
.flags
& BSF_POSTMESSAGE
)
2107 Ret
= UserPostMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2109 else //Everything else,,,, if ( parm.flags & BSF_SENDNOTIFYMESSAGE)
2111 Ret
= UserSendNotifyMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2116 case FNID_SENDMESSAGECALLBACK
:
2118 CALL_BACK_INFO CallBackInfo
;
2123 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2124 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2126 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2133 if (!co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2134 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
))
2136 DPRINT1("Callback failure!\n");
2140 case FNID_SENDMESSAGE
:
2142 Ret
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2148 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2149 RtlCopyMemory((PVOID
)ResultInfo
, &Ret
, sizeof(ULONG_PTR
));
2151 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2160 case FNID_SENDMESSAGETIMEOUT
:
2162 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2167 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2168 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2170 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2178 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, &dsm
);
2184 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2185 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2187 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2196 // CallNextHook bypass.
2197 case FNID_CALLWNDPROC
:
2198 case FNID_CALLWNDPROCRET
:
2201 PCLIENTINFO ClientInfo
;
2202 PHOOK NextObj
, Hook
;
2204 pti
= GetW32ThreadInfo();
2206 Hook
= pti
->sphkCurrent
;
2210 NextObj
= Hook
->phkNext
;
2211 ClientInfo
= pti
->pClientInfo
;
2214 ClientInfo
->phkCurrent
= NextObj
;
2216 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2222 if (!ClientInfo
|| !NextObj
) break;
2224 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2226 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2231 CWP
.wParam
= wParam
;
2232 CWP
.lParam
= lParam
;
2233 DPRINT("WH_CALLWNDPROC: Hook %x NextHook %x\n", Hook
, NextObj
);
2235 lResult
= co_IntCallHookProc( Hook
->HookId
,
2237 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2248 CWPR
.wParam
= wParam
;
2249 CWPR
.lParam
= lParam
;
2250 CWPR
.lResult
= ClientInfo
->dwHookData
;
2252 lResult
= co_IntCallHookProc( Hook
->HookId
,
2254 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2266 case FNID_DEFWINDOWPROC
:
2267 case FNID_CALLWNDPROC
:
2268 case FNID_CALLWNDPROCRET
:
2273 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2274 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2276 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2292 #define INFINITE 0xFFFFFFFF
2293 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2297 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2298 IN DWORD dwMilliseconds
,
2302 PPROCESSINFO W32Process
;
2306 LARGE_INTEGER Timeout
;
2308 UserEnterExclusive();
2310 Status
= ObReferenceObjectByHandle(hProcess
,
2311 PROCESS_QUERY_INFORMATION
,
2317 if (!NT_SUCCESS(Status
))
2320 SetLastNtError(Status
);
2324 pti
= PsGetCurrentThreadWin32Thread();
2326 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2328 if ( PsGetProcessExitProcessCalled(Process
) ||
2330 pti
->ppi
== W32Process
)
2332 ObDereferenceObject(Process
);
2334 EngSetLastError(ERROR_INVALID_PARAMETER
);
2338 Handles
[0] = Process
;
2339 Handles
[1] = W32Process
->InputIdleEvent
;
2340 Handles
[2] = pti
->MessageQueue
->NewMessages
; // pEventQueueServer; IntMsqSetWakeMask returns hEventQueueClient
2344 ObDereferenceObject(Process
);
2346 return STATUS_SUCCESS
; /* no event to wait on */
2349 if (dwMilliseconds
!= INFINITE
)
2350 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2352 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2353 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2355 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2356 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2359 DPRINT("WFII: ppi 0x%x\n",W32Process
);
2360 DPRINT("WFII: waiting for %p\n", Handles
[1] );
2364 Status
= KeWaitForMultipleObjects( 3,
2370 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2372 UserEnterExclusive();
2374 if (!NT_SUCCESS(Status
))
2376 SetLastNtError(Status
);
2377 Status
= WAIT_FAILED
;
2389 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2390 DPRINT1("WFII: WAIT 2\n");
2394 case STATUS_TIMEOUT
:
2395 DPRINT1("WFII: timeout\n");
2400 DPRINT1("WFII: finished\n");
2401 Status
= STATUS_SUCCESS
;
2408 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2410 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
2411 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2413 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
2414 ObDereferenceObject(Process
);