update for HEAD-2003091401
[reactos.git] / subsys / win32k / ntuser / msgqueue.c
index 664e347..2af0945 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
@@ -30,6 +48,7 @@ static MSG SystemMessageQueue[SYSTEM_MESSAGE_QUEUE_SIZE];
 static ULONG SystemMessageQueueHead = 0;
 static ULONG SystemMessageQueueTail = 0;
 static ULONG SystemMessageQueueCount = 0;
+static ULONG SystemMessageQueueMouseMove = -1;
 static KSPIN_LOCK SystemMessageQueueLock;
 
 static ULONG HardwareMessageQueueStamp = 0;
@@ -38,18 +57,42 @@ static FAST_MUTEX HardwareMessageQueueLock;
 
 static KEVENT HardwareMessageEvent;
 
+static PAGED_LOOKASIDE_LIST MessageLookasideList;
+
 /* FUNCTIONS *****************************************************************/
 
-VOID
+/* check the queue status */
+inline BOOL MsqIsSignaled( PUSER_MESSAGE_QUEUE Queue )
+{
+    return ((Queue->WakeBits & Queue->WakeMask) || (Queue->ChangedBits & Queue->ChangedMask));
+}
+
+/* set some queue bits */
+inline VOID MsqSetQueueBits( PUSER_MESSAGE_QUEUE Queue, WORD Bits )
+{
+    Queue->WakeBits |= Bits;
+    Queue->ChangedBits |= Bits;
+    if (MsqIsSignaled( Queue )) KeSetEvent(&Queue->NewMessages, IO_NO_INCREMENT, FALSE);
+}
+
+/* clear some queue bits */
+inline VOID MsqClearQueueBits( PUSER_MESSAGE_QUEUE Queue, WORD Bits )
+{
+    Queue->WakeBits &= ~Bits;
+    Queue->ChangedBits &= ~Bits;
+}
+
+VOID FASTCALL
 MsqIncPaintCountQueue(PUSER_MESSAGE_QUEUE Queue)
 {
   ExAcquireFastMutex(&Queue->Lock);
   Queue->PaintCount++;
   Queue->PaintPosted = TRUE;
+  KeSetEvent(&Queue->NewMessages, IO_NO_INCREMENT, FALSE);
   ExReleaseFastMutex(&Queue->Lock);
 }
 
-VOID
+VOID FASTCALL
 MsqDecPaintCountQueue(PUSER_MESSAGE_QUEUE Queue)
 {
   ExAcquireFastMutex(&Queue->Lock);
@@ -62,7 +105,7 @@ MsqDecPaintCountQueue(PUSER_MESSAGE_QUEUE Queue)
 }
 
 
-NTSTATUS
+NTSTATUS FASTCALL
 MsqInitializeImpl(VOID)
 {
   /*CurrentFocusMessageQueue = NULL;*/
@@ -70,132 +113,143 @@ MsqInitializeImpl(VOID)
   KeInitializeEvent(&HardwareMessageEvent, NotificationEvent, 0);
   KeInitializeSpinLock(&SystemMessageQueueLock);
   ExInitializeFastMutex(&HardwareMessageQueueLock);
+
+  ExInitializePagedLookasideList(&MessageLookasideList,
+                                NULL,
+                                NULL,
+                                0,
+                                sizeof(USER_MESSAGE),
+                                0,
+                                256);
+
   return(STATUS_SUCCESS);
 }
 
-VOID
-MsqInsertSystemMessage(MSG* Msg)
+VOID FASTCALL
+MsqInsertSystemMessage(MSG* Msg, BOOL RemMouseMoveMsg)
 {
   KIRQL OldIrql;
+  ULONG mmov = (ULONG)-1;
 
   KeAcquireSpinLock(&SystemMessageQueueLock, &OldIrql);
-  if (SystemMessageQueueCount == SYSTEM_MESSAGE_QUEUE_SIZE)
+
+  /* only insert WM_MOUSEMOVE messages if not already in system message queue */
+  if((Msg->message == WM_MOUSEMOVE) && RemMouseMoveMsg)
+    mmov = SystemMessageQueueMouseMove;
+
+  if(mmov != (ULONG)-1)
+  {
+    /* insert message at the queue head */
+    while (mmov != SystemMessageQueueHead )
+    {
+      ULONG prev = mmov ? mmov - 1 : SYSTEM_MESSAGE_QUEUE_SIZE - 1;
+      SystemMessageQueue[mmov] = SystemMessageQueue[prev];
+      mmov = prev;
+    }
+    SystemMessageQueue[SystemMessageQueueHead] = *Msg;
+  }
+  else
+  {
+    if (SystemMessageQueueCount == SYSTEM_MESSAGE_QUEUE_SIZE)
     {
       KeReleaseSpinLock(&SystemMessageQueueLock, OldIrql);
       return;
     }
-  SystemMessageQueue[SystemMessageQueueTail] = *Msg;
-  SystemMessageQueueTail = 
-    (SystemMessageQueueTail + 1) % SYSTEM_MESSAGE_QUEUE_SIZE;
-  SystemMessageQueueCount++;
+    SystemMessageQueue[SystemMessageQueueTail] = *Msg;
+    if(Msg->message == WM_MOUSEMOVE)
+      SystemMessageQueueMouseMove = SystemMessageQueueTail;
+    SystemMessageQueueTail =
+      (SystemMessageQueueTail + 1) % SYSTEM_MESSAGE_QUEUE_SIZE;
+    SystemMessageQueueCount++;
+  }
   KeReleaseSpinLock(&SystemMessageQueueLock, OldIrql);
   KeSetEvent(&HardwareMessageEvent, IO_NO_INCREMENT, FALSE);
 }
 
-BOOL STATIC
+BOOL STATIC STDCALL
 MsqTranslateMouseMessage(HWND hWnd, UINT FilterLow, UINT FilterHigh,
-                        PUSER_MESSAGE Message, BOOL Remove, 
+                        PUSER_MESSAGE Message, BOOL Remove,
                         PWINDOW_OBJECT ScopeWin, PUSHORT HitTest,
                         PPOINT ScreenPoint, PBOOL MouseClick)
 {
-  static ULONG ClkTime = 0;
-  static USHORT ClkMessage = 0;
-  static HWND ClkWnd = 0;
-  static POINT ClkPos = {0, 0};
-
   USHORT Msg = Message->Msg.message;
   PWINDOW_OBJECT Window;
   POINT Point;
-  ULONG Click = 0;
 
-  /* FIXME: Handle window capture. */
+  if ((Window = IntGetCaptureWindow()) == NULL)
+  {
+    *HitTest = WinPosWindowFromPoint(ScopeWin, Message->Msg.pt, &Window);
+  }
+  else
+  {
+    *HitTest = HTCLIENT;
+  }
 
-  *HitTest = WinPosWindowFromPoint(ScopeWin, Message->Msg.pt, &Window);
-  
   if (Window == NULL)
-    {
-      ExFreePool(Message);
-      return(FALSE);
-    }
+  {
+    ExFreePool(Message);
+    return(FALSE);
+  }
   if (Window->MessageQueue != PsGetWin32Thread()->MessageQueue)
-    {      
-      ExAcquireFastMutex(&Window->MessageQueue->Lock);
-      InsertTailList(&Window->MessageQueue->HardwareMessagesListHead,
-                    &Message->ListEntry);
-      ExReleaseFastMutex(&Window->MessageQueue->Lock);
-      KeSetEvent(&Window->MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE);
-      return(FALSE);
-    }
+  {
+    ExAcquireFastMutex(&Window->MessageQueue->Lock);
+    InsertTailList(&Window->MessageQueue->HardwareMessagesListHead,
+                   &Message->ListEntry);
+    ExReleaseFastMutex(&Window->MessageQueue->Lock);
+    KeSetEvent(&Window->MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE);
+    return(FALSE);
+  }
 
-  if (hWnd != NULL && Window->Self != hWnd && 
-      !W32kIsChildWindow(hWnd, Window->Self))
-    {
-      return(FALSE);
-    }
+  if (hWnd != NULL && Window->Self != hWnd &&
+      !IntIsChildWindow(hWnd, Window->Self))
+  {
+    return(FALSE);
+  }
 
-  if (Msg == WM_LBUTTONDOWN || Msg == WM_RBUTTONDOWN || Msg == WM_MBUTTONDOWN)
-    {
-      (*MouseClick) = Click = 1;
-    }
-  if (Click)
-    {
-      if (W32kGetClassLong(Window, GCL_STYLE) & CS_DBLCLKS ||
-         (*HitTest) != HTCLIENT)
+  if (Msg == WM_LBUTTONDBLCLK || Msg == WM_RBUTTONDBLCLK || Msg == WM_MBUTTONDBLCLK)
+  {
+    if (((*HitTest) != HTCLIENT) || !(IntGetClassLong(Window, GCL_STYLE, FALSE) & CS_DBLCLKS))
        {
-         if (Msg == ClkMessage &&
-             Window->Self == ClkWnd &&
-             (Message->Msg.time - ClkTime) < 452 &&
-             abs(Message->Msg.pt.x - ClkPos.x) < 2 &&
-             abs(Message->Msg.pt.y - ClkPos.y) < 2)
-           {
-             Msg += (WM_LBUTTONDBLCLK - WM_LBUTTONDOWN);
-             Click++;
-           }
+      Msg -= (WM_LBUTTONDBLCLK - WM_LBUTTONDOWN);
+      /* FIXME set WindowStation's system cursor variables:
+               LastBtnDown to Msg.time
+      */
        }
-    }
+       else
+       {
+         /* FIXME check if the dblclick was made in the same window, if
+                  not, change it to a normal click message */
+       }
+  }
 
   *ScreenPoint = Message->Msg.pt;
+  Point = Message->Msg.pt;
 
   if ((*HitTest) != HTCLIENT)
-    {
-      Msg += WM_NCMOUSEMOVE - WM_MOUSEMOVE;
-      Message->Msg.wParam = *HitTest;
-    }
+  {
+    Msg += WM_NCMOUSEMOVE - WM_MOUSEMOVE;
+    Message->Msg.wParam = *HitTest;
+  }
   else
-    {
-      Point = Message->Msg.pt;
-
-      Point.x -= Window->ClientRect.left;
-      Point.y -= Window->ClientRect.top;
-    }
+  {
+    Point.x -= Window->ClientRect.left;
+    Point.y -= Window->ClientRect.top;
+  }
 
   /* FIXME: Check message filter. */
 
-  if (Remove && Click)
+  if (Remove)
     {
-      if (Click == 1)
-       {
-         ClkTime = Message->Msg.time;
-         ClkMessage = Msg;
-         ClkWnd = Window->Self;
-         ClkPos = (*ScreenPoint);
-       }
-      else
-       {
-         ClkTime = 0;
-         ClkWnd = NULL;
-       }
+      Message->Msg.hwnd = Window->Self;
+      Message->Msg.message = Msg;
+      Message->Msg.lParam = MAKELONG(Point.x, Point.y);
     }
 
-  Message->Msg.hwnd = Window->Self;
-  Message->Msg.message = Msg;
-  Message->Msg.lParam = MAKELONG(Point.x, Point.y);
-
   return(TRUE);
 }
 
-BOOL
-MsqPeekHardwareMessage(PUSER_MESSAGE_QUEUE MessageQueue, HWND hWnd, 
+BOOL STDCALL
+MsqPeekHardwareMessage(PUSER_MESSAGE_QUEUE MessageQueue, HWND hWnd,
                       UINT FilterLow, UINT FilterHigh, BOOL Remove,
                       PUSER_MESSAGE* Message)
 {
@@ -208,34 +262,35 @@ MsqPeekHardwareMessage(PUSER_MESSAGE_QUEUE MessageQueue, HWND hWnd,
   ULONG ActiveStamp;
   PWINDOW_OBJECT DesktopWindow;
 
-  DesktopWindow = W32kGetWindowObject(W32kGetDesktopWindow());
+  DesktopWindow = IntGetWindowObject(IntGetDesktopWindow());
 
   /* Process messages in the message queue itself. */
   ExAcquireFastMutex(&MessageQueue->Lock);
   CurrentEntry = MessageQueue->HardwareMessagesListHead.Flink;
   while (CurrentEntry != &MessageQueue->HardwareMessagesListHead)
     {
-      PUSER_MESSAGE Current = 
+      PUSER_MESSAGE Current =
        CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, ListEntry);
       CurrentEntry = CurrentEntry->Flink;
-      RemoveEntryList(&Current->ListEntry);
-      if (Current->Msg.message >= WM_MOUSEFIRST && 
+      if (Current->Msg.message >= WM_MOUSEFIRST &&
          Current->Msg.message <= WM_MOUSELAST)
        {
          Accept = MsqTranslateMouseMessage(hWnd, FilterLow, FilterHigh,
-                                           Current, Remove, 
+                                           Current, Remove,
                                            DesktopWindow, &HitTest,
                                            &ScreenPoint, &MouseClick);
          if (Accept)
            {
-             RemoveEntryList(&Current->ListEntry);
+             if (Remove)
+               {
+                 RemoveEntryList(&Current->ListEntry);
+               }
              ExReleaseFastMutex(&MessageQueue->Lock);
              *Message = Current;
-             W32kReleaseWindowObject(DesktopWindow);
+             IntReleaseWindowObject(DesktopWindow);
              return(TRUE);
            }
        }
-      CurrentEntry = CurrentEntry->Flink;
     }
   ExReleaseFastMutex(&MessageQueue->Lock);
 
@@ -244,20 +299,25 @@ MsqPeekHardwareMessage(PUSER_MESSAGE_QUEUE MessageQueue, HWND hWnd,
   /* Transfer all messages from the DPC accessible queue to the main queue. */
   KeAcquireSpinLock(&SystemMessageQueueLock, &OldIrql);
   while (SystemMessageQueueCount > 0)
-    {      
+    {
       PUSER_MESSAGE UserMsg;
       MSG Msg;
 
       Msg = SystemMessageQueue[SystemMessageQueueHead];
-      SystemMessageQueueHead = 
+      SystemMessageQueueHead =
        (SystemMessageQueueHead + 1) % SYSTEM_MESSAGE_QUEUE_SIZE;
       SystemMessageQueueCount--;
       KeReleaseSpinLock(&SystemMessageQueueLock, OldIrql);
-      UserMsg = ExAllocatePool(NonPagedPool, sizeof(USER_MESSAGE));
+      UserMsg = ExAllocateFromPagedLookasideList(&MessageLookasideList);
       UserMsg->Msg = Msg;
       InsertTailList(&HardwareMessageQueueHead, &UserMsg->ListEntry);
       KeAcquireSpinLock(&SystemMessageQueueLock, &OldIrql);
     }
+  /*
+   * we could set this to -1 conditionally if we find one, but
+   * this is more efficient and just as effective.
+   */
+  SystemMessageQueueMouseMove = -1;
   KeReleaseSpinLock(&SystemMessageQueueLock, OldIrql);
   HardwareMessageQueueStamp++;
 
@@ -265,11 +325,11 @@ MsqPeekHardwareMessage(PUSER_MESSAGE_QUEUE MessageQueue, HWND hWnd,
   CurrentEntry = HardwareMessageQueueHead.Flink;
   while (CurrentEntry != &HardwareMessageQueueHead)
     {
-      PUSER_MESSAGE Current = 
+      PUSER_MESSAGE Current =
        CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, ListEntry);
       CurrentEntry = CurrentEntry->Flink;
       RemoveEntryList(&Current->ListEntry);
-      if (Current->Msg.message >= WM_MOUSEFIRST && 
+      if (Current->Msg.message >= WM_MOUSEFIRST &&
          Current->Msg.message <= WM_MOUSELAST)
        {
          ActiveStamp = HardwareMessageQueueStamp;
@@ -291,7 +351,7 @@ MsqPeekHardwareMessage(PUSER_MESSAGE_QUEUE MessageQueue, HWND hWnd,
                }
              KeReleaseSpinLock(&SystemMessageQueueLock, OldIrql);
 
-             /* 
+             /*
                 If we aren't removing the message then add it to the private
                 queue.
              */
@@ -301,8 +361,8 @@ MsqPeekHardwareMessage(PUSER_MESSAGE_QUEUE MessageQueue, HWND hWnd,
                                 &Current->ListEntry);
                }
              ExReleaseFastMutex(&HardwareMessageQueueLock);
-             *Message = Current;            
-             W32kReleaseWindowObject(DesktopWindow);
+             *Message = Current;
+             IntReleaseWindowObject(DesktopWindow);
              return(TRUE);
            }
          /* If the contents of the queue changed then restart processing. */
@@ -311,7 +371,7 @@ MsqPeekHardwareMessage(PUSER_MESSAGE_QUEUE MessageQueue, HWND hWnd,
              CurrentEntry = HardwareMessageQueueHead.Flink;
              continue;
            }
-       }      
+       }
     }
   /* Check if the system message queue is now empty. */
   KeAcquireSpinLock(&SystemMessageQueueLock, &OldIrql);
@@ -325,59 +385,70 @@ MsqPeekHardwareMessage(PUSER_MESSAGE_QUEUE MessageQueue, HWND hWnd,
   return(FALSE);
 }
 
-VOID
+VOID STDCALL
 MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
-#if 0
-  MSG Msg;
+  PUSER_MESSAGE_QUEUE FocusMessageQueue;
   PUSER_MESSAGE Message;
+  MSG Msg;
 
-  if (CurrentFocusMessageQueue == NULL)
+  DPRINT("MsqPostKeyboardMessage(uMsg 0x%x, wParam 0x%x, lParam 0x%x)\n",
+    uMsg, wParam, lParam);
+
+  FocusMessageQueue = IntGetFocusMessageQueue();
+  if (FocusMessageQueue == NULL)
     {
+      DPRINT("No focus message queue\n");
       return;
     }
 
-  Msg.hwnd = CurrentFocusMessageQueue->FocusWindow;
-  Msg.message = uMsg;
-  Msg.wParam = wParam;
-  Msg.lParam = lParam;
-  /* FIXME: Initialize time and point. */
-
-  Message = MsqCreateMessage(&Msg);
-  MsqPostMessage(CurrentFocusMessageQueue, Message, TRUE);
-#endif
+  if (FocusMessageQueue->FocusWindow != (HWND)0)
+    {
+      Msg.hwnd = FocusMessageQueue->FocusWindow;
+      Msg.message = uMsg;
+      Msg.wParam = wParam;
+      Msg.lParam = lParam;
+      /* FIXME: Initialize time and point. */
+
+      Message = MsqCreateMessage(&Msg);
+      MsqPostMessage(FocusMessageQueue, Message);
+    }
+  else
+    {
+      DPRINT("Invalid focus window handle\n");
+    }
 }
 
-VOID
+VOID FASTCALL
 MsqInitializeMessage(PUSER_MESSAGE Message,
                     LPMSG Msg)
 {
   RtlMoveMemory(&Message->Msg, Msg, sizeof(MSG));
 }
 
-PUSER_MESSAGE
+PUSER_MESSAGE FASTCALL
 MsqCreateMessage(LPMSG Msg)
 {
   PUSER_MESSAGE Message;
-  
-  Message = (PUSER_MESSAGE)ExAllocatePool(PagedPool, sizeof(USER_MESSAGE));
+
+  Message = ExAllocateFromPagedLookasideList(&MessageLookasideList);
   if (!Message)
     {
       return NULL;
     }
-  
+
   MsqInitializeMessage(Message, Msg);
-  
+
   return Message;
 }
 
-VOID
+VOID FASTCALL
 MsqDestroyMessage(PUSER_MESSAGE Message)
 {
-  ExFreePool(Message);
+  ExFreeToPagedLookasideList(&MessageLookasideList, Message);
 }
 
-VOID
+VOID FASTCALL
 MsqDispatchSentNotifyMessages(PUSER_MESSAGE_QUEUE MessageQueue)
 {
   PLIST_ENTRY ListEntry;
@@ -387,11 +458,11 @@ MsqDispatchSentNotifyMessages(PUSER_MESSAGE_QUEUE MessageQueue)
   {
     ExAcquireFastMutex(&MessageQueue->Lock);
     ListEntry = RemoveHeadList(&MessageQueue->SentMessagesListHead);
-    Message = CONTAINING_RECORD(ListEntry, USER_SENT_MESSAGE_NOTIFY, 
+    Message = CONTAINING_RECORD(ListEntry, USER_SENT_MESSAGE_NOTIFY,
                                ListEntry);
     ExReleaseFastMutex(&MessageQueue->Lock);
 
-    W32kCallSentMessageCallback(Message->CompletionCallback,
+    IntCallSentMessageCallback(Message->CompletionCallback,
                                Message->hWnd,
                                Message->Msg,
                                Message->CompletionCallbackContext,
@@ -399,13 +470,13 @@ MsqDispatchSentNotifyMessages(PUSER_MESSAGE_QUEUE MessageQueue)
   }
 }
 
-BOOLEAN
+BOOLEAN FASTCALL
 MsqPeekSentMessages(PUSER_MESSAGE_QUEUE MessageQueue)
 {
   return(!IsListEmpty(&MessageQueue->SentMessagesListHead));
 }
 
-BOOLEAN
+BOOLEAN FASTCALL
 MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
 {
   PUSER_SENT_MESSAGE Message;
@@ -424,7 +495,7 @@ MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
   ExReleaseFastMutex(&MessageQueue->Lock);
 
   /* Call the window procedure. */
-  Result = W32kCallWindowProc(NULL,
+  Result = IntCallWindowProc(NULL,
                              Message->Msg.hwnd,
                              Message->Msg.message,
                              Message->Msg.wParam,
@@ -445,9 +516,9 @@ MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
   /* Notify the sender if they specified a callback. */
   if (Message->CompletionCallback != NULL)
     {
-      NotifyMessage = ExAllocatePool(NonPagedPool, 
+      NotifyMessage = ExAllocatePool(NonPagedPool,
                                     sizeof(USER_SENT_MESSAGE_NOTIFY));
-      NotifyMessage->CompletionCallback = 
+      NotifyMessage->CompletionCallback =
        Message->CompletionCallback;
       NotifyMessage->CompletionCallbackContext =
        Message->CompletionCallbackContext;
@@ -461,26 +532,28 @@ MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
   return(TRUE);
 }
 
-VOID
+VOID FASTCALL
 MsqSendNotifyMessage(PUSER_MESSAGE_QUEUE MessageQueue,
                     PUSER_SENT_MESSAGE_NOTIFY NotifyMessage)
 {
   ExAcquireFastMutex(&MessageQueue->Lock);
-  InsertTailList(&MessageQueue->NotifyMessagesListHead, 
+  InsertTailList(&MessageQueue->NotifyMessagesListHead,
                 &NotifyMessage->ListEntry);
+  KeSetEvent(&MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE);
   ExReleaseFastMutex(&MessageQueue->Lock);
 }
 
-VOID
+VOID FASTCALL
 MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
               PUSER_SENT_MESSAGE Message)
 {
   ExAcquireFastMutex(&MessageQueue->Lock);
   InsertTailList(&MessageQueue->SentMessagesListHead, &Message->ListEntry);
+  KeSetEvent(&MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE);
   ExReleaseFastMutex(&MessageQueue->Lock);
 }
 
-VOID
+VOID FASTCALL
 MsqPostMessage(PUSER_MESSAGE_QUEUE MessageQueue, PUSER_MESSAGE Message)
 {
   ExAcquireFastMutex(&MessageQueue->Lock);
@@ -490,7 +563,17 @@ MsqPostMessage(PUSER_MESSAGE_QUEUE MessageQueue, PUSER_MESSAGE Message)
   ExReleaseFastMutex(&MessageQueue->Lock);
 }
 
-BOOLEAN
+VOID FASTCALL
+MsqPostQuitMessage(PUSER_MESSAGE_QUEUE MessageQueue, ULONG ExitCode)
+{
+  ExAcquireFastMutex(&MessageQueue->Lock);
+  MessageQueue->QuitPosted = TRUE;
+  MessageQueue->QuitExitCode = ExitCode;
+  KeSetEvent(&MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE);
+  ExReleaseFastMutex(&MessageQueue->Lock);
+}
+
+BOOLEAN STDCALL
 MsqFindMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
               IN BOOLEAN Hardware,
               IN BOOLEAN Remove,
@@ -509,13 +592,13 @@ MsqFindMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
                                    MsgFilterLow, MsgFilterHigh,
                                    Remove, Message));
     }
-  
+
   ExAcquireFastMutex(&MessageQueue->Lock);
   CurrentEntry = MessageQueue->PostedMessagesListHead.Flink;
   ListHead = &MessageQueue->PostedMessagesListHead;
   while (CurrentEntry != ListHead)
     {
-      CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, 
+      CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
                                         ListEntry);
       if ((Wnd == 0 || Wnd == CurrentMessage->Msg.hwnd) &&
          ((MsgFilterLow == 0 && MsgFilterHigh == 0) ||
@@ -536,7 +619,7 @@ MsqFindMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
   return(FALSE);
 }
 
-NTSTATUS
+NTSTATUS FASTCALL
 MsqWaitForNewMessages(PUSER_MESSAGE_QUEUE MessageQueue)
 {
   PVOID WaitObjects[2] = {&MessageQueue->NewMessages, &HardwareMessageEvent};
@@ -550,7 +633,7 @@ MsqWaitForNewMessages(PUSER_MESSAGE_QUEUE MessageQueue)
                                  NULL));
 }
 
-VOID
+VOID FASTCALL
 MsqInitializeMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue)
 {
   InitializeListHead(&MessageQueue->PostedMessagesListHead);
@@ -559,45 +642,45 @@ MsqInitializeMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue)
   ExInitializeFastMutex(&MessageQueue->Lock);
   MessageQueue->QuitPosted = FALSE;
   MessageQueue->QuitExitCode = 0;
-  KeInitializeEvent(&MessageQueue->NewMessages, NotificationEvent, FALSE);
+  KeInitializeEvent(&MessageQueue->NewMessages, SynchronizationEvent, FALSE);
   MessageQueue->QueueStatus = 0;
   MessageQueue->FocusWindow = NULL;
 }
 
-VOID
+VOID FASTCALL
 MsqFreeMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue)
 {
   PLIST_ENTRY CurrentEntry;
   PUSER_MESSAGE CurrentMessage;
-  
+
   CurrentEntry = MessageQueue->PostedMessagesListHead.Flink;
   while (CurrentEntry != &MessageQueue->PostedMessagesListHead)
     {
-      CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE, 
+      CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
                                         ListEntry);
       CurrentEntry = CurrentEntry->Flink;
-      ExFreePool(CurrentMessage);
+      MsqDestroyMessage(CurrentMessage);
     }
 }
 
-PUSER_MESSAGE_QUEUE
+PUSER_MESSAGE_QUEUE FASTCALL
 MsqCreateMessageQueue(VOID)
 {
   PUSER_MESSAGE_QUEUE MessageQueue;
 
-  MessageQueue = (PUSER_MESSAGE_QUEUE)ExAllocatePool(PagedPool, 
+  MessageQueue = (PUSER_MESSAGE_QUEUE)ExAllocatePool(PagedPool,
                                   sizeof(USER_MESSAGE_QUEUE));
   if (!MessageQueue)
     {
       return NULL;
     }
-  
+
   MsqInitializeMessageQueue(MessageQueue);
-  
+
   return MessageQueue;
 }
 
-VOID
+VOID FASTCALL
 MsqDestroyMessageQueue(PUSER_MESSAGE_QUEUE MessageQueue)
 {
   MsqFreeMessageQueue(MessageQueue);