update for HEAD-2003091401
[reactos.git] / subsys / win32k / ntuser / message.c
index b687dc4..da114fe 100644 (file)
@@ -1,3 +1,21 @@
+/*
+ *  ReactOS W32 Subsystem
+ *  Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
 /* $Id$
  *
  * COPYRIGHT:        See COPYING in the top level directory
@@ -13,7 +31,6 @@
 
 #include <ddk/ntddk.h>
 #include <win32k/win32k.h>
-#include <include/guicheck.h>
 #include <include/msgqueue.h>
 #include <include/window.h>
 #include <include/class.h>
 #include <include/winsta.h>
 #include <include/callback.h>
 #include <include/painting.h>
+#include <internal/safe.h>
 
-//#define NDEBUG
+#define NDEBUG
 #include <debug.h>
 
 /* FUNCTIONS *****************************************************************/
 
-NTSTATUS
-W32kInitMessageImpl(VOID)
+NTSTATUS FASTCALL
+IntInitMessageImpl(VOID)
 {
-  return(STATUS_SUCCESS);
+  return STATUS_SUCCESS;
 }
 
-NTSTATUS
-W32kCleanupMessageImpl(VOID)
+NTSTATUS FASTCALL
+IntCleanupMessageImpl(VOID)
 {
-  return(STATUS_SUCCESS);
+  return STATUS_SUCCESS;
 }
 
 
 LRESULT STDCALL
-NtUserDispatchMessage(CONST MSG* lpMsg)
+NtUserDispatchMessage(CONST MSG* UnsafeMsg)
 {
   LRESULT Result;
-  ULONG PaintingFlag;
   PWINDOW_OBJECT WindowObject;
   NTSTATUS Status;
+  MSG Msg;
+
+  Status = MmCopyFromCaller(&Msg, (PVOID) UnsafeMsg, sizeof(MSG));
+  if (! NT_SUCCESS(Status))
+    {
+    SetLastNtError(Status);
+    return 0;
+    }
 
   /* Process timer messages. */
-  if (lpMsg->message == WM_TIMER)
+  if (Msg.message == WM_TIMER)
     {
-      if (lpMsg->lParam)
+      if (Msg.lParam)
        {
          /* FIXME: Call hooks. */
 
          /* FIXME: Check for continuing validity of timer. */
 
-         return(W32kCallWindowProc((WNDPROC)lpMsg->lParam,
-                                     lpMsg->hwnd,
-                                     lpMsg->message,
-                                     lpMsg->wParam,
-                                     0 /* GetTickCount() */));
+         return IntCallWindowProc((WNDPROC)Msg.lParam,
+                                     Msg.hwnd,
+                                     Msg.message,
+                                     Msg.wParam,
+                                     0 /* GetTickCount() */);
        }
     }
 
   /* Get the window object. */
   Status = 
     ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
-                              lpMsg->hwnd,
+                              Msg.hwnd,
                               otWindow,
                               (PVOID*)&WindowObject);
   if (!NT_SUCCESS(Status))
     {
-      return(0);
-    }
-
-  /* FIXME: Check for paint message. */
-  PaintingFlag = (lpMsg->message == WM_PAINT);
-  if (PaintingFlag)
-    {
-      WindowObject->Flags |= WINDOWOBJECT_NEED_BEGINPAINT;
+      SetLastNtError(Status);
+      return 0;
     }
 
   /* FIXME: Call hook procedures. */
 
   /* Call the window procedure. */
-  Result = W32kCallWindowProc(NULL /* WndProc */,
-                             lpMsg->hwnd,
-                             lpMsg->message,
-                             lpMsg->wParam,
-                             lpMsg->lParam);
-
-  if (PaintingFlag && WindowObject->Flags & WINDOWOBJECT_NEED_BEGINPAINT &&
-      WindowObject->UpdateRegion)
-    {
-      DbgBreakPoint();
-    }
+  if (WindowObject->Unicode == TRUE)
+  {
+       Result = IntCallWindowProc(WindowObject->WndProcW,
+                                       Msg.hwnd,
+                                       Msg.message,
+                                       Msg.wParam,
+                                       Msg.lParam);
+  }
+  else
+  {
+       Result = IntCallWindowProc(WindowObject->WndProcA,
+                                       Msg.hwnd,
+                                       Msg.message,
+                                       Msg.wParam,
+                                       Msg.lParam);
+  }
 
-  return(Result);
+  return Result;
 }
 
-BOOL STDCALL
-NtUserGetMessage(LPMSG lpMsg,
-                HWND hWnd,
-                UINT wMsgFilterMin,
-                UINT wMsgFilterMax)
 /*
- * FUNCTION: Get a message from the calling thread's message queue.
- * ARGUMENTS:
- *      lpMsg - Pointer to the structure which receives the returned message.
- *      hWnd - Window whose messages are to be retrieved.
- *      wMsgFilterMin - Integer value of the lowest message value to be
- *                      retrieved.
- *      wMsgFilterMax - Integer value of the highest message value to be
- *                      retrieved.
+ * Internal version of PeekMessage() doing all the work
  */
+BOOL STDCALL
+IntPeekMessage(LPMSG Msg,
+                HWND Wnd,
+                UINT MsgFilterMin,
+                UINT MsgFilterMax,
+                UINT RemoveMsg)
 {
   PUSER_MESSAGE_QUEUE ThreadQueue;
   BOOLEAN Present;
   PUSER_MESSAGE Message;
-  NTSTATUS Status;
+  BOOLEAN RemoveMessages;
 
-  /* Initialize the thread's win32 state if necessary. */ 
-  W32kGuiCheck();
+  /* The queues and order in which they are checked are documented in the MSDN
+     article on GetMessage() */
 
   ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
 
-  do
-    {
-      /* Dispatch sent messages here. */
-      while (MsqDispatchOneSentMessage(ThreadQueue));
+  /* Inspect RemoveMsg flags */
+  /* FIXME: The only flag we process is PM_REMOVE - processing of others must still be implemented */
+  RemoveMessages = RemoveMsg & PM_REMOVE;
+
+  /* Dispatch sent messages here. */
+  while (MsqDispatchOneSentMessage(ThreadQueue))
+    ;
       
-      /* Now look for a quit message. */
-      /* FIXME: WINE checks the message number filter here. */
-      if (ThreadQueue->QuitPosted)
-       {
-         lpMsg->hwnd = hWnd;
-         lpMsg->message = WM_QUIT;
-         lpMsg->wParam = ThreadQueue->QuitExitCode;
-         lpMsg->lParam = 0;
-         ThreadQueue->QuitPosted = FALSE;
-         return(FALSE);
-       }
+  /* Now look for a quit message. */
+  /* FIXME: WINE checks the message number filter here. */
+  if (ThreadQueue->QuitPosted)
+  {
+    Msg->hwnd = Wnd;
+    Msg->message = WM_QUIT;
+    Msg->wParam = ThreadQueue->QuitExitCode;
+    Msg->lParam = 0;
+    if (RemoveMessages)
+      {
+        ThreadQueue->QuitPosted = FALSE;
+      }
+    return TRUE;
+  }
 
-      /* Now check for normal messages. */
-      Present = MsqFindMessage(ThreadQueue,
-                              FALSE,
-                              TRUE,
-                              hWnd,
-                              wMsgFilterMin,
-                              wMsgFilterMax,
-                              &Message);
-      if (Present)
+  /* Now check for normal messages. */
+  Present = MsqFindMessage(ThreadQueue,
+                           FALSE,
+                           RemoveMessages,
+                           Wnd,
+                           MsgFilterMin,
+                           MsgFilterMax,
+                           &Message);
+  if (Present)
+    {
+      RtlCopyMemory(Msg, &Message->Msg, sizeof(MSG));
+      if (RemoveMessages)
        {
-         RtlCopyMemory(lpMsg, &Message->Msg, sizeof(MSG));
-         ExFreePool(Message);
-         return(TRUE);
+         MsqDestroyMessage(Message);
        }
+      return TRUE;
+    }
 
-      /* Check for hardware events. */
-      Present = MsqFindMessage(ThreadQueue,
-                              TRUE,
-                              TRUE,
-                              hWnd,
-                              wMsgFilterMin,
-                              wMsgFilterMax,
-                              &Message);
-      if (Present)
+  /* Check for hardware events. */
+  Present = MsqFindMessage(ThreadQueue,
+                           TRUE,
+                           RemoveMessages,
+                           Wnd,
+                           MsgFilterMin,
+                           MsgFilterMax,
+                           &Message);
+  if (Present)
+    {
+      RtlCopyMemory(Msg, &Message->Msg, sizeof(MSG));
+      if (RemoveMessages)
        {
-         RtlCopyMemory(lpMsg, &Message->Msg, sizeof(MSG));
-         ExFreePool(Message);
-         return(TRUE);
+         MsqDestroyMessage(Message);
        }
+      return TRUE;
+    }
 
-      /* Check for sent messages again. */
-      while (MsqDispatchOneSentMessage(ThreadQueue));
+  /* Check for sent messages again. */
+  while (MsqDispatchOneSentMessage(ThreadQueue))
+    ;
 
-      /* Check for paint messages. */
-      if (ThreadQueue->PaintPosted)
-       {
-         PWINDOW_OBJECT WindowObject;
+  /* Check for paint messages. */
+  if (ThreadQueue->PaintPosted)
+    {
+      PWINDOW_OBJECT WindowObject;
 
-         lpMsg->hwnd = PaintingFindWinToRepaint(hWnd, PsGetWin32Thread());
-         lpMsg->message = WM_PAINT;
-         lpMsg->wParam = lpMsg->lParam = 0;
+      Msg->hwnd = PaintingFindWinToRepaint(Wnd, PsGetWin32Thread());
+      Msg->message = WM_PAINT;
+      Msg->wParam = Msg->lParam = 0;
 
-         WindowObject = W32kGetWindowObject(lpMsg->hwnd);
-         if (WindowObject != NULL)
+      WindowObject = IntGetWindowObject(Msg->hwnd);
+      if (WindowObject != NULL)
+       {
+         if (WindowObject->Style & WS_MINIMIZE &&
+             (HICON)NtUserGetClassLong(Msg->hwnd, GCL_HICON, FALSE) != NULL)
            {
-             if (WindowObject->Style & WS_MINIMIZE &&
-                 (HICON)NtUserGetClassLong(lpMsg->hwnd, GCL_HICON) != NULL)
-               {
-                 lpMsg->message = WM_PAINTICON;
-                 lpMsg->wParam = 1;
-               }
+             Msg->message = WM_PAINTICON;
+             Msg->wParam = 1;
+           }
 
-             if (lpMsg->hwnd == NULL || lpMsg->hwnd == hWnd ||
-                 W32kIsChildWindow(hWnd, lpMsg->hwnd))
+         if (Msg->hwnd == NULL || Msg->hwnd == Wnd ||
+             IntIsChildWindow(Wnd, Msg->hwnd))
+           {
+             if (WindowObject->Flags & WINDOWOBJECT_NEED_INTERNALPAINT &&
+                 WindowObject->UpdateRegion == NULL)
                {
-                 if (WindowObject->Flags & WINDOWOBJECT_NEED_INTERNALPAINT &&
-                     WindowObject->UpdateRegion == NULL)
+                 WindowObject->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT;
+                 if (RemoveMessages)
                    {
-                     WindowObject->Flags &= ~WINDOWOBJECT_NEED_INTERNALPAINT;
                      MsqDecPaintCountQueue(WindowObject->MessageQueue);
                    }
                }
-             W32kReleaseWindowObject(WindowObject);
            }
+         IntReleaseWindowObject(WindowObject);
+       }
+
+      return TRUE;
+    }
 
-         return(TRUE); 
+  return FALSE;
+}
+
+BOOL STDCALL
+NtUserPeekMessage(LPMSG UnsafeMsg,
+                  HWND Wnd,
+                  UINT MsgFilterMin,
+                  UINT MsgFilterMax,
+                  UINT RemoveMsg)
+{
+  MSG SafeMsg;
+  NTSTATUS Status;
+  BOOL Present;
+  PWINDOW_OBJECT Window;
+
+  /* Validate input */
+  if (NULL != Wnd)
+    {
+      Status = ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
+                                          Wnd, otWindow, (PVOID*)&Window);
+      if (!NT_SUCCESS(Status))
+        {
+         Wnd = NULL;
+        }
+      else
+       {
+         ObmDereferenceObject(Window);
        }
+    }
+  if (MsgFilterMax < MsgFilterMin)
+    {
+      MsgFilterMin = 0;
+      MsgFilterMax = 0;
+    }
 
-      /* Nothing found so far. Wait for new messages. */
-      Status = MsqWaitForNewMessages(ThreadQueue);
+  Present = IntPeekMessage(&SafeMsg, Wnd, MsgFilterMin, MsgFilterMax, RemoveMsg);
+  if (Present)
+    {
+      Status = MmCopyToCaller(UnsafeMsg, &SafeMsg, sizeof(MSG));
+      if (! NT_SUCCESS(Status))
+       {
+         /* There is error return documented for PeekMessage().
+             Do the best we can */
+         SetLastNtError(Status);
+         return FALSE;
+       }
     }
-  while (Status >= STATUS_WAIT_0 && Status <= STATUS_WAIT_63);
-  return((BOOLEAN)(-1));
+
+  return Present;
 }
 
-DWORD
-STDCALL
-NtUserMessageCall(
-  DWORD Unknown0,
-  DWORD Unknown1,
-  DWORD Unknown2,
-  DWORD Unknown3,
-  DWORD Unknown4,
-  DWORD Unknown5,
-  DWORD Unknown6)
+static BOOL STDCALL
+IntWaitMessage(HWND Wnd,
+                UINT MsgFilterMin,
+                UINT MsgFilterMax)
 {
-  UNIMPLEMENTED
+  PUSER_MESSAGE_QUEUE ThreadQueue;
+  NTSTATUS Status;
+  MSG Msg;
 
-  return 0;
+  ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
+
+  do
+    {
+      if (IntPeekMessage(&Msg, Wnd, MsgFilterMin, MsgFilterMax, PM_NOREMOVE))
+       {
+         return TRUE;
+       }
+
+      /* Nothing found. Wait for new messages. */
+      Status = MsqWaitForNewMessages(ThreadQueue);
+    }
+  while (STATUS_WAIT_0 <= STATUS_WAIT_0 && Status <= STATUS_WAIT_63);
+
+  SetLastNtError(Status);
+
+  return FALSE;
 }
 
 BOOL STDCALL
-NtUserPeekMessage(LPMSG lpMsg,
-  HWND hWnd,
-  UINT wMsgFilterMin,
-  UINT wMsgFilterMax,
-  UINT wRemoveMsg)
+NtUserGetMessage(LPMSG UnsafeMsg,
+                HWND Wnd,
+                UINT MsgFilterMin,
+                UINT MsgFilterMax)
 /*
  * FUNCTION: Get a message from the calling thread's message queue.
  * ARGUMENTS:
- *      lpMsg - Pointer to the structure which receives the returned message.
- *      hWnd - Window whose messages are to be retrieved.
- *      wMsgFilterMin - Integer value of the lowest message value to be
- *                      retrieved.
- *      wMsgFilterMax - Integer value of the highest message value to be
- *                      retrieved.
- *      wRemoveMsg - Specificies whether or not to remove messages from the queue after processing
+ *      UnsafeMsg - Pointer to the structure which receives the returned message.
+ *      Wnd - Window whose messages are to be retrieved.
+ *      MsgFilterMin - Integer value of the lowest message value to be
+ *                     retrieved.
+ *      MsgFilterMax - Integer value of the highest message value to be
+ *                     retrieved.
  */
 {
-  PUSER_MESSAGE_QUEUE ThreadQueue;
-  BOOLEAN Present;
-  PUSER_MESSAGE Message;
-  BOOLEAN RemoveMessages;
-
-  /* Initialize the thread's win32 state if necessary. */ 
-  W32kGuiCheck();
-
-  ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
-
-  /* Inspect wRemoveMsg flags */
-  /* FIXME: The only flag we process is PM_REMOVE - processing of others must still be implemented */
-  RemoveMessages = wRemoveMsg & PM_REMOVE;
-
-  /* FIXME: Dispatch sent messages here. */
-      
-  /* Now look for a quit message. */
-  /* FIXME: WINE checks the message number filter here. */
-  if (ThreadQueue->QuitPosted)
-  {
-         lpMsg->hwnd = hWnd;
-         lpMsg->message = WM_QUIT;
-         lpMsg->wParam = ThreadQueue->QuitExitCode;
-         lpMsg->lParam = 0;
-         ThreadQueue->QuitPosted = FALSE;
-         return(FALSE);
-  }
+  BOOL GotMessage;
+  MSG SafeMsg;
+  NTSTATUS Status;
+  PWINDOW_OBJECT Window;
 
-  /* Now check for normal messages. */
-  Present = MsqFindMessage(ThreadQueue,
-       FALSE,
-       RemoveMessages,
-       hWnd,
-       wMsgFilterMin,
-       wMsgFilterMax,
-       &Message);
-  if (Present)
-  {
-         RtlCopyMemory(lpMsg, &Message->Msg, sizeof(MSG));
-         ExFreePool(Message);
-         return(TRUE);
-  }
+  /* Validate input */
+  if (NULL != Wnd)
+    {
+      Status = ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
+                                          Wnd, otWindow, (PVOID*)&Window);
+      if (!NT_SUCCESS(Status))
+        {
+         Wnd = NULL;
+        }
+      else
+       {
+         ObmDereferenceObject(Window);
+       }
+    }
+  if (MsgFilterMax < MsgFilterMin)
+    {
+      MsgFilterMin = 0;
+      MsgFilterMax = 0;
+    }
 
-  /* Check for hardware events. */
-  Present = MsqFindMessage(ThreadQueue,
-       TRUE,
-       RemoveMessages,
-       hWnd,
-       wMsgFilterMin,
-       wMsgFilterMax,
-       &Message);
-  if (Present)
-  {
-         RtlCopyMemory(lpMsg, &Message->Msg, sizeof(MSG));
-         ExFreePool(Message);
-         return(TRUE);
-  }
+  do
+    {
+      GotMessage = IntPeekMessage(&SafeMsg, Wnd, MsgFilterMin, MsgFilterMax, PM_REMOVE);
+      if (GotMessage)
+       {
+         Status = MmCopyToCaller(UnsafeMsg, &SafeMsg, sizeof(MSG));
+         if (! NT_SUCCESS(Status))
+           {
+             SetLastNtError(Status);
+             return (BOOL) -1;
+           }
+       }
+      else
+       {
+         IntWaitMessage(Wnd, MsgFilterMin, MsgFilterMax);
+       }
+    }
+  while (! GotMessage);
 
-  /* FIXME: Check for sent messages again. */
+  return WM_QUIT != SafeMsg.message;
+}
 
-  /* FIXME: Check for paint messages. */
+DWORD
+STDCALL
+NtUserMessageCall(
+  DWORD Unknown0,
+  DWORD Unknown1,
+  DWORD Unknown2,
+  DWORD Unknown3,
+  DWORD Unknown4,
+  DWORD Unknown5,
+  DWORD Unknown6)
+{
+  UNIMPLEMENTED
 
-  return((BOOLEAN)(-1));
+  return 0;
 }
 
 BOOL STDCALL
@@ -325,9 +411,34 @@ NtUserPostMessage(HWND hWnd,
                  WPARAM wParam,
                  LPARAM lParam)
 {
-  UNIMPLEMENTED;
-    
-  return 0;
+  PWINDOW_OBJECT Window;
+  MSG Mesg;
+  PUSER_MESSAGE Message;
+  NTSTATUS Status;
+
+  if (WM_QUIT == Msg)
+    {
+      MsqPostQuitMessage(PsGetWin32Thread()->MessageQueue, wParam);
+    }
+  else
+    {
+      Status = ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
+                                          hWnd, otWindow, (PVOID*)&Window);
+      if (!NT_SUCCESS(Status))
+        {
+         SetLastNtError(Status);
+          return FALSE;
+        }
+      Mesg.hwnd = hWnd;
+      Mesg.message = Msg;
+      Mesg.wParam = wParam;
+      Mesg.lParam = lParam;
+      Message = MsqCreateMessage(&Mesg);
+      MsqPostMessage(Window->MessageQueue, Message);
+      ObmDereferenceObject(Window);
+    }
+
+  return TRUE;
 }
 
 BOOL STDCALL
@@ -336,9 +447,34 @@ NtUserPostThreadMessage(DWORD idThread,
                        WPARAM wParam,
                        LPARAM lParam)
 {
-  UNIMPLEMENTED;
+  MSG Mesg;
 
-  return 0;
+  PUSER_MESSAGE Message;
+  PETHREAD peThread;
+  PW32THREAD pThread;
+  NTSTATUS Status;
+
+  Status = PsLookupThreadByThreadId((void *)idThread,&peThread);
+  
+  if( Status == STATUS_SUCCESS ) {
+    pThread = peThread->Win32Thread;
+    if( !pThread || !pThread->MessageQueue )
+      {
+       ObDereferenceObject( peThread );
+       return FALSE;
+      }
+    Mesg.hwnd = 0;
+    Mesg.message = Msg;
+    Mesg.wParam = wParam;
+    Mesg.lParam = lParam;
+    Message = MsqCreateMessage(&Mesg);
+    MsqPostMessage(pThread->MessageQueue, Message);
+    ObDereferenceObject( peThread );
+    return TRUE;
+  } else {
+    SetLastNtError( Status );
+    return FALSE;
+  }
 }
 
 DWORD STDCALL
@@ -350,7 +486,7 @@ NtUserQuerySendMessage(DWORD Unknown0)
 }
 
 LRESULT STDCALL
-W32kSendMessage(HWND hWnd,
+IntSendMessage(HWND hWnd,
                UINT Msg,
                WPARAM wParam,
                LPARAM lParam,
@@ -371,30 +507,38 @@ W32kSendMessage(HWND hWnd,
                               (PVOID*)&Window);
   if (!NT_SUCCESS(Status))
     {
-      return(FALSE);
+      return 0;
     }
 
   /* FIXME: Check for an exiting window. */
 
-  if (Window->MessageQueue == PsGetWin32Thread()->MessageQueue)
+  if (NULL != PsGetWin32Thread() &&
+      Window->MessageQueue == PsGetWin32Thread()->MessageQueue)
     {
       if (KernelMessage)
        {
-         Result = W32kCallTrampolineWindowProc(NULL, hWnd, Msg, wParam,
+         Result = IntCallTrampolineWindowProc(NULL, hWnd, Msg, wParam,
                                                lParam);
-         return(Result);
+         return Result;
        }
       else
        {
-         Result = W32kCallWindowProc(NULL, hWnd, Msg, wParam, lParam);
-         return(Result);
+       if (Window->Unicode == TRUE)
+       {
+         Result = IntCallWindowProc(Window->WndProcW, hWnd, Msg, wParam, lParam);
+       }
+       else
+       {
+         Result = IntCallWindowProc(Window->WndProcA, hWnd, Msg, wParam, lParam);
+       }
+         return Result;
        }
     }
   else
     {
       PUSER_SENT_MESSAGE Message;
       PKEVENT CompletionEvent;
-      
+
       CompletionEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
       KeInitializeEvent(CompletionEvent, NotificationEvent, FALSE);
 
@@ -417,22 +561,22 @@ W32kSendMessage(HWND hWnd,
                                     NULL);
       if (Status == STATUS_WAIT_0)
        {
-         return(Result);
+         return Result;
        }
       else
        {
-         return(FALSE);
+         return FALSE;
        }
     }
 }
 
 LRESULT STDCALL
-NtUserSendMessage(HWND hWnd,
+NtUserSendMessage(HWND Wnd,
                  UINT Msg,
                  WPARAM wParam,
                  LPARAM lParam)
 {
-  return(W32kSendMessage(hWnd, Msg, wParam, lParam, FALSE));
+  return IntSendMessage(Wnd, Msg, wParam, lParam, FALSE);
 }
 
 BOOL STDCALL
@@ -443,7 +587,9 @@ NtUserSendMessageCallback(HWND hWnd,
                          SENDASYNCPROC lpCallBack,
                          ULONG_PTR dwData)
 {
-  return(0);
+  UNIMPLEMENTED;
+
+  return 0;
 }
 
 BOOL STDCALL
@@ -460,9 +606,30 @@ NtUserSendNotifyMessage(HWND hWnd,
 BOOL STDCALL
 NtUserWaitMessage(VOID)
 {
-  UNIMPLEMENTED;
 
-  return 0;
+  return IntWaitMessage(NULL, 0, 0);
+}
+
+
+DWORD STDCALL
+NtUserGetQueueStatus(BOOL ClearChanges)
+{
+   PUSER_MESSAGE_QUEUE Queue;
+   DWORD Result;
+
+   Queue = PsGetWin32Thread()->MessageQueue;
+
+   ExAcquireFastMutex(&Queue->Lock);
+
+   Result = MAKELONG(Queue->ChangedBits, Queue->WakeBits);
+   if (ClearChanges)
+   {
+      Queue->ChangedBits = 0;
+   }
+
+   ExReleaseFastMutex(&Queue->Lock);
+
+   return Result;
 }
 
 /* EOF */