* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: message.c,v 1.55 2004/04/07 17:52:32 gvg Exp $
+/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
/* INCLUDES ******************************************************************/
-#include <ddk/ntddk.h>
-#include <win32k/win32k.h>
-#include <include/msgqueue.h>
-#include <include/window.h>
-#include <include/class.h>
-#include <include/error.h>
-#include <include/object.h>
-#include <include/winsta.h>
-#include <include/callback.h>
-#include <include/painting.h>
-#include <include/input.h>
-#include <include/desktop.h>
-#include <include/tags.h>
-#include <internal/safe.h>
+#include <w32k.h>
#define NDEBUG
#include <debug.h>
typedef struct
{
- UINT uFlags;
- UINT uTimeout;
- ULONG_PTR uResult;
-} DOSENDMESSAGE, *PDOSENDMESSAGE;
+ UINT uFlags;
+ UINT uTimeout;
+ ULONG_PTR Result;
+}
+DOSENDMESSAGE, *PDOSENDMESSAGE;
/* FUNCTIONS *****************************************************************/
NTSTATUS FASTCALL
IntInitMessageImpl(VOID)
{
- return STATUS_SUCCESS;
+ return STATUS_SUCCESS;
}
NTSTATUS FASTCALL
IntCleanupMessageImpl(VOID)
{
- return STATUS_SUCCESS;
+ return STATUS_SUCCESS;
}
-LRESULT FASTCALL
-IntDispatchMessage(MSG* Msg)
+#define MMS_SIZE_WPARAM -1
+#define MMS_SIZE_WPARAMWCHAR -2
+#define MMS_SIZE_LPARAMSZ -3
+#define MMS_SIZE_SPECIAL -4
+#define MMS_FLAG_READ 0x01
+#define MMS_FLAG_WRITE 0x02
+#define MMS_FLAG_READWRITE (MMS_FLAG_READ | MMS_FLAG_WRITE)
+typedef struct tagMSGMEMORY
{
- LRESULT Result;
- PWINDOW_OBJECT WindowObject;
- /* Process timer messages. */
- if (Msg->message == WM_TIMER)
- {
- if (Msg->lParam)
- {
- LARGE_INTEGER LargeTickCount;
- /* FIXME: Call hooks. */
-
- /* FIXME: Check for continuing validity of timer. */
-
- KeQueryTickCount(&LargeTickCount);
- return IntCallWindowProc((WNDPROC)Msg->lParam,
- FALSE,
- Msg->hwnd,
- Msg->message,
- Msg->wParam,
- (LPARAM)LargeTickCount.u.LowPart,
- -1);
- }
- }
-
- if( Msg->hwnd == 0 ) return 0;
-
- /* Get the window object. */
- WindowObject = IntGetWindowObject(Msg->hwnd);
- if(!WindowObject)
- {
- SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
- return 0;
- }
- if(WindowObject->OwnerThread != PsGetCurrentThread())
- {
- IntReleaseWindowObject(WindowObject);
- DPRINT("Window doesn't belong to the calling thread!\n");
- return 0;
- }
- /* FIXME: Call hook procedures. */
-
- /* Call the window procedure. */
- if (0xFFFF0000 != ((DWORD) WindowObject->WndProcW & 0xFFFF0000))
- {
- Result = IntCallWindowProc(WindowObject->WndProcW,
- FALSE,
- Msg->hwnd,
- Msg->message,
- Msg->wParam,
- Msg->lParam,
- -1);
- }
- else
- {
- Result = IntCallWindowProc(WindowObject->WndProcA,
- TRUE,
- Msg->hwnd,
- Msg->message,
- Msg->wParam,
- Msg->lParam,
- -1);
- }
-
- IntReleaseWindowObject(WindowObject);
-
- return Result;
+ UINT Message;
+ UINT Size;
+ INT Flags;
+}
+MSGMEMORY, *PMSGMEMORY;
+
+static MSGMEMORY MsgMemory[] =
+ {
+ { WM_CREATE, MMS_SIZE_SPECIAL, MMS_FLAG_READWRITE },
+ { WM_DDE_ACK, sizeof(KMDDELPARAM), MMS_FLAG_READ },
+ { WM_DDE_EXECUTE, MMS_SIZE_WPARAM, MMS_FLAG_READ },
+ { WM_GETMINMAXINFO, sizeof(MINMAXINFO), MMS_FLAG_READWRITE },
+ { WM_GETTEXT, MMS_SIZE_WPARAMWCHAR, MMS_FLAG_WRITE },
+ { WM_NCCALCSIZE, MMS_SIZE_SPECIAL, MMS_FLAG_READWRITE },
+ { WM_NCCREATE, MMS_SIZE_SPECIAL, MMS_FLAG_READWRITE },
+ { WM_SETTEXT, MMS_SIZE_LPARAMSZ, MMS_FLAG_READ },
+ { WM_STYLECHANGED, sizeof(STYLESTRUCT), MMS_FLAG_READ },
+ { WM_STYLECHANGING, sizeof(STYLESTRUCT), MMS_FLAG_READWRITE },
+ { WM_COPYDATA, MMS_SIZE_SPECIAL, MMS_FLAG_READ },
+ { WM_WINDOWPOSCHANGED, sizeof(WINDOWPOS), MMS_FLAG_READ },
+ { WM_WINDOWPOSCHANGING, sizeof(WINDOWPOS), MMS_FLAG_READWRITE },
+ };
+
+static PMSGMEMORY FASTCALL
+FindMsgMemory(UINT Msg)
+{
+ PMSGMEMORY MsgMemoryEntry;
+
+ /* See if this message type is present in the table */
+ for (MsgMemoryEntry = MsgMemory;
+ MsgMemoryEntry < MsgMemory + sizeof(MsgMemory) / sizeof(MSGMEMORY);
+ MsgMemoryEntry++)
+ {
+ if (Msg == MsgMemoryEntry->Message)
+ {
+ return MsgMemoryEntry;
+ }
+ }
+
+ return NULL;
}
+static UINT FASTCALL
+MsgMemorySize(PMSGMEMORY MsgMemoryEntry, WPARAM wParam, LPARAM lParam)
+{
+ CREATESTRUCTW *Cs;
+ PUNICODE_STRING WindowName;
+ PUNICODE_STRING ClassName;
+ UINT Size;
+
+ _SEH_TRY {
+ if (MMS_SIZE_WPARAM == MsgMemoryEntry->Size)
+ {
+ return (UINT) wParam;
+ }
+ else if (MMS_SIZE_WPARAMWCHAR == MsgMemoryEntry->Size)
+ {
+ return (UINT) (wParam * sizeof(WCHAR));
+ }
+ else if (MMS_SIZE_LPARAMSZ == MsgMemoryEntry->Size)
+ {
+ return (UINT) ((wcslen((PWSTR) lParam) + 1) * sizeof(WCHAR));
+ }
+ else if (MMS_SIZE_SPECIAL == MsgMemoryEntry->Size)
+ {
+ switch(MsgMemoryEntry->Message)
+ {
+ case WM_CREATE:
+ case WM_NCCREATE:
+ Cs = (CREATESTRUCTW *) lParam;
+ WindowName = (PUNICODE_STRING) Cs->lpszName;
+ ClassName = (PUNICODE_STRING) Cs->lpszClass;
+ Size = sizeof(CREATESTRUCTW) + WindowName->Length + sizeof(WCHAR);
+ if (IS_ATOM(ClassName->Buffer))
+ {
+ Size += sizeof(WCHAR) + sizeof(ATOM);
+ }
+ else
+ {
+ Size += sizeof(WCHAR) + ClassName->Length + sizeof(WCHAR);
+ }
+ return Size;
+ break;
+
+ case WM_NCCALCSIZE:
+ return wParam ? sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS) : sizeof(RECT);
+ break;
+
+ case WM_COPYDATA:
+ return sizeof(COPYDATASTRUCT) + ((PCOPYDATASTRUCT)lParam)->cbData;
+
+ default:
+ assert(FALSE);
+ return 0;
+ break;
+ }
+ }
+ else
+ {
+ return MsgMemoryEntry->Size;
+ }
+ } _SEH_HANDLE {
+
+ DPRINT1("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH_GetExceptionCode());
+ } _SEH_END;
+ return 0;
+}
+
+static FASTCALL NTSTATUS
+PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+ NCCALCSIZE_PARAMS *UnpackedNcCalcsize;
+ NCCALCSIZE_PARAMS *PackedNcCalcsize;
+ CREATESTRUCTW *UnpackedCs;
+ CREATESTRUCTW *PackedCs;
+ PUNICODE_STRING WindowName;
+ PUNICODE_STRING ClassName;
+ UINT Size;
+ PCHAR CsData;
+
+ *lParamPacked = lParam;
+ if (WM_NCCALCSIZE == Msg && wParam)
+ {
+ UnpackedNcCalcsize = (NCCALCSIZE_PARAMS *) lParam;
+ if (UnpackedNcCalcsize->lppos != (PWINDOWPOS) (UnpackedNcCalcsize + 1))
+ {
+ PackedNcCalcsize = ExAllocatePoolWithTag(PagedPool,
+ sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS),
+ TAG_MSG);
+ if (NULL == PackedNcCalcsize)
+ {
+ DPRINT1("Not enough memory to pack lParam\n");
+ return STATUS_NO_MEMORY;
+ }
+ RtlCopyMemory(PackedNcCalcsize, UnpackedNcCalcsize, sizeof(NCCALCSIZE_PARAMS));
+ PackedNcCalcsize->lppos = (PWINDOWPOS) (PackedNcCalcsize + 1);
+ RtlCopyMemory(PackedNcCalcsize->lppos, UnpackedNcCalcsize->lppos, sizeof(WINDOWPOS));
+ *lParamPacked = (LPARAM) PackedNcCalcsize;
+ }
+ }
+ else if (WM_CREATE == Msg || WM_NCCREATE == Msg)
+ {
+ UnpackedCs = (CREATESTRUCTW *) lParam;
+ WindowName = (PUNICODE_STRING) UnpackedCs->lpszName;
+ ClassName = (PUNICODE_STRING) UnpackedCs->lpszClass;
+ Size = sizeof(CREATESTRUCTW) + WindowName->Length + sizeof(WCHAR);
+ if (IS_ATOM(ClassName->Buffer))
+ {
+ Size += sizeof(WCHAR) + sizeof(ATOM);
+ }
+ else
+ {
+ Size += sizeof(WCHAR) + ClassName->Length + sizeof(WCHAR);
+ }
+ PackedCs = ExAllocatePoolWithTag(PagedPool, Size, TAG_MSG);
+ if (NULL == PackedCs)
+ {
+ DPRINT1("Not enough memory to pack lParam\n");
+ return STATUS_NO_MEMORY;
+ }
+ RtlCopyMemory(PackedCs, UnpackedCs, sizeof(CREATESTRUCTW));
+ CsData = (PCHAR) (PackedCs + 1);
+ PackedCs->lpszName = (LPCWSTR) (CsData - (PCHAR) PackedCs);
+ RtlCopyMemory(CsData, WindowName->Buffer, WindowName->Length);
+ CsData += WindowName->Length;
+ *((WCHAR *) CsData) = L'\0';
+ CsData += sizeof(WCHAR);
+ PackedCs->lpszClass = (LPCWSTR) (CsData - (PCHAR) PackedCs);
+ if (IS_ATOM(ClassName->Buffer))
+ {
+ *((WCHAR *) CsData) = L'A';
+ CsData += sizeof(WCHAR);
+ *((ATOM *) CsData) = (ATOM)(DWORD_PTR) ClassName->Buffer;
+ CsData += sizeof(ATOM);
+ }
+ else
+ {
+ *((WCHAR *) CsData) = L'S';
+ CsData += sizeof(WCHAR);
+ RtlCopyMemory(CsData, ClassName->Buffer, ClassName->Length);
+ CsData += ClassName->Length;
+ *((WCHAR *) CsData) = L'\0';
+ CsData += sizeof(WCHAR);
+ }
+ ASSERT(CsData == (PCHAR) PackedCs + Size);
+ *lParamPacked = (LPARAM) PackedCs;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static FASTCALL NTSTATUS
+UnpackParam(LPARAM lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+ NCCALCSIZE_PARAMS *UnpackedParams;
+ NCCALCSIZE_PARAMS *PackedParams;
+ PWINDOWPOS UnpackedWindowPos;
+
+ if (lParamPacked == lParam)
+ {
+ return STATUS_SUCCESS;
+ }
+
+ if (WM_NCCALCSIZE == Msg && wParam)
+ {
+ PackedParams = (NCCALCSIZE_PARAMS *) lParamPacked;
+ UnpackedParams = (NCCALCSIZE_PARAMS *) lParam;
+ UnpackedWindowPos = UnpackedParams->lppos;
+ RtlCopyMemory(UnpackedParams, PackedParams, sizeof(NCCALCSIZE_PARAMS));
+ UnpackedParams->lppos = UnpackedWindowPos;
+ RtlCopyMemory(UnpackedWindowPos, PackedParams + 1, sizeof(WINDOWPOS));
+ ExFreePool((PVOID) lParamPacked);
+
+ return STATUS_SUCCESS;
+ }
+ else if (WM_CREATE == Msg || WM_NCCREATE == Msg)
+ {
+ ExFreePool((PVOID) lParamPacked);
+
+ return STATUS_SUCCESS;
+ }
+
+ ASSERT(FALSE);
+
+ return STATUS_INVALID_PARAMETER;
+}
+
+BOOL
+STDCALL
+NtUserCallMsgFilter(
+ LPMSG msg,
+ INT code)
+{
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserCallMsgFilter\n");
+ UserEnterExclusive();
+
+ if (co_HOOK_CallHooks( WH_SYSMSGFILTER, code, 0, (LPARAM)msg))
+ RETURN( TRUE);
+ RETURN( co_HOOK_CallHooks( WH_MSGFILTER, code, 0, (LPARAM)msg));
+
+CLEANUP:
+ DPRINT("Leave NtUserCallMsgFilter. ret=%i\n", _ret_);
+ UserLeave();
+ END_CLEANUP;
+}
LRESULT STDCALL
-NtUserDispatchMessage(CONST MSG* UnsafeMsg)
+NtUserDispatchMessage(PNTUSERDISPATCHMESSAGEINFO UnsafeMsgInfo)
{
- NTSTATUS Status;
- MSG Msg;
-
- Status = MmCopyFromCaller(&Msg, (PVOID) UnsafeMsg, sizeof(MSG));
- if (! NT_SUCCESS(Status))
- {
- SetLastNtError(Status);
- return 0;
- }
-
- return IntDispatchMessage(&Msg);
+ NTSTATUS Status;
+ NTUSERDISPATCHMESSAGEINFO MsgInfo;
+ LRESULT Result = TRUE;
+ DECLARE_RETURN(LRESULT);
+
+ DPRINT("Enter NtUserDispatchMessage\n");
+ UserEnterExclusive();
+
+ Status = MmCopyFromCaller(&MsgInfo, UnsafeMsgInfo, sizeof(NTUSERDISPATCHMESSAGEINFO));
+ if (! NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN( 0);
+ }
+
+ /* Process timer messages. */
+ if (WM_TIMER == MsgInfo.Msg.message && 0 != MsgInfo.Msg.lParam)
+ {
+ LARGE_INTEGER LargeTickCount;
+ /* FIXME: Call hooks. */
+
+ /* FIXME: Check for continuing validity of timer. */
+
+ MsgInfo.HandledByKernel = FALSE;
+ KeQueryTickCount(&LargeTickCount);
+ MsgInfo.Proc = (WNDPROC) MsgInfo.Msg.lParam;
+ MsgInfo.Msg.lParam = (LPARAM)LargeTickCount.u.LowPart;
+ }
+ else if (NULL == MsgInfo.Msg.hwnd)
+ {
+ MsgInfo.HandledByKernel = TRUE;
+ Result = 0;
+ }
+ else
+ {
+ PWINDOW_OBJECT Window;
+
+ /* Get the window object. */
+ Window = UserGetWindowObject(MsgInfo.Msg.hwnd);
+ if (NULL == Window)
+ {
+ MsgInfo.HandledByKernel = TRUE;
+ Result = 0;
+ }
+ else
+ {
+ if (Window->OwnerThread != PsGetCurrentThread())
+ {
+ DPRINT1("Window doesn't belong to the calling thread!\n");
+ MsgInfo.HandledByKernel = TRUE;
+ Result = 0;
+ }
+ else
+ {
+ /* FIXME: Call hook procedures. */
+
+ MsgInfo.HandledByKernel = FALSE;
+ Result = 0;
+ if (0xFFFF0000 != ((DWORD) Window->WndProcW & 0xFFFF0000))
+ {
+ if (0xFFFF0000 != ((DWORD) Window->WndProcA & 0xFFFF0000))
+ {
+ /* Both Unicode and Ansi winprocs are real, use whatever
+ usermode prefers */
+ MsgInfo.Proc = (MsgInfo.Ansi ? Window->WndProcA
+ : Window->WndProcW);
+ }
+ else
+ {
+ /* Real Unicode winproc */
+ MsgInfo.Ansi = FALSE;
+ MsgInfo.Proc = Window->WndProcW;
+ }
+ }
+ else
+ {
+ /* Must have real Ansi winproc */
+ MsgInfo.Ansi = TRUE;
+ MsgInfo.Proc = Window->WndProcA;
+ }
+ }
+ }
+ }
+ Status = MmCopyToCaller(UnsafeMsgInfo, &MsgInfo, sizeof(NTUSERDISPATCHMESSAGEINFO));
+ if (! NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN( 0);
+ }
+
+ RETURN( Result);
+
+CLEANUP:
+ DPRINT("Leave NtUserDispatchMessage. ret=%i\n", _ret_);
+ UserLeave();
+ END_CLEANUP;
}
BOOL STDCALL
NtUserTranslateMessage(LPMSG lpMsg,
- HKL dwhkl)
+ HKL dwhkl)
{
- NTSTATUS Status;
- MSG SafeMsg;
+ NTSTATUS Status;
+ MSG SafeMsg;
+ DECLARE_RETURN(BOOL);
- Status = MmCopyFromCaller(&SafeMsg, lpMsg, sizeof(MSG));
- if(!NT_SUCCESS(Status))
- {
- SetLastNtError(Status);
- return FALSE;
- }
+ DPRINT("Enter NtUserTranslateMessage\n");
+ UserEnterExclusive();
- return IntTranslateKbdMessage(&SafeMsg, dwhkl);
+ Status = MmCopyFromCaller(&SafeMsg, lpMsg, sizeof(MSG));
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN( FALSE);
+ }
+
+ RETURN( IntTranslateKbdMessage(&SafeMsg, dwhkl));
+
+CLEANUP:
+ DPRINT("Leave NtUserTranslateMessage: ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
VOID FASTCALL
-IntSendSpecialMessages(PUSER_MESSAGE_QUEUE ThreadQueue, LPMSG Msg)
+co_IntSendHitTestMessages(PUSER_MESSAGE_QUEUE ThreadQueue, LPMSG Msg)
{
- if(!Msg->hwnd || ThreadQueue->CaptureWindow)
- {
- return;
- }
-
- switch(Msg->message)
- {
- case WM_MOUSEMOVE:
- {
- IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(HTCLIENT, Msg->message));
- break;
- }
- case WM_NCMOUSEMOVE:
- {
- IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(Msg->wParam, Msg->message));
- break;
- }
- case WM_LBUTTONDOWN:
- case WM_MBUTTONDOWN:
- case WM_RBUTTONDOWN:
- case WM_XBUTTONDOWN:
- case WM_LBUTTONDBLCLK:
- case WM_MBUTTONDBLCLK:
- case WM_RBUTTONDBLCLK:
- case WM_XBUTTONDBLCLK:
- {
- WPARAM wParam;
-
- if(!IntGetWindowStationObject(InputWindowStation))
+ if(!Msg->hwnd || ThreadQueue->CaptureWindow)
+ {
+ return;
+ }
+
+ switch(Msg->message)
+ {
+ case WM_MOUSEMOVE:
+ {
+ co_IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(HTCLIENT, Msg->message));
+ break;
+ }
+ case WM_NCMOUSEMOVE:
+ {
+ co_IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(Msg->wParam, Msg->message));
+ break;
+ }
+ case WM_LBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_XBUTTONDOWN:
+ case WM_LBUTTONDBLCLK:
+ case WM_MBUTTONDBLCLK:
+ case WM_RBUTTONDBLCLK:
+ case WM_XBUTTONDBLCLK:
+ {
+ WPARAM wParam;
+ PSYSTEM_CURSORINFO CurInfo;
+
+ if(!IntGetWindowStationObject(InputWindowStation))
+ {
+ break;
+ }
+ CurInfo = IntGetSysCursorInfo(InputWindowStation);
+ wParam = (WPARAM)(CurInfo->ButtonsDown);
+ ObDereferenceObject(InputWindowStation);
+
+ co_IntSendMessage(Msg->hwnd, WM_MOUSEMOVE, wParam, Msg->lParam);
+ co_IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(HTCLIENT, Msg->message));
+ break;
+ }
+ case WM_NCLBUTTONDOWN:
+ case WM_NCMBUTTONDOWN:
+ case WM_NCRBUTTONDOWN:
+ case WM_NCXBUTTONDOWN:
+ case WM_NCLBUTTONDBLCLK:
+ case WM_NCMBUTTONDBLCLK:
+ case WM_NCRBUTTONDBLCLK:
+ case WM_NCXBUTTONDBLCLK:
+ {
+ co_IntSendMessage(Msg->hwnd, WM_NCMOUSEMOVE, (WPARAM)Msg->wParam, Msg->lParam);
+ co_IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(Msg->wParam, Msg->message));
+ break;
+ }
+ }
+}
+
+BOOL FASTCALL
+co_IntActivateWindowMouse(PUSER_MESSAGE_QUEUE ThreadQueue, LPMSG Msg, PWINDOW_OBJECT MsgWindow,
+ USHORT *HitTest)
+{
+ ULONG Result;
+ PWINDOW_OBJECT Parent;
+
+ ASSERT_REFS_CO(MsgWindow);
+
+ if(*HitTest == (USHORT)HTTRANSPARENT)
+ {
+ /* eat the message, search again! */
+ return TRUE;
+ }
+
+ Parent = IntGetParent(MsgWindow);//fixme: deref retval?
+ /* fixme: abort if no parent ? */
+ Result = co_IntSendMessage(MsgWindow->hSelf,
+ WM_MOUSEACTIVATE,
+ (WPARAM) (Parent ? Parent->hSelf : NULL),
+ (LPARAM)MAKELONG(*HitTest, Msg->message)
+ );
+
+ switch (Result)
+ {
+ case MA_NOACTIVATEANDEAT:
+ return TRUE;
+ case MA_NOACTIVATE:
+ break;
+ case MA_ACTIVATEANDEAT:
+ co_IntMouseActivateWindow(MsgWindow);
+ return TRUE;
+ default:
+ /* MA_ACTIVATE */
+ co_IntMouseActivateWindow(MsgWindow);
+ break;
+ }
+
+ return FALSE;
+}
+
+BOOL FASTCALL
+co_IntTranslateMouseMessage(PUSER_MESSAGE_QUEUE ThreadQueue, LPMSG Msg, USHORT *HitTest, BOOL Remove)
+{
+ PWINDOW_OBJECT Window;
+ USER_REFERENCE_ENTRY Ref, DesktopRef;
+
+ if(!(Window = UserGetWindowObject(Msg->hwnd)))
+ {
+ /* let's just eat the message?! */
+ return TRUE;
+ }
+
+ UserRefObjectCo(Window, &Ref);
+
+ if(ThreadQueue == Window->MessageQueue &&
+ ThreadQueue->CaptureWindow != Window->hSelf)
+ {
+ /* only send WM_NCHITTEST messages if we're not capturing the window! */
+ *HitTest = co_IntSendMessage(Window->hSelf, WM_NCHITTEST, 0,
+ MAKELONG(Msg->pt.x, Msg->pt.y));
+
+ if(*HitTest == (USHORT)HTTRANSPARENT)
{
- break;
+ PWINDOW_OBJECT DesktopWindow;
+ HWND hDesktop = IntGetDesktopWindow();
+
+ if((DesktopWindow = UserGetWindowObject(hDesktop)))
+ {
+ PWINDOW_OBJECT Wnd;
+
+ UserRefObjectCo(DesktopWindow, &DesktopRef);
+
+ co_WinPosWindowFromPoint(DesktopWindow, Window->MessageQueue, &Msg->pt, &Wnd);
+ if(Wnd)
+ {
+ if(Wnd != Window)
+ {
+ /* post the message to the other window */
+ Msg->hwnd = Wnd->hSelf;
+ if(!(Wnd->Status & WINDOWSTATUS_DESTROYING))
+ {
+ MsqPostMessage(Wnd->MessageQueue, Msg, FALSE,
+ Msg->message == WM_MOUSEMOVE ? QS_MOUSEMOVE :
+ QS_MOUSEBUTTON);
+ }
+
+ /* eat the message */
+ UserDerefObject(Wnd);
+ UserDerefObjectCo(DesktopWindow);
+ UserDerefObjectCo(Window);
+ return TRUE;
+ }
+ UserDerefObject(Wnd);
+ }
+
+ UserDerefObjectCo(DesktopWindow);
+ }
}
- wParam = (WPARAM)InputWindowStation->SystemCursor.ButtonsDown;
- ObDereferenceObject(InputWindowStation);
-
- IntSendMessage(Msg->hwnd, WM_MOUSEMOVE, wParam, Msg->lParam);
- IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(HTCLIENT, Msg->message));
- break;
- }
- case WM_NCLBUTTONDOWN:
- case WM_NCMBUTTONDOWN:
- case WM_NCRBUTTONDOWN:
- case WM_NCXBUTTONDOWN:
- case WM_NCLBUTTONDBLCLK:
- case WM_NCMBUTTONDBLCLK:
- case WM_NCRBUTTONDBLCLK:
- case WM_NCXBUTTONDBLCLK:
- {
- IntSendMessage(Msg->hwnd, WM_NCMOUSEMOVE, (WPARAM)Msg->wParam, Msg->lParam);
- IntSendMessage(Msg->hwnd, WM_SETCURSOR, (WPARAM)Msg->hwnd, MAKELPARAM(Msg->wParam, Msg->message));
- break;
- }
- }
+ }
+ else
+ {
+ *HitTest = HTCLIENT;
+ }
+
+ if(IS_BTN_MESSAGE(Msg->message, DOWN))
+ {
+ /* generate double click messages, if necessary */
+ if ((((*HitTest) != HTCLIENT) ||
+ (IntGetClassLong(Window, GCL_STYLE, FALSE) & CS_DBLCLKS)) &&
+ MsqIsDblClk(Msg, Remove))
+ {
+ Msg->message += WM_LBUTTONDBLCLK - WM_LBUTTONDOWN;
+ }
+ }
+
+ if(Msg->message != WM_MOUSEWHEEL)
+ {
+
+ if ((*HitTest) != HTCLIENT)
+ {
+ Msg->message += WM_NCMOUSEMOVE - WM_MOUSEMOVE;
+ if((Msg->message == WM_NCRBUTTONUP) &&
+ (((*HitTest) == HTCAPTION) || ((*HitTest) == HTSYSMENU)))
+ {
+ Msg->message = WM_CONTEXTMENU;
+ Msg->wParam = (WPARAM)Window->hSelf;
+ }
+ else
+ {
+ Msg->wParam = *HitTest;
+ }
+ Msg->lParam = MAKELONG(Msg->pt.x, Msg->pt.y);
+ }
+ else if(ThreadQueue->MoveSize == NULL &&
+ ThreadQueue->MenuOwner == NULL)
+ {
+ /* NOTE: Msg->pt should remain in screen coordinates. -- FiN */
+ Msg->lParam = MAKELONG(
+ Msg->pt.x - (WORD)Window->ClientRect.left,
+ Msg->pt.y - (WORD)Window->ClientRect.top);
+ }
+ }
+
+ UserDerefObjectCo(Window);
+ return FALSE;
}
+
/*
* Internal version of PeekMessage() doing all the work
*/
-BOOL STDCALL
-IntPeekMessage(LPMSG Msg,
- HWND Wnd,
- UINT MsgFilterMin,
- UINT MsgFilterMax,
- UINT RemoveMsg)
+BOOL FASTCALL
+co_IntPeekMessage(PUSER_MESSAGE Msg,
+ HWND hWnd,
+ UINT MsgFilterMin,
+ UINT MsgFilterMax,
+ UINT RemoveMsg)
{
- LARGE_INTEGER LargeTickCount;
- PUSER_MESSAGE_QUEUE ThreadQueue;
- BOOLEAN Present;
- PUSER_MESSAGE Message;
- BOOLEAN RemoveMessages;
-
- /* The queues and order in which they are checked are documented in the MSDN
- article on GetMessage() */
-
- ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
-
- KeQueryTickCount(&LargeTickCount);
- ThreadQueue->LastMsgRead = LargeTickCount.u.LowPart;
-
- /* Inspect RemoveMsg flags */
- /* FIXME: The only flag we process is PM_REMOVE - processing of others must still be implemented */
- RemoveMessages = RemoveMsg & PM_REMOVE;
-
- /* Dispatch sent messages here. */
- while (MsqDispatchOneSentMessage(ThreadQueue))
- ;
-
- /* Now look for a quit message. */
- /* FIXME: WINE checks the message number filter here. */
- if (ThreadQueue->QuitPosted)
- {
- Msg->hwnd = Wnd;
- Msg->message = WM_QUIT;
- Msg->wParam = ThreadQueue->QuitExitCode;
- Msg->lParam = 0;
- if (RemoveMessages)
+ LARGE_INTEGER LargeTickCount;
+ PUSER_MESSAGE_QUEUE ThreadQueue;
+ PUSER_MESSAGE Message;
+ BOOL Present, RemoveMessages;
+ USER_REFERENCE_ENTRY Ref;
+
+ /* The queues and order in which they are checked are documented in the MSDN
+ article on GetMessage() */
+
+ ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
+
+ /* Inspect RemoveMsg flags */
+ /* FIXME: The only flag we process is PM_REMOVE - processing of others must still be implemented */
+ RemoveMessages = RemoveMsg & PM_REMOVE;
+
+CheckMessages:
+
+ Present = FALSE;
+
+ KeQueryTickCount(&LargeTickCount);
+ ThreadQueue->LastMsgRead = LargeTickCount.u.LowPart;
+
+ /* Dispatch sent messages here. */
+ while (co_MsqDispatchOneSentMessage(ThreadQueue))
+ ;
+
+ /* Now look for a quit message. */
+
+ if (ThreadQueue->QuitPosted)
+ {
+ /* According to the PSDK, WM_QUIT messages are always returned, regardless
+ of the filter specified */
+ Msg->Msg.hwnd = NULL;
+ Msg->Msg.message = WM_QUIT;
+ Msg->Msg.wParam = ThreadQueue->QuitExitCode;
+ Msg->Msg.lParam = 0;
+ Msg->FreeLParam = FALSE;
+ if (RemoveMessages)
{
- ThreadQueue->QuitPosted = FALSE;
+ ThreadQueue->QuitPosted = FALSE;
}
- return TRUE;
- }
-
- /* Now check for normal messages. */
- Present = MsqFindMessage(ThreadQueue,
- FALSE,
- RemoveMessages,
- Wnd,
- MsgFilterMin,
- MsgFilterMax,
- &Message);
- if (Present)
- {
- RtlCopyMemory(Msg, &Message->Msg, sizeof(MSG));
- if (RemoveMessages)
- {
- MsqDestroyMessage(Message);
- IntSendSpecialMessages(ThreadQueue, Msg);
- }
return TRUE;
- }
-
- /* Check for hardware events. */
- Present = MsqFindMessage(ThreadQueue,
- TRUE,
- RemoveMessages,
- Wnd,
- MsgFilterMin,
- MsgFilterMax,
- &Message);
- if (Present)
- {
- RtlCopyMemory(Msg, &Message->Msg, sizeof(MSG));
+ }
+
+ /* Now check for normal messages. */
+ Present = co_MsqFindMessage(ThreadQueue,
+ FALSE,
+ RemoveMessages,
+ hWnd,
+ MsgFilterMin,
+ MsgFilterMax,
+ &Message);
+ if (Present)
+ {
+ RtlCopyMemory(Msg, Message, sizeof(USER_MESSAGE));
if (RemoveMessages)
- {
- MsqDestroyMessage(Message);
- IntSendSpecialMessages(ThreadQueue, Msg);
- }
+ {
+ MsqDestroyMessage(Message);
+ }
+ goto MessageFound;
+ }
+
+ /* Check for hardware events. */
+ Present = co_MsqFindMessage(ThreadQueue,
+ TRUE,
+ RemoveMessages,
+ hWnd,
+ MsgFilterMin,
+ MsgFilterMax,
+ &Message);
+ if (Present)
+ {
+ RtlCopyMemory(Msg, Message, sizeof(USER_MESSAGE));
+ if (RemoveMessages)
+ {
+ MsqDestroyMessage(Message);
+ }
+ goto MessageFound;
+ }
+
+ /* Check for sent messages again. */
+ while (co_MsqDispatchOneSentMessage(ThreadQueue))
+ ;
+
+ /* Check for paint messages. */
+ if (IntGetPaintMessage(hWnd, MsgFilterMin, MsgFilterMax, PsGetWin32Thread(), &Msg->Msg, RemoveMessages))
+ {
+ Msg->FreeLParam = FALSE;
return TRUE;
- }
+ }
- /* Check for sent messages again. */
- while (MsqDispatchOneSentMessage(ThreadQueue))
- ;
+ /* Check for WM_(SYS)TIMER messages */
+ Present = MsqGetTimerMessage(ThreadQueue, hWnd, MsgFilterMin, MsgFilterMax,
+ &Msg->Msg, RemoveMessages);
+ if (Present)
+ {
+ Msg->FreeLParam = FALSE;
+ goto MessageFound;
+ }
+
+ if(Present)
+ {
+MessageFound:
+
+ if(RemoveMessages)
+ {
+ PWINDOW_OBJECT MsgWindow = NULL;
+
+ if(Msg->Msg.hwnd && (MsgWindow = UserGetWindowObject(Msg->Msg.hwnd)) &&
+ Msg->Msg.message >= WM_MOUSEFIRST && Msg->Msg.message <= WM_MOUSELAST)
+ {
+ USHORT HitTest;
+
+ UserRefObjectCo(MsgWindow, &Ref);
+
+ if(co_IntTranslateMouseMessage(ThreadQueue, &Msg->Msg, &HitTest, TRUE))
+ /* FIXME - check message filter again, if the message doesn't match anymore,
+ search again */
+ {
+ UserDerefObjectCo(MsgWindow);
+ /* eat the message, search again */
+ goto CheckMessages;
+ }
+
+ if(ThreadQueue->CaptureWindow == NULL)
+ {
+ co_IntSendHitTestMessages(ThreadQueue, &Msg->Msg);
+ if((Msg->Msg.message != WM_MOUSEMOVE && Msg->Msg.message != WM_NCMOUSEMOVE) &&
+ IS_BTN_MESSAGE(Msg->Msg.message, DOWN) &&
+ co_IntActivateWindowMouse(ThreadQueue, &Msg->Msg, MsgWindow, &HitTest))
+ {
+ UserDerefObjectCo(MsgWindow);
+ /* eat the message, search again */
+ goto CheckMessages;
+ }
+ }
+
+ UserDerefObjectCo(MsgWindow);
+ }
+ else
+ {
+ co_IntSendHitTestMessages(ThreadQueue, &Msg->Msg);
+ }
+
+// if(MsgWindow)
+// {
+// UserDerefObject(MsgWindow);
+// }
+
+ return TRUE;
+ }
+
+ USHORT HitTest;
+ if((Msg->Msg.hwnd && Msg->Msg.message >= WM_MOUSEFIRST && Msg->Msg.message <= WM_MOUSELAST) &&
+ co_IntTranslateMouseMessage(ThreadQueue, &Msg->Msg, &HitTest, FALSE))
+ /* FIXME - check message filter again, if the message doesn't match anymore,
+ search again */
+ {
+ /* eat the message, search again */
+ goto CheckMessages;
+ }
- /* Check for paint messages. */
- if (IntGetPaintMessage(Wnd, PsGetWin32Thread(), Msg, RemoveMessages))
- {
return TRUE;
- }
+ }
- return FALSE;
+ return Present;
}
BOOL STDCALL
-NtUserPeekMessage(LPMSG UnsafeMsg,
- HWND Wnd,
+NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo,
+ HWND hWnd,
UINT MsgFilterMin,
UINT MsgFilterMax,
UINT RemoveMsg)
{
- MSG SafeMsg;
- NTSTATUS Status;
- BOOL Present;
- PWINDOW_OBJECT Window;
-
- /* Validate input */
- if (NULL != Wnd)
- {
- Window = IntGetWindowObject(Wnd);
- if(!Window)
- Wnd = NULL;
- else
- IntReleaseWindowObject(Window);
- }
- if (MsgFilterMax < MsgFilterMin)
- {
+ NTSTATUS Status;
+ BOOL Present;
+ NTUSERGETMESSAGEINFO Info;
+ PWINDOW_OBJECT Window;
+ PMSGMEMORY MsgMemoryEntry;
+ PVOID UserMem;
+ UINT Size;
+ USER_MESSAGE Msg;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserPeekMessage\n");
+ UserEnterExclusive();
+
+ /* Validate input */
+ if (hWnd && hWnd != INVALID_HANDLE_VALUE)
+ {
+ if (!(Window = UserGetWindowObject(hWnd)))
+ {
+ RETURN(-1);
+ }
+ }
+
+ if (MsgFilterMax < MsgFilterMin)
+ {
MsgFilterMin = 0;
MsgFilterMax = 0;
- }
+ }
- Present = IntPeekMessage(&SafeMsg, Wnd, MsgFilterMin, MsgFilterMax, RemoveMsg);
- if (Present)
- {
- Status = MmCopyToCaller(UnsafeMsg, &SafeMsg, sizeof(MSG));
+ Present = co_IntPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, RemoveMsg);
+ if (Present)
+ {
+ Info.Msg = Msg.Msg;
+ /* See if this message type is present in the table */
+ MsgMemoryEntry = FindMsgMemory(Info.Msg.message);
+ if (NULL == MsgMemoryEntry)
+ {
+ /* Not present, no copying needed */
+ Info.LParamSize = 0;
+ }
+ else
+ {
+ /* Determine required size */
+ Size = MsgMemorySize(MsgMemoryEntry, Info.Msg.wParam,
+ Info.Msg.lParam);
+ /* Allocate required amount of user-mode memory */
+ Info.LParamSize = Size;
+ UserMem = NULL;
+ Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem, 0,
+ &Info.LParamSize, MEM_COMMIT, PAGE_READWRITE);
+ if (! NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN( (BOOL) -1);
+ }
+ /* Transfer lParam data to user-mode mem */
+ Status = MmCopyToCaller(UserMem, (PVOID) Info.Msg.lParam, Size);
+ if (! NT_SUCCESS(Status))
+ {
+ ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID *) &UserMem,
+ &Info.LParamSize, MEM_DECOMMIT);
+ SetLastNtError(Status);
+ RETURN( (BOOL) -1);
+ }
+ Info.Msg.lParam = (LPARAM) UserMem;
+ }
+ if (RemoveMsg && Msg.FreeLParam && 0 != Msg.Msg.lParam)
+ {
+ ExFreePool((void *) Msg.Msg.lParam);
+ }
+ Status = MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERGETMESSAGEINFO));
if (! NT_SUCCESS(Status))
- {
- /* There is error return documented for PeekMessage().
- Do the best we can */
- SetLastNtError(Status);
- return FALSE;
- }
- }
-
- return Present;
+ {
+ SetLastNtError(Status);
+ RETURN( (BOOL) -1);
+ }
+ }
+
+ RETURN( Present);
+
+CLEANUP:
+ DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
-static BOOL STDCALL
-IntWaitMessage(HWND Wnd,
- UINT MsgFilterMin,
- UINT MsgFilterMax)
+static BOOL FASTCALL
+co_IntWaitMessage(HWND Wnd,
+ UINT MsgFilterMin,
+ UINT MsgFilterMax)
{
- PUSER_MESSAGE_QUEUE ThreadQueue;
- NTSTATUS Status;
- MSG Msg;
+ PUSER_MESSAGE_QUEUE ThreadQueue;
+ NTSTATUS Status;
+ USER_MESSAGE Msg;
- ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
+ ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
- do
- {
- if (IntPeekMessage(&Msg, Wnd, MsgFilterMin, MsgFilterMax, PM_NOREMOVE))
- {
- return TRUE;
- }
+ do
+ {
+ if (co_IntPeekMessage(&Msg, Wnd, MsgFilterMin, MsgFilterMax, PM_NOREMOVE))
+ {
+ return TRUE;
+ }
/* Nothing found. Wait for new messages. */
- Status = MsqWaitForNewMessages(ThreadQueue);
- }
- while (STATUS_WAIT_0 <= STATUS_WAIT_0 && Status <= STATUS_WAIT_63);
+ Status = co_MsqWaitForNewMessages(ThreadQueue, Wnd, MsgFilterMin, MsgFilterMax);
+ }
+ while ((STATUS_WAIT_0 <= Status && Status <= STATUS_WAIT_63) || STATUS_TIMEOUT == Status);
- SetLastNtError(Status);
+ SetLastNtError(Status);
- return FALSE;
+ return FALSE;
}
BOOL STDCALL
-NtUserGetMessage(LPMSG UnsafeMsg,
- HWND Wnd,
- UINT MsgFilterMin,
- UINT MsgFilterMax)
+NtUserGetMessage(PNTUSERGETMESSAGEINFO UnsafeInfo,
+ HWND hWnd,
+ UINT MsgFilterMin,
+ UINT MsgFilterMax)
/*
* FUNCTION: Get a message from the calling thread's message queue.
* ARGUMENTS:
* retrieved.
*/
{
- BOOL GotMessage;
- MSG SafeMsg;
- NTSTATUS Status;
- PWINDOW_OBJECT Window;
-
- /* Validate input */
- if (NULL != Wnd)
- {
- Window = IntGetWindowObject(Wnd);
- if(!Window)
- Wnd = NULL;
- else
- IntReleaseWindowObject(Window);
- }
- if (MsgFilterMax < MsgFilterMin)
- {
+ BOOL GotMessage;
+ NTUSERGETMESSAGEINFO Info;
+ NTSTATUS Status;
+ PWINDOW_OBJECT Window = NULL;
+ PMSGMEMORY MsgMemoryEntry;
+ PVOID UserMem;
+ UINT Size;
+ USER_MESSAGE Msg;
+ DECLARE_RETURN(BOOL);
+// USER_REFERENCE_ENTRY Ref;
+
+ DPRINT("Enter NtUserGetMessage\n");
+ UserEnterExclusive();
+
+ /* Validate input */
+ if (hWnd && !(Window = UserGetWindowObject(hWnd)))
+ {
+ RETURN(-1);
+ }
+
+// if (Window) UserRefObjectCo(Window, &Ref);
+
+ if (MsgFilterMax < MsgFilterMin)
+ {
MsgFilterMin = 0;
MsgFilterMax = 0;
- }
+ }
- do
- {
- GotMessage = IntPeekMessage(&SafeMsg, Wnd, MsgFilterMin, MsgFilterMax, PM_REMOVE);
+ do
+ {
+ GotMessage = co_IntPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, PM_REMOVE);
if (GotMessage)
- {
- Status = MmCopyToCaller(UnsafeMsg, &SafeMsg, sizeof(MSG));
- if (! NT_SUCCESS(Status))
- {
- SetLastNtError(Status);
- return (BOOL) -1;
- }
- }
+ {
+ Info.Msg = Msg.Msg;
+ /* See if this message type is present in the table */
+ MsgMemoryEntry = FindMsgMemory(Info.Msg.message);
+ if (NULL == MsgMemoryEntry)
+ {
+ /* Not present, no copying needed */
+ Info.LParamSize = 0;
+ }
+ else
+ {
+ /* Determine required size */
+ Size = MsgMemorySize(MsgMemoryEntry, Info.Msg.wParam,
+ Info.Msg.lParam);
+ /* Allocate required amount of user-mode memory */
+ Info.LParamSize = Size;
+ UserMem = NULL;
+ Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &UserMem, 0,
+ &Info.LParamSize, MEM_COMMIT, PAGE_READWRITE);
+
+ if (! NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN( (BOOL) -1);
+ }
+ /* Transfer lParam data to user-mode mem */
+ Status = MmCopyToCaller(UserMem, (PVOID) Info.Msg.lParam, Size);
+ if (! NT_SUCCESS(Status))
+ {
+ ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID *) &UserMem,
+ &Info.LParamSize, MEM_DECOMMIT);
+ SetLastNtError(Status);
+ RETURN( (BOOL) -1);
+ }
+ Info.Msg.lParam = (LPARAM) UserMem;
+ }
+ if (Msg.FreeLParam && 0 != Msg.Msg.lParam)
+ {
+ ExFreePool((void *) Msg.Msg.lParam);
+ }
+ Status = MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERGETMESSAGEINFO));
+ if (! NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN( (BOOL) -1);
+ }
+ }
+ else if (! co_IntWaitMessage(hWnd, MsgFilterMin, MsgFilterMax))
+ {
+ RETURN( (BOOL) -1);
+ }
+ }
+ while (! GotMessage);
+
+ RETURN( WM_QUIT != Info.Msg.message);
+
+CLEANUP:
+// if (Window) UserDerefObjectCo(Window);
+
+ DPRINT("Leave NtUserGetMessage\n");
+ UserLeave();
+ END_CLEANUP;
+}
+
+DWORD
+STDCALL
+NtUserMessageCall(
+ DWORD Unknown0,
+ DWORD Unknown1,
+ DWORD Unknown2,
+ DWORD Unknown3,
+ DWORD Unknown4,
+ DWORD Unknown5,
+ DWORD Unknown6)
+{
+ UNIMPLEMENTED
+
+ return 0;
+}
+
+static NTSTATUS FASTCALL
+CopyMsgToKernelMem(MSG *KernelModeMsg, MSG *UserModeMsg, PMSGMEMORY MsgMemoryEntry)
+{
+ NTSTATUS Status;
+
+ PVOID KernelMem;
+ UINT Size;
+
+ *KernelModeMsg = *UserModeMsg;
+
+ /* See if this message type is present in the table */
+ if (NULL == MsgMemoryEntry)
+ {
+ /* Not present, no copying needed */
+ return STATUS_SUCCESS;
+ }
+
+ /* Determine required size */
+ Size = MsgMemorySize(MsgMemoryEntry, UserModeMsg->wParam, UserModeMsg->lParam);
+
+ if (0 != Size)
+ {
+ /* Allocate kernel mem */
+ KernelMem = ExAllocatePoolWithTag(PagedPool, Size, TAG_MSG);
+ if (NULL == KernelMem)
+ {
+ DPRINT1("Not enough memory to copy message to kernel mem\n");
+ return STATUS_NO_MEMORY;
+ }
+ KernelModeMsg->lParam = (LPARAM) KernelMem;
+
+ /* Copy data if required */
+ if (0 != (MsgMemoryEntry->Flags & MMS_FLAG_READ))
+ {
+ Status = MmCopyFromCaller(KernelMem, (PVOID) UserModeMsg->lParam, Size);
+ if (! NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to copy message to kernel: invalid usermode buffer\n");
+ ExFreePool(KernelMem);
+ return Status;
+ }
+ }
else
- {
- IntWaitMessage(Wnd, MsgFilterMin, MsgFilterMax);
- }
- }
- while (! GotMessage);
+ {
+ /* Make sure we don't pass any secrets to usermode */
+ RtlZeroMemory(KernelMem, Size);
+ }
+ }
+ else
+ {
+ KernelModeMsg->lParam = 0;
+ }
- return WM_QUIT != SafeMsg.message;
+ return STATUS_SUCCESS;
}
-DWORD
-STDCALL
-NtUserMessageCall(
- DWORD Unknown0,
- DWORD Unknown1,
- DWORD Unknown2,
- DWORD Unknown3,
- DWORD Unknown4,
- DWORD Unknown5,
- DWORD Unknown6)
+static NTSTATUS FASTCALL
+CopyMsgToUserMem(MSG *UserModeMsg, MSG *KernelModeMsg)
{
- UNIMPLEMENTED
+ NTSTATUS Status;
+ PMSGMEMORY MsgMemoryEntry;
+ UINT Size;
+
+ /* See if this message type is present in the table */
+ MsgMemoryEntry = FindMsgMemory(UserModeMsg->message);
+ if (NULL == MsgMemoryEntry)
+ {
+ /* Not present, no copying needed */
+ return STATUS_SUCCESS;
+ }
+
+ /* Determine required size */
+ Size = MsgMemorySize(MsgMemoryEntry, UserModeMsg->wParam, UserModeMsg->lParam);
+
+ if (0 != Size)
+ {
+ /* Copy data if required */
+ if (0 != (MsgMemoryEntry->Flags & MMS_FLAG_WRITE))
+ {
+ Status = MmCopyToCaller((PVOID) UserModeMsg->lParam, (PVOID) KernelModeMsg->lParam, Size);
+ if (! NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to copy message from kernel: invalid usermode buffer\n");
+ ExFreePool((PVOID) KernelModeMsg->lParam);
+ return Status;
+ }
+ }
+
+ ExFreePool((PVOID) KernelModeMsg->lParam);
+ }
- return 0;
+ return STATUS_SUCCESS;
}
-BOOL STDCALL
-NtUserPostMessage(HWND hWnd,
- UINT Msg,
- WPARAM wParam,
- LPARAM lParam)
+BOOL FASTCALL
+UserPostMessage(HWND Wnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam)
{
- PWINDOW_OBJECT Window;
- MSG Mesg;
- LARGE_INTEGER LargeTickCount;
+ MSG UserModeMsg, KernelModeMsg;
+ LARGE_INTEGER LargeTickCount;
+ NTSTATUS Status;
+ PMSGMEMORY MsgMemoryEntry;
- if (WM_QUIT == Msg)
- {
+ if (WM_QUIT == Msg)
+ {
MsqPostQuitMessage(PsGetWin32Thread()->MessageQueue, wParam);
- }
- else if (hWnd == HWND_BROADCAST)
- {
+ }
+ else if (Wnd == HWND_BROADCAST)
+ {
HWND *List;
PWINDOW_OBJECT DesktopWindow;
ULONG i;
- DesktopWindow = IntGetWindowObject(IntGetDesktopWindow());
+ DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
List = IntWinListChildren(DesktopWindow);
- IntReleaseWindowObject(DesktopWindow);
+
if (List != NULL)
- {
- for (i = 0; List[i]; i++)
- NtUserPostMessage(List[i], Msg, wParam, lParam);
- ExFreePool(List);
- }
- }
- else
- {
- Window = IntGetWindowObject(hWnd);
- if (!Window)
- {
- SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
- return FALSE;
- }
- Mesg.hwnd = hWnd;
- Mesg.message = Msg;
- Mesg.wParam = wParam;
- Mesg.lParam = lParam;
- Mesg.pt.x = PsGetWin32Process()->WindowStation->SystemCursor.x;
- Mesg.pt.y = PsGetWin32Process()->WindowStation->SystemCursor.y;
+ {
+ for (i = 0; List[i]; i++)
+ UserPostMessage(List[i], Msg, wParam, lParam);
+ ExFreePool(List);
+ }
+ }
+ else
+ {
+ PWINDOW_OBJECT Window;
+
+ Window = UserGetWindowObject(Wnd);
+ if (NULL == Window)
+ {
+ return FALSE;
+ }
+ if(Window->Status & WINDOWSTATUS_DESTROYING)
+ {
+ DPRINT1("Attempted to post message to window 0x%x that is being destroyed!\n", Wnd);
+ /* FIXME - last error code? */
+ return FALSE;
+ }
+
+ UserModeMsg.hwnd = Wnd;
+ UserModeMsg.message = Msg;
+ UserModeMsg.wParam = wParam;
+ UserModeMsg.lParam = lParam;
+ MsgMemoryEntry = FindMsgMemory(UserModeMsg.message);
+ Status = CopyMsgToKernelMem(&KernelModeMsg, &UserModeMsg, MsgMemoryEntry);
+ if (! NT_SUCCESS(Status))
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ IntGetCursorLocation(PsGetWin32Thread()->Desktop->WindowStation,
+ &KernelModeMsg.pt);
KeQueryTickCount(&LargeTickCount);
- Mesg.time = LargeTickCount.u.LowPart;
- MsqPostMessage(Window->MessageQueue, &Mesg);
- IntReleaseWindowObject(Window);
- }
+ KernelModeMsg.time = LargeTickCount.u.LowPart;
+ MsqPostMessage(Window->MessageQueue, &KernelModeMsg,
+ NULL != MsgMemoryEntry && 0 != KernelModeMsg.lParam,
+ QS_POSTMESSAGE);
+ }
- return TRUE;
+ return TRUE;
}
+
BOOL STDCALL
-NtUserPostThreadMessage(DWORD idThread,
- UINT Msg,
- WPARAM wParam,
- LPARAM lParam)
+NtUserPostMessage(HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam)
{
- MSG Mesg;
+ DECLARE_RETURN(BOOL);
- PETHREAD peThread;
- PW32THREAD pThread;
- NTSTATUS Status;
+ DPRINT("Enter NtUserPostMessage\n");
+ UserEnterExclusive();
- Status = PsLookupThreadByThreadId((void *)idThread,&peThread);
-
- if( Status == STATUS_SUCCESS ) {
- pThread = peThread->Win32Thread;
- if( !pThread || !pThread->MessageQueue )
- {
- ObDereferenceObject( peThread );
- return FALSE;
- }
- Mesg.hwnd = 0;
- Mesg.message = Msg;
- Mesg.wParam = wParam;
- Mesg.lParam = lParam;
- MsqPostMessage(pThread->MessageQueue, &Mesg);
- ObDereferenceObject( peThread );
- return TRUE;
- } else {
- SetLastNtError( Status );
- return FALSE;
- }
-}
-
-DWORD STDCALL
-NtUserQuerySendMessage(DWORD Unknown0)
-{
- UNIMPLEMENTED;
+ RETURN(UserPostMessage(hWnd, Msg, wParam, lParam));
- return 0;
+CLEANUP:
+ DPRINT("Leave NtUserPostMessage, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
-#define MMS_SIZE_WPARAM -1
-#define MMS_SIZE_WPARAMWCHAR -2
-#define MMS_SIZE_LPARAMSZ -3
-#define MMS_SIZE_SPECIAL -4
-#define MMS_FLAG_READ 0x01
-#define MMS_FLAG_WRITE 0x02
-#define MMS_FLAG_READWRITE (MMS_FLAG_READ | MMS_FLAG_WRITE)
-typedef struct tagMSGMEMORY
- {
- UINT Message;
- UINT Size;
- INT Flags;
- } MSGMEMORY, *PMSGMEMORY;
-
-static MSGMEMORY MsgMemory[] =
- {
- { WM_CREATE, sizeof(CREATESTRUCTW), MMS_FLAG_READWRITE },
- { WM_GETMINMAXINFO, sizeof(MINMAXINFO), MMS_FLAG_READWRITE },
- { WM_GETTEXT, MMS_SIZE_WPARAMWCHAR, MMS_FLAG_WRITE },
- { WM_NCCALCSIZE, MMS_SIZE_SPECIAL, MMS_FLAG_READWRITE },
- { WM_NCCREATE, sizeof(CREATESTRUCTW), MMS_FLAG_READWRITE },
- { WM_SETTEXT, MMS_SIZE_LPARAMSZ, MMS_FLAG_READ },
- { WM_STYLECHANGED, sizeof(STYLESTRUCT), MMS_FLAG_READ },
- { WM_STYLECHANGING, sizeof(STYLESTRUCT), MMS_FLAG_READWRITE },
- { WM_WINDOWPOSCHANGED, sizeof(WINDOWPOS), MMS_FLAG_READ },
- { WM_WINDOWPOSCHANGING, sizeof(WINDOWPOS), MMS_FLAG_READWRITE },
- };
-
-static PMSGMEMORY FASTCALL
-FindMsgMemory(UINT Msg)
- {
- PMSGMEMORY MsgMemoryEntry;
-
- /* See if this message type is present in the table */
- for (MsgMemoryEntry = MsgMemory;
- MsgMemoryEntry < MsgMemory + sizeof(MsgMemory) / sizeof(MSGMEMORY);
- MsgMemoryEntry++)
- {
- if (Msg == MsgMemoryEntry->Message)
- {
- return MsgMemoryEntry;
- }
- }
-
- return NULL;
-}
-static UINT FASTCALL
-MsgMemorySize(PMSGMEMORY MsgMemoryEntry, WPARAM wParam, LPARAM lParam)
-{
- if (MMS_SIZE_WPARAM == MsgMemoryEntry->Size)
- {
- return (UINT) wParam;
- }
- else if (MMS_SIZE_WPARAMWCHAR == MsgMemoryEntry->Size)
- {
- return (UINT) (wParam * sizeof(WCHAR));
- }
- else if (MMS_SIZE_LPARAMSZ == MsgMemoryEntry->Size)
- {
- return (UINT) ((wcslen((PWSTR) lParam) + 1) * sizeof(WCHAR));
- }
- else if (MMS_SIZE_SPECIAL == MsgMemoryEntry->Size)
- {
- switch(MsgMemoryEntry->Message)
- {
- case WM_NCCALCSIZE:
- return wParam ? sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS) : sizeof(RECT);
- break;
- default:
- assert(FALSE);
- return 0;
- break;
- }
- }
- else
- {
- return MsgMemoryEntry->Size;
- }
-}
-static FASTCALL NTSTATUS
-PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam)
+BOOL STDCALL
+NtUserPostThreadMessage(DWORD idThread,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam)
{
- NCCALCSIZE_PARAMS *UnpackedParams;
- NCCALCSIZE_PARAMS *PackedParams;
+ MSG UserModeMsg, KernelModeMsg;
+ PETHREAD peThread;
+ PW32THREAD pThread;
+ NTSTATUS Status;
+ PMSGMEMORY MsgMemoryEntry;
+ DECLARE_RETURN(BOOL);
- *lParamPacked = lParam;
- if (WM_NCCALCSIZE == Msg && wParam)
- {
- UnpackedParams = (NCCALCSIZE_PARAMS *) lParam;
- if (UnpackedParams->lppos != (PWINDOWPOS) (UnpackedParams + 1))
- {
- PackedParams = ExAllocatePoolWithTag(PagedPool,
- sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS),
- TAG_MSG);
- if (NULL == PackedParams)
- {
- DPRINT1("Not enough memory to pack lParam\n");
- return STATUS_NO_MEMORY;
- }
- RtlCopyMemory(PackedParams, UnpackedParams, sizeof(NCCALCSIZE_PARAMS));
- PackedParams->lppos = (PWINDOWPOS) (PackedParams + 1);
- RtlCopyMemory(PackedParams->lppos, UnpackedParams->lppos, sizeof(WINDOWPOS));
- *lParamPacked = (LPARAM) PackedParams;
- }
- }
-
- return STATUS_SUCCESS;
-}
+ DPRINT("Enter NtUserPostThreadMessage\n");
+ UserEnterExclusive();
-static FASTCALL NTSTATUS
-UnpackParam(LPARAM lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam)
-{
- NCCALCSIZE_PARAMS *UnpackedParams;
- NCCALCSIZE_PARAMS *PackedParams;
- PWINDOWPOS UnpackedWindowPos;
+ Status = PsLookupThreadByThreadId((HANDLE)idThread,&peThread);
- if (lParamPacked == lParam)
- {
- return STATUS_SUCCESS;
- }
+ if( Status == STATUS_SUCCESS )
+ {
+ pThread = (PW32THREAD)peThread->Tcb.Win32Thread;
+ if( !pThread || !pThread->MessageQueue )
+ {
+ ObDereferenceObject( peThread );
+ RETURN( FALSE);
+ }
- if (WM_NCCALCSIZE == Msg && wParam)
- {
- PackedParams = (NCCALCSIZE_PARAMS *) lParamPacked;
- UnpackedParams = (NCCALCSIZE_PARAMS *) lParam;
- UnpackedWindowPos = UnpackedParams->lppos;
- RtlCopyMemory(UnpackedParams, PackedParams, sizeof(NCCALCSIZE_PARAMS));
- UnpackedParams->lppos = UnpackedWindowPos;
- RtlCopyMemory(UnpackedWindowPos, PackedParams + 1, sizeof(WINDOWPOS));
- ExFreePool((PVOID) lParamPacked);
+ UserModeMsg.hwnd = NULL;
+ UserModeMsg.message = Msg;
+ UserModeMsg.wParam = wParam;
+ UserModeMsg.lParam = lParam;
+ MsgMemoryEntry = FindMsgMemory(UserModeMsg.message);
+ Status = CopyMsgToKernelMem(&KernelModeMsg, &UserModeMsg, MsgMemoryEntry);
+ if (! NT_SUCCESS(Status))
+ {
+ ObDereferenceObject( peThread );
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ RETURN( FALSE);
+ }
+ MsqPostMessage(pThread->MessageQueue, &KernelModeMsg,
+ NULL != MsgMemoryEntry && 0 != KernelModeMsg.lParam,
+ QS_POSTMESSAGE);
+ ObDereferenceObject( peThread );
+ RETURN( TRUE);
+ }
+ else
+ {
+ SetLastNtError( Status );
+ RETURN( FALSE);
+ }
- return STATUS_SUCCESS;
- }
+CLEANUP:
+ DPRINT("Leave NtUserPostThreadMessage, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
- assert(FALSE);
+DWORD STDCALL
+NtUserQuerySendMessage(DWORD Unknown0)
+{
+ UNIMPLEMENTED;
- return STATUS_INVALID_PARAMETER;
+ return 0;
}
-LRESULT STDCALL
-IntSendMessage(HWND hWnd,
- UINT Msg,
- WPARAM wParam,
- LPARAM lParam)
+LRESULT FASTCALL
+co_IntSendMessage(HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam)
{
- LRESULT Result = 0;
- if(IntSendMessageTimeout(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0, &Result))
- {
- return Result;
- }
- return 0;
+ ULONG_PTR Result = 0;
+ if(co_IntSendMessageTimeout(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0, &Result))
+ {
+ return (LRESULT)Result;
+ }
+ return 0;
}
-static LRESULT STDCALL
-IntSendMessageTimeoutSingle(HWND hWnd,
- UINT Msg,
- WPARAM wParam,
- LPARAM lParam,
- UINT uFlags,
- UINT uTimeout,
- ULONG_PTR *uResult)
+static
+LRESULT FASTCALL
+co_IntSendMessageTimeoutSingle(HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam,
+ UINT uFlags,
+ UINT uTimeout,
+ ULONG_PTR *uResult)
{
- LRESULT Result;
- NTSTATUS Status;
- PWINDOW_OBJECT Window;
- PMSGMEMORY MsgMemoryEntry;
- INT lParamBufferSize;
- LPARAM lParamPacked;
- PW32THREAD Win32Thread;
-
- /* FIXME: Call hooks. */
- Window = IntGetWindowObject(hWnd);
- if (!Window)
- {
- SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
- return FALSE;
- }
+ ULONG_PTR Result;
+ NTSTATUS Status;
+ PWINDOW_OBJECT Window = NULL;
+ PMSGMEMORY MsgMemoryEntry;
+ INT lParamBufferSize;
+ LPARAM lParamPacked;
+ PW32THREAD Win32Thread;
+ DECLARE_RETURN(LRESULT);
+ USER_REFERENCE_ENTRY Ref;
+
+ /* FIXME: Call hooks. */
+ if (!(Window = UserGetWindowObject(hWnd)))
+ {
+ RETURN( FALSE);
+ }
+
+ UserRefObjectCo(Window, &Ref);
- Win32Thread = PsGetWin32Thread();
+ Win32Thread = PsGetWin32Thread();
- if (NULL != Win32Thread &&
- Window->MessageQueue == Win32Thread->MessageQueue)
- {
+ if (NULL != Win32Thread &&
+ Window->MessageQueue == Win32Thread->MessageQueue)
+ {
if (Win32Thread->IsExiting)
- {
- /* Never send messages to exiting threads */
- IntReleaseWindowObject(Window);
- return FALSE;
- }
+ {
+ /* Never send messages to exiting threads */
+ RETURN( FALSE);
+ }
/* See if this message type is present in the table */
MsgMemoryEntry = FindMsgMemory(Msg);
if (NULL == MsgMemoryEntry)
- {
- lParamBufferSize = -1;
- }
+ {
+ lParamBufferSize = -1;
+ }
else
- {
- lParamBufferSize = MsgMemorySize(MsgMemoryEntry, wParam, lParam);
- }
+ {
+ lParamBufferSize = MsgMemorySize(MsgMemoryEntry, wParam, lParam);
+ }
if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam)))
- {
- IntReleaseWindowObject(Window);
- DPRINT1("Failed to pack message parameters\n");
- return FALSE;
- }
+ {
+ DPRINT1("Failed to pack message parameters\n");
+ RETURN( FALSE);
+ }
if (0xFFFF0000 != ((DWORD) Window->WndProcW & 0xFFFF0000))
- {
- Result = IntCallWindowProc(Window->WndProcW, FALSE, hWnd, Msg, wParam,
- lParamPacked,lParamBufferSize);
- }
+ {
+ Result = (ULONG_PTR)co_IntCallWindowProc(Window->WndProcW, FALSE, hWnd, Msg, wParam,
+ lParamPacked,lParamBufferSize);
+ }
else
- {
- Result = IntCallWindowProc(Window->WndProcA, TRUE, hWnd, Msg, wParam,
- lParamPacked,lParamBufferSize);
- }
- if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam)))
- {
- IntReleaseWindowObject(Window);
- DPRINT1("Failed to unpack message parameters\n");
- if(uResult)
- *uResult = Result;
- return TRUE;
- }
-
- IntReleaseWindowObject(Window);
+ {
+ Result = (ULONG_PTR)co_IntCallWindowProc(Window->WndProcA, TRUE, hWnd, Msg, wParam,
+ lParamPacked,lParamBufferSize);
+ }
+
if(uResult)
- *uResult = Result;
- return TRUE;
- }
-
- if(uFlags & SMTO_ABORTIFHUNG && MsqIsHung(Window->MessageQueue))
- {
- IntReleaseWindowObject(Window);
- /* FIXME - Set a LastError? */
- return FALSE;
- }
-
- Status = MsqSendMessage(Window->MessageQueue, hWnd, Msg, wParam, lParam,
- uTimeout, (uFlags & SMTO_BLOCK), &Result);
- if(Status == STATUS_TIMEOUT)
- {
- IntReleaseWindowObject(Window);
- SetLastWin32Error(ERROR_TIMEOUT);
- return FALSE;
- }
-
- IntReleaseWindowObject(Window);
- if(uResult)
- *uResult = Result;
- return TRUE;
-}
+ {
+ *uResult = Result;
+ }
+
+ if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam)))
+ {
+ DPRINT1("Failed to unpack message parameters\n");
+ RETURN( TRUE);
+ }
+
+ RETURN( TRUE);
+ }
+
+ if(uFlags & SMTO_ABORTIFHUNG && MsqIsHung(Window->MessageQueue))
+ {
+ /* FIXME - Set a LastError? */
+ RETURN( FALSE);
+ }
+
+ if(Window->Status & WINDOWSTATUS_DESTROYING)
+ {
+ /* FIXME - last error? */
+ DPRINT1("Attempted to send message to window 0x%x that is being destroyed!\n", hWnd);
+ RETURN( FALSE);
+ }
+
+ Status = co_MsqSendMessage(Window->MessageQueue, hWnd, Msg, wParam, lParam,
+ uTimeout, (uFlags & SMTO_BLOCK), FALSE, uResult);
-LRESULT STDCALL
-IntSendMessageTimeout(HWND hWnd,
- UINT Msg,
- WPARAM wParam,
- LPARAM lParam,
- UINT uFlags,
- UINT uTimeout,
- ULONG_PTR *uResult)
-{
- PWINDOW_OBJECT DesktopWindow;
- HWND *Children;
- HWND *Child;
-
- if (HWND_BROADCAST != hWnd)
- {
- return IntSendMessageTimeoutSingle(hWnd, Msg, wParam, lParam, uFlags, uTimeout, uResult);
- }
-
- DesktopWindow = IntGetWindowObject(IntGetDesktopWindow());
- if (NULL == DesktopWindow)
- {
- SetLastWin32Error(ERROR_INTERNAL_ERROR);
- return 0;
- }
- Children = IntWinListChildren(DesktopWindow);
- IntReleaseWindowObject(DesktopWindow);
- if (NULL == Children)
- {
- return 0;
- }
- for (Child = Children; NULL != *Child; Child++)
- {
- IntSendMessageTimeoutSingle(*Child, Msg, wParam, lParam, uFlags, uTimeout, uResult);
- }
+ if (STATUS_TIMEOUT == Status)
+ {
+ /* MSDN says GetLastError() should return 0 after timeout */
+ SetLastWin32Error(0);
+ RETURN( FALSE);
+ }
+ else if (! NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN( FALSE);
+ }
- return (LRESULT) TRUE;
+ RETURN( TRUE);
+
+CLEANUP:
+ if (Window) UserDerefObjectCo(Window);
+ END_CLEANUP;
}
-static NTSTATUS FASTCALL
-CopyMsgToKernelMem(MSG *KernelModeMsg, MSG *UserModeMsg)
+LRESULT FASTCALL
+co_IntSendMessageTimeout(HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam,
+ UINT uFlags,
+ UINT uTimeout,
+ ULONG_PTR *uResult)
{
- NTSTATUS Status;
- PMSGMEMORY MsgMemoryEntry;
- PVOID KernelMem;
- UINT Size;
+ PWINDOW_OBJECT DesktopWindow;
+ HWND *Children;
+ HWND *Child;
- *KernelModeMsg = *UserModeMsg;
+ if (HWND_BROADCAST != hWnd)
+ {
+ return co_IntSendMessageTimeoutSingle(hWnd, Msg, wParam, lParam, uFlags, uTimeout, uResult);
+ }
- /* See if this message type is present in the table */
- MsgMemoryEntry = FindMsgMemory(UserModeMsg->message);
- if (NULL == MsgMemoryEntry)
- {
- /* Not present, no copying needed */
- return STATUS_SUCCESS;
- }
+ DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
+ if (NULL == DesktopWindow)
+ {
+ SetLastWin32Error(ERROR_INTERNAL_ERROR);
+ return 0;
+ }
- /* Determine required size */
- Size = MsgMemorySize(MsgMemoryEntry, UserModeMsg->wParam, UserModeMsg->lParam);
+ Children = IntWinListChildren(DesktopWindow);
+ if (NULL == Children)
+ {
+ return 0;
+ }
- if (0 != Size)
- {
- /* Allocate kernel mem */
- KernelMem = ExAllocatePoolWithTag(PagedPool, Size, TAG_MSG);
- if (NULL == KernelMem)
- {
- DPRINT1("Not enough memory to copy message to kernel mem\n");
- return STATUS_NO_MEMORY;
- }
- KernelModeMsg->lParam = (LPARAM) KernelMem;
+ for (Child = Children; NULL != *Child; Child++)
+ {
+ co_IntSendMessageTimeoutSingle(*Child, Msg, wParam, lParam, uFlags, uTimeout, uResult);
+ }
- /* Copy data if required */
- if (0 != (MsgMemoryEntry->Flags & MMS_FLAG_READ))
- {
- Status = MmCopyFromCaller(KernelMem, (PVOID) UserModeMsg->lParam, Size);
- if (! NT_SUCCESS(Status))
- {
- DPRINT1("Failed to copy message to kernel: invalid usermode buffer\n");
- ExFreePool(KernelMem);
- return Status;
- }
- }
- else
- {
- /* Make sure we don't pass any secrets to usermode */
- RtlZeroMemory(KernelMem, Size);
- }
- }
- else
- {
- KernelModeMsg->lParam = 0;
- }
+ ExFreePool(Children);
- return STATUS_SUCCESS;
+ return (LRESULT) TRUE;
}
-static NTSTATUS FASTCALL
-CopyMsgToUserMem(MSG *UserModeMsg, MSG *KernelModeMsg)
+
+/* This function posts a message if the destination's message queue belongs to
+ another thread, otherwise it sends the message. It does not support broadcast
+ messages! */
+LRESULT FASTCALL
+co_IntPostOrSendMessage(HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam)
{
- NTSTATUS Status;
- PMSGMEMORY MsgMemoryEntry;
- UINT Size;
-
- /* See if this message type is present in the table */
- MsgMemoryEntry = FindMsgMemory(UserModeMsg->message);
- if (NULL == MsgMemoryEntry)
- {
- /* Not present, no copying needed */
- return STATUS_SUCCESS;
- }
+ ULONG_PTR Result;
+ PWINDOW_OBJECT Window;
- /* Determine required size */
- Size = MsgMemorySize(MsgMemoryEntry, UserModeMsg->wParam, UserModeMsg->lParam);
+ if(hWnd == HWND_BROADCAST)
+ {
+ return 0;
+ }
- if (0 != Size)
- {
- /* Copy data if required */
- if (0 != (MsgMemoryEntry->Flags & MMS_FLAG_WRITE))
- {
- Status = MmCopyToCaller((PVOID) UserModeMsg->lParam, (PVOID) KernelModeMsg->lParam, Size);
- if (! NT_SUCCESS(Status))
- {
- DPRINT1("Failed to copy message from kernel: invalid usermode buffer\n");
- ExFreePool((PVOID) KernelModeMsg->lParam);
- return Status;
- }
- }
+ if(!(Window = UserGetWindowObject(hWnd)))
+ {
+ return 0;
+ }
- ExFreePool((PVOID) KernelModeMsg->lParam);
- }
+ if(Window->MessageQueue != PsGetWin32Thread()->MessageQueue)
+ {
+ Result = UserPostMessage(hWnd, Msg, wParam, lParam);
+ }
+ else
+ {
+ if(!co_IntSendMessageTimeoutSingle(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0, &Result))
+ {
+ Result = 0;
+ }
+ }
- return STATUS_SUCCESS;
+ return (LRESULT)Result;
}
LRESULT FASTCALL
-IntDoSendMessage(HWND Wnd,
- UINT Msg,
- WPARAM wParam,
- LPARAM lParam,
- PDOSENDMESSAGE dsm,
- PNTUSERSENDMESSAGEINFO UnsafeInfo)
+co_IntDoSendMessage(HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam,
+ PDOSENDMESSAGE dsm,
+ PNTUSERSENDMESSAGEINFO UnsafeInfo)
{
- LRESULT Result;
- NTSTATUS Status;
- PWINDOW_OBJECT Window;
- NTUSERSENDMESSAGEINFO Info;
- MSG UserModeMsg;
- MSG KernelModeMsg;
-
- RtlZeroMemory(&Info, sizeof(NTUSERSENDMESSAGEINFO));
-
- /* FIXME: Call hooks. */
- if (HWND_BROADCAST != Wnd)
- {
- Window = IntGetWindowObject(Wnd);
+ LRESULT Result = TRUE;
+ NTSTATUS Status;
+ PWINDOW_OBJECT Window;
+ NTUSERSENDMESSAGEINFO Info;
+ MSG UserModeMsg;
+ MSG KernelModeMsg;
+ PMSGMEMORY MsgMemoryEntry;
+
+ RtlZeroMemory(&Info, sizeof(NTUSERSENDMESSAGEINFO));
+
+ /* FIXME: Call hooks. */
+ if (HWND_BROADCAST != hWnd)
+ {
+ Window = UserGetWindowObject(hWnd);
if (NULL == Window)
- {
- /* Tell usermode to not touch this one */
- Info.HandledByKernel = TRUE;
- MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
- SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
- return 0;
- }
- }
-
- /* FIXME: Check for an exiting window. */
-
- /* See if the current thread can handle the message */
- if (HWND_BROADCAST != Wnd && NULL != PsGetWin32Thread() &&
- Window->MessageQueue == PsGetWin32Thread()->MessageQueue)
- {
+ {
+ /* Tell usermode to not touch this one */
+ Info.HandledByKernel = TRUE;
+ MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
+ return 0;
+ }
+ }
+
+ /* FIXME: Check for an exiting window. */
+
+ /* See if the current thread can handle the message */
+ if (HWND_BROADCAST != hWnd && NULL != PsGetWin32Thread() &&
+ Window->MessageQueue == PsGetWin32Thread()->MessageQueue)
+ {
/* Gather the information usermode needs to call the window proc directly */
Info.HandledByKernel = FALSE;
if (0xFFFF0000 != ((DWORD) Window->WndProcW & 0xFFFF0000))
- {
- if (0xFFFF0000 != ((DWORD) Window->WndProcA & 0xFFFF0000))
- {
- /* Both Unicode and Ansi winprocs are real, see what usermode prefers */
- Status = MmCopyFromCaller(&(Info.Ansi), &(UnsafeInfo->Ansi),
- sizeof(BOOL));
- if (! NT_SUCCESS(Status))
- {
- Info.Ansi = ! Window->Unicode;
- }
- Info.Proc = (Info.Ansi ? Window->WndProcA : Window->WndProcW);
- }
- else
+ {
+ if (0xFFFF0000 != ((DWORD) Window->WndProcA & 0xFFFF0000))
+ {
+ /* Both Unicode and Ansi winprocs are real, see what usermode prefers */
+ Status = MmCopyFromCaller(&(Info.Ansi), &(UnsafeInfo->Ansi),
+ sizeof(BOOL));
+ if (! NT_SUCCESS(Status))
{
- /* Real Unicode winproc */
- Info.Ansi = FALSE;
- Info.Proc = Window->WndProcW;
+ Info.Ansi = ! Window->Unicode;
}
- }
+ Info.Proc = (Info.Ansi ? Window->WndProcA : Window->WndProcW);
+ }
+ else
+ {
+ /* Real Unicode winproc */
+ Info.Ansi = FALSE;
+ Info.Proc = Window->WndProcW;
+ }
+ }
else
- {
- /* Must have real Ansi winproc */
- Info.Ansi = TRUE;
- Info.Proc = Window->WndProcA;
- }
- IntReleaseWindowObject(Window);
- }
- else
- {
+ {
+ /* Must have real Ansi winproc */
+ Info.Ansi = TRUE;
+ Info.Proc = Window->WndProcA;
+ }
+ }
+ else
+ {
/* Must be handled by other thread */
- if (HWND_BROADCAST != Wnd)
- {
- IntReleaseWindowObject(Window);
- }
+// if (HWND_BROADCAST != hWnd)
+// {
+// UserDerefObject(Window);
+// }
Info.HandledByKernel = TRUE;
- UserModeMsg.hwnd = Wnd;
+ UserModeMsg.hwnd = hWnd;
UserModeMsg.message = Msg;
UserModeMsg.wParam = wParam;
UserModeMsg.lParam = lParam;
- Status = CopyMsgToKernelMem(&KernelModeMsg, &UserModeMsg);
+ MsgMemoryEntry = FindMsgMemory(UserModeMsg.message);
+ Status = CopyMsgToKernelMem(&KernelModeMsg, &UserModeMsg, MsgMemoryEntry);
if (! NT_SUCCESS(Status))
- {
- MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- return (dsm ? 0 : -1);
- }
+ {
+ MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return (dsm ? 0 : -1);
+ }
if(!dsm)
{
- Result = IntSendMessage(KernelModeMsg.hwnd, KernelModeMsg.message,
- KernelModeMsg.wParam, KernelModeMsg.lParam);
+ Result = co_IntSendMessage(KernelModeMsg.hwnd, KernelModeMsg.message,
+ KernelModeMsg.wParam, KernelModeMsg.lParam);
}
else
{
- Result = IntSendMessageTimeout(KernelModeMsg.hwnd, KernelModeMsg.message,
- KernelModeMsg.wParam, KernelModeMsg.lParam,
- dsm->uFlags, dsm->uTimeout, &dsm->uResult);
+ Result = co_IntSendMessageTimeout(KernelModeMsg.hwnd, KernelModeMsg.message,
+ KernelModeMsg.wParam, KernelModeMsg.lParam,
+ dsm->uFlags, dsm->uTimeout, &dsm->Result);
}
Status = CopyMsgToUserMem(&UserModeMsg, &KernelModeMsg);
if (! NT_SUCCESS(Status))
- {
- MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- return(dsm ? 0 : -1);
- }
- }
-
- Status = MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
- if (! NT_SUCCESS(Status))
- {
+ {
+ MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ return(dsm ? 0 : -1);
+ }
+ }
+
+ Status = MmCopyToCaller(UnsafeInfo, &Info, sizeof(NTUSERSENDMESSAGEINFO));
+ if (! NT_SUCCESS(Status))
+ {
SetLastWin32Error(ERROR_INVALID_PARAMETER);
- }
+ }
- return Result;
+ return (LRESULT)Result;
}
LRESULT STDCALL
NtUserSendMessageTimeout(HWND hWnd,
- UINT Msg,
- WPARAM wParam,
- LPARAM lParam,
- UINT uFlags,
- UINT uTimeout,
- ULONG_PTR *uResult,
- PNTUSERSENDMESSAGEINFO UnsafeInfo)
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam,
+ UINT uFlags,
+ UINT uTimeout,
+ ULONG_PTR *uResult,
+ PNTUSERSENDMESSAGEINFO UnsafeInfo)
{
- DOSENDMESSAGE dsm;
- LRESULT Result;
-
- dsm.uFlags = uFlags;
- dsm.uTimeout = uTimeout;
- Result = IntDoSendMessage(hWnd, Msg, wParam, lParam, &dsm, UnsafeInfo);
- if(uResult)
- {
- NTSTATUS Status;
-
- Status = MmCopyToCaller(uResult, &dsm.uResult, sizeof(ULONG_PTR));
- if(!NT_SUCCESS(Status))
- {
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- }
- return Result;
+ DOSENDMESSAGE dsm;
+ LRESULT Result;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserSendMessageTimeout\n");
+ UserEnterExclusive();
+
+ dsm.uFlags = uFlags;
+ dsm.uTimeout = uTimeout;
+ Result = co_IntDoSendMessage(hWnd, Msg, wParam, lParam, &dsm, UnsafeInfo);
+ if(uResult != NULL && Result != 0)
+ {
+ NTSTATUS Status;
+
+ Status = MmCopyToCaller(uResult, &dsm.Result, sizeof(ULONG_PTR));
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ RETURN( FALSE);
+ }
+ }
+ RETURN( Result);
+
+CLEANUP:
+ DPRINT("Leave NtUserSendMessageTimeout, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
LRESULT STDCALL
NtUserSendMessage(HWND Wnd,
- UINT Msg,
- WPARAM wParam,
- LPARAM lParam,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam,
PNTUSERSENDMESSAGEINFO UnsafeInfo)
{
- return IntDoSendMessage(Wnd, Msg, wParam, lParam, NULL, UnsafeInfo);
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserSendMessage\n");
+ UserEnterExclusive();
+
+ RETURN(co_IntDoSendMessage(Wnd, Msg, wParam, lParam, NULL, UnsafeInfo));
+
+CLEANUP:
+ DPRINT("Leave NtUserSendMessage, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
BOOL STDCALL
NtUserSendMessageCallback(HWND hWnd,
- UINT Msg,
- WPARAM wParam,
- LPARAM lParam,
- SENDASYNCPROC lpCallBack,
- ULONG_PTR dwData)
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam,
+ SENDASYNCPROC lpCallBack,
+ ULONG_PTR dwData)
{
- UNIMPLEMENTED;
+ UNIMPLEMENTED;
- return 0;
+ return 0;
}
BOOL STDCALL
NtUserSendNotifyMessage(HWND hWnd,
- UINT Msg,
- WPARAM wParam,
- LPARAM lParam)
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam)
{
- UNIMPLEMENTED;
+ UNIMPLEMENTED;
- return 0;
+ return 0;
}
BOOL STDCALL
NtUserWaitMessage(VOID)
{
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("EnterNtUserWaitMessage\n");
+ UserEnterExclusive();
- return IntWaitMessage(NULL, 0, 0);
+ RETURN(co_IntWaitMessage(NULL, 0, 0));
+
+CLEANUP:
+ DPRINT("Leave NtUserWaitMessage, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
DWORD STDCALL
{
PUSER_MESSAGE_QUEUE Queue;
DWORD Result;
+ DECLARE_RETURN(DWORD);
- Queue = PsGetWin32Thread()->MessageQueue;
+ DPRINT("Enter NtUserGetQueueStatus\n");
+ UserEnterExclusive();
- IntLockMessageQueue(Queue);
+ Queue = PsGetWin32Thread()->MessageQueue;
- Result = MAKELONG(Queue->ChangedBits, Queue->WakeBits);
+ Result = MAKELONG(Queue->QueueBits, Queue->ChangedBits);
if (ClearChanges)
{
Queue->ChangedBits = 0;
}
- IntUnLockMessageQueue(Queue);
+ RETURN( Result);
- return Result;
+CLEANUP:
+ DPRINT("Leave NtUserGetQueueStatus, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
BOOL STDCALL
IntInitMessagePumpHook()
{
- PsGetCurrentThread()->Win32Thread->MessagePumpHookValue++;
- return TRUE;
+ ((PW32THREAD)PsGetCurrentThread()->Tcb.Win32Thread)->MessagePumpHookValue++;
+ return TRUE;
}
BOOL STDCALL
IntUninitMessagePumpHook()
{
- if (PsGetCurrentThread()->Win32Thread->MessagePumpHookValue <= 0)
- {
- return FALSE;
- }
- PsGetCurrentThread()->Win32Thread->MessagePumpHookValue--;
- return TRUE;
+ if (((PW32THREAD)PsGetCurrentThread()->Tcb.Win32Thread)->MessagePumpHookValue <= 0)
+ {
+ return FALSE;
+ }
+ ((PW32THREAD)PsGetCurrentThread()->Tcb.Win32Thread)->MessagePumpHookValue--;
+ return TRUE;
}
/* EOF */