Author: jimtabor
Date: Thu Dec 3 21:09:42 2009
New Revision: 44393
URL:
http://svn.reactos.org/svn/reactos?rev=44393&view=rev
Log:
[Win32k]
- Reformat message.c
- [Start] Re-implement Get/PeekMessage support.
Modified:
trunk/reactos/subsystems/win32/win32k/ntuser/message.c
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/message.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/message.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/message.c [iso-8859-1] Thu Dec 3
21:09:42 2009
@@ -14,6 +14,8 @@
#define NDEBUG
#include <debug.h>
+
+#define PM_BADMSGFLAGS ~((QS_RAWINPUT <<
16)|PM_QS_SENDMESSAGE|PM_QS_PAINT|PM_QS_POSTMESSAGE|PM_QS_INPUT|PM_NOYIELD|PM_REMOVE)
typedef struct
{
@@ -421,123 +423,6 @@
return retval;
}
-
-BOOL
-APIENTRY
-NtUserCallMsgFilter(
- LPMSG lpmsg,
- INT code)
-{
- BOOL BadChk = FALSE, Ret = TRUE;
- MSG Msg;
- DECLARE_RETURN(BOOL);
-
- DPRINT("Enter NtUserCallMsgFilter\n");
- UserEnterExclusive();
- if (lpmsg)
- {
- _SEH2_TRY
- {
- ProbeForRead((PVOID)lpmsg,
- sizeof(MSG),
- 1);
- RtlCopyMemory( &Msg,
- (PVOID)lpmsg,
- sizeof(MSG));
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- BadChk = TRUE;
- }
- _SEH2_END;
- }
- else
- RETURN( FALSE);
-
- if (BadChk) RETURN( FALSE);
-
- if (!co_HOOK_CallHooks( WH_SYSMSGFILTER, code, 0, (LPARAM)&Msg))
- {
- Ret = co_HOOK_CallHooks( WH_MSGFILTER, code, 0, (LPARAM)&Msg);
- }
-
- _SEH2_TRY
- {
- ProbeForWrite((PVOID)lpmsg,
- sizeof(MSG),
- 1);
- RtlCopyMemory((PVOID)lpmsg,
- &Msg,
- sizeof(MSG));
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- BadChk = TRUE;
- }
- _SEH2_END;
- if (BadChk) RETURN( FALSE);
- RETURN( Ret)
-
-CLEANUP:
- DPRINT("Leave NtUserCallMsgFilter. ret=%i\n", _ret_);
- UserLeave();
- END_CLEANUP;
-}
-
-LRESULT APIENTRY
-NtUserDispatchMessage(PMSG UnsafeMsgInfo)
-{
- LRESULT Res = 0;
- BOOL Hit = FALSE;
- MSG SafeMsg;
-
- UserEnterExclusive();
- _SEH2_TRY
- {
- ProbeForRead(UnsafeMsgInfo, sizeof(MSG), 1);
- RtlCopyMemory(&SafeMsg, UnsafeMsgInfo, sizeof(MSG));
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- SetLastNtError(_SEH2_GetExceptionCode());
- Hit = TRUE;
- }
- _SEH2_END;
-
- if (!Hit) Res = IntDispatchMessage(&SafeMsg);
-
- UserLeave();
- return Res;
-}
-
-
-BOOL APIENTRY
-NtUserTranslateMessage(LPMSG lpMsg,
- HKL dwhkl)
-{
- NTSTATUS Status;
- MSG SafeMsg;
- DECLARE_RETURN(BOOL);
-
- DPRINT("Enter NtUserTranslateMessage\n");
- UserEnterExclusive();
-
- 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
co_IntSendHitTestMessages(PUSER_MESSAGE_QUEUE ThreadQueue, LPMSG Msg)
{
@@ -756,7 +641,6 @@
return FALSE;
}
-
/*
* Internal version of PeekMessage() doing all the work
*/
@@ -992,105 +876,17 @@
return Present;
}
-BOOL APIENTRY
-NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo,
- HWND hWnd,
- UINT MsgFilterMin,
- UINT MsgFilterMax,
- UINT RemoveMsg)
-{
- 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();
-
- if (hWnd == (HWND)-1 || hWnd == (HWND)0x0000FFFF || hWnd == (HWND)0xFFFFFFFF)
- hWnd = (HWND)1;
-
- /* Validate input */
- if (hWnd && hWnd != (HWND)1)
- {
- if (!(Window = UserGetWindowObject(hWnd)))
- {
- RETURN(-1);
- }
- }
- else
- {
- Window = (PWINDOW_OBJECT)hWnd;
- }
-
- if (MsgFilterMax < MsgFilterMin)
- {
- MsgFilterMin = 0;
- MsgFilterMax = 0;
- }
-
- Present = co_IntPeekMessage(&Msg, Window, 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_RELEASE);
- 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))
- {
- SetLastNtError(Status);
- RETURN( (BOOL) -1);
- }
- }
-
- RETURN( Present);
-
-CLEANUP:
- DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_);
- UserLeave();
- END_CLEANUP;
-}
+BOOL FASTCALL
+co_IntGetPeekMessage( PMSG pMsg,
+ HWND hWnd,
+ UINT MsgFilterMin,
+ UINT MsgFilterMax,
+ UINT RemoveMsg,
+ BOOL bGMSG)
+{
+ return FALSE;
+}
+
static BOOL FASTCALL
co_IntWaitMessage(PWINDOW_OBJECT Window,
@@ -1111,7 +907,6 @@
{
return TRUE;
}
-
/* Nothing found. Wait for new messages. */
Status = co_MsqWaitForNewMessages(ThreadQueue, Window, MsgFilterMin,
MsgFilterMax);
}
@@ -1121,6 +916,814 @@
return FALSE;
}
+
+
+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");
+ ExFreePoolWithTag(KernelMem, TAG_MSG);
+ return Status;
+ }
+ }
+ else
+ {
+ /* Make sure we don't pass any secrets to usermode */
+ RtlZeroMemory(KernelMem, Size);
+ }
+ }
+ else
+ {
+ KernelModeMsg->lParam = 0;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS FASTCALL
+CopyMsgToUserMem(MSG *UserModeMsg, MSG *KernelModeMsg)
+{
+ 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 STATUS_SUCCESS;
+}
+
+BOOL FASTCALL
+UserPostThreadMessage( DWORD idThread,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ MSG Message;
+ PETHREAD peThread;
+ PTHREADINFO pThread;
+ LARGE_INTEGER LargeTickCount;
+ NTSTATUS Status;
+
+ DPRINT1("UserPostThreadMessage wParam 0x%x lParam 0x%x\n", wParam,lParam);
+
+ if (FindMsgMemory(Msg) != 0)
+ {
+ SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY );
+ return FALSE;
+ }
+
+ Status = PsLookupThreadByThreadId((HANDLE)idThread,&peThread);
+
+ if( Status == STATUS_SUCCESS )
+ {
+ pThread = (PTHREADINFO)peThread->Tcb.Win32Thread;
+ if( !pThread || !pThread->MessageQueue || (pThread->TIF_flags &
TIF_INCLEANUP))
+ {
+ ObDereferenceObject( peThread );
+ return FALSE;
+ }
+
+ Message.hwnd = NULL;
+ Message.message = Msg;
+ Message.wParam = wParam;
+ Message.lParam = lParam;
+ IntGetCursorLocation(pThread->Desktop->WindowStation, &Message.pt);
+ KeQueryTickCount(&LargeTickCount);
+ pThread->timeLast = Message.time =
MsqCalculateMessageTime(&LargeTickCount);
+ MsqPostMessage(pThread->MessageQueue, &Message, FALSE, QS_POSTMESSAGE);
+ ObDereferenceObject( peThread );
+ return TRUE;
+ }
+ else
+ {
+ SetLastNtError( Status );
+ }
+ return FALSE;
+}
+
+BOOL FASTCALL
+UserPostMessage(HWND Wnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ PTHREADINFO pti;
+ MSG Message;
+ LARGE_INTEGER LargeTickCount;
+
+ if (FindMsgMemory(Msg) != 0)
+ {
+ SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY );
+ return FALSE;
+ }
+
+ if (!Wnd)
+ return UserPostThreadMessage( PtrToInt(PsGetCurrentThreadId()),
+ Msg,
+ wParam,
+ lParam);
+
+ if (Wnd == HWND_BROADCAST)
+ {
+ HWND *List;
+ PWINDOW_OBJECT DesktopWindow;
+ ULONG i;
+
+ DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
+ List = IntWinListChildren(DesktopWindow);
+
+ if (List != NULL)
+ {
+ for (i = 0; List[i]; i++)
+ UserPostMessage(List[i], Msg, wParam, lParam);
+ ExFreePool(List);
+ }
+ }
+ else
+ {
+ PWINDOW_OBJECT Window;
+
+ Window = UserGetWindowObject(Wnd);
+ if ( !Window || !Window->Wnd )
+ {
+ return FALSE;
+ }
+
+ pti = Window->Wnd->head.pti;
+ if ( pti->TIF_flags & TIF_INCLEANUP )
+ {
+ DPRINT1("Attempted to post message to window 0x%x when the thread is in
cleanup!\n", Wnd);
+ 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;
+ }
+
+ if (WM_QUIT == Msg)
+ {
+ MsqPostQuitMessage(Window->MessageQueue, wParam);
+ }
+ else
+ {
+ Message.hwnd = Wnd;
+ Message.message = Msg;
+ Message.wParam = wParam;
+ Message.lParam = lParam;
+ IntGetCursorLocation(pti->Desktop->WindowStation, &Message.pt);
+ KeQueryTickCount(&LargeTickCount);
+ pti->timeLast = Message.time = MsqCalculateMessageTime(&LargeTickCount);
+ MsqPostMessage(Window->MessageQueue, &Message, FALSE, QS_POSTMESSAGE);
+ }
+ }
+ return TRUE;
+}
+
+
+LRESULT FASTCALL
+co_IntSendMessage(HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ ULONG_PTR Result = 0;
+ if(co_IntSendMessageTimeout(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0, &Result))
+ {
+ return (LRESULT)Result;
+ }
+ return 0;
+}
+
+static
+LRESULT FASTCALL
+co_IntSendMessageTimeoutSingle(HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam,
+ UINT uFlags,
+ UINT uTimeout,
+ ULONG_PTR *uResult)
+{
+ ULONG_PTR Result;
+ NTSTATUS Status;
+ PWINDOW_OBJECT Window = NULL;
+ PMSGMEMORY MsgMemoryEntry;
+ INT lParamBufferSize;
+ LPARAM lParamPacked;
+ PTHREADINFO Win32Thread;
+ DECLARE_RETURN(LRESULT);
+ USER_REFERENCE_ENTRY Ref;
+
+ if (!(Window = UserGetWindowObject(hWnd)))
+ {
+ RETURN( FALSE);
+ }
+
+ UserRefObjectCo(Window, &Ref);
+
+ Win32Thread = PsGetCurrentThreadWin32Thread();
+
+ IntCallWndProc( Window, hWnd, Msg, wParam, lParam);
+
+ if (NULL != Win32Thread &&
+ Window->MessageQueue == Win32Thread->MessageQueue)
+ {
+ if (Win32Thread->TIF_flags & TIF_INCLEANUP)
+ {
+ /* 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;
+ }
+ else
+ {
+ lParamBufferSize = MsgMemorySize(MsgMemoryEntry, wParam, lParam);
+ }
+
+ if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam)))
+ {
+ DPRINT1("Failed to pack message parameters\n");
+ RETURN( FALSE);
+ }
+
+ Result = (ULONG_PTR)co_IntCallWindowProc( Window->Wnd->lpfnWndProc,
+ !Window->Wnd->Unicode,
+ hWnd,
+ Msg,
+ wParam,
+ lParamPacked,
+ lParamBufferSize);
+ if(uResult)
+ {
+ *uResult = Result;
+ }
+
+ IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
+
+ 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);
+ }
+
+ do
+ {
+ Status = co_MsqSendMessage( Window->MessageQueue,
+ hWnd,
+ Msg,
+ wParam,
+ lParam,
+ uTimeout,
+ (uFlags & SMTO_BLOCK),
+ MSQ_NORMAL,
+ uResult);
+ }
+ while ((STATUS_TIMEOUT == Status) &&
+ (uFlags & SMTO_NOTIMEOUTIFNOTHUNG) &&
+ !MsqIsHung(Window->MessageQueue));
+
+ IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
+
+ if (STATUS_TIMEOUT == Status)
+ {
+/*
+ MSDN says:
+ Microsoft Windows 2000: If GetLastError returns zero, then the function
+ timed out.
+ XP+ : If the function fails or times out, the return value is zero.
+ To get extended error information, call GetLastError. If GetLastError
+ returns ERROR_TIMEOUT, then the function timed out.
+ */
+ SetLastWin32Error(ERROR_TIMEOUT);
+ RETURN( FALSE);
+ }
+ else if (! NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN( FALSE);
+ }
+
+ RETURN( TRUE);
+
+CLEANUP:
+ if (Window) UserDerefObjectCo(Window);
+ END_CLEANUP;
+}
+
+LRESULT FASTCALL
+co_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 co_IntSendMessageTimeoutSingle(hWnd, Msg, wParam, lParam, uFlags, uTimeout,
uResult);
+ }
+
+ DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
+ if (NULL == DesktopWindow)
+ {
+ SetLastWin32Error(ERROR_INTERNAL_ERROR);
+ return 0;
+ }
+
+ Children = IntWinListChildren(DesktopWindow);
+ if (NULL == Children)
+ {
+ return 0;
+ }
+
+ for (Child = Children; NULL != *Child; Child++)
+ {
+ co_IntSendMessageTimeoutSingle(*Child, Msg, wParam, lParam, uFlags, uTimeout,
uResult);
+ }
+
+ ExFreePool(Children);
+
+ return (LRESULT) TRUE;
+}
+
+
+/* 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)
+{
+ ULONG_PTR Result;
+ PTHREADINFO pti;
+ PWINDOW_OBJECT Window;
+
+ if(hWnd == HWND_BROADCAST)
+ {
+ return 0;
+ }
+
+ if(!(Window = UserGetWindowObject(hWnd)))
+ {
+ return 0;
+ }
+
+ pti = PsGetCurrentThreadWin32Thread();
+ if(Window->MessageQueue != pti->MessageQueue && FindMsgMemory(Msg) ==0)
+ {
+ Result = UserPostMessage(hWnd, Msg, wParam, lParam);
+ }
+ else
+ {
+ if(!co_IntSendMessageTimeoutSingle(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0,
&Result)) {
+ Result = 0;
+ }
+ }
+
+ return (LRESULT)Result;
+}
+
+LRESULT FASTCALL
+co_IntDoSendMessage(HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam,
+ PDOSENDMESSAGE dsm,
+ PNTUSERSENDMESSAGEINFO UnsafeInfo)
+{
+ PTHREADINFO pti;
+ LRESULT Result = TRUE;
+ NTSTATUS Status;
+ PWINDOW_OBJECT Window = NULL;
+ 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));
+ return 0;
+ }
+ if (!Window->Wnd)
+ return 0;
+ }
+
+ /* FIXME: Check for an exiting window. */
+
+ /* See if the current thread can handle the message */
+ pti = PsGetCurrentThreadWin32Thread();
+ if (HWND_BROADCAST != hWnd && NULL != pti &&
+ Window->MessageQueue == pti->MessageQueue)
+ {
+ /* Gather the information usermode needs to call the window proc directly */
+ Info.HandledByKernel = FALSE;
+
+ Status = MmCopyFromCaller(&(Info.Ansi), &(UnsafeInfo->Ansi),
+ sizeof(BOOL));
+ if (! NT_SUCCESS(Status))
+ {
+ Info.Ansi = ! Window->Wnd->Unicode;
+ }
+
+ IntCallWndProc( Window, hWnd, Msg, wParam, lParam);
+
+ Info.Ansi = !Window->Wnd->Unicode;
+ Info.Proc = Window->Wnd->lpfnWndProc;
+
+ // Make the call from here if CALLWNDPROC or CALLWNDPROCRET are hooked
+ // or just do it in User32!
+
+ IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, &Result);
+ }
+ else
+ {
+ /* Must be handled by other thread */
+// if (HWND_BROADCAST != hWnd)
+// {
+// UserDereferenceObject(Window);
+// }
+ Info.HandledByKernel = TRUE;
+ UserModeMsg.hwnd = hWnd;
+ UserModeMsg.message = Msg;
+ UserModeMsg.wParam = wParam;
+ UserModeMsg.lParam = lParam;
+ 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);
+ }
+ if(!dsm)
+ {
+ Result = co_IntSendMessage(KernelModeMsg.hwnd, KernelModeMsg.message,
+ KernelModeMsg.wParam, KernelModeMsg.lParam);
+ }
+ else
+ {
+ 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))
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ }
+
+ return (LRESULT)Result;
+}
+
+
+BOOL FASTCALL
+UserSendNotifyMessage(HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ BOOL Result = TRUE;
+
+ if (FindMsgMemory(Msg) != 0)
+ {
+ SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY );
+ return FALSE;
+ }
+
+ // Basicly the same as IntPostOrSendMessage
+ if (hWnd == HWND_BROADCAST) //Handle Broadcast
+ {
+ HWND *List;
+ PWINDOW_OBJECT DesktopWindow;
+ ULONG i;
+
+ DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
+ List = IntWinListChildren(DesktopWindow);
+
+ if (List != NULL)
+ {
+ for (i = 0; List[i]; i++)
+ {
+ UserSendNotifyMessage(List[i], Msg, wParam, lParam);
+ }
+ ExFreePool(List);
+ }
+ }
+ else
+ {
+ ULONG_PTR PResult;
+ PTHREADINFO pti;
+ PWINDOW_OBJECT Window;
+ MSG Message;
+
+ if(!(Window = UserGetWindowObject(hWnd))) return FALSE;
+
+ pti = PsGetCurrentThreadWin32Thread();
+ if(Window->MessageQueue != pti->MessageQueue)
+ { // Send message w/o waiting for it.
+ Result = UserPostMessage(hWnd, Msg, wParam, lParam);
+ }
+ else
+ { // Handle message and callback.
+ Message.hwnd = hWnd;
+ Message.message = Msg;
+ Message.wParam = wParam;
+ Message.lParam = lParam;
+
+ Result = co_IntSendMessageTimeoutSingle( hWnd, Msg, wParam, lParam, SMTO_NORMAL,
0, &PResult);
+ }
+ }
+ return Result;
+}
+
+
+DWORD APIENTRY
+IntGetQueueStatus(BOOL ClearChanges)
+{
+ PTHREADINFO pti;
+ PUSER_MESSAGE_QUEUE Queue;
+ DWORD Result;
+ DECLARE_RETURN(DWORD);
+
+ DPRINT("Enter IntGetQueueStatus\n");
+
+ pti = PsGetCurrentThreadWin32Thread();
+ Queue = pti->MessageQueue;
+
+ Result = MAKELONG(Queue->QueueBits, Queue->ChangedBits);
+ if (ClearChanges)
+ {
+ Queue->ChangedBits = 0;
+ }
+
+ RETURN(Result);
+
+CLEANUP:
+ DPRINT("Leave IntGetQueueStatus, ret=%i\n",_ret_);
+ END_CLEANUP;
+}
+
+BOOL APIENTRY
+IntInitMessagePumpHook()
+{
+ if (((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti)
+ {
+ ((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti->dwcPumpHook++;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL APIENTRY
+IntUninitMessagePumpHook()
+{
+ if (((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti)
+ {
+ if
(((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti->dwcPumpHook <=
0)
+ {
+ return FALSE;
+ }
+
((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti->dwcPumpHook--;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/** Functions ******************************************************************/
+
+BOOL APIENTRY
+NtUserPostMessage(HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserPostMessage\n");
+ UserEnterExclusive();
+
+ RETURN( UserPostMessage(hWnd, Msg, wParam, lParam));
+
+CLEANUP:
+ DPRINT("Leave NtUserPostMessage, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+BOOL APIENTRY
+NtUserPostThreadMessage(DWORD idThread,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserPostThreadMessage\n");
+ UserEnterExclusive();
+
+ RETURN( UserPostThreadMessage( idThread,
+ Msg,
+ wParam,
+ lParam));
+
+CLEANUP:
+ DPRINT("Leave NtUserPostThreadMessage, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+DWORD APIENTRY
+NtUserQuerySendMessage(DWORD Unknown0)
+{
+ UNIMPLEMENTED;
+
+ return 0;
+}
+
+LRESULT APIENTRY
+NtUserSendMessageTimeout(HWND hWnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam,
+ UINT uFlags,
+ UINT uTimeout,
+ ULONG_PTR *uResult,
+ PNTUSERSENDMESSAGEINFO UnsafeInfo)
+{
+ 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 APIENTRY
+NtUserSendMessage(HWND Wnd,
+ UINT Msg,
+ WPARAM wParam,
+ LPARAM lParam,
+ PNTUSERSENDMESSAGEINFO 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 APIENTRY
+NtUserWaitMessage(VOID)
+{
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("EnterNtUserWaitMessage\n");
+ UserEnterExclusive();
+
+ RETURN(co_IntWaitMessage(NULL, 0, 0));
+
+CLEANUP:
+ DPRINT("Leave NtUserWaitMessage, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
BOOL APIENTRY
NtUserGetMessage(PNTUSERGETMESSAGEINFO UnsafeInfo,
@@ -1236,812 +1839,319 @@
}
-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");
- ExFreePoolWithTag(KernelMem, TAG_MSG);
- return Status;
- }
- }
- else
- {
- /* Make sure we don't pass any secrets to usermode */
- RtlZeroMemory(KernelMem, Size);
- }
- }
- else
- {
- KernelModeMsg->lParam = 0;
- }
-
- return STATUS_SUCCESS;
-}
-
-static NTSTATUS FASTCALL
-CopyMsgToUserMem(MSG *UserModeMsg, MSG *KernelModeMsg)
-{
- 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 STATUS_SUCCESS;
-}
-
-BOOL FASTCALL
-UserPostThreadMessage( DWORD idThread,
- UINT Msg,
- WPARAM wParam,
- LPARAM lParam)
-{
- MSG Message;
- PETHREAD peThread;
- PTHREADINFO pThread;
- LARGE_INTEGER LargeTickCount;
- NTSTATUS Status;
-
- DPRINT1("UserPostThreadMessage wParam 0x%x lParam 0x%x\n", wParam,lParam);
-
- if (FindMsgMemory(Msg) != 0)
- {
- SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY );
- return FALSE;
- }
-
- Status = PsLookupThreadByThreadId((HANDLE)idThread,&peThread);
-
- if( Status == STATUS_SUCCESS )
- {
- pThread = (PTHREADINFO)peThread->Tcb.Win32Thread;
- if( !pThread || !pThread->MessageQueue || (pThread->TIF_flags &
TIF_INCLEANUP))
- {
- ObDereferenceObject( peThread );
- return FALSE;
- }
-
- Message.hwnd = NULL;
- Message.message = Msg;
- Message.wParam = wParam;
- Message.lParam = lParam;
- IntGetCursorLocation(pThread->Desktop->WindowStation, &Message.pt);
- KeQueryTickCount(&LargeTickCount);
- pThread->timeLast = Message.time =
MsqCalculateMessageTime(&LargeTickCount);
- MsqPostMessage(pThread->MessageQueue, &Message, FALSE, QS_POSTMESSAGE);
- ObDereferenceObject( peThread );
- return TRUE;
- }
- else
- {
- SetLastNtError( Status );
- }
- return FALSE;
-}
-
-BOOL FASTCALL
-UserPostMessage(HWND Wnd,
- UINT Msg,
- WPARAM wParam,
- LPARAM lParam)
-{
- PTHREADINFO pti;
- MSG Message;
- LARGE_INTEGER LargeTickCount;
-
- if (FindMsgMemory(Msg) != 0)
- {
- SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY );
- return FALSE;
- }
-
- if (!Wnd)
- return UserPostThreadMessage( PtrToInt(PsGetCurrentThreadId()),
- Msg,
- wParam,
- lParam);
-
- if (Wnd == HWND_BROADCAST)
- {
- HWND *List;
- PWINDOW_OBJECT DesktopWindow;
- ULONG i;
-
- DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
- List = IntWinListChildren(DesktopWindow);
-
- if (List != NULL)
- {
- for (i = 0; List[i]; i++)
- UserPostMessage(List[i], Msg, wParam, lParam);
- ExFreePool(List);
- }
- }
- else
- {
- PWINDOW_OBJECT Window;
-
- Window = UserGetWindowObject(Wnd);
- if ( !Window || !Window->Wnd )
- {
- return FALSE;
- }
-
- pti = Window->Wnd->head.pti;
- if ( pti->TIF_flags & TIF_INCLEANUP )
- {
- DPRINT1("Attempted to post message to window 0x%x when the thread is in
cleanup!\n", Wnd);
- 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;
- }
-
- if (WM_QUIT == Msg)
- {
- MsqPostQuitMessage(Window->MessageQueue, wParam);
- }
- else
- {
- Message.hwnd = Wnd;
- Message.message = Msg;
- Message.wParam = wParam;
- Message.lParam = lParam;
- IntGetCursorLocation(pti->Desktop->WindowStation, &Message.pt);
- KeQueryTickCount(&LargeTickCount);
- pti->timeLast = Message.time = MsqCalculateMessageTime(&LargeTickCount);
- MsqPostMessage(Window->MessageQueue, &Message, FALSE, QS_POSTMESSAGE);
- }
- }
- return TRUE;
-}
-
-
-BOOL APIENTRY
-NtUserPostMessage(HWND hWnd,
- UINT Msg,
- WPARAM wParam,
- LPARAM lParam)
-{
+BOOL
+APIENTRY
+NtUserGetMessageX(
+ PMSG pMsg,
+ HWND hWnd,
+ UINT MsgFilterMin,
+ UINT MsgFilterMax)
+{
+ MSG Msg;
+ BOOL Ret = FALSE;
DECLARE_RETURN(BOOL);
- DPRINT("Enter NtUserPostMessage\n");
+ DPRINT("Enter NtUserGetMessage\n");
UserEnterExclusive();
- RETURN( UserPostMessage(hWnd, Msg, wParam, lParam));
+ if ( (MsgFilterMin|MsgFilterMax) & ~WM_MAXIMUM )
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ RETURN( Ret);
+ }
+
+ Ret = co_IntGetPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, PM_REMOVE,
TRUE);
+
+ if (Ret)
+ {
+ _SEH2_TRY
+ {
+ ProbeForWrite(pMsg, sizeof(MSG), 1);
+ RtlCopyMemory(pMsg, &Msg, sizeof(MSG));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastNtError(_SEH2_GetExceptionCode());
+ Ret = FALSE;
+ }
+ _SEH2_END;
+ }
+ RETURN( Ret);
CLEANUP:
- DPRINT("Leave NtUserPostMessage, ret=%i\n",_ret_);
+ DPRINT("Leave NtUserGetMessage\n");
UserLeave();
END_CLEANUP;
}
-
-
BOOL APIENTRY
-NtUserPostThreadMessage(DWORD idThread,
- UINT Msg,
- WPARAM wParam,
- LPARAM lParam)
-{
+NtUserPeekMessage(PNTUSERGETMESSAGEINFO UnsafeInfo,
+ HWND hWnd,
+ UINT MsgFilterMin,
+ UINT MsgFilterMax,
+ UINT RemoveMsg)
+{
+ NTSTATUS Status;
+ BOOL Present;
+ NTUSERGETMESSAGEINFO Info;
+ PWINDOW_OBJECT Window;
+ PMSGMEMORY MsgMemoryEntry;
+ PVOID UserMem;
+ UINT Size;
+ USER_MESSAGE Msg;
DECLARE_RETURN(BOOL);
- DPRINT("Enter NtUserPostThreadMessage\n");
+ DPRINT("Enter NtUserPeekMessage\n");
UserEnterExclusive();
- RETURN( UserPostThreadMessage( idThread,
- Msg,
- wParam,
- lParam));
+ if (hWnd == (HWND)-1 || hWnd == (HWND)0x0000FFFF || hWnd == (HWND)0xFFFFFFFF)
+ hWnd = (HWND)1;
+
+ /* Validate input */
+ if (hWnd && hWnd != (HWND)1)
+ {
+ if (!(Window = UserGetWindowObject(hWnd)))
+ {
+ RETURN(-1);
+ }
+ }
+ else
+ {
+ Window = (PWINDOW_OBJECT)hWnd;
+ }
+
+ if (MsgFilterMax < MsgFilterMin)
+ {
+ MsgFilterMin = 0;
+ MsgFilterMax = 0;
+ }
+
+ Present = co_IntPeekMessage(&Msg, Window, 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_RELEASE);
+ 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))
+ {
+ SetLastNtError(Status);
+ RETURN( (BOOL) -1);
+ }
+ }
+
+ RETURN( Present);
CLEANUP:
- DPRINT("Leave NtUserPostThreadMessage, ret=%i\n",_ret_);
+ DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
-DWORD APIENTRY
-NtUserQuerySendMessage(DWORD Unknown0)
-{
- UNIMPLEMENTED;
-
- return 0;
-}
-
-LRESULT FASTCALL
-co_IntSendMessage(HWND hWnd,
- UINT Msg,
- WPARAM wParam,
- LPARAM lParam)
-{
- ULONG_PTR Result = 0;
- if(co_IntSendMessageTimeout(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0, &Result))
- {
- return (LRESULT)Result;
- }
- return 0;
-}
-
-static
-LRESULT FASTCALL
-co_IntSendMessageTimeoutSingle(HWND hWnd,
- UINT Msg,
- WPARAM wParam,
- LPARAM lParam,
- UINT uFlags,
- UINT uTimeout,
- ULONG_PTR *uResult)
-{
- ULONG_PTR Result;
+BOOL
+APIENTRY
+NtUserPeekMessageX(
+ PMSG pMsg,
+ HWND hWnd,
+ UINT MsgFilterMin,
+ UINT MsgFilterMax,
+ UINT RemoveMsg)
+{
+ MSG Msg;
+ BOOL Ret = FALSE;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserPeekMessage\n");
+ UserEnterExclusive();
+
+ if ( RemoveMsg & PM_BADMSGFLAGS )
+ {
+ SetLastWin32Error(ERROR_INVALID_FLAGS);
+ RETURN( Ret);
+ }
+
+ Ret = co_IntGetPeekMessage(&Msg, hWnd, MsgFilterMin, MsgFilterMax, RemoveMsg,
FALSE);
+
+ if (Ret)
+ {
+ _SEH2_TRY
+ {
+ ProbeForWrite(pMsg, sizeof(MSG), 1);
+ RtlCopyMemory(pMsg, &Msg, sizeof(MSG));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastNtError(_SEH2_GetExceptionCode());
+ Ret = FALSE;
+ }
+ _SEH2_END;
+ }
+ RETURN( Ret);
+
+CLEANUP:
+ DPRINT("Leave NtUserPeekMessage, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+BOOL
+APIENTRY
+NtUserCallMsgFilter(
+ LPMSG lpmsg,
+ INT code)
+{
+ BOOL BadChk = FALSE, Ret = FALSE;
+ MSG Msg;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserCallMsgFilter\n");
+ UserEnterExclusive();
+ if (lpmsg)
+ {
+ _SEH2_TRY
+ {
+ ProbeForRead((PVOID)lpmsg,
+ sizeof(MSG),
+ 1);
+ RtlCopyMemory( &Msg,
+ (PVOID)lpmsg,
+ sizeof(MSG));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ BadChk = TRUE;
+ }
+ _SEH2_END;
+ }
+ else
+ RETURN( FALSE);
+
+ if (BadChk) RETURN( FALSE);
+
+ if ( ISITHOOKED(WH_SYSMSGFILTER) &&
+ co_HOOK_CallHooks( WH_SYSMSGFILTER, code, 0, (LPARAM)&Msg))
+ {
+ Ret = TRUE;
+ }
+ else
+ {
+ if ( ISITHOOKED(WH_MSGFILTER) )
+ {
+ Ret = co_HOOK_CallHooks( WH_MSGFILTER, code, 0, (LPARAM)&Msg);
+ }
+ }
+
+ _SEH2_TRY
+ {
+ ProbeForWrite((PVOID)lpmsg,
+ sizeof(MSG),
+ 1);
+ RtlCopyMemory((PVOID)lpmsg,
+ &Msg,
+ sizeof(MSG));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ BadChk = TRUE;
+ }
+ _SEH2_END;
+ if (BadChk) RETURN( FALSE);
+ RETURN( Ret)
+
+CLEANUP:
+ DPRINT("Leave NtUserCallMsgFilter. ret=%i\n", _ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+LRESULT APIENTRY
+NtUserDispatchMessage(PMSG UnsafeMsgInfo)
+{
+ LRESULT Res = 0;
+ BOOL Hit = FALSE;
+ MSG SafeMsg;
+
+ UserEnterExclusive();
+ _SEH2_TRY
+ {
+ ProbeForRead(UnsafeMsgInfo, sizeof(MSG), 1);
+ RtlCopyMemory(&SafeMsg, UnsafeMsgInfo, sizeof(MSG));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastNtError(_SEH2_GetExceptionCode());
+ Hit = TRUE;
+ }
+ _SEH2_END;
+
+ if (!Hit) Res = IntDispatchMessage(&SafeMsg);
+
+ UserLeave();
+ return Res;
+}
+
+
+BOOL APIENTRY
+NtUserTranslateMessage(LPMSG lpMsg,
+ HKL dwhkl)
+{
NTSTATUS Status;
- PWINDOW_OBJECT Window = NULL;
- PMSGMEMORY MsgMemoryEntry;
- INT lParamBufferSize;
- LPARAM lParamPacked;
- PTHREADINFO Win32Thread;
- DECLARE_RETURN(LRESULT);
- USER_REFERENCE_ENTRY Ref;
-
- if (!(Window = UserGetWindowObject(hWnd)))
- {
- RETURN( FALSE);
- }
-
- UserRefObjectCo(Window, &Ref);
-
- Win32Thread = PsGetCurrentThreadWin32Thread();
-
- IntCallWndProc( Window, hWnd, Msg, wParam, lParam);
-
- if (NULL != Win32Thread &&
- Window->MessageQueue == Win32Thread->MessageQueue)
- {
- if (Win32Thread->TIF_flags & TIF_INCLEANUP)
- {
- /* 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;
- }
- else
- {
- lParamBufferSize = MsgMemorySize(MsgMemoryEntry, wParam, lParam);
- }
-
- if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam)))
- {
- DPRINT1("Failed to pack message parameters\n");
- RETURN( FALSE);
- }
-
- Result = (ULONG_PTR)co_IntCallWindowProc( Window->Wnd->lpfnWndProc,
- !Window->Wnd->Unicode,
- hWnd,
- Msg,
- wParam,
- lParamPacked,
- lParamBufferSize);
- if(uResult)
- {
- *uResult = Result;
- }
-
- IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
-
- 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);
- }
-
- do
- {
- Status = co_MsqSendMessage( Window->MessageQueue,
- hWnd,
- Msg,
- wParam,
- lParam,
- uTimeout,
- (uFlags & SMTO_BLOCK),
- MSQ_NORMAL,
- uResult);
- }
- while ((STATUS_TIMEOUT == Status) &&
- (uFlags & SMTO_NOTIMEOUTIFNOTHUNG) &&
- !MsqIsHung(Window->MessageQueue));
-
- IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
-
- if (STATUS_TIMEOUT == Status)
- {
-/*
- MSDN says:
- Microsoft Windows 2000: If GetLastError returns zero, then the function
- timed out.
- XP+ : If the function fails or times out, the return value is zero.
- To get extended error information, call GetLastError. If GetLastError
- returns ERROR_TIMEOUT, then the function timed out.
- */
- SetLastWin32Error(ERROR_TIMEOUT);
- RETURN( FALSE);
- }
- else if (! NT_SUCCESS(Status))
+ MSG SafeMsg;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserTranslateMessage\n");
+ UserEnterExclusive();
+
+ Status = MmCopyFromCaller(&SafeMsg, lpMsg, sizeof(MSG));
+ if(!NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN( FALSE);
}
- RETURN( TRUE);
+ RETURN( IntTranslateKbdMessage(&SafeMsg, dwhkl));
CLEANUP:
- if (Window) UserDerefObjectCo(Window);
- END_CLEANUP;
-}
-
-LRESULT FASTCALL
-co_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 co_IntSendMessageTimeoutSingle(hWnd, Msg, wParam, lParam, uFlags, uTimeout,
uResult);
- }
-
- DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
- if (NULL == DesktopWindow)
- {
- SetLastWin32Error(ERROR_INTERNAL_ERROR);
- return 0;
- }
-
- Children = IntWinListChildren(DesktopWindow);
- if (NULL == Children)
- {
- return 0;
- }
-
- for (Child = Children; NULL != *Child; Child++)
- {
- co_IntSendMessageTimeoutSingle(*Child, Msg, wParam, lParam, uFlags, uTimeout,
uResult);
- }
-
- ExFreePool(Children);
-
- return (LRESULT) TRUE;
-}
-
-
-/* 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)
-{
- ULONG_PTR Result;
- PTHREADINFO pti;
- PWINDOW_OBJECT Window;
-
- if(hWnd == HWND_BROADCAST)
- {
- return 0;
- }
-
- if(!(Window = UserGetWindowObject(hWnd)))
- {
- return 0;
- }
-
- pti = PsGetCurrentThreadWin32Thread();
- if(Window->MessageQueue != pti->MessageQueue && FindMsgMemory(Msg) ==0)
- {
- Result = UserPostMessage(hWnd, Msg, wParam, lParam);
- }
- else
- {
- if(!co_IntSendMessageTimeoutSingle(hWnd, Msg, wParam, lParam, SMTO_NORMAL, 0,
&Result)) {
- Result = 0;
- }
- }
-
- return (LRESULT)Result;
-}
-
-LRESULT FASTCALL
-co_IntDoSendMessage(HWND hWnd,
- UINT Msg,
- WPARAM wParam,
- LPARAM lParam,
- PDOSENDMESSAGE dsm,
- PNTUSERSENDMESSAGEINFO UnsafeInfo)
-{
- PTHREADINFO pti;
- LRESULT Result = TRUE;
- NTSTATUS Status;
- PWINDOW_OBJECT Window = NULL;
- 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));
- return 0;
- }
- if (!Window->Wnd)
- return 0;
- }
-
- /* FIXME: Check for an exiting window. */
-
- /* See if the current thread can handle the message */
- pti = PsGetCurrentThreadWin32Thread();
- if (HWND_BROADCAST != hWnd && NULL != pti &&
- Window->MessageQueue == pti->MessageQueue)
- {
- /* Gather the information usermode needs to call the window proc directly */
- Info.HandledByKernel = FALSE;
-
- Status = MmCopyFromCaller(&(Info.Ansi), &(UnsafeInfo->Ansi),
- sizeof(BOOL));
- if (! NT_SUCCESS(Status))
- {
- Info.Ansi = ! Window->Wnd->Unicode;
- }
-
- IntCallWndProc( Window, hWnd, Msg, wParam, lParam);
-
- Info.Ansi = !Window->Wnd->Unicode;
- Info.Proc = Window->Wnd->lpfnWndProc;
-
- // Make the call from here if CALLWNDPROC or CALLWNDPROCRET are hooked
- // or just do it in User32!
-
- IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, &Result);
- }
- else
- {
- /* Must be handled by other thread */
-// if (HWND_BROADCAST != hWnd)
-// {
-// UserDereferenceObject(Window);
-// }
- Info.HandledByKernel = TRUE;
- UserModeMsg.hwnd = hWnd;
- UserModeMsg.message = Msg;
- UserModeMsg.wParam = wParam;
- UserModeMsg.lParam = lParam;
- 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);
- }
- if(!dsm)
- {
- Result = co_IntSendMessage(KernelModeMsg.hwnd, KernelModeMsg.message,
- KernelModeMsg.wParam, KernelModeMsg.lParam);
- }
- else
- {
- 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))
- {
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- }
-
- return (LRESULT)Result;
-}
-
-LRESULT APIENTRY
-NtUserSendMessageTimeout(HWND hWnd,
- UINT Msg,
- WPARAM wParam,
- LPARAM lParam,
- UINT uFlags,
- UINT uTimeout,
- ULONG_PTR *uResult,
- PNTUSERSENDMESSAGEINFO UnsafeInfo)
-{
- 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_);
+ DPRINT("Leave NtUserTranslateMessage: ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
-
-LRESULT APIENTRY
-NtUserSendMessage(HWND Wnd,
- UINT Msg,
- WPARAM wParam,
- LPARAM lParam,
- PNTUSERSENDMESSAGEINFO 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 FASTCALL
-UserSendNotifyMessage(HWND hWnd,
- UINT Msg,
- WPARAM wParam,
- LPARAM lParam)
-{
- BOOL Result = TRUE;
-
- if (FindMsgMemory(Msg) != 0)
- {
- SetLastWin32Error(ERROR_MESSAGE_SYNC_ONLY );
- return FALSE;
- }
-
- // Basicly the same as IntPostOrSendMessage
- if (hWnd == HWND_BROADCAST) //Handle Broadcast
- {
- HWND *List;
- PWINDOW_OBJECT DesktopWindow;
- ULONG i;
-
- DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
- List = IntWinListChildren(DesktopWindow);
-
- if (List != NULL)
- {
- for (i = 0; List[i]; i++)
- {
- UserSendNotifyMessage(List[i], Msg, wParam, lParam);
- }
- ExFreePool(List);
- }
- }
- else
- {
- ULONG_PTR PResult;
- PTHREADINFO pti;
- PWINDOW_OBJECT Window;
- MSG Message;
-
- if(!(Window = UserGetWindowObject(hWnd))) return FALSE;
-
- pti = PsGetCurrentThreadWin32Thread();
- if(Window->MessageQueue != pti->MessageQueue)
- { // Send message w/o waiting for it.
- Result = UserPostMessage(hWnd, Msg, wParam, lParam);
- }
- else
- { // Handle message and callback.
- Message.hwnd = hWnd;
- Message.message = Msg;
- Message.wParam = wParam;
- Message.lParam = lParam;
-
- Result = co_IntSendMessageTimeoutSingle( hWnd, Msg, wParam, lParam, SMTO_NORMAL,
0, &PResult);
- }
- }
- return Result;
-}
-
-
-BOOL APIENTRY
-NtUserWaitMessage(VOID)
-{
- DECLARE_RETURN(BOOL);
-
- DPRINT("EnterNtUserWaitMessage\n");
- UserEnterExclusive();
-
- RETURN(co_IntWaitMessage(NULL, 0, 0));
-
-CLEANUP:
- DPRINT("Leave NtUserWaitMessage, ret=%i\n",_ret_);
- UserLeave();
- END_CLEANUP;
-}
-
-DWORD APIENTRY
-IntGetQueueStatus(BOOL ClearChanges)
-{
- PTHREADINFO pti;
- PUSER_MESSAGE_QUEUE Queue;
- DWORD Result;
- DECLARE_RETURN(DWORD);
-
- DPRINT("Enter IntGetQueueStatus\n");
-
- pti = PsGetCurrentThreadWin32Thread();
- Queue = pti->MessageQueue;
-
- Result = MAKELONG(Queue->QueueBits, Queue->ChangedBits);
- if (ClearChanges)
- {
- Queue->ChangedBits = 0;
- }
-
- RETURN(Result);
-
-CLEANUP:
- DPRINT("Leave IntGetQueueStatus, ret=%i\n",_ret_);
- END_CLEANUP;
-}
-
-BOOL APIENTRY
-IntInitMessagePumpHook()
-{
- if (((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti)
- {
- ((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti->dwcPumpHook++;
- return TRUE;
- }
- return FALSE;
-}
-
-BOOL APIENTRY
-IntUninitMessagePumpHook()
-{
- if (((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti)
- {
- if
(((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti->dwcPumpHook <=
0)
- {
- return FALSE;
- }
-
((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->pcti->dwcPumpHook--;
- return TRUE;
- }
- return FALSE;
-}
-
BOOL APIENTRY
NtUserMessageCall(