2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
24 * FILE: subsys/win32k/ntuser/message.c
25 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
27 * 06-06-2001 CSH Created
30 /* INCLUDES ******************************************************************/
43 DOSENDMESSAGE
, *PDOSENDMESSAGE
;
45 /* FUNCTIONS *****************************************************************/
48 IntInitMessageImpl(VOID
)
50 return STATUS_SUCCESS
;
54 IntCleanupMessageImpl(VOID
)
56 return STATUS_SUCCESS
;
59 #define MMS_SIZE_WPARAM -1
60 #define MMS_SIZE_WPARAMWCHAR -2
61 #define MMS_SIZE_LPARAMSZ -3
62 #define MMS_SIZE_SPECIAL -4
63 #define MMS_FLAG_READ 0x01
64 #define MMS_FLAG_WRITE 0x02
65 #define MMS_FLAG_READWRITE (MMS_FLAG_READ | MMS_FLAG_WRITE)
66 typedef struct tagMSGMEMORY
72 MSGMEMORY
, *PMSGMEMORY
;
74 static MSGMEMORY MsgMemory
[] =
76 { WM_CREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
77 { WM_DDE_ACK
, sizeof(KMDDELPARAM
), MMS_FLAG_READ
},
78 { WM_DDE_EXECUTE
, MMS_SIZE_WPARAM
, MMS_FLAG_READ
},
79 { WM_GETMINMAXINFO
, sizeof(MINMAXINFO
), MMS_FLAG_READWRITE
},
80 { WM_GETTEXT
, MMS_SIZE_WPARAMWCHAR
, MMS_FLAG_WRITE
},
81 { WM_NCCALCSIZE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
82 { WM_NCCREATE
, MMS_SIZE_SPECIAL
, MMS_FLAG_READWRITE
},
83 { WM_SETTEXT
, MMS_SIZE_LPARAMSZ
, MMS_FLAG_READ
},
84 { WM_STYLECHANGED
, sizeof(STYLESTRUCT
), MMS_FLAG_READ
},
85 { WM_STYLECHANGING
, sizeof(STYLESTRUCT
), MMS_FLAG_READWRITE
},
86 { WM_COPYDATA
, MMS_SIZE_SPECIAL
, MMS_FLAG_READ
},
87 { WM_WINDOWPOSCHANGED
, sizeof(WINDOWPOS
), MMS_FLAG_READ
},
88 { WM_WINDOWPOSCHANGING
, sizeof(WINDOWPOS
), MMS_FLAG_READWRITE
},
91 static PMSGMEMORY FASTCALL
92 FindMsgMemory(UINT Msg
)
94 PMSGMEMORY MsgMemoryEntry
;
96 /* See if this message type is present in the table */
97 for (MsgMemoryEntry
= MsgMemory
;
98 MsgMemoryEntry
< MsgMemory
+ sizeof(MsgMemory
) / sizeof(MSGMEMORY
);
101 if (Msg
== MsgMemoryEntry
->Message
)
103 return MsgMemoryEntry
;
111 MsgMemorySize(PMSGMEMORY MsgMemoryEntry
, WPARAM wParam
, LPARAM lParam
)
114 PUNICODE_STRING WindowName
;
115 PUNICODE_STRING ClassName
;
120 if (MMS_SIZE_WPARAM
== MsgMemoryEntry
->Size
)
124 else if (MMS_SIZE_WPARAMWCHAR
== MsgMemoryEntry
->Size
)
126 Size
= (UINT
) (wParam
* sizeof(WCHAR
));
128 else if (MMS_SIZE_LPARAMSZ
== MsgMemoryEntry
->Size
)
130 Size
= (UINT
) ((wcslen((PWSTR
) lParam
) + 1) * sizeof(WCHAR
));
132 else if (MMS_SIZE_SPECIAL
== MsgMemoryEntry
->Size
)
134 switch(MsgMemoryEntry
->Message
)
138 Cs
= (CREATESTRUCTW
*) lParam
;
139 WindowName
= (PUNICODE_STRING
) Cs
->lpszName
;
140 ClassName
= (PUNICODE_STRING
) Cs
->lpszClass
;
141 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
142 if (IS_ATOM(ClassName
->Buffer
))
144 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
148 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
153 Size
= wParam
? sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
) : sizeof(RECT
);
157 Size
= sizeof(COPYDATASTRUCT
) + ((PCOPYDATASTRUCT
)lParam
)->cbData
;
168 Size
= MsgMemoryEntry
->Size
;
173 DPRINT1("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH_GetExceptionCode());
181 PackParam(LPARAM
*lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
183 NCCALCSIZE_PARAMS
*UnpackedNcCalcsize
;
184 NCCALCSIZE_PARAMS
*PackedNcCalcsize
;
185 CREATESTRUCTW
*UnpackedCs
;
186 CREATESTRUCTW
*PackedCs
;
187 PUNICODE_STRING WindowName
;
188 PUNICODE_STRING ClassName
;
192 *lParamPacked
= lParam
;
193 if (WM_NCCALCSIZE
== Msg
&& wParam
)
195 UnpackedNcCalcsize
= (NCCALCSIZE_PARAMS
*) lParam
;
196 if (UnpackedNcCalcsize
->lppos
!= (PWINDOWPOS
) (UnpackedNcCalcsize
+ 1))
198 PackedNcCalcsize
= ExAllocatePoolWithTag(PagedPool
,
199 sizeof(NCCALCSIZE_PARAMS
) + sizeof(WINDOWPOS
),
201 if (NULL
== PackedNcCalcsize
)
203 DPRINT1("Not enough memory to pack lParam\n");
204 return STATUS_NO_MEMORY
;
206 RtlCopyMemory(PackedNcCalcsize
, UnpackedNcCalcsize
, sizeof(NCCALCSIZE_PARAMS
));
207 PackedNcCalcsize
->lppos
= (PWINDOWPOS
) (PackedNcCalcsize
+ 1);
208 RtlCopyMemory(PackedNcCalcsize
->lppos
, UnpackedNcCalcsize
->lppos
, sizeof(WINDOWPOS
));
209 *lParamPacked
= (LPARAM
) PackedNcCalcsize
;
212 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
214 UnpackedCs
= (CREATESTRUCTW
*) lParam
;
215 WindowName
= (PUNICODE_STRING
) UnpackedCs
->lpszName
;
216 ClassName
= (PUNICODE_STRING
) UnpackedCs
->lpszClass
;
217 Size
= sizeof(CREATESTRUCTW
) + WindowName
->Length
+ sizeof(WCHAR
);
218 if (IS_ATOM(ClassName
->Buffer
))
220 Size
+= sizeof(WCHAR
) + sizeof(ATOM
);
224 Size
+= sizeof(WCHAR
) + ClassName
->Length
+ sizeof(WCHAR
);
226 PackedCs
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
227 if (NULL
== PackedCs
)
229 DPRINT1("Not enough memory to pack lParam\n");
230 return STATUS_NO_MEMORY
;
232 RtlCopyMemory(PackedCs
, UnpackedCs
, sizeof(CREATESTRUCTW
));
233 CsData
= (PCHAR
) (PackedCs
+ 1);
234 PackedCs
->lpszName
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
235 RtlCopyMemory(CsData
, WindowName
->Buffer
, WindowName
->Length
);
236 CsData
+= WindowName
->Length
;
237 *((WCHAR
*) CsData
) = L
'\0';
238 CsData
+= sizeof(WCHAR
);
239 PackedCs
->lpszClass
= (LPCWSTR
) (CsData
- (PCHAR
) PackedCs
);
240 if (IS_ATOM(ClassName
->Buffer
))
242 *((WCHAR
*) CsData
) = L
'A';
243 CsData
+= sizeof(WCHAR
);
244 *((ATOM
*) CsData
) = (ATOM
)(DWORD_PTR
) ClassName
->Buffer
;
245 CsData
+= sizeof(ATOM
);
249 *((WCHAR
*) CsData
) = L
'S';
250 CsData
+= sizeof(WCHAR
);
251 RtlCopyMemory(CsData
, ClassName
->Buffer
, ClassName
->Length
);
252 CsData
+= ClassName
->Length
;
253 *((WCHAR
*) CsData
) = L
'\0';
254 CsData
+= sizeof(WCHAR
);
256 ASSERT(CsData
== (PCHAR
) PackedCs
+ Size
);
257 *lParamPacked
= (LPARAM
) PackedCs
;
260 return STATUS_SUCCESS
;
264 UnpackParam(LPARAM lParamPacked
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
266 NCCALCSIZE_PARAMS
*UnpackedParams
;
267 NCCALCSIZE_PARAMS
*PackedParams
;
268 PWINDOWPOS UnpackedWindowPos
;
270 if (lParamPacked
== lParam
)
272 return STATUS_SUCCESS
;
275 if (WM_NCCALCSIZE
== Msg
&& wParam
)
277 PackedParams
= (NCCALCSIZE_PARAMS
*) lParamPacked
;
278 UnpackedParams
= (NCCALCSIZE_PARAMS
*) lParam
;
279 UnpackedWindowPos
= UnpackedParams
->lppos
;
280 RtlCopyMemory(UnpackedParams
, PackedParams
, sizeof(NCCALCSIZE_PARAMS
));
281 UnpackedParams
->lppos
= UnpackedWindowPos
;
282 RtlCopyMemory(UnpackedWindowPos
, PackedParams
+ 1, sizeof(WINDOWPOS
));
283 ExFreePool((PVOID
) lParamPacked
);
285 return STATUS_SUCCESS
;
287 else if (WM_CREATE
== Msg
|| WM_NCCREATE
== Msg
)
289 ExFreePool((PVOID
) lParamPacked
);
291 return STATUS_SUCCESS
;
296 return STATUS_INVALID_PARAMETER
;
305 DECLARE_RETURN(BOOL
);
307 DPRINT("Enter NtUserCallMsgFilter\n");
308 UserEnterExclusive();
310 if (co_HOOK_CallHooks( WH_SYSMSGFILTER
, code
, 0, (LPARAM
)msg
))
312 RETURN( co_HOOK_CallHooks( WH_MSGFILTER
, code
, 0, (LPARAM
)msg
));
315 DPRINT("Leave NtUserCallMsgFilter. ret=%i\n", _ret_
);
321 NtUserDispatchMessage(PNTUSERDISPATCHMESSAGEINFO UnsafeMsgInfo
)
324 NTUSERDISPATCHMESSAGEINFO MsgInfo
;
325 LRESULT Result
= TRUE
;
326 DECLARE_RETURN(LRESULT
);
328 DPRINT("Enter NtUserDispatchMessage\n");
329 UserEnterExclusive();
331 Status
= MmCopyFromCaller(&MsgInfo
, UnsafeMsgInfo
, sizeof(NTUSERDISPATCHMESSAGEINFO
));
332 if (! NT_SUCCESS(Status
))
334 SetLastNtError(Status
);
338 /* Process timer messages. */
339 if (WM_TIMER
== MsgInfo
.Msg
.message
&& 0 != MsgInfo
.Msg
.lParam
)
341 LARGE_INTEGER LargeTickCount
;
342 /* FIXME: Call hooks. */
344 /* FIXME: Check for continuing validity of timer. */
346 MsgInfo
.HandledByKernel
= FALSE
;
347 KeQueryTickCount(&LargeTickCount
);
348 MsgInfo
.Proc
= (WNDPROC
) MsgInfo
.Msg
.lParam
;
349 MsgInfo
.Msg
.lParam
= (LPARAM
)LargeTickCount
.u
.LowPart
;
351 else if (NULL
== MsgInfo
.Msg
.hwnd
)
353 MsgInfo
.HandledByKernel
= TRUE
;
358 PWINDOW_OBJECT Window
;
360 /* Get the window object. */
361 Window
= UserGetWindowObject(MsgInfo
.Msg
.hwnd
);
364 MsgInfo
.HandledByKernel
= TRUE
;
369 if (Window
->OwnerThread
!= PsGetCurrentThread())
371 DPRINT1("Window doesn't belong to the calling thread!\n");
372 MsgInfo
.HandledByKernel
= TRUE
;
377 /* FIXME: Call hook procedures. */
379 MsgInfo
.HandledByKernel
= FALSE
;
382 if (Window
->Wnd
->IsSystem
)
384 MsgInfo
.Proc
= (!MsgInfo
.Ansi
? Window
->Wnd
->WndProc
: Window
->Wnd
->WndProcExtra
);
388 MsgInfo
.Ansi
= !Window
->Wnd
->Unicode
;
389 MsgInfo
.Proc
= Window
->Wnd
->WndProc
;
394 Status
= MmCopyToCaller(UnsafeMsgInfo
, &MsgInfo
, sizeof(NTUSERDISPATCHMESSAGEINFO
));
395 if (! NT_SUCCESS(Status
))
397 SetLastNtError(Status
);
404 DPRINT("Leave NtUserDispatchMessage. ret=%i\n", _ret_
);
411 NtUserTranslateMessage(LPMSG lpMsg
,
416 DECLARE_RETURN(BOOL
);
418 DPRINT("Enter NtUserTranslateMessage\n");
419 UserEnterExclusive();
421 Status
= MmCopyFromCaller(&SafeMsg
, lpMsg
, sizeof(MSG
));
422 if(!NT_SUCCESS(Status
))
424 SetLastNtError(Status
);
428 RETURN( IntTranslateKbdMessage(&SafeMsg
, dwhkl
));
431 DPRINT("Leave NtUserTranslateMessage: ret=%i\n",_ret_
);
438 co_IntSendHitTestMessages(PUSER_MESSAGE_QUEUE ThreadQueue
, LPMSG Msg
)
440 if(!Msg
->hwnd
|| ThreadQueue
->CaptureWindow
)
449 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(HTCLIENT
, Msg
->message
));
454 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(Msg
->wParam
, Msg
->message
));
461 case WM_LBUTTONDBLCLK
:
462 case WM_MBUTTONDBLCLK
:
463 case WM_RBUTTONDBLCLK
:
464 case WM_XBUTTONDBLCLK
:
467 PSYSTEM_CURSORINFO CurInfo
;
469 if(!IntGetWindowStationObject(InputWindowStation
))
473 CurInfo
= IntGetSysCursorInfo(InputWindowStation
);
474 wParam
= (WPARAM
)(CurInfo
->ButtonsDown
);
475 ObDereferenceObject(InputWindowStation
);
477 co_IntSendMessage(Msg
->hwnd
, WM_MOUSEMOVE
, wParam
, Msg
->lParam
);
478 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(HTCLIENT
, Msg
->message
));
481 case WM_NCLBUTTONDOWN
:
482 case WM_NCMBUTTONDOWN
:
483 case WM_NCRBUTTONDOWN
:
484 case WM_NCXBUTTONDOWN
:
485 case WM_NCLBUTTONDBLCLK
:
486 case WM_NCMBUTTONDBLCLK
:
487 case WM_NCRBUTTONDBLCLK
:
488 case WM_NCXBUTTONDBLCLK
:
490 co_IntSendMessage(Msg
->hwnd
, WM_NCMOUSEMOVE
, (WPARAM
)Msg
->wParam
, Msg
->lParam
);
491 co_IntSendMessage(Msg
->hwnd
, WM_SETCURSOR
, (WPARAM
)Msg
->hwnd
, MAKELPARAM(Msg
->wParam
, Msg
->message
));
498 co_IntActivateWindowMouse(PUSER_MESSAGE_QUEUE ThreadQueue
, LPMSG Msg
, PWINDOW_OBJECT MsgWindow
,
502 PWINDOW_OBJECT Parent
;
504 ASSERT_REFS_CO(MsgWindow
);
506 if(*HitTest
== (USHORT
)HTTRANSPARENT
)
508 /* eat the message, search again! */
512 Parent
= IntGetParent(MsgWindow
);//fixme: deref retval?
513 /* fixme: abort if no parent ? */
514 Result
= co_IntSendMessage(MsgWindow
->hSelf
,
516 (WPARAM
) (Parent
? Parent
->hSelf
: NULL
),
517 (LPARAM
)MAKELONG(*HitTest
, Msg
->message
)
522 case MA_NOACTIVATEANDEAT
:
526 case MA_ACTIVATEANDEAT
:
527 co_IntMouseActivateWindow(MsgWindow
);
531 co_IntMouseActivateWindow(MsgWindow
);
539 co_IntTranslateMouseMessage(PUSER_MESSAGE_QUEUE ThreadQueue
, LPMSG Msg
, USHORT
*HitTest
, BOOL Remove
)
541 PWINDOW_OBJECT Window
;
542 USER_REFERENCE_ENTRY Ref
, DesktopRef
;
544 if(!(Window
= UserGetWindowObject(Msg
->hwnd
)))
546 /* let's just eat the message?! */
550 UserRefObjectCo(Window
, &Ref
);
552 if(ThreadQueue
== Window
->MessageQueue
&&
553 ThreadQueue
->CaptureWindow
!= Window
->hSelf
)
555 /* only send WM_NCHITTEST messages if we're not capturing the window! */
556 *HitTest
= co_IntSendMessage(Window
->hSelf
, WM_NCHITTEST
, 0,
557 MAKELONG(Msg
->pt
.x
, Msg
->pt
.y
));
559 if(*HitTest
== (USHORT
)HTTRANSPARENT
)
561 PWINDOW_OBJECT DesktopWindow
;
562 HWND hDesktop
= IntGetDesktopWindow();
564 if((DesktopWindow
= UserGetWindowObject(hDesktop
)))
568 UserRefObjectCo(DesktopWindow
, &DesktopRef
);
570 co_WinPosWindowFromPoint(DesktopWindow
, Window
->MessageQueue
, &Msg
->pt
, &Wnd
);
575 /* post the message to the other window */
576 Msg
->hwnd
= Wnd
->hSelf
;
577 if(!(Wnd
->Status
& WINDOWSTATUS_DESTROYING
))
579 MsqPostMessage(Wnd
->MessageQueue
, Msg
, FALSE
,
580 Msg
->message
== WM_MOUSEMOVE
? QS_MOUSEMOVE
:
584 /* eat the message */
585 UserDerefObject(Wnd
);
586 UserDerefObjectCo(DesktopWindow
);
587 UserDerefObjectCo(Window
);
590 UserDerefObject(Wnd
);
593 UserDerefObjectCo(DesktopWindow
);
602 if(IS_BTN_MESSAGE(Msg
->message
, DOWN
))
604 /* generate double click messages, if necessary */
605 if ((((*HitTest
) != HTCLIENT
) ||
606 (Window
->Wnd
->Class
->Style
& CS_DBLCLKS
)) &&
607 MsqIsDblClk(Msg
, Remove
))
609 Msg
->message
+= WM_LBUTTONDBLCLK
- WM_LBUTTONDOWN
;
613 if(Msg
->message
!= WM_MOUSEWHEEL
)
616 if ((*HitTest
) != HTCLIENT
)
618 Msg
->message
+= WM_NCMOUSEMOVE
- WM_MOUSEMOVE
;
619 if((Msg
->message
== WM_NCRBUTTONUP
) &&
620 (((*HitTest
) == HTCAPTION
) || ((*HitTest
) == HTSYSMENU
)))
622 Msg
->message
= WM_CONTEXTMENU
;
623 Msg
->wParam
= (WPARAM
)Window
->hSelf
;
627 Msg
->wParam
= *HitTest
;
629 Msg
->lParam
= MAKELONG(Msg
->pt
.x
, Msg
->pt
.y
);
631 else if(ThreadQueue
->MoveSize
== NULL
&&
632 ThreadQueue
->MenuOwner
== NULL
)
634 /* NOTE: Msg->pt should remain in screen coordinates. -- FiN */
635 Msg
->lParam
= MAKELONG(
636 Msg
->pt
.x
- (WORD
)Window
->Wnd
->ClientRect
.left
,
637 Msg
->pt
.y
- (WORD
)Window
->Wnd
->ClientRect
.top
);
641 UserDerefObjectCo(Window
);
647 * Internal version of PeekMessage() doing all the work
650 co_IntPeekMessage(PUSER_MESSAGE Msg
,
656 LARGE_INTEGER LargeTickCount
;
657 PUSER_MESSAGE_QUEUE ThreadQueue
;
658 PUSER_MESSAGE Message
;
659 BOOL Present
, RemoveMessages
;
660 USER_REFERENCE_ENTRY Ref
;
663 /* The queues and order in which they are checked are documented in the MSDN
664 article on GetMessage() */
666 ThreadQueue
= (PUSER_MESSAGE_QUEUE
)PsGetCurrentThreadWin32Thread()->MessageQueue
;
668 /* Inspect RemoveMsg flags */
669 /* FIXME: The only flag we process is PM_REMOVE - processing of others must still be implemented */
670 RemoveMessages
= RemoveMsg
& PM_REMOVE
;
676 KeQueryTickCount(&LargeTickCount
);
677 ThreadQueue
->LastMsgRead
= LargeTickCount
.u
.LowPart
;
679 /* Dispatch sent messages here. */
680 while (co_MsqDispatchOneSentMessage(ThreadQueue
))
683 /* Now look for a quit message. */
685 if (ThreadQueue
->QuitPosted
)
687 /* According to the PSDK, WM_QUIT messages are always returned, regardless
688 of the filter specified */
689 Msg
->Msg
.hwnd
= NULL
;
690 Msg
->Msg
.message
= WM_QUIT
;
691 Msg
->Msg
.wParam
= ThreadQueue
->QuitExitCode
;
693 Msg
->FreeLParam
= FALSE
;
696 ThreadQueue
->QuitPosted
= FALSE
;
701 /* Now check for normal messages. */
702 Present
= co_MsqFindMessage(ThreadQueue
,
711 RtlCopyMemory(Msg
, Message
, sizeof(USER_MESSAGE
));
714 MsqDestroyMessage(Message
);
719 /* Check for hardware events. */
720 Present
= co_MsqFindMessage(ThreadQueue
,
729 RtlCopyMemory(Msg
, Message
, sizeof(USER_MESSAGE
));
732 MsqDestroyMessage(Message
);
737 /* Check for sent messages again. */
738 while (co_MsqDispatchOneSentMessage(ThreadQueue
))
741 /* Check for paint messages. */
742 if (IntGetPaintMessage(hWnd
, MsgFilterMin
, MsgFilterMax
, PsGetCurrentThreadWin32Thread(), &Msg
->Msg
, RemoveMessages
))
744 Msg
->FreeLParam
= FALSE
;
748 /* Check for WM_(SYS)TIMER messages */
749 Present
= MsqGetTimerMessage(ThreadQueue
, hWnd
, MsgFilterMin
, MsgFilterMax
,
750 &Msg
->Msg
, RemoveMessages
);
753 Msg
->FreeLParam
= FALSE
;
763 PWINDOW_OBJECT MsgWindow
= NULL
;
765 if(Msg
->Msg
.hwnd
&& (MsgWindow
= UserGetWindowObject(Msg
->Msg
.hwnd
)) &&
766 Msg
->Msg
.message
>= WM_MOUSEFIRST
&& Msg
->Msg
.message
<= WM_MOUSELAST
)
770 UserRefObjectCo(MsgWindow
, &Ref
);
772 if(co_IntTranslateMouseMessage(ThreadQueue
, &Msg
->Msg
, &HitTest
, TRUE
))
773 /* FIXME - check message filter again, if the message doesn't match anymore,
776 UserDerefObjectCo(MsgWindow
);
777 /* eat the message, search again */
781 if(ThreadQueue
->CaptureWindow
== NULL
)
783 co_IntSendHitTestMessages(ThreadQueue
, &Msg
->Msg
);
784 if((Msg
->Msg
.message
!= WM_MOUSEMOVE
&& Msg
->Msg
.message
!= WM_NCMOUSEMOVE
) &&
785 IS_BTN_MESSAGE(Msg
->Msg
.message
, DOWN
) &&
786 co_IntActivateWindowMouse(ThreadQueue
, &Msg
->Msg
, MsgWindow
, &HitTest
))
788 UserDerefObjectCo(MsgWindow
);
789 /* eat the message, search again */
794 UserDerefObjectCo(MsgWindow
);
798 co_IntSendHitTestMessages(ThreadQueue
, &Msg
->Msg
);
803 // UserDerefObject(MsgWindow);
809 if((Msg
->Msg
.hwnd
&& Msg
->Msg
.message
>= WM_MOUSEFIRST
&& Msg
->Msg
.message
<= WM_MOUSELAST
) &&
810 co_IntTranslateMouseMessage(ThreadQueue
, &Msg
->Msg
, &HitTest
, FALSE
))
811 /* FIXME - check message filter again, if the message doesn't match anymore,
814 /* eat the message, search again */
825 NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo
,
833 NTUSERGETMESSAGEINFO Info
;
834 PWINDOW_OBJECT Window
;
835 PMSGMEMORY MsgMemoryEntry
;
839 DECLARE_RETURN(BOOL
);
841 DPRINT("Enter NtUserPeekMessage\n");
842 UserEnterExclusive();
845 if (hWnd
&& hWnd
!= INVALID_HANDLE_VALUE
)
847 if (!(Window
= UserGetWindowObject(hWnd
)))
853 if (MsgFilterMax
< MsgFilterMin
)
859 Present
= co_IntPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, RemoveMsg
);
863 /* See if this message type is present in the table */
864 MsgMemoryEntry
= FindMsgMemory(Info
.Msg
.message
);
865 if (NULL
== MsgMemoryEntry
)
867 /* Not present, no copying needed */
872 /* Determine required size */
873 Size
= MsgMemorySize(MsgMemoryEntry
, Info
.Msg
.wParam
,
875 /* Allocate required amount of user-mode memory */
876 Info
.LParamSize
= Size
;
878 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem
, 0,
879 &Info
.LParamSize
, MEM_COMMIT
, PAGE_READWRITE
);
880 if (! NT_SUCCESS(Status
))
882 SetLastNtError(Status
);
885 /* Transfer lParam data to user-mode mem */
886 Status
= MmCopyToCaller(UserMem
, (PVOID
) Info
.Msg
.lParam
, Size
);
887 if (! NT_SUCCESS(Status
))
889 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &UserMem
,
890 &Info
.LParamSize
, MEM_RELEASE
);
891 SetLastNtError(Status
);
894 Info
.Msg
.lParam
= (LPARAM
) UserMem
;
896 if (RemoveMsg
&& Msg
.FreeLParam
&& 0 != Msg
.Msg
.lParam
)
898 ExFreePool((void *) Msg
.Msg
.lParam
);
900 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERGETMESSAGEINFO
));
901 if (! NT_SUCCESS(Status
))
903 SetLastNtError(Status
);
911 DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_
);
917 co_IntWaitMessage(HWND Wnd
,
921 PUSER_MESSAGE_QUEUE ThreadQueue
;
925 ThreadQueue
= (PUSER_MESSAGE_QUEUE
)PsGetCurrentThreadWin32Thread()->MessageQueue
;
929 if (co_IntPeekMessage(&Msg
, Wnd
, MsgFilterMin
, MsgFilterMax
, PM_NOREMOVE
))
934 /* Nothing found. Wait for new messages. */
935 Status
= co_MsqWaitForNewMessages(ThreadQueue
, Wnd
, MsgFilterMin
, MsgFilterMax
);
937 while ((STATUS_WAIT_0
<= Status
&& Status
<= STATUS_WAIT_63
) || STATUS_TIMEOUT
== Status
);
939 SetLastNtError(Status
);
945 NtUserGetMessage(PNTUSERGETMESSAGEINFO UnsafeInfo
,
950 * FUNCTION: Get a message from the calling thread's message queue.
952 * UnsafeMsg - Pointer to the structure which receives the returned message.
953 * Wnd - Window whose messages are to be retrieved.
954 * MsgFilterMin - Integer value of the lowest message value to be
956 * MsgFilterMax - Integer value of the highest message value to be
961 NTUSERGETMESSAGEINFO Info
;
963 PWINDOW_OBJECT Window
= NULL
;
964 PMSGMEMORY MsgMemoryEntry
;
968 DECLARE_RETURN(BOOL
);
969 // USER_REFERENCE_ENTRY Ref;
971 DPRINT("Enter NtUserGetMessage\n");
972 UserEnterExclusive();
975 if (hWnd
&& !(Window
= UserGetWindowObject(hWnd
)))
980 // if (Window) UserRefObjectCo(Window, &Ref);
982 if (MsgFilterMax
< MsgFilterMin
)
990 GotMessage
= co_IntPeekMessage(&Msg
, hWnd
, MsgFilterMin
, MsgFilterMax
, PM_REMOVE
);
994 /* See if this message type is present in the table */
995 MsgMemoryEntry
= FindMsgMemory(Info
.Msg
.message
);
996 if (NULL
== MsgMemoryEntry
)
998 /* Not present, no copying needed */
1003 /* Determine required size */
1004 Size
= MsgMemorySize(MsgMemoryEntry
, Info
.Msg
.wParam
,
1006 /* Allocate required amount of user-mode memory */
1007 Info
.LParamSize
= Size
;
1009 Status
= ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem
, 0,
1010 &Info
.LParamSize
, MEM_COMMIT
, PAGE_READWRITE
);
1012 if (! NT_SUCCESS(Status
))
1014 SetLastNtError(Status
);
1017 /* Transfer lParam data to user-mode mem */
1018 Status
= MmCopyToCaller(UserMem
, (PVOID
) Info
.Msg
.lParam
, Size
);
1019 if (! NT_SUCCESS(Status
))
1021 ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID
*) &UserMem
,
1022 &Info
.LParamSize
, MEM_DECOMMIT
);
1023 SetLastNtError(Status
);
1026 Info
.Msg
.lParam
= (LPARAM
) UserMem
;
1028 if (Msg
.FreeLParam
&& 0 != Msg
.Msg
.lParam
)
1030 ExFreePool((void *) Msg
.Msg
.lParam
);
1032 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERGETMESSAGEINFO
));
1033 if (! NT_SUCCESS(Status
))
1035 SetLastNtError(Status
);
1039 else if (! co_IntWaitMessage(hWnd
, MsgFilterMin
, MsgFilterMax
))
1044 while (! GotMessage
);
1046 RETURN( WM_QUIT
!= Info
.Msg
.message
);
1049 // if (Window) UserDerefObjectCo(Window);
1051 DPRINT("Leave NtUserGetMessage\n");
1072 static NTSTATUS FASTCALL
1073 CopyMsgToKernelMem(MSG
*KernelModeMsg
, MSG
*UserModeMsg
, PMSGMEMORY MsgMemoryEntry
)
1080 *KernelModeMsg
= *UserModeMsg
;
1082 /* See if this message type is present in the table */
1083 if (NULL
== MsgMemoryEntry
)
1085 /* Not present, no copying needed */
1086 return STATUS_SUCCESS
;
1089 /* Determine required size */
1090 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
1094 /* Allocate kernel mem */
1095 KernelMem
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_MSG
);
1096 if (NULL
== KernelMem
)
1098 DPRINT1("Not enough memory to copy message to kernel mem\n");
1099 return STATUS_NO_MEMORY
;
1101 KernelModeMsg
->lParam
= (LPARAM
) KernelMem
;
1103 /* Copy data if required */
1104 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_READ
))
1106 Status
= MmCopyFromCaller(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
1107 if (! NT_SUCCESS(Status
))
1109 DPRINT1("Failed to copy message to kernel: invalid usermode buffer\n");
1110 ExFreePool(KernelMem
);
1116 /* Make sure we don't pass any secrets to usermode */
1117 RtlZeroMemory(KernelMem
, Size
);
1122 KernelModeMsg
->lParam
= 0;
1125 return STATUS_SUCCESS
;
1128 static NTSTATUS FASTCALL
1129 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
1132 PMSGMEMORY MsgMemoryEntry
;
1135 /* See if this message type is present in the table */
1136 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
1137 if (NULL
== MsgMemoryEntry
)
1139 /* Not present, no copying needed */
1140 return STATUS_SUCCESS
;
1143 /* Determine required size */
1144 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
1148 /* Copy data if required */
1149 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
1151 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
1152 if (! NT_SUCCESS(Status
))
1154 DPRINT1("Failed to copy message from kernel: invalid usermode buffer\n");
1155 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
1160 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
1163 return STATUS_SUCCESS
;
1167 UserPostMessage(HWND Wnd
,
1172 MSG UserModeMsg
, KernelModeMsg
;
1173 LARGE_INTEGER LargeTickCount
;
1175 PMSGMEMORY MsgMemoryEntry
;
1179 MsqPostQuitMessage(PsGetCurrentThreadWin32Thread()->MessageQueue
, wParam
);
1181 else if (Wnd
== HWND_BROADCAST
)
1184 PWINDOW_OBJECT DesktopWindow
;
1187 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1188 List
= IntWinListChildren(DesktopWindow
);
1192 for (i
= 0; List
[i
]; i
++)
1193 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1199 PWINDOW_OBJECT Window
;
1201 Window
= UserGetWindowObject(Wnd
);
1206 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
1208 DPRINT1("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd
);
1209 /* FIXME - last error code? */
1213 UserModeMsg
.hwnd
= Wnd
;
1214 UserModeMsg
.message
= Msg
;
1215 UserModeMsg
.wParam
= wParam
;
1216 UserModeMsg
.lParam
= lParam
;
1217 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1218 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1219 if (! NT_SUCCESS(Status
))
1221 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1224 IntGetCursorLocation(PsGetCurrentThreadWin32Thread()->Desktop
->WindowStation
,
1226 KeQueryTickCount(&LargeTickCount
);
1227 KernelModeMsg
.time
= MsqCalculateMessageTime(&LargeTickCount
);
1228 MsqPostMessage(Window
->MessageQueue
, &KernelModeMsg
,
1229 NULL
!= MsgMemoryEntry
&& 0 != KernelModeMsg
.lParam
,
1238 NtUserPostMessage(HWND hWnd
,
1243 DECLARE_RETURN(BOOL
);
1245 DPRINT("Enter NtUserPostMessage\n");
1246 UserEnterExclusive();
1248 RETURN(UserPostMessage(hWnd
, Msg
, wParam
, lParam
));
1251 DPRINT("Leave NtUserPostMessage, ret=%i\n",_ret_
);
1259 NtUserPostThreadMessage(DWORD idThread
,
1264 MSG UserModeMsg
, KernelModeMsg
;
1268 PMSGMEMORY MsgMemoryEntry
;
1269 DECLARE_RETURN(BOOL
);
1271 DPRINT("Enter NtUserPostThreadMessage\n");
1272 UserEnterExclusive();
1274 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
1276 if( Status
== STATUS_SUCCESS
)
1278 pThread
= (PW32THREAD
)peThread
->Tcb
.Win32Thread
;
1279 if( !pThread
|| !pThread
->MessageQueue
)
1281 ObDereferenceObject( peThread
);
1285 UserModeMsg
.hwnd
= NULL
;
1286 UserModeMsg
.message
= Msg
;
1287 UserModeMsg
.wParam
= wParam
;
1288 UserModeMsg
.lParam
= lParam
;
1289 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1290 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1291 if (! NT_SUCCESS(Status
))
1293 ObDereferenceObject( peThread
);
1294 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1297 MsqPostMessage(pThread
->MessageQueue
, &KernelModeMsg
,
1298 NULL
!= MsgMemoryEntry
&& 0 != KernelModeMsg
.lParam
,
1300 ObDereferenceObject( peThread
);
1305 SetLastNtError( Status
);
1310 DPRINT("Leave NtUserPostThreadMessage, ret=%i\n",_ret_
);
1316 NtUserQuerySendMessage(DWORD Unknown0
)
1324 co_IntSendMessage(HWND hWnd
,
1329 ULONG_PTR Result
= 0;
1330 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1332 return (LRESULT
)Result
;
1339 co_IntSendMessageTimeoutSingle(HWND hWnd
,
1349 PWINDOW_OBJECT Window
= NULL
;
1350 PMSGMEMORY MsgMemoryEntry
;
1351 INT lParamBufferSize
;
1352 LPARAM lParamPacked
;
1353 PW32THREAD Win32Thread
;
1354 DECLARE_RETURN(LRESULT
);
1355 USER_REFERENCE_ENTRY Ref
;
1357 /* FIXME: Call hooks. */
1358 if (!(Window
= UserGetWindowObject(hWnd
)))
1363 UserRefObjectCo(Window
, &Ref
);
1365 Win32Thread
= PsGetCurrentThreadWin32Thread();
1367 if (NULL
!= Win32Thread
&&
1368 Window
->MessageQueue
== Win32Thread
->MessageQueue
)
1370 if (Win32Thread
->IsExiting
)
1372 /* Never send messages to exiting threads */
1376 /* See if this message type is present in the table */
1377 MsgMemoryEntry
= FindMsgMemory(Msg
);
1378 if (NULL
== MsgMemoryEntry
)
1380 lParamBufferSize
= -1;
1384 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1387 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
)))
1389 DPRINT1("Failed to pack message parameters\n");
1393 Result
= (ULONG_PTR
)co_IntCallWindowProc(Window
->Wnd
->WndProc
, !Window
->Wnd
->Unicode
, hWnd
, Msg
, wParam
,
1394 lParamPacked
,lParamBufferSize
);
1401 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
)))
1403 DPRINT1("Failed to unpack message parameters\n");
1410 if(uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->MessageQueue
))
1412 /* FIXME - Set a LastError? */
1416 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
1418 /* FIXME - last error? */
1419 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1423 Status
= co_MsqSendMessage(Window
->MessageQueue
, hWnd
, Msg
, wParam
, lParam
,
1424 uTimeout
, (uFlags
& SMTO_BLOCK
), FALSE
, uResult
);
1427 if (STATUS_TIMEOUT
== Status
)
1429 /* MSDN says GetLastError() should return 0 after timeout */
1430 SetLastWin32Error(0);
1433 else if (! NT_SUCCESS(Status
))
1435 SetLastNtError(Status
);
1442 if (Window
) UserDerefObjectCo(Window
);
1447 co_IntSendMessageTimeout(HWND hWnd
,
1455 PWINDOW_OBJECT DesktopWindow
;
1459 if (HWND_BROADCAST
!= hWnd
)
1461 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1464 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1465 if (NULL
== DesktopWindow
)
1467 SetLastWin32Error(ERROR_INTERNAL_ERROR
);
1471 Children
= IntWinListChildren(DesktopWindow
);
1472 if (NULL
== Children
)
1477 for (Child
= Children
; NULL
!= *Child
; Child
++)
1479 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1482 ExFreePool(Children
);
1484 return (LRESULT
) TRUE
;
1488 /* This function posts a message if the destination's message queue belongs to
1489 another thread, otherwise it sends the message. It does not support broadcast
1492 co_IntPostOrSendMessage(HWND hWnd
,
1498 PWINDOW_OBJECT Window
;
1500 if(hWnd
== HWND_BROADCAST
)
1505 if(!(Window
= UserGetWindowObject(hWnd
)))
1510 if(Window
->MessageQueue
!= PsGetCurrentThreadWin32Thread()->MessageQueue
)
1512 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1516 if(!co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1522 return (LRESULT
)Result
;
1526 co_IntDoSendMessage(HWND hWnd
,
1531 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1533 LRESULT Result
= TRUE
;
1535 PWINDOW_OBJECT Window
;
1536 NTUSERSENDMESSAGEINFO Info
;
1539 PMSGMEMORY MsgMemoryEntry
;
1541 RtlZeroMemory(&Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1543 /* FIXME: Call hooks. */
1544 if (HWND_BROADCAST
!= hWnd
)
1546 Window
= UserGetWindowObject(hWnd
);
1549 /* Tell usermode to not touch this one */
1550 Info
.HandledByKernel
= TRUE
;
1551 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1556 /* FIXME: Check for an exiting window. */
1558 /* See if the current thread can handle the message */
1559 if (HWND_BROADCAST
!= hWnd
&& NULL
!= PsGetCurrentThreadWin32Thread() &&
1560 Window
->MessageQueue
== PsGetCurrentThreadWin32Thread()->MessageQueue
)
1562 /* Gather the information usermode needs to call the window proc directly */
1563 Info
.HandledByKernel
= FALSE
;
1565 Status
= MmCopyFromCaller(&(Info
.Ansi
), &(UnsafeInfo
->Ansi
),
1567 if (! NT_SUCCESS(Status
))
1569 Info
.Ansi
= ! Window
->Wnd
->Unicode
;
1572 if (Window
->Wnd
->IsSystem
)
1574 Info
.Proc
= (!Info
.Ansi
? Window
->Wnd
->WndProc
: Window
->Wnd
->WndProcExtra
);
1578 Info
.Ansi
= !Window
->Wnd
->Unicode
;
1579 Info
.Proc
= Window
->Wnd
->WndProc
;
1584 /* Must be handled by other thread */
1585 // if (HWND_BROADCAST != hWnd)
1587 // UserDerefObject(Window);
1589 Info
.HandledByKernel
= TRUE
;
1590 UserModeMsg
.hwnd
= hWnd
;
1591 UserModeMsg
.message
= Msg
;
1592 UserModeMsg
.wParam
= wParam
;
1593 UserModeMsg
.lParam
= lParam
;
1594 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1595 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1596 if (! NT_SUCCESS(Status
))
1598 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1599 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1600 return (dsm
? 0 : -1);
1604 Result
= co_IntSendMessage(KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1605 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
);
1609 Result
= co_IntSendMessageTimeout(KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1610 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
,
1611 dsm
->uFlags
, dsm
->uTimeout
, &dsm
->Result
);
1613 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1614 if (! NT_SUCCESS(Status
))
1616 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1617 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1618 return(dsm
? 0 : -1);
1622 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1623 if (! NT_SUCCESS(Status
))
1625 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1628 return (LRESULT
)Result
;
1632 NtUserSendMessageTimeout(HWND hWnd
,
1639 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1643 DECLARE_RETURN(BOOL
);
1645 DPRINT("Enter NtUserSendMessageTimeout\n");
1646 UserEnterExclusive();
1648 dsm
.uFlags
= uFlags
;
1649 dsm
.uTimeout
= uTimeout
;
1650 Result
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, &dsm
, UnsafeInfo
);
1651 if(uResult
!= NULL
&& Result
!= 0)
1655 Status
= MmCopyToCaller(uResult
, &dsm
.Result
, sizeof(ULONG_PTR
));
1656 if(!NT_SUCCESS(Status
))
1658 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1665 DPRINT("Leave NtUserSendMessageTimeout, ret=%i\n",_ret_
);
1671 NtUserSendMessage(HWND Wnd
,
1675 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1677 DECLARE_RETURN(BOOL
);
1679 DPRINT("Enter NtUserSendMessage\n");
1680 UserEnterExclusive();
1682 RETURN(co_IntDoSendMessage(Wnd
, Msg
, wParam
, lParam
, NULL
, UnsafeInfo
));
1685 DPRINT("Leave NtUserSendMessage, ret=%i\n",_ret_
);
1691 NtUserSendMessageCallback(HWND hWnd
,
1695 SENDASYNCPROC lpCallBack
,
1705 UserSendNotifyMessage(HWND hWnd
,
1711 // Basicly the same as IntPostOrSendMessage
1712 if (hWnd
== HWND_BROADCAST
) //Handle Broadcast
1715 PWINDOW_OBJECT DesktopWindow
;
1718 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1719 List
= IntWinListChildren(DesktopWindow
);
1723 for (i
= 0; List
[i
]; i
++)
1725 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1733 PWINDOW_OBJECT Window
;
1737 PMSGMEMORY MsgMemoryEntry
;
1739 if(!(Window
= UserGetWindowObject(hWnd
))) return FALSE
;
1741 if(Window
->MessageQueue
!= PsGetCurrentThreadWin32Thread()->MessageQueue
)
1742 { // Send message w/o waiting for it.
1743 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1746 { // Handle message and callback.
1747 UserModeMsg
.hwnd
= hWnd
;
1748 UserModeMsg
.message
= Msg
;
1749 UserModeMsg
.wParam
= wParam
;
1750 UserModeMsg
.lParam
= lParam
;
1751 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1752 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1753 if (! NT_SUCCESS(Status
))
1755 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1758 Result
= co_IntSendMessageTimeoutSingle(
1759 KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1760 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
,
1761 SMTO_NORMAL
, 0, &PResult
);
1763 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1764 if (! NT_SUCCESS(Status
))
1766 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1776 NtUserSendNotifyMessage(HWND hWnd
,
1781 DECLARE_RETURN(BOOL
);
1783 DPRINT("EnterNtUserSendNotifyMessage\n");
1784 UserEnterExclusive();
1786 RETURN(UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
));
1789 DPRINT("Leave NtUserSendNotifyMessage, ret=%i\n",_ret_
);
1797 NtUserWaitMessage(VOID
)
1799 DECLARE_RETURN(BOOL
);
1801 DPRINT("EnterNtUserWaitMessage\n");
1802 UserEnterExclusive();
1804 RETURN(co_IntWaitMessage(NULL
, 0, 0));
1807 DPRINT("Leave NtUserWaitMessage, ret=%i\n",_ret_
);
1813 NtUserGetQueueStatus(BOOL ClearChanges
)
1815 PUSER_MESSAGE_QUEUE Queue
;
1817 DECLARE_RETURN(DWORD
);
1819 DPRINT("Enter NtUserGetQueueStatus\n");
1820 UserEnterExclusive();
1822 Queue
= PsGetCurrentThreadWin32Thread()->MessageQueue
;
1824 Result
= MAKELONG(Queue
->QueueBits
, Queue
->ChangedBits
);
1827 Queue
->ChangedBits
= 0;
1833 DPRINT("Leave NtUserGetQueueStatus, ret=%i\n",_ret_
);
1839 IntInitMessagePumpHook()
1841 ((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->MessagePumpHookValue
++;
1846 IntUninitMessagePumpHook()
1848 if (((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->MessagePumpHookValue
<= 0)
1852 ((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->MessagePumpHookValue
--;