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
,TAG_WINLIST
);//ExFreePool(List);
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
);
1553 co_IntDoSendMessage( HWND hWnd
,
1560 LRESULT Result
= TRUE
;
1565 PMSGMEMORY MsgMemoryEntry
;
1567 if (HWND_BROADCAST
!= hWnd
)
1569 Window
= UserGetWindowObject(hWnd
);
1576 /* Check for an exiting window. */
1577 if (Window
&& Window
->state
& WNDS_DESTROYED
)
1579 DPRINT1("co_IntDoSendMessage Window Exiting!\n");
1582 /* See if the current thread can handle the message */
1583 pti
= PsGetCurrentThreadWin32Thread();
1585 UserModeMsg
.hwnd
= hWnd
;
1586 UserModeMsg
.message
= Msg
;
1587 UserModeMsg
.wParam
= wParam
;
1588 UserModeMsg
.lParam
= lParam
;
1589 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1591 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1592 if (! NT_SUCCESS(Status
))
1594 EngSetLastError(ERROR_INVALID_PARAMETER
);
1595 return (dsm
? 0 : -1);
1600 Result
= co_IntSendMessage( KernelModeMsg
.hwnd
,
1601 KernelModeMsg
.message
,
1602 KernelModeMsg
.wParam
,
1603 KernelModeMsg
.lParam
);
1607 Result
= co_IntSendMessageTimeout( KernelModeMsg
.hwnd
,
1608 KernelModeMsg
.message
,
1609 KernelModeMsg
.wParam
,
1610 KernelModeMsg
.lParam
,
1616 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1617 if (! NT_SUCCESS(Status
))
1619 EngSetLastError(ERROR_INVALID_PARAMETER
);
1620 return(dsm
? 0 : -1);
1623 return (LRESULT
)Result
;
1627 UserSendNotifyMessage( HWND hWnd
,
1634 if (is_pointer_message(Msg
))
1636 EngSetLastError(ERROR_MESSAGE_SYNC_ONLY
);
1640 // Basicly the same as IntPostOrSendMessage
1641 if (hWnd
== HWND_BROADCAST
) //Handle Broadcast
1647 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1648 List
= IntWinListChildren(DesktopWindow
);
1652 UserSendNotifyMessage(DesktopWindow
->head
.h
, Msg
, wParam
, lParam
);
1653 for (i
= 0; List
[i
]; i
++)
1655 Ret
= UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1658 DPRINT1("SendNotifyMessage: Failed in Broadcast!\n");
1667 ULONG_PTR lResult
= 0;
1668 Ret
= co_IntSendMessageWithCallBack( hWnd
,
1681 IntGetQueueStatus(DWORD Changes
)
1684 PUSER_MESSAGE_QUEUE Queue
;
1687 pti
= PsGetCurrentThreadWin32Thread();
1688 Queue
= pti
->MessageQueue
;
1690 Changes
&= (QS_ALLINPUT
|QS_ALLPOSTMESSAGE
|QS_SMRESULT
);
1692 /* High word, types of messages currently in the queue.
1693 Low word, types of messages that have been added to the queue and that
1694 are still in the queue
1696 Result
= MAKELONG(pti
->pcti
->fsChangeBits
& Changes
, pti
->pcti
->fsWakeBits
& Changes
);
1698 pti
->pcti
->fsChangeBits
&= ~Changes
;
1704 IntInitMessagePumpHook()
1706 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1710 pti
->pcti
->dwcPumpHook
++;
1717 IntUninitMessagePumpHook()
1719 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1723 if (pti
->pcti
->dwcPumpHook
<= 0)
1727 pti
->pcti
->dwcPumpHook
--;
1733 /** Functions ******************************************************************/
1736 NtUserPostMessage(HWND hWnd
,
1743 UserEnterExclusive();
1745 ret
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1753 NtUserPostThreadMessage(DWORD idThread
,
1760 UserEnterExclusive();
1762 ret
= UserPostThreadMessage( idThread
, Msg
, wParam
, lParam
);
1770 NtUserWaitMessage(VOID
)
1774 UserEnterExclusive();
1775 DPRINT("NtUserWaitMessage Enter\n");
1776 ret
= co_IntWaitMessage(NULL
, 0, 0);
1777 DPRINT("NtUserWaitMessage Leave\n");
1784 NtUserGetMessage(PMSG pMsg
,
1792 if ( (MsgFilterMin
|MsgFilterMax
) & ~WM_MAXIMUM
)
1794 EngSetLastError(ERROR_INVALID_PARAMETER
);
1798 UserEnterExclusive();
1800 RtlZeroMemory(&Msg
, sizeof(MSG
));
1802 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
, TRUE
);
1810 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
1811 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
1813 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1815 SetLastNtError(_SEH2_GetExceptionCode());
1825 NtUserPeekMessage( PMSG pMsg
,
1834 if ( RemoveMsg
& PM_BADMSGFLAGS
)
1836 EngSetLastError(ERROR_INVALID_FLAGS
);
1840 UserEnterExclusive();
1842 RtlZeroMemory(&Msg
, sizeof(MSG
));
1844 Ret
= co_IntGetPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
, FALSE
);
1852 ProbeForWrite(pMsg
, sizeof(MSG
), 1);
1853 RtlCopyMemory(pMsg
, &Msg
, sizeof(MSG
));
1855 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1857 SetLastNtError(_SEH2_GetExceptionCode());
1867 NtUserCallMsgFilter( LPMSG lpmsg
, INT code
)
1874 ProbeForRead(lpmsg
, sizeof(MSG
), 1);
1875 RtlCopyMemory( &Msg
, lpmsg
, sizeof(MSG
));
1877 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1879 _SEH2_YIELD(return FALSE
);
1883 UserEnterExclusive();
1885 if ( co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)&Msg
))
1891 Ret
= co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)&Msg
);
1898 ProbeForWrite(lpmsg
, sizeof(MSG
), 1);
1899 RtlCopyMemory(lpmsg
, &Msg
, sizeof(MSG
));
1901 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1911 NtUserDispatchMessage(PMSG UnsafeMsgInfo
)
1918 ProbeForRead(UnsafeMsgInfo
, sizeof(MSG
), 1);
1919 RtlCopyMemory(&SafeMsg
, UnsafeMsgInfo
, sizeof(MSG
));
1921 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1923 SetLastNtError(_SEH2_GetExceptionCode());
1924 _SEH2_YIELD(return FALSE
);
1928 UserEnterExclusive();
1930 Res
= IntDispatchMessage(&SafeMsg
);
1938 NtUserTranslateMessage(LPMSG lpMsg
, UINT flags
)
1945 ProbeForRead(lpMsg
, sizeof(MSG
), 1);
1946 RtlCopyMemory(&SafeMsg
, lpMsg
, sizeof(MSG
));
1948 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1950 SetLastNtError(_SEH2_GetExceptionCode());
1951 _SEH2_YIELD(return FALSE
);
1955 UserEnterExclusive();
1957 Ret
= IntTranslateKbdMessage(&SafeMsg
, flags
);
1965 NtUserMessageCall( HWND hWnd
,
1969 ULONG_PTR ResultInfo
,
1970 DWORD dwType
, // fnID?
1973 LRESULT lResult
= 0;
1976 USER_REFERENCE_ENTRY Ref
;
1978 UserEnterExclusive();
1980 /* Validate input */
1981 if (hWnd
&& (hWnd
!= INVALID_HANDLE_VALUE
))
1983 Window
= UserGetWindowObject(hWnd
);
1993 case FNID_DEFWINDOWPROC
:
1994 if (Window
) UserRefObjectCo(Window
, &Ref
);
1995 lResult
= IntDefWindowProc(Window
, Msg
, wParam
, lParam
, Ansi
);
1997 if (Window
) UserDerefObjectCo(Window
);
1999 case FNID_SENDNOTIFYMESSAGE
:
2000 Ret
= UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
);
2002 case FNID_BROADCASTSYSTEMMESSAGE
:
2005 DWORD_PTR RetVal
= 0;
2011 ProbeForWrite((PVOID
)ResultInfo
, sizeof(BROADCASTPARM
), 1);
2012 RtlCopyMemory(&parm
, (PVOID
)ResultInfo
, sizeof(BROADCASTPARM
));
2014 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2024 if ( parm
.recipients
& BSM_ALLDESKTOPS
||
2025 parm
.recipients
== BSM_ALLCOMPONENTS
)
2028 else if (parm
.recipients
& BSM_APPLICATIONS
)
2030 if (parm
.flags
& BSF_QUERY
)
2032 if (parm
.flags
& BSF_FORCEIFHUNG
|| parm
.flags
& BSF_NOHANG
)
2034 co_IntSendMessageTimeout( HWND_BROADCAST
,
2042 else if (parm
.flags
& BSF_NOTIMEOUTIFNOTHUNG
)
2044 co_IntSendMessageTimeout( HWND_BROADCAST
,
2048 SMTO_NOTIMEOUTIFNOTHUNG
,
2054 co_IntSendMessageTimeout( HWND_BROADCAST
,
2064 else if (parm
.flags
& BSF_POSTMESSAGE
)
2066 Ret
= UserPostMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2068 else //Everything else,,,, if ( parm.flags & BSF_SENDNOTIFYMESSAGE)
2070 Ret
= UserSendNotifyMessage(HWND_BROADCAST
, Msg
, wParam
, lParam
);
2075 case FNID_SENDMESSAGECALLBACK
:
2077 CALL_BACK_INFO CallBackInfo
;
2082 ProbeForRead((PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
), 1);
2083 RtlCopyMemory(&CallBackInfo
, (PVOID
)ResultInfo
, sizeof(CALL_BACK_INFO
));
2085 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2092 if (!co_IntSendMessageWithCallBack(hWnd
, Msg
, wParam
, lParam
,
2093 CallBackInfo
.CallBack
, CallBackInfo
.Context
, &uResult
))
2095 DPRINT1("Callback failure!\n");
2099 case FNID_SENDMESSAGE
:
2101 Ret
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, 0);
2107 ProbeForWrite((PVOID
)ResultInfo
, sizeof(ULONG_PTR
), 1);
2108 RtlCopyMemory((PVOID
)ResultInfo
, &Ret
, sizeof(ULONG_PTR
));
2110 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2119 case FNID_SENDMESSAGETIMEOUT
:
2121 DOSENDMESSAGE dsm
, *pdsm
= (PDOSENDMESSAGE
)ResultInfo
;
2126 ProbeForRead(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2127 RtlCopyMemory(&dsm
, pdsm
, sizeof(DOSENDMESSAGE
));
2129 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2137 Ret
= co_IntDoSendMessage( hWnd
, Msg
, wParam
, lParam
, &dsm
);
2143 ProbeForWrite(pdsm
, sizeof(DOSENDMESSAGE
), 1);
2144 RtlCopyMemory(pdsm
, &dsm
, sizeof(DOSENDMESSAGE
));
2146 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2155 // CallNextHook bypass.
2156 case FNID_CALLWNDPROC
:
2157 case FNID_CALLWNDPROCRET
:
2160 PCLIENTINFO ClientInfo
;
2161 PHOOK NextObj
, Hook
;
2163 pti
= GetW32ThreadInfo();
2165 Hook
= pti
->sphkCurrent
;
2169 NextObj
= Hook
->phkNext
;
2170 ClientInfo
= pti
->pClientInfo
;
2173 ClientInfo
->phkCurrent
= NextObj
;
2175 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2181 if (!ClientInfo
|| !NextObj
) break;
2183 NextObj
->phkNext
= IntGetNextHook(NextObj
);
2185 if ( Hook
->HookId
== WH_CALLWNDPROC
)
2190 CWP
.wParam
= wParam
;
2191 CWP
.lParam
= lParam
;
2192 DPRINT("WH_CALLWNDPROC: Hook %x NextHook %x\n", Hook
, NextObj
);
2194 lResult
= co_IntCallHookProc( Hook
->HookId
,
2196 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2207 CWPR
.wParam
= wParam
;
2208 CWPR
.lParam
= lParam
;
2209 CWPR
.lResult
= ClientInfo
->dwHookData
;
2211 lResult
= co_IntCallHookProc( Hook
->HookId
,
2213 ((ClientInfo
->CI_flags
& CI_CURTHPRHOOK
) ? 1 : 0),
2225 case FNID_DEFWINDOWPROC
:
2226 case FNID_CALLWNDPROC
:
2227 case FNID_CALLWNDPROCRET
:
2232 ProbeForWrite((PVOID
)ResultInfo
, sizeof(LRESULT
), 1);
2233 RtlCopyMemory((PVOID
)ResultInfo
, &lResult
, sizeof(LRESULT
));
2235 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2251 #define INFINITE 0xFFFFFFFF
2252 #define WAIT_FAILED ((DWORD)0xFFFFFFFF)
2256 NtUserWaitForInputIdle( IN HANDLE hProcess
,
2257 IN DWORD dwMilliseconds
,
2261 PPROCESSINFO W32Process
;
2265 LARGE_INTEGER Timeout
;
2267 UserEnterExclusive();
2269 Status
= ObReferenceObjectByHandle(hProcess
,
2270 PROCESS_QUERY_INFORMATION
,
2276 if (!NT_SUCCESS(Status
))
2279 SetLastNtError(Status
);
2283 pti
= PsGetCurrentThreadWin32Thread();
2285 W32Process
= (PPROCESSINFO
)Process
->Win32Process
;
2287 if ( PsGetProcessExitProcessCalled(Process
) ||
2289 pti
->ppi
== W32Process
)
2291 ObDereferenceObject(Process
);
2293 EngSetLastError(ERROR_INVALID_PARAMETER
);
2297 Handles
[0] = Process
;
2298 Handles
[1] = W32Process
->InputIdleEvent
;
2299 Handles
[2] = pti
->MessageQueue
->NewMessages
; // pEventQueueServer; IntMsqSetWakeMask returns hEventQueueClient
2303 ObDereferenceObject(Process
);
2305 return STATUS_SUCCESS
; /* no event to wait on */
2308 if (dwMilliseconds
!= INFINITE
)
2309 Timeout
.QuadPart
= (LONGLONG
) dwMilliseconds
* (LONGLONG
) -10000;
2311 W32Process
->W32PF_flags
|= W32PF_WAITFORINPUTIDLE
;
2312 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2314 pti
->TIF_flags
|= TIF_WAITFORINPUTIDLE
;
2315 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2318 DPRINT("WFII: ppi 0x%x\n",W32Process
);
2319 DPRINT("WFII: waiting for %p\n", Handles
[1] );
2323 Status
= KeWaitForMultipleObjects( 3,
2329 dwMilliseconds
== INFINITE
? NULL
: &Timeout
,
2331 UserEnterExclusive();
2333 if (!NT_SUCCESS(Status
))
2335 SetLastNtError(Status
);
2336 Status
= WAIT_FAILED
;
2348 co_IntGetPeekMessage( &Msg
, 0, 0, 0, PM_REMOVE
| PM_QS_SENDMESSAGE
, FALSE
);
2349 DPRINT1("WFII: WAIT 2\n");
2353 case STATUS_TIMEOUT
:
2354 DPRINT1("WFII: timeout\n");
2359 DPRINT1("WFII: finished\n");
2360 Status
= STATUS_SUCCESS
;
2367 for (pti
= W32Process
->ptiList
; pti
; pti
= pti
->ptiSibling
)
2369 pti
->TIF_flags
&= ~TIF_WAITFORINPUTIDLE
;
2370 pti
->pClientInfo
->dwTIFlags
= pti
->TIF_flags
;
2372 W32Process
->W32PF_flags
&= ~W32PF_WAITFORINPUTIDLE
;
2373 ObDereferenceObject(Process
);