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
->IsSystem
)
384 MsgInfo
.Proc
= (!MsgInfo
.Ansi
? Window
->WndProc
: Window
->WndProcExtra
);
388 MsgInfo
.Ansi
= !Window
->Unicode
;
389 MsgInfo
.Proc
= Window
->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
->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
->ClientRect
.left
,
637 Msg
->pt
.y
- (WORD
)Window
->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_DECOMMIT
);
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
))
1107 DPRINT1("Copy message to kernel from the User! %x from %x\n", KernelMem
, UserModeMsg
->lParam
);
1108 RtlCopyMemory(KernelMem
, (PVOID
) UserModeMsg
->lParam
, Size
);
1109 Status
= STATUS_SUCCESS
;
1112 // Status = MmCopyFromCaller(KernelMem, (PVOID) UserModeMsg->lParam, Size);
1113 // if (! NT_SUCCESS(Status))
1115 // DPRINT1("Failed to copy message to kernel: invalid usermode buffer\n");
1116 // ExFreePool(KernelMem);
1122 /* Make sure we don't pass any secrets to usermode */
1123 RtlZeroMemory(KernelMem
, Size
);
1128 KernelModeMsg
->lParam
= 0;
1131 return STATUS_SUCCESS
;
1134 static NTSTATUS FASTCALL
1135 CopyMsgToUserMem(MSG
*UserModeMsg
, MSG
*KernelModeMsg
)
1138 PMSGMEMORY MsgMemoryEntry
;
1141 /* See if this message type is present in the table */
1142 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
->message
);
1143 if (NULL
== MsgMemoryEntry
)
1145 /* Not present, no copying needed */
1146 return STATUS_SUCCESS
;
1149 /* Determine required size */
1150 Size
= MsgMemorySize(MsgMemoryEntry
, UserModeMsg
->wParam
, UserModeMsg
->lParam
);
1154 /* Copy data if required */
1155 if (0 != (MsgMemoryEntry
->Flags
& MMS_FLAG_WRITE
))
1157 Status
= MmCopyToCaller((PVOID
) UserModeMsg
->lParam
, (PVOID
) KernelModeMsg
->lParam
, Size
);
1158 if (! NT_SUCCESS(Status
))
1160 DPRINT1("Failed to copy message from kernel: invalid usermode buffer\n");
1161 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
1166 ExFreePool((PVOID
) KernelModeMsg
->lParam
);
1169 return STATUS_SUCCESS
;
1173 UserPostMessage(HWND Wnd
,
1178 MSG UserModeMsg
, KernelModeMsg
;
1179 LARGE_INTEGER LargeTickCount
;
1181 PMSGMEMORY MsgMemoryEntry
;
1185 MsqPostQuitMessage(PsGetCurrentThreadWin32Thread()->MessageQueue
, wParam
);
1187 else if (Wnd
== HWND_BROADCAST
)
1190 PWINDOW_OBJECT DesktopWindow
;
1193 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1194 List
= IntWinListChildren(DesktopWindow
);
1198 for (i
= 0; List
[i
]; i
++)
1199 UserPostMessage(List
[i
], Msg
, wParam
, lParam
);
1205 PWINDOW_OBJECT Window
;
1207 Window
= UserGetWindowObject(Wnd
);
1212 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
1214 DPRINT1("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd
);
1215 /* FIXME - last error code? */
1219 UserModeMsg
.hwnd
= Wnd
;
1220 UserModeMsg
.message
= Msg
;
1221 UserModeMsg
.wParam
= wParam
;
1222 UserModeMsg
.lParam
= lParam
;
1223 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1224 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1225 if (! NT_SUCCESS(Status
))
1227 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1230 IntGetCursorLocation(PsGetCurrentThreadWin32Thread()->Desktop
->WindowStation
,
1232 KeQueryTickCount(&LargeTickCount
);
1233 KernelModeMsg
.time
= LargeTickCount
.u
.LowPart
;
1234 MsqPostMessage(Window
->MessageQueue
, &KernelModeMsg
,
1235 NULL
!= MsgMemoryEntry
&& 0 != KernelModeMsg
.lParam
,
1244 NtUserPostMessage(HWND hWnd
,
1249 DECLARE_RETURN(BOOL
);
1251 DPRINT("Enter NtUserPostMessage\n");
1252 UserEnterExclusive();
1254 RETURN(UserPostMessage(hWnd
, Msg
, wParam
, lParam
));
1257 DPRINT("Leave NtUserPostMessage, ret=%i\n",_ret_
);
1265 NtUserPostThreadMessage(DWORD idThread
,
1270 MSG UserModeMsg
, KernelModeMsg
;
1274 PMSGMEMORY MsgMemoryEntry
;
1275 DECLARE_RETURN(BOOL
);
1277 DPRINT("Enter NtUserPostThreadMessage\n");
1278 UserEnterExclusive();
1280 Status
= PsLookupThreadByThreadId((HANDLE
)idThread
,&peThread
);
1282 if( Status
== STATUS_SUCCESS
)
1284 pThread
= (PW32THREAD
)peThread
->Tcb
.Win32Thread
;
1285 if( !pThread
|| !pThread
->MessageQueue
)
1287 ObDereferenceObject( peThread
);
1291 UserModeMsg
.hwnd
= NULL
;
1292 UserModeMsg
.message
= Msg
;
1293 UserModeMsg
.wParam
= wParam
;
1294 UserModeMsg
.lParam
= lParam
;
1295 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1296 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1297 if (! NT_SUCCESS(Status
))
1299 ObDereferenceObject( peThread
);
1300 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1303 MsqPostMessage(pThread
->MessageQueue
, &KernelModeMsg
,
1304 NULL
!= MsgMemoryEntry
&& 0 != KernelModeMsg
.lParam
,
1306 ObDereferenceObject( peThread
);
1311 SetLastNtError( Status
);
1316 DPRINT("Leave NtUserPostThreadMessage, ret=%i\n",_ret_
);
1322 NtUserQuerySendMessage(DWORD Unknown0
)
1330 co_IntSendMessage(HWND hWnd
,
1335 ULONG_PTR Result
= 0;
1336 if(co_IntSendMessageTimeout(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1338 return (LRESULT
)Result
;
1345 co_IntSendMessageTimeoutSingle(HWND hWnd
,
1355 PWINDOW_OBJECT Window
= NULL
;
1356 PMSGMEMORY MsgMemoryEntry
;
1357 INT lParamBufferSize
;
1358 LPARAM lParamPacked
;
1359 PW32THREAD Win32Thread
;
1360 DECLARE_RETURN(LRESULT
);
1361 USER_REFERENCE_ENTRY Ref
;
1363 /* FIXME: Call hooks. */
1364 if (!(Window
= UserGetWindowObject(hWnd
)))
1369 UserRefObjectCo(Window
, &Ref
);
1371 Win32Thread
= PsGetCurrentThreadWin32Thread();
1373 if (NULL
!= Win32Thread
&&
1374 Window
->MessageQueue
== Win32Thread
->MessageQueue
)
1376 if (Win32Thread
->IsExiting
)
1378 /* Never send messages to exiting threads */
1382 /* See if this message type is present in the table */
1383 MsgMemoryEntry
= FindMsgMemory(Msg
);
1384 if (NULL
== MsgMemoryEntry
)
1386 lParamBufferSize
= -1;
1390 lParamBufferSize
= MsgMemorySize(MsgMemoryEntry
, wParam
, lParam
);
1393 if (! NT_SUCCESS(PackParam(&lParamPacked
, Msg
, wParam
, lParam
)))
1395 DPRINT1("Failed to pack message parameters\n");
1399 Result
= (ULONG_PTR
)co_IntCallWindowProc(Window
->WndProc
, !Window
->Unicode
, hWnd
, Msg
, wParam
,
1400 lParamPacked
,lParamBufferSize
);
1407 if (! NT_SUCCESS(UnpackParam(lParamPacked
, Msg
, wParam
, lParam
)))
1409 DPRINT1("Failed to unpack message parameters\n");
1416 if(uFlags
& SMTO_ABORTIFHUNG
&& MsqIsHung(Window
->MessageQueue
))
1418 /* FIXME - Set a LastError? */
1422 if(Window
->Status
& WINDOWSTATUS_DESTROYING
)
1424 /* FIXME - last error? */
1425 DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd
);
1429 Status
= co_MsqSendMessage(Window
->MessageQueue
, hWnd
, Msg
, wParam
, lParam
,
1430 uTimeout
, (uFlags
& SMTO_BLOCK
), FALSE
, uResult
);
1433 if (STATUS_TIMEOUT
== Status
)
1435 /* MSDN says GetLastError() should return 0 after timeout */
1436 SetLastWin32Error(0);
1439 else if (! NT_SUCCESS(Status
))
1441 SetLastNtError(Status
);
1448 if (Window
) UserDerefObjectCo(Window
);
1453 co_IntSendMessageTimeout(HWND hWnd
,
1461 PWINDOW_OBJECT DesktopWindow
;
1465 if (HWND_BROADCAST
!= hWnd
)
1467 return co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1470 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1471 if (NULL
== DesktopWindow
)
1473 SetLastWin32Error(ERROR_INTERNAL_ERROR
);
1477 Children
= IntWinListChildren(DesktopWindow
);
1478 if (NULL
== Children
)
1483 for (Child
= Children
; NULL
!= *Child
; Child
++)
1485 co_IntSendMessageTimeoutSingle(*Child
, Msg
, wParam
, lParam
, uFlags
, uTimeout
, uResult
);
1488 ExFreePool(Children
);
1490 return (LRESULT
) TRUE
;
1494 /* This function posts a message if the destination's message queue belongs to
1495 another thread, otherwise it sends the message. It does not support broadcast
1498 co_IntPostOrSendMessage(HWND hWnd
,
1504 PWINDOW_OBJECT Window
;
1506 if(hWnd
== HWND_BROADCAST
)
1511 if(!(Window
= UserGetWindowObject(hWnd
)))
1516 if(Window
->MessageQueue
!= PsGetCurrentThreadWin32Thread()->MessageQueue
)
1518 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1522 if(!co_IntSendMessageTimeoutSingle(hWnd
, Msg
, wParam
, lParam
, SMTO_NORMAL
, 0, &Result
))
1528 return (LRESULT
)Result
;
1532 co_IntDoSendMessage(HWND hWnd
,
1537 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1539 LRESULT Result
= TRUE
;
1541 PWINDOW_OBJECT Window
;
1542 NTUSERSENDMESSAGEINFO Info
;
1545 PMSGMEMORY MsgMemoryEntry
;
1547 RtlZeroMemory(&Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1549 /* FIXME: Call hooks. */
1550 if (HWND_BROADCAST
!= hWnd
)
1552 Window
= UserGetWindowObject(hWnd
);
1555 /* Tell usermode to not touch this one */
1556 Info
.HandledByKernel
= TRUE
;
1557 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1562 /* FIXME: Check for an exiting window. */
1564 /* See if the current thread can handle the message */
1565 if (HWND_BROADCAST
!= hWnd
&& NULL
!= PsGetCurrentThreadWin32Thread() &&
1566 Window
->MessageQueue
== PsGetCurrentThreadWin32Thread()->MessageQueue
)
1568 /* Gather the information usermode needs to call the window proc directly */
1569 Info
.HandledByKernel
= FALSE
;
1571 Status
= MmCopyFromCaller(&(Info
.Ansi
), &(UnsafeInfo
->Ansi
),
1573 if (! NT_SUCCESS(Status
))
1575 Info
.Ansi
= ! Window
->Unicode
;
1578 if (Window
->IsSystem
)
1580 Info
.Proc
= (!Info
.Ansi
? Window
->WndProc
: Window
->WndProcExtra
);
1584 Info
.Ansi
= !Window
->Unicode
;
1585 Info
.Proc
= Window
->WndProc
;
1590 /* Must be handled by other thread */
1591 // if (HWND_BROADCAST != hWnd)
1593 // UserDerefObject(Window);
1595 Info
.HandledByKernel
= TRUE
;
1596 UserModeMsg
.hwnd
= hWnd
;
1597 UserModeMsg
.message
= Msg
;
1598 UserModeMsg
.wParam
= wParam
;
1599 UserModeMsg
.lParam
= lParam
;
1600 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1601 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1602 if (! NT_SUCCESS(Status
))
1604 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1605 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1606 return (dsm
? 0 : -1);
1610 Result
= co_IntSendMessage(KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1611 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
);
1615 Result
= co_IntSendMessageTimeout(KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1616 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
,
1617 dsm
->uFlags
, dsm
->uTimeout
, &dsm
->Result
);
1619 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1620 if (! NT_SUCCESS(Status
))
1622 MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1623 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1624 return(dsm
? 0 : -1);
1628 Status
= MmCopyToCaller(UnsafeInfo
, &Info
, sizeof(NTUSERSENDMESSAGEINFO
));
1629 if (! NT_SUCCESS(Status
))
1631 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1634 return (LRESULT
)Result
;
1638 NtUserSendMessageTimeout(HWND hWnd
,
1645 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1649 DECLARE_RETURN(BOOL
);
1651 DPRINT("Enter NtUserSendMessageTimeout\n");
1652 UserEnterExclusive();
1654 dsm
.uFlags
= uFlags
;
1655 dsm
.uTimeout
= uTimeout
;
1656 Result
= co_IntDoSendMessage(hWnd
, Msg
, wParam
, lParam
, &dsm
, UnsafeInfo
);
1657 if(uResult
!= NULL
&& Result
!= 0)
1661 Status
= MmCopyToCaller(uResult
, &dsm
.Result
, sizeof(ULONG_PTR
));
1662 if(!NT_SUCCESS(Status
))
1664 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1671 DPRINT("Leave NtUserSendMessageTimeout, ret=%i\n",_ret_
);
1677 NtUserSendMessage(HWND Wnd
,
1681 PNTUSERSENDMESSAGEINFO UnsafeInfo
)
1683 DECLARE_RETURN(BOOL
);
1685 DPRINT("Enter NtUserSendMessage\n");
1686 UserEnterExclusive();
1688 RETURN(co_IntDoSendMessage(Wnd
, Msg
, wParam
, lParam
, NULL
, UnsafeInfo
));
1691 DPRINT("Leave NtUserSendMessage, ret=%i\n",_ret_
);
1697 NtUserSendMessageCallback(HWND hWnd
,
1701 SENDASYNCPROC lpCallBack
,
1711 UserSendNotifyMessage(HWND hWnd
,
1717 // Basicly the same as IntPostOrSendMessage
1718 if (hWnd
== HWND_BROADCAST
) //Handle Broadcast
1721 PWINDOW_OBJECT DesktopWindow
;
1724 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
1725 List
= IntWinListChildren(DesktopWindow
);
1729 for (i
= 0; List
[i
]; i
++)
1731 UserSendNotifyMessage(List
[i
], Msg
, wParam
, lParam
);
1739 PWINDOW_OBJECT Window
;
1743 PMSGMEMORY MsgMemoryEntry
;
1745 if(!(Window
= UserGetWindowObject(hWnd
))) return FALSE
;
1747 if(Window
->MessageQueue
!= PsGetCurrentThreadWin32Thread()->MessageQueue
)
1748 { // Send message w/o waiting for it.
1749 Result
= UserPostMessage(hWnd
, Msg
, wParam
, lParam
);
1752 { // Handle message and callback.
1753 UserModeMsg
.hwnd
= hWnd
;
1754 UserModeMsg
.message
= Msg
;
1755 UserModeMsg
.wParam
= wParam
;
1756 UserModeMsg
.lParam
= lParam
;
1757 MsgMemoryEntry
= FindMsgMemory(UserModeMsg
.message
);
1758 Status
= CopyMsgToKernelMem(&KernelModeMsg
, &UserModeMsg
, MsgMemoryEntry
);
1759 if (! NT_SUCCESS(Status
))
1761 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1764 Result
= co_IntSendMessageTimeoutSingle(
1765 KernelModeMsg
.hwnd
, KernelModeMsg
.message
,
1766 KernelModeMsg
.wParam
, KernelModeMsg
.lParam
,
1767 SMTO_NORMAL
, 0, &PResult
);
1769 Status
= CopyMsgToUserMem(&UserModeMsg
, &KernelModeMsg
);
1770 if (! NT_SUCCESS(Status
))
1772 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1782 NtUserSendNotifyMessage(HWND hWnd
,
1787 DECLARE_RETURN(BOOL
);
1789 DPRINT("EnterNtUserSendNotifyMessage\n");
1790 UserEnterExclusive();
1792 RETURN(UserSendNotifyMessage(hWnd
, Msg
, wParam
, lParam
));
1795 DPRINT("Leave NtUserSendNotifyMessage, ret=%i\n",_ret_
);
1803 NtUserWaitMessage(VOID
)
1805 DECLARE_RETURN(BOOL
);
1807 DPRINT("EnterNtUserWaitMessage\n");
1808 UserEnterExclusive();
1810 RETURN(co_IntWaitMessage(NULL
, 0, 0));
1813 DPRINT("Leave NtUserWaitMessage, ret=%i\n",_ret_
);
1819 NtUserGetQueueStatus(BOOL ClearChanges
)
1821 PUSER_MESSAGE_QUEUE Queue
;
1823 DECLARE_RETURN(DWORD
);
1825 DPRINT("Enter NtUserGetQueueStatus\n");
1826 UserEnterExclusive();
1828 Queue
= PsGetCurrentThreadWin32Thread()->MessageQueue
;
1830 Result
= MAKELONG(Queue
->QueueBits
, Queue
->ChangedBits
);
1833 Queue
->ChangedBits
= 0;
1839 DPRINT("Leave NtUserGetQueueStatus, ret=%i\n",_ret_
);
1845 IntInitMessagePumpHook()
1847 ((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->MessagePumpHookValue
++;
1852 IntUninitMessagePumpHook()
1854 if (((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->MessagePumpHookValue
<= 0)
1858 ((PW32THREAD
)PsGetCurrentThread()->Tcb
.Win32Thread
)->MessagePumpHookValue
--;