[ros-diffs] [jimtabor] 44393: [Win32k] - Reformat message.c - [Start] Re-implement Get/PeekMessage support.

jimtabor at svn.reactos.org jimtabor at svn.reactos.org
Thu Dec 3 21:09:43 CET 2009


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/ntuser/message.c?rev=44393&r1=44392&r2=44393&view=diff
==============================================================================
--- 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(




More information about the Ros-diffs mailing list