Index: include/reactos/undocuser.h
===================================================================
--- include/reactos/undocuser.h	(revision 58773)
+++ include/reactos/undocuser.h	(working copy)
@@ -76,6 +76,10 @@
 
 /* Non SDK Queue state flags. */
 #define QS_SMRESULT 0x8000 /* see "Undoc. Windows" */
+//
+#define QS_EVENT          0x2000
+#define QS_SYSEVENT       (QS_EVENT|QS_SENDMESSAGE)
+//
 
 //
 // Definitions used by WM_CLIENTSHUTDOWN
Index: win32ss/user/ntuser/event.c
===================================================================
--- win32ss/user/ntuser/event.c	(revision 58773)
+++ win32ss/user/ntuser/event.c	(working copy)
@@ -113,7 +113,7 @@
 
    /* FIXME: Should get timeout from
     * HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */
-   Status = co_MsqSendMessage( pEH->head.pti->MessageQueue,
+   Status = co_MsqSendMessage( pEH->head.pti,
                                hwnd,
                                event,
                                0,
Index: win32ss/user/ntuser/focus.c
===================================================================
--- win32ss/user/ntuser/focus.c	(revision 58773)
+++ win32ss/user/ntuser/focus.c	(working copy)
@@ -296,18 +296,18 @@
 VOID FASTCALL
 FindRemoveAsyncMsg(PWND Wnd)
 {
-   PUSER_MESSAGE_QUEUE MessageQueue;
+   PTHREADINFO pti;
    PUSER_SENT_MESSAGE Message;
    PLIST_ENTRY Entry;
 
    if (!Wnd) return;
 
-   MessageQueue = Wnd->head.pti->MessageQueue;
+   pti = Wnd->head.pti;
 
-   if (!IsListEmpty(&MessageQueue->SentMessagesListHead))
+   if (!IsListEmpty(&pti->SentMessagesListHead))
    {
       // Scan sent queue messages to see if we received async messages.
-      Entry = MessageQueue->SentMessagesListHead.Flink;
+      Entry = pti->SentMessagesListHead.Flink;
       Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
       do
       {
@@ -321,7 +321,7 @@
          Entry = Message->ListEntry.Flink;
          Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
       }
-      while (Entry != &MessageQueue->SentMessagesListHead);
+      while (Entry != &pti->SentMessagesListHead);
    }
 }
 
@@ -787,7 +787,7 @@
       }
    }
 
-   hWndPrev = MsqSetStateWindow(ThreadQueue, MSQ_STATE_CAPTURE, hWnd);
+   hWndPrev = MsqSetStateWindow(pti, MSQ_STATE_CAPTURE, hWnd);
 
    if (hWndPrev)
    {
@@ -815,8 +815,8 @@
       MOUSEINPUT mi;
    /// These are HACKS!
       /* Also remove other windows if not capturing anymore */
-      MsqSetStateWindow(ThreadQueue, MSQ_STATE_MENUOWNER, NULL);
-      MsqSetStateWindow(ThreadQueue, MSQ_STATE_MOVESIZE, NULL);
+      MsqSetStateWindow(pti, MSQ_STATE_MENUOWNER, NULL);
+      MsqSetStateWindow(pti, MSQ_STATE_MOVESIZE, NULL);
    ///
       /* Somebody may have missed some mouse movements */
       mi.dx = 0;
Index: win32ss/user/ntuser/hook.c
===================================================================
--- win32ss/user/ntuser/hook.c	(revision 58773)
+++ win32ss/user/ntuser/hook.c	(working copy)
@@ -295,7 +295,7 @@
 
     /* FIXME: Should get timeout from
      * HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */
-    Status = co_MsqSendMessage( pti->MessageQueue,
+    Status = co_MsqSendMessage( pti,
                                 IntToPtr(Code), // hWnd
                                 Hook->HookId,   // Msg
                                 wParam,
Index: win32ss/user/ntuser/keyboard.c
===================================================================
--- win32ss/user/ntuser/keyboard.c	(revision 58773)
+++ win32ss/user/ntuser/keyboard.c	(working copy)
@@ -763,6 +763,7 @@
 {
     WORD wSimpleVk = 0, wFixedVk, wVk2;
     PUSER_MESSAGE_QUEUE pFocusQueue;
+    PTHREADINFO pti;
     BOOL bExt = (dwFlags & KEYEVENTF_EXTENDEDKEY) ? TRUE : FALSE;
     BOOL bIsDown = (dwFlags & KEYEVENTF_KEYUP) ? FALSE : TRUE;
     BOOL bPacket = (dwFlags & KEYEVENTF_UNICODE) ? TRUE : FALSE;
@@ -873,6 +874,14 @@
            Wnd = pFocusQueue->spwndActive;
         }
 
+        if ( !Wnd || Wnd->state2 & WNDS2_INDESTROY || Wnd->state & WNDS_DESTROYED )
+        {
+           ERR("ProcessKeyEvent Active Focus window is dead!\n");
+           return FALSE;
+        }
+ 
+        pti = Wnd->head.pti;
+
         /* Init message */
         Msg.hwnd = UserHMGetHandle(Wnd);
         Msg.wParam = wFixedVk & 0xFF; /* Note: It's simplified by msg queue */
@@ -900,7 +909,7 @@
 
         /* Post a keyboard message */
         TRACE("Posting keyboard msg %u wParam 0x%x lParam 0x%x\n", Msg.message, Msg.wParam, Msg.lParam);
-        MsqPostMessage(pFocusQueue, &Msg, TRUE, QS_KEY, 0);
+        MsqPostMessage(pti, &Msg, TRUE, QS_KEY, 0);
     }
 
     return TRUE;
@@ -913,7 +922,6 @@
     PKL pKl = NULL;
     PKBDTABLES pKbdTbl;
     PUSER_MESSAGE_QUEUE pFocusQueue;
-    struct _ETHREAD *pFocusThread;
     LARGE_INTEGER LargeTickCount;
     DWORD dwTime;
     BOOL bExt = (pKbdInput->dwFlags & KEYEVENTF_EXTENDEDKEY) ? TRUE : FALSE;
@@ -923,11 +931,9 @@
     /* Find the target thread whose locale is in effect */
     pFocusQueue = IntGetFocusMessageQueue();
 
-    if (pFocusQueue)
+    if (pFocusQueue && pFocusQueue->ptiOwner)
     {
-        pFocusThread = pFocusQueue->Thread;
-        if (pFocusThread && pFocusThread->Tcb.Win32Thread)
-            pKl = ((PTHREADINFO)pFocusThread->Tcb.Win32Thread)->KeyboardLayout;
+        pKl = pFocusQueue->ptiOwner->KeyboardLayout;
     }
 
     if (!pKl)
@@ -997,7 +1003,6 @@
     PKL pKl = NULL;
     PKBDTABLES pKbdTbl;
     PUSER_MESSAGE_QUEUE pFocusQueue;
-    struct _ETHREAD *pFocusThread;
 
     /* Calculate scan code with prefix */
     wScanCode = pKbdInputData->MakeCode & 0x7F;
@@ -1009,11 +1014,9 @@
     /* Find the target thread whose locale is in effect */
     pFocusQueue = IntGetFocusMessageQueue();
 
-    if (pFocusQueue)
+    if (pFocusQueue && pFocusQueue->ptiOwner)
     {
-        pFocusThread = pFocusQueue->Thread;
-        if (pFocusThread && pFocusThread->Tcb.Win32Thread)
-            pKl = ((PTHREADINFO)pFocusThread->Tcb.Win32Thread)->KeyboardLayout;
+        pKl = pFocusQueue->ptiOwner->KeyboardLayout;
     }
 
     if (!pKl)
@@ -1121,7 +1124,7 @@
         NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
         NewMsg.wParam = HIWORD(lpMsg->lParam);
         NewMsg.lParam = LOWORD(lpMsg->lParam);
-        MsqPostMessage(pti->MessageQueue, &NewMsg, FALSE, QS_KEY, 0);
+        MsqPostMessage(pti, &NewMsg, FALSE, QS_KEY, 0);
         return TRUE;
     }
 
@@ -1150,7 +1153,7 @@
         {
             TRACE("Msg: %x '%lc' (%04x) %08x\n", NewMsg.message, wch[i], wch[i], NewMsg.lParam);
             NewMsg.wParam = wch[i];
-            MsqPostMessage(pti->MessageQueue, &NewMsg, FALSE, QS_KEY, 0);
+            MsqPostMessage(pti, &NewMsg, FALSE, QS_KEY, 0);
         }
         bResult = TRUE;
     }
Index: win32ss/user/ntuser/main.c
===================================================================
--- win32ss/user/ntuser/main.c	(revision 58773)
+++ win32ss/user/ntuser/main.c	(working copy)
@@ -254,6 +254,7 @@
     int i;
     NTSTATUS Status = STATUS_SUCCESS;
     PTEB pTeb;
+    LARGE_INTEGER LargeTickCount;
 
     Process = Thread->ThreadsProcess;
 
@@ -281,8 +282,13 @@
     TRACE_CH(UserThread, "Allocated pti 0x%p for TID %p\n", ptiCurrent, Thread->Cid.UniqueThread);
 
     /* Initialize the THREADINFO */
+    IntReferenceThreadInfo(ptiCurrent);
     InitializeListHead(&ptiCurrent->WindowListHead);
     InitializeListHead(&ptiCurrent->W32CallbackListHead);
+    InitializeListHead(&ptiCurrent->PostedMessagesListHead);
+    InitializeListHead(&ptiCurrent->SentMessagesListHead);
+    InitializeListHead(&ptiCurrent->DispatchingMessagesHead);
+    InitializeListHead(&ptiCurrent->LocalDispatchingMessagesHead);
     InitializeListHead(&ptiCurrent->PtiLink);
     for (i = 0; i < NB_HOOKS; i++)
     {
@@ -293,6 +299,27 @@
     ptiCurrent->ptiSibling = ptiCurrent->ppi->ptiList;
     ptiCurrent->ppi->ptiList = ptiCurrent;
     ptiCurrent->ppi->cThreads++;
+
+    ptiCurrent->hEventQueueClient = NULL;
+    Status = ZwCreateEvent(&ptiCurrent->hEventQueueClient, EVENT_ALL_ACCESS,
+                            NULL, SynchronizationEvent, FALSE);
+    if (!NT_SUCCESS(Status))
+    {
+       goto error;
+    }
+   Status = ObReferenceObjectByHandle(ptiCurrent->hEventQueueClient, 0,
+                                       ExEventObjectType, KernelMode,
+                                       (PVOID*)&ptiCurrent->pEventQueueServer, NULL);
+    if (!NT_SUCCESS(Status))
+    {
+       ZwClose(ptiCurrent->hEventQueueClient);
+       ptiCurrent->hEventQueueClient = NULL;
+       goto error;
+    }
+
+    KeQueryTickCount(&LargeTickCount);
+    ptiCurrent->timeLast = LargeTickCount.u.LowPart;
+    
     ptiCurrent->MessageQueue = MsqCreateMessageQueue(ptiCurrent);
     if(ptiCurrent->MessageQueue == NULL)
     {
@@ -402,6 +429,35 @@
     return Status;
 }
 
+/*
+  Called from IntDereferenceThreadInfo.
+ */
+VOID
+FASTCALL
+UserDeleteW32Thread(PTHREADINFO pti)
+{
+    if (!pti->RefCount)
+    {
+       ERR_CH(UserThread,"UserDeleteW32Thread pti 0x%p\n",pti);
+       if (pti->hEventQueueClient != NULL)
+          ZwClose(pti->hEventQueueClient);
+       pti->hEventQueueClient = NULL;
+
+       /* Free the message queue */
+       if (pti->MessageQueue)
+       {
+          MsqDestroyMessageQueue(pti);
+       }
+
+       MsqCleanupThreadMsgs(pti);
+
+       IntSetThreadDesktop(NULL, TRUE);
+
+       PsSetThreadWin32Thread(pti->pEThread, NULL);
+       ExFreePoolWithTag(pti, USERTAG_THREADINFO);
+    }
+}
+
 NTSTATUS
 NTAPI
 UserDestroyThreadInfo(struct _ETHREAD *Thread)
@@ -439,7 +495,7 @@
     if (ptiCurrent->pqAttach && ptiCurrent->MessageQueue)
     {
        PTHREADINFO ptiTo;
-       ptiTo = PsGetThreadWin32Thread(ptiCurrent->MessageQueue->Thread);
+       ptiTo = ptiCurrent->MessageQueue->ptiOwner;
        TRACE_CH(UserThread,"Attached Thread ptiFrom is getting switched!\n");
        if (ptiTo) UserAttachThreadInput( ptiCurrent, ptiTo, FALSE);
        else
@@ -487,7 +543,7 @@
         HOOK_DestroyThreadHooks(Thread);
         EVENT_DestroyThreadEvents(Thread);
         DestroyTimersForThread(ptiCurrent);
-        KeSetEvent(ptiCurrent->MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE);
+        KeSetEvent(ptiCurrent->pEventQueueServer, IO_NO_INCREMENT, FALSE);
         UnregisterThreadHotKeys(Thread);
 /*
         if (IsListEmpty(&ptiCurrent->WindowListHead))
@@ -520,12 +576,6 @@
         }
     }
 
-    /* Free the message queue */
-    if (ptiCurrent->MessageQueue)
-    {
-       MsqDestroyMessageQueue(ptiCurrent);
-    }
-
     /* Find the THREADINFO in the PROCESSINFO's list */
     ppti = &ppiCurrent->ptiList;
     while (*ppti != NULL && *ppti != ptiCurrent)
@@ -547,8 +597,7 @@
     TRACE_CH(UserThread,"Freeing pti 0x%p\n", ptiCurrent);
 
     /* Free the THREADINFO */
-    PsSetThreadWin32Thread(Thread, NULL);
-    ExFreePoolWithTag(ptiCurrent, USERTAG_THREADINFO);
+    IntDereferenceThreadInfo(ptiCurrent);
 
     return STATUS_SUCCESS;
 }
Index: win32ss/user/ntuser/message.c
===================================================================
--- win32ss/user/ntuser/message.c	(revision 58773)
+++ win32ss/user/ntuser/message.c	(working copy)
@@ -508,7 +508,7 @@
    ForegroundQueue = IntGetFocusMessageQueue();
 
    if (ForegroundQueue)
-      ptiForeground = ForegroundQueue->Thread->Tcb.Win32Thread;
+       ptiForeground = ForegroundQueue->ptiOwner;
 
    pti = PsGetCurrentThreadWin32Thread();
 
@@ -762,22 +762,15 @@
 {
     PTHREADINFO pti;
     LARGE_INTEGER LargeTickCount;
-    PUSER_MESSAGE_QUEUE ThreadQueue;
     BOOL RemoveMessages;
     UINT ProcessMask;
     BOOL Hit = FALSE;
 
     pti = PsGetCurrentThreadWin32Thread();
-    ThreadQueue = pti->MessageQueue;
 
     RemoveMessages = RemoveMsg & PM_REMOVE;
     ProcessMask = HIWORD(RemoveMsg);
-
-    if (ThreadQueue->ptiSysLock && ThreadQueue->ptiSysLock != pti)
-    {
-       ERR("PeekMessage: Thread Q 0x%p is locked 0x%p to another pti 0x%p!\n", ThreadQueue, ThreadQueue->ptiSysLock, pti );
-    }
-
+    
  /* Hint, "If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns
     all available messages (that is, no range filtering is performed)".        */
     if (!ProcessMask) ProcessMask = (QS_ALLPOSTMESSAGE|QS_ALLINPUT);
@@ -787,11 +780,11 @@
     do
     {
         KeQueryTickCount(&LargeTickCount);
-        ThreadQueue->LastMsgRead = LargeTickCount.u.LowPart;
+        pti->timeLast = LargeTickCount.u.LowPart;
         pti->pcti->tickLastMsgChecked = LargeTickCount.u.LowPart;
 
         /* Dispatch sent messages here. */
-        while ( co_MsqDispatchOneSentMessage(ThreadQueue) )
+        while ( co_MsqDispatchOneSentMessage(pti) )
         {
            /* if some PM_QS* flags were specified, only handle sent messages from now on */
            if (HIWORD(RemoveMsg) && !bGMSG) Hit = TRUE; // wine does this; ProcessMask = QS_SENDMESSAGE;
@@ -816,7 +809,7 @@
         /* Now check for normal messages. */
         if (( (ProcessMask & QS_POSTMESSAGE) ||
               (ProcessMask & QS_HOTKEY) ) &&
-            MsqPeekMessage( ThreadQueue,
+            MsqPeekMessage( pti,
                             RemoveMessages,
                             Window,
                             MsgFilterMin,
@@ -828,18 +821,18 @@
         }
 
         /* Now look for a quit message. */
-        if (ThreadQueue->QuitPosted)
+        if (pti->QuitPosted)
         {
             /* According to the PSDK, WM_QUIT messages are always returned, regardless
                of the filter specified */
             Msg->hwnd = NULL;
             Msg->message = WM_QUIT;
-            Msg->wParam = ThreadQueue->QuitExitCode;
+            Msg->wParam = pti->exitCode;
             Msg->lParam = 0;
             if (RemoveMessages)
             {
-                ThreadQueue->QuitPosted = FALSE;
-                ClearMsgBitsMask(ThreadQueue, QS_POSTMESSAGE);
+                pti->QuitPosted = FALSE;
+                ClearMsgBitsMask(pti, QS_POSTMESSAGE);
                 pti->pcti->fsWakeBits &= ~QS_ALLPOSTMESSAGE;
                 pti->pcti->fsChangeBits &= ~QS_ALLPOSTMESSAGE;
             }
@@ -848,7 +841,7 @@
 
         /* Check for hardware events. */
         if ((ProcessMask & QS_MOUSE) &&
-            co_MsqPeekMouseMove( ThreadQueue,
+            co_MsqPeekMouseMove( pti,
                                  RemoveMessages,
                                  Window,
                                  MsgFilterMin,
@@ -859,7 +852,7 @@
         }
 
         if ((ProcessMask & QS_INPUT) &&
-            co_MsqPeekHardwareMessage( ThreadQueue,
+            co_MsqPeekHardwareMessage( pti,
                                        RemoveMessages,
                                        Window,
                                        MsgFilterMin,
@@ -871,7 +864,7 @@
         }
 
         /* Check for sent messages again. */
-        while ( co_MsqDispatchOneSentMessage(ThreadQueue) )
+        while ( co_MsqDispatchOneSentMessage(pti) )
         {
            if (HIWORD(RemoveMsg) && !bGMSG) Hit = TRUE;
         }
@@ -912,12 +905,10 @@
                    UINT MsgFilterMax )
 {
     PTHREADINFO pti;
-    PUSER_MESSAGE_QUEUE ThreadQueue;
     NTSTATUS Status = STATUS_SUCCESS;
     MSG Msg;
 
     pti = PsGetCurrentThreadWin32Thread();
-    ThreadQueue = pti->MessageQueue;
 
     do
     {
@@ -932,7 +923,7 @@
         }
 
         /* Nothing found. Wait for new messages. */
-        Status = co_MsqWaitForNewMessages( ThreadQueue,
+        Status = co_MsqWaitForNewMessages( pti,
                                            Window,
                                            MsgFilterMin,
                                            MsgFilterMax);
@@ -1027,7 +1018,7 @@
 
         if ( bGMSG )
         {
-            Status = co_MsqWaitForNewMessages( pti->MessageQueue,
+            Status = co_MsqWaitForNewMessages( pti,
                                                Window,
                                                MsgFilterMin,
                                                MsgFilterMax);
@@ -1105,7 +1096,7 @@
 
         KeQueryTickCount(&LargeTickCount);
         Message.time = MsqCalculateMessageTime(&LargeTickCount);
-        MsqPostMessage(pThread->MessageQueue, &Message, FALSE, QS_POSTMESSAGE, 0);
+        MsqPostMessage(pThread, &Message, FALSE, QS_POSTMESSAGE, 0);
         ObDereferenceObject( peThread );
         return TRUE;
     }
@@ -1224,11 +1215,11 @@
 
         if (WM_QUIT == Msg)
         {
-            MsqPostQuitMessage(Window->head.pti->MessageQueue, wParam);
+            MsqPostQuitMessage(Window->head.pti, wParam);
         }
         else
         {
-            MsqPostMessage(Window->head.pti->MessageQueue, &Message, FALSE, QS_POSTMESSAGE, 0);
+            MsqPostMessage(Window->head.pti, &Message, FALSE, QS_POSTMESSAGE, 0);
         }
     }
     return TRUE;
@@ -1279,7 +1270,7 @@
     Win32Thread = PsGetCurrentThreadWin32Thread();
 
     if ( Win32Thread &&
-         Window->head.pti->MessageQueue == Win32Thread->MessageQueue)
+         Window->head.pti == Win32Thread)
     {
         if (Win32Thread->TIF_flags & TIF_INCLEANUP)
         {
@@ -1365,7 +1356,7 @@
         RETURN( TRUE);
     }
 
-    if (uFlags & SMTO_ABORTIFHUNG && MsqIsHung(Window->head.pti->MessageQueue))
+    if (uFlags & SMTO_ABORTIFHUNG && MsqIsHung(Window->head.pti))
     {
         // FIXME: Set window hung and add to a list.
         /* FIXME: Set a LastError? */
@@ -1381,7 +1372,7 @@
 
     do
     {
-        Status = co_MsqSendMessage( Window->head.pti->MessageQueue,
+        Status = co_MsqSendMessage( Window->head.pti,
                                     hWnd,
                                     Msg,
                                     wParam,
@@ -1393,7 +1384,7 @@
     }
     while ((STATUS_TIMEOUT == Status) &&
            (uFlags & SMTO_NOTIMEOUTIFNOTHUNG) &&
-           !MsqIsHung(Window->head.pti->MessageQueue)); // FIXME: Set window hung and add to a list.
+           !MsqIsHung(Window->head.pti)); // FIXME: Set window hung and add to a list.
 
     if (STATUS_TIMEOUT == Status)
     {
@@ -1553,7 +1544,7 @@
     }
 
     if (Msg & 0x80000000 &&
-        Window->head.pti->MessageQueue == Win32Thread->MessageQueue)
+        Window->head.pti == Win32Thread)
     {
        if (Win32Thread->TIF_flags & TIF_INCLEANUP) RETURN( FALSE);
 
@@ -1574,14 +1565,14 @@
         lParamBufferSize = MsgMemorySize(MsgMemoryEntry, wParam, lParam);
     }
 
-    if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam, Window->head.pti->MessageQueue != Win32Thread->MessageQueue)))
+    if (! NT_SUCCESS(PackParam(&lParamPacked, Msg, wParam, lParam, Window->head.pti != Win32Thread)))
     {
         ERR("Failed to pack message parameters\n");
         RETURN( FALSE);
     }
 
     /* If it can be sent now, then send it. */
-    if (Window->head.pti->MessageQueue == Win32Thread->MessageQueue)
+    if (Window->head.pti == Win32Thread)
     {
         if (Win32Thread->TIF_flags & TIF_INCLEANUP)
         {
@@ -1631,7 +1622,7 @@
         }
     }
 
-    if (Window->head.pti->MessageQueue == Win32Thread->MessageQueue)
+    if (Window->head.pti == Win32Thread)
     {
         if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE)))
         {
@@ -1646,12 +1637,6 @@
         RETURN( FALSE);
     }
 
-    IntReferenceMessageQueue(Window->head.pti->MessageQueue);
-    /* Take reference on this MessageQueue if its a callback. It will be released
-       when message is processed or removed from target hwnd MessageQueue */
-    if (CompletionCallback)
-       IntReferenceMessageQueue(Win32Thread->MessageQueue);
-
     Message->Msg.hwnd = hWnd;
     Message->Msg.message = Msg;
     Message->Msg.wParam = wParam;
@@ -1660,8 +1645,9 @@
     Message->Result = 0;
     Message->lResult = 0;
     Message->QS_Flags = 0;
-    Message->SenderQueue = NULL; // mjmartin, you are right! This is null.
-    Message->CallBackSenderQueue = Win32Thread->MessageQueue;
+    Message->ptiReceiver = Window->head.pti;
+    Message->ptiSender = NULL; // mjmartin, you are right! This is null.
+    Message->ptiCallBackSender = Win32Thread;
     Message->DispatchingListEntry.Flink = NULL;
     Message->CompletionCallback = CompletionCallback;
     Message->CompletionCallbackContext = CompletionCallbackContext;
@@ -1669,9 +1655,11 @@
     Message->HasPackedLParam = (lParamBufferSize > 0);
     Message->QS_Flags = QS_SENDMESSAGE;
 
-    InsertTailList(&Window->head.pti->MessageQueue->SentMessagesListHead, &Message->ListEntry);
-    MsqWakeQueue(Window->head.pti->MessageQueue, QS_SENDMESSAGE, TRUE);
-    IntDereferenceMessageQueue(Window->head.pti->MessageQueue);
+    if (Msg & 0x80000000) // Higher priority event message!
+       InsertHeadList(&Window->head.pti->SentMessagesListHead, &Message->ListEntry);
+    else
+       InsertTailList(&Window->head.pti->SentMessagesListHead, &Message->ListEntry);
+    MsqWakeQueue(Window->head.pti, QS_SENDMESSAGE, TRUE);
 
     RETURN(TRUE);
 
@@ -2351,7 +2339,7 @@
 
                            if ( parm.flags & BSF_IGNORECURRENTTASK )
                            {
-                              if ( pwnd->head.pti->MessageQueue == gptiCurrent->MessageQueue )
+                              if ( pwnd->head.pti == gptiCurrent )
                                  continue;
                            }
                            co_IntSendMessageTimeout( List[i],
@@ -2406,7 +2394,7 @@
 
                            if ( parm.flags & BSF_IGNORECURRENTTASK )
                            {
-                              if ( pwnd->head.pti->MessageQueue == gptiCurrent->MessageQueue )
+                              if ( pwnd->head.pti == gptiCurrent )
                                  continue;
                            }
                            UserPostMessage(List[i], Msg, wParam, lParam);
@@ -2432,7 +2420,7 @@
 
                            if ( parm.flags & BSF_IGNORECURRENTTASK )
                            {
-                              if ( pwnd->head.pti->MessageQueue == gptiCurrent->MessageQueue )
+                              if ( pwnd->head.pti == gptiCurrent )
                                  continue;
                            }
                            UserSendNotifyMessage(List[i], Msg, wParam, lParam);
@@ -2489,7 +2477,7 @@
 
                         if ( parm.flags & BSF_IGNORECURRENTTASK )
                         {
-                           if ( pwnd->head.pti->MessageQueue == gptiCurrent->MessageQueue )
+                           if ( pwnd->head.pti == gptiCurrent )
                               continue;
                         }
                         co_IntSendMessageTimeout( List[i],
@@ -2543,7 +2531,7 @@
 
                         if ( parm.flags & BSF_IGNORECURRENTTASK )
                         {
-                           if ( pwnd->head.pti->MessageQueue == gptiCurrent->MessageQueue )
+                           if ( pwnd->head.pti == gptiCurrent )
                               continue;
                         }
                         UserPostMessage(List[i], Msg, wParam, lParam);
@@ -2569,7 +2557,7 @@
 
                         if ( parm.flags & BSF_IGNORECURRENTTASK )
                         {
-                           if ( pwnd->head.pti->MessageQueue == gptiCurrent->MessageQueue )
+                           if ( pwnd->head.pti == gptiCurrent )
                               continue;
                         }
                         UserSendNotifyMessage(List[i], Msg, wParam, lParam);
@@ -2812,7 +2800,7 @@
 
     Handles[0] = Process;
     Handles[1] = W32Process->InputIdleEvent;
-    Handles[2] = pti->MessageQueue->NewMessages; // pEventQueueServer; IntMsqSetWakeMask returns hEventQueueClient
+    Handles[2] = pti->pEventQueueServer; // IntMsqSetWakeMask returns hEventQueueClient
 
     if (!Handles[1])
     {
Index: win32ss/user/ntuser/misc.c
===================================================================
--- win32ss/user/ntuser/misc.c	(revision 58773)
+++ win32ss/user/ntuser/misc.c	(working copy)
@@ -188,7 +188,7 @@
            ret = ISMEX_NOSEND;
            if (Message)
            {
-             if (Message->SenderQueue)
+             if (Message->ptiSender)
                 ret = ISMEX_SEND;
              else
              {
@@ -213,7 +213,7 @@
            LARGE_INTEGER LargeTickCount;
            pti = PsGetCurrentThreadWin32Thread();
            KeQueryTickCount(&LargeTickCount);
-           pti->MessageQueue->LastMsgRead = LargeTickCount.u.LowPart;
+           pti->timeLast = LargeTickCount.u.LowPart;
            pti->pcti->tickLastMsgChecked = LargeTickCount.u.LowPart;
          }
          break;
Index: win32ss/user/ntuser/msgqueue.c
===================================================================
--- win32ss/user/ntuser/msgqueue.c	(revision 58773)
+++ win32ss/user/ntuser/msgqueue.c	(working copy)
@@ -347,7 +347,6 @@
 IntMsqSetWakeMask(DWORD WakeMask)
 {
    PTHREADINFO Win32Thread;
-   PUSER_MESSAGE_QUEUE MessageQueue;
    HANDLE MessageEventHandle;
    DWORD dwFlags = HIWORD(WakeMask);
 
@@ -355,9 +354,8 @@
    if (Win32Thread == NULL || Win32Thread->MessageQueue == NULL)
       return 0;
 
-   MessageQueue = Win32Thread->MessageQueue;
 // Win32Thread->pEventQueueServer; IntMsqSetWakeMask returns Win32Thread->hEventQueueClient
-   MessageEventHandle = MessageQueue->NewMessagesHandle;
+   MessageEventHandle = Win32Thread->hEventQueueClient;
 
    if (Win32Thread->pcti)
    {
@@ -365,7 +363,7 @@
            ( (dwFlags & MWMO_INPUTAVAILABLE) && (Win32Thread->pcti->fsWakeBits & LOWORD(WakeMask)) ) )
       {
          ERR("Chg 0x%x Wake 0x%x Mask 0x%x\n",Win32Thread->pcti->fsChangeBits, Win32Thread->pcti->fsWakeBits, WakeMask);
-         KeSetEvent(MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE); // Wake it up!
+         KeSetEvent(Win32Thread->pEventQueueServer, IO_NO_INCREMENT, FALSE); // Wake it up!
          return MessageEventHandle;
       }
    }
@@ -396,55 +394,64 @@
    and even if the bits are all cleared. The same as cTimers/cPaintsReady.
    I think this is the best solution... (jt) */
 VOID FASTCALL
-MsqWakeQueue(PUSER_MESSAGE_QUEUE Queue, DWORD MessageBits, BOOL KeyEvent)
+MsqWakeQueue(PTHREADINFO pti, DWORD MessageBits, BOOL KeyEvent)
 {
-   PTHREADINFO pti;
+   PUSER_MESSAGE_QUEUE Queue;
 
+   Queue = pti->MessageQueue;
+
    if (Queue->QF_flags & QF_INDESTROY)
    {
       ERR("This Message Queue is in Destroy!\n");
    }
-   pti = Queue->Thread->Tcb.Win32Thread;
+
    pti->pcti->fsWakeBits |= MessageBits;
    pti->pcti->fsChangeBits |= MessageBits;
 
    // Start bit accounting to help clear the main set of bits.
-   if (MessageBits & QS_KEY)         Queue->nCntsQBits[QSRosKey]++;
-   if (MessageBits & QS_MOUSEMOVE)   Queue->nCntsQBits[QSRosMouseMove]++;
-   if (MessageBits & QS_MOUSEBUTTON) Queue->nCntsQBits[QSRosMouseButton]++;
-   if (MessageBits & QS_POSTMESSAGE) Queue->nCntsQBits[QSRosPostMessage]++;
-   if (MessageBits & QS_SENDMESSAGE) Queue->nCntsQBits[QSRosSendMessage]++;
-   if (MessageBits & QS_HOTKEY)      Queue->nCntsQBits[QSRosHotKey]++;
+   if (MessageBits & QS_KEY)
+   {
+      pti->nCntsQBits[QSRosKey]++;
+   }
+   if (MessageBits & QS_MOUSE)
+   {
+      if (MessageBits & QS_MOUSEMOVE)   pti->nCntsQBits[QSRosMouseMove]++;
+      if (MessageBits & QS_MOUSEBUTTON) pti->nCntsQBits[QSRosMouseButton]++;
+   }
+   if (MessageBits & QS_POSTMESSAGE) pti->nCntsQBits[QSRosPostMessage]++;
+   if (MessageBits & QS_SENDMESSAGE) pti->nCntsQBits[QSRosSendMessage]++;
+   if (MessageBits & QS_HOTKEY)      pti->nCntsQBits[QSRosHotKey]++;
+   if (MessageBits & QS_EVENT)       pti->nCntsQBits[QSRosEvent]++;
 
    if (KeyEvent)
-      KeSetEvent(Queue->NewMessages, IO_NO_INCREMENT, FALSE);
+      KeSetEvent(pti->pEventQueueServer, IO_NO_INCREMENT, FALSE);
 }
 
 VOID FASTCALL
-ClearMsgBitsMask(PUSER_MESSAGE_QUEUE Queue, UINT MessageBits)
+ClearMsgBitsMask(PTHREADINFO pti, UINT MessageBits)
 {
-   PTHREADINFO pti;
+   PUSER_MESSAGE_QUEUE Queue;
    UINT ClrMask = 0;
 
-   pti = Queue->Thread->Tcb.Win32Thread;
+   Queue = pti->MessageQueue;
 
    if (MessageBits & QS_KEY)
    {
-      if (--Queue->nCntsQBits[QSRosKey] == 0) ClrMask |= QS_KEY;
+      if (--pti->nCntsQBits[QSRosKey] == 0) ClrMask |= QS_KEY;
    }
    if (MessageBits & QS_MOUSEMOVE) // ReactOS hard coded.
    {  // Account for tracking mouse moves..
-      if (--Queue->nCntsQBits[QSRosMouseMove] == 0) ClrMask |= QS_MOUSEMOVE;
+      if (--pti->nCntsQBits[QSRosMouseMove] == 0) ClrMask |= QS_MOUSEMOVE;
       // Handle mouse move bits here.
       if (Queue->MouseMoved) ClrMask |= QS_MOUSEMOVE;
    }
    if (MessageBits & QS_MOUSEBUTTON)
    {
-      if (--Queue->nCntsQBits[QSRosMouseButton] == 0) ClrMask |= QS_MOUSEBUTTON;
+      if (--pti->nCntsQBits[QSRosMouseButton] == 0) ClrMask |= QS_MOUSEBUTTON;
    }
    if (MessageBits & QS_POSTMESSAGE)
    {
-      if (--Queue->nCntsQBits[QSRosPostMessage] == 0) ClrMask |= QS_POSTMESSAGE;
+      if (--pti->nCntsQBits[QSRosPostMessage] == 0) ClrMask |= QS_POSTMESSAGE;
    }
    if (MessageBits & QS_TIMER) // ReactOS hard coded.
    {  // Handle timer bits here.
@@ -462,11 +469,11 @@
    }
    if (MessageBits & QS_SENDMESSAGE)
    {
-      if (--Queue->nCntsQBits[QSRosSendMessage] == 0) ClrMask |= QS_SENDMESSAGE;
+      if (--pti->nCntsQBits[QSRosSendMessage] == 0) ClrMask |= QS_SENDMESSAGE;
    }
    if (MessageBits & QS_HOTKEY)
    {
-      if (--Queue->nCntsQBits[QSRosHotKey] == 0) ClrMask |= QS_HOTKEY;
+      if (--pti->nCntsQBits[QSRosHotKey] == 0) ClrMask |= QS_HOTKEY;
    }
 
    pti->pcti->fsWakeBits &= ~ClrMask;
@@ -474,26 +481,24 @@
 }
 
 VOID FASTCALL
-MsqIncPaintCountQueue(PUSER_MESSAGE_QUEUE Queue)
+MsqIncPaintCountQueue(PTHREADINFO pti)
 {
-   PTHREADINFO pti;
-   pti = Queue->Thread->Tcb.Win32Thread;
    pti->cPaintsReady++;
-   MsqWakeQueue(Queue, QS_PAINT, TRUE);
+   MsqWakeQueue(pti, QS_PAINT, TRUE);
 }
 
 VOID FASTCALL
-MsqDecPaintCountQueue(PUSER_MESSAGE_QUEUE Queue)
+MsqDecPaintCountQueue(PTHREADINFO pti)
 {
-   ClearMsgBitsMask(Queue, QS_PAINT);
+   ClearMsgBitsMask(pti, QS_PAINT);
 }
 
 VOID FASTCALL
-MsqPostMouseMove(PUSER_MESSAGE_QUEUE MessageQueue, MSG* Msg)
+MsqPostMouseMove(PTHREADINFO pti, MSG* Msg)
 {
-    MessageQueue->MouseMoveMsg = *Msg;
-    MessageQueue->MouseMoved = TRUE;
-    MsqWakeQueue(MessageQueue, QS_MOUSEMOVE, TRUE);
+    pti->MessageQueue->MouseMoveMsg = *Msg;
+    pti->MessageQueue->MouseMoved = TRUE;
+    MsqWakeQueue(pti, QS_MOUSEMOVE, TRUE);
 }
 
 VOID FASTCALL
@@ -504,6 +509,7 @@
    PDESKTOP pDesk;
    PWND pwnd, pwndDesktop;
    HDC hdcScreen;
+   PTHREADINFO pti;
    PUSER_MESSAGE_QUEUE MessageQueue;
    PSYSTEM_CURSORINFO CurInfo;
 
@@ -564,9 +570,10 @@
    /* Check if we found a window */
    if (Msg->hwnd != NULL && pwnd != NULL)
    {
-       MessageQueue = pwnd->head.pti->MessageQueue;
+       pti = pwnd->head.pti;
+       MessageQueue = pti->MessageQueue;
 
-       if ( pwnd->head.pti->TIF_flags & TIF_INCLEANUP || MessageQueue->QF_flags & QF_INDESTROY)
+       if ( pti->TIF_flags & TIF_INCLEANUP || MessageQueue->QF_flags & QF_INDESTROY)
        {
           ERR("Mouse is over the Window Thread is Dead!\n");
           return;
@@ -617,12 +624,12 @@
            gpqCursor = MessageQueue;
 
            /* Mouse move is a special case */
-           MsqPostMouseMove(MessageQueue, Msg);
+           MsqPostMouseMove(pti, Msg);
        }
        else
        {
            TRACE("Posting mouse message to hwnd=0x%x!\n", UserHMGetHandle(pwnd));
-           MsqPostMessage(MessageQueue, Msg, TRUE, QS_MOUSEBUTTON, 0);
+           MsqPostMessage(pti, Msg, TRUE, QS_MOUSEBUTTON, 0);
        }
    }
    else if (hdcScreen)
@@ -675,7 +682,7 @@
    KeQueryTickCount(&LargeTickCount);
    Mesg.time    = MsqCalculateMessageTime(&LargeTickCount);
    Mesg.pt      = gpsi->ptCursor;
-   MsqPostMessage(Window->head.pti->MessageQueue, &Mesg, FALSE, Type, 0);
+   MsqPostMessage(Window->head.pti, &Mesg, FALSE, Type, 0);
    UserDereferenceObject(Window);
    ObDereferenceObject (Thread);
 
@@ -704,41 +711,38 @@
 }
 
 BOOLEAN FASTCALL
-co_MsqDispatchOneSentMessage(_In_ PUSER_MESSAGE_QUEUE MessageQueue)
+co_MsqDispatchOneSentMessage(_In_ PTHREADINFO pti)
 {
    PUSER_SENT_MESSAGE SaveMsg, Message;
    PLIST_ENTRY Entry;
-   PTHREADINFO pti;
    BOOL Ret;
    LRESULT Result = 0;
 
-   if (IsListEmpty(&MessageQueue->SentMessagesListHead))
+   if (IsListEmpty(&pti->SentMessagesListHead))
    {
       return(FALSE);
    }
 
    /* remove it from the list of pending messages */
-   Entry = RemoveHeadList(&MessageQueue->SentMessagesListHead);
+   Entry = RemoveHeadList(&pti->SentMessagesListHead);
    Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
 
-   pti = MessageQueue->Thread->Tcb.Win32Thread;
-
    SaveMsg = pti->pusmCurrent;
    pti->pusmCurrent = Message;
 
    // Processing a message sent to it from another thread.
-   if ( ( Message->SenderQueue && MessageQueue != Message->SenderQueue) ||
-        ( Message->CallBackSenderQueue && MessageQueue != Message->CallBackSenderQueue ))
+   if ( ( Message->ptiSender && pti != Message->ptiSender) ||
+        ( Message->ptiCallBackSender && pti != Message->ptiCallBackSender ))
    {  // most likely, but, to be sure.
       pti->pcti->CTI_flags |= CTI_INSENDMESSAGE; // Let the user know...
    }
 
    /* insert it to the list of messages that are currently dispatched by this
       message queue */
-   InsertTailList(&MessageQueue->LocalDispatchingMessagesHead,
+   InsertTailList(&pti->LocalDispatchingMessagesHead,
                   &Message->ListEntry);
 
-   ClearMsgBitsMask(MessageQueue, Message->QS_Flags);
+   ClearMsgBitsMask(pti, Message->QS_Flags);
 
    if (Message->HookMessage == MSQ_ISHOOK)
    {  // Direct Hook Call processor
@@ -761,7 +765,7 @@
                                   Message->Msg.wParam);
    }
    else if ((Message->CompletionCallback) &&
-            (Message->CallBackSenderQueue == MessageQueue))
+            (Message->ptiCallBackSender == pti))
    {   /* Call the callback routine */
       if (Message->QS_Flags & QS_SMRESULT)
       {
@@ -777,7 +781,7 @@
       {
          /* The message has not been processed yet, reinsert it. */
          RemoveEntryList(&Message->ListEntry);
-         InsertTailList(&Message->CallBackSenderQueue->SentMessagesListHead, &Message->ListEntry);
+         InsertTailList(&Message->ptiCallBackSender->SentMessagesListHead, &Message->ListEntry);
          TRACE("Callback Message not processed yet. Requeuing the message\n");
          Ret = FALSE;
          goto Exit;
@@ -798,22 +802,21 @@
    /* If the message is a callback, insert it in the callback senders MessageQueue */
    if (Message->CompletionCallback)
    {
-      if (Message->CallBackSenderQueue)
+      if (Message->ptiCallBackSender)
       {
          Message->lResult = Result;
          Message->QS_Flags |= QS_SMRESULT;
 
          /* insert it in the callers message queue */
-         InsertTailList(&Message->CallBackSenderQueue->SentMessagesListHead, &Message->ListEntry);
-         MsqWakeQueue(Message->CallBackSenderQueue, QS_SENDMESSAGE, TRUE);
-         IntDereferenceMessageQueue(Message->CallBackSenderQueue);
+         InsertTailList(&Message->ptiCallBackSender->SentMessagesListHead, &Message->ListEntry);
+         MsqWakeQueue(Message->ptiCallBackSender, QS_SENDMESSAGE, TRUE);
       }
       Ret = TRUE;
       goto Exit;
    }
 
    /* remove the message from the dispatching list if needed, so lock the sender's message queue */
-   if (Message->SenderQueue)
+   if (Message->ptiSender)
    {
       if (Message->DispatchingListEntry.Flink != NULL)
       {
@@ -847,14 +850,6 @@
       KeSetEvent(Message->CompletionEvent, IO_NO_INCREMENT, FALSE);
    }
 
-   /* if the message has a sender */
-   if (Message->SenderQueue)
-   {
-       /* dereference our and the sender's message queue */
-      IntDereferenceMessageQueue(Message->SenderQueue);
-      IntDereferenceMessageQueue(MessageQueue);
-   }
-
    /* free the message */
    ExFreePoolWithTag(Message, TAG_USRMSG);
    Ret = TRUE;
@@ -867,22 +862,20 @@
 }
 
 VOID APIENTRY
-MsqRemoveWindowMessagesFromQueue(PVOID pWindow)
+MsqRemoveWindowMessagesFromQueue(PWND Window)
 {
+   PTHREADINFO pti;
    PUSER_SENT_MESSAGE SentMessage;
    PUSER_MESSAGE PostedMessage;
-   PUSER_MESSAGE_QUEUE MessageQueue;
    PLIST_ENTRY CurrentEntry, ListHead;
-   PWND Window = pWindow;
 
    ASSERT(Window);
 
-   MessageQueue = Window->head.pti->MessageQueue;
-   ASSERT(MessageQueue);
+   pti = Window->head.pti;
 
    /* remove the posted messages for this window */
-   CurrentEntry = MessageQueue->PostedMessagesListHead.Flink;
-   ListHead = &MessageQueue->PostedMessagesListHead;
+   CurrentEntry = pti->PostedMessagesListHead.Flink;
+   ListHead = &pti->PostedMessagesListHead;
    while (CurrentEntry != ListHead)
    {
       PostedMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
@@ -890,9 +883,9 @@
       if (PostedMessage->Msg.hwnd == Window->head.h)
       {
          RemoveEntryList(&PostedMessage->ListEntry);
-         ClearMsgBitsMask(MessageQueue, PostedMessage->QS_Flags);
+         ClearMsgBitsMask(pti, PostedMessage->QS_Flags);
          MsqDestroyMessage(PostedMessage);
-         CurrentEntry = MessageQueue->PostedMessagesListHead.Flink;
+         CurrentEntry = pti->PostedMessagesListHead.Flink;
       }
       else
       {
@@ -900,12 +893,9 @@
       }
    }
 
-   /* Reference we message queue, so it won't get deleted */
-   IntReferenceMessageQueue(MessageQueue);
-
    /* remove the sent messages for this window */
-   CurrentEntry = MessageQueue->SentMessagesListHead.Flink;
-   ListHead = &MessageQueue->SentMessagesListHead;
+   CurrentEntry = pti->SentMessagesListHead.Flink;
+   ListHead = &pti->SentMessagesListHead;
    while (CurrentEntry != ListHead)
    {
       SentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE,
@@ -915,15 +905,10 @@
          TRACE("Notify the sender and remove a message from the queue that had not been dispatched\n");
 
          RemoveEntryList(&SentMessage->ListEntry);
-         ClearMsgBitsMask(MessageQueue, SentMessage->QS_Flags);
+         ClearMsgBitsMask(pti, SentMessage->QS_Flags);
 
-         /* if it is a callback and this queue is not the sender queue, dereference queue */
-         if ((SentMessage->CompletionCallback) && (SentMessage->CallBackSenderQueue != MessageQueue))
-         {
-            IntDereferenceMessageQueue(SentMessage->CallBackSenderQueue);
-         }
          /* Only if the message has a sender was the queue referenced */
-         if ((SentMessage->SenderQueue)
+         if ((SentMessage->ptiSender)
             && (SentMessage->DispatchingListEntry.Flink != NULL))
          {
             RemoveEntryList(&SentMessage->DispatchingListEntry);
@@ -941,27 +926,16 @@
                ExFreePool((PVOID)SentMessage->Msg.lParam);
          }
 
-         /* if the message has a sender */
-         if (SentMessage->SenderQueue)
-         {
-            /* dereference our and the sender's message queue */
-            IntDereferenceMessageQueue(MessageQueue);
-            IntDereferenceMessageQueue(SentMessage->SenderQueue);
-         }
-
          /* free the message */
          ExFreePoolWithTag(SentMessage, TAG_USRMSG);
 
-         CurrentEntry = MessageQueue->SentMessagesListHead.Flink;
+         CurrentEntry = pti->SentMessagesListHead.Flink;
       }
       else
       {
          CurrentEntry = CurrentEntry->Flink;
       }
    }
-
-   /* Remove the reference we added */
-   IntDereferenceMessageQueue(MessageQueue);
 }
 
 BOOL FASTCALL
@@ -1000,8 +974,9 @@
     Message->CompletionEvent = NULL;
     Message->Result = 0;
     Message->lResult = 0;
-    Message->SenderQueue = NULL;
-    Message->CallBackSenderQueue = ptiSender->MessageQueue;
+    Message->ptiReceiver = ptiReceiver;
+    Message->ptiSender = NULL;
+    Message->ptiCallBackSender = ptiSender;
     Message->DispatchingListEntry.Flink = NULL;
     Message->CompletionCallback = CompletionCallback;
     Message->CompletionCallbackContext = CompletionCallbackContext;
@@ -1009,33 +984,29 @@
     Message->HasPackedLParam = HasPackedLParam;
     Message->QS_Flags = QS_SENDMESSAGE;
 
-    InsertTailList(&ptiReceiver->MessageQueue->SentMessagesListHead, &Message->ListEntry);
-    MsqWakeQueue(ptiReceiver->MessageQueue, QS_SENDMESSAGE, TRUE);
-    IntDereferenceMessageQueue(ptiReceiver->MessageQueue);
+    InsertTailList(&ptiReceiver->SentMessagesListHead, &Message->ListEntry);
+    MsqWakeQueue(ptiReceiver, QS_SENDMESSAGE, TRUE);
 
     return TRUE;
 }
 
 NTSTATUS FASTCALL
-co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
+co_MsqSendMessage(PTHREADINFO ptirec,
                   HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam,
                   UINT uTimeout, BOOL Block, INT HookMessage,
                   ULONG_PTR *uResult)
 {
-   PTHREADINFO pti, ptirec;
+   PTHREADINFO pti;
    PUSER_SENT_MESSAGE Message;
    KEVENT CompletionEvent;
    NTSTATUS WaitStatus;
-   PUSER_MESSAGE_QUEUE ThreadQueue;
    LARGE_INTEGER Timeout;
    PLIST_ENTRY Entry;
    PWND pWnd;
    LRESULT Result = 0;   //// Result could be trashed. ////
 
    pti = PsGetCurrentThreadWin32Thread();
-   ThreadQueue = pti->MessageQueue;
-   ptirec = MessageQueue->Thread->Tcb.Win32Thread;
-   ASSERT(ThreadQueue != MessageQueue);
+   ASSERT(pti != ptirec);
    ASSERT(ptirec->pcti); // Send must have a client side to receive it!!!!
 
    /* Don't send from or to a dying thread */
@@ -1105,24 +1076,22 @@
    Message->Result = &Result;
    Message->lResult = 0;
    Message->QS_Flags = 0;
-   Message->SenderQueue = ThreadQueue;
-   Message->CallBackSenderQueue = NULL;
-   IntReferenceMessageQueue(ThreadQueue);
+   Message->ptiReceiver = ptirec;
+   Message->ptiSender = pti;
+   Message->ptiCallBackSender = NULL;
    Message->CompletionCallback = NULL;
    Message->CompletionCallbackContext = 0;
    Message->HookMessage = HookMessage;
    Message->HasPackedLParam = FALSE;
 
-   IntReferenceMessageQueue(MessageQueue);
-
    /* Add it to the list of pending messages */
-   InsertTailList(&ThreadQueue->DispatchingMessagesHead, &Message->DispatchingListEntry);
+   InsertTailList(&pti->DispatchingMessagesHead, &Message->DispatchingListEntry);
 
    /* Queue it in the destination's message queue */
-   InsertTailList(&MessageQueue->SentMessagesListHead, &Message->ListEntry);
+   InsertTailList(&ptirec->SentMessagesListHead, &Message->ListEntry);
 
    Message->QS_Flags = QS_SENDMESSAGE;
-   MsqWakeQueue(MessageQueue, QS_SENDMESSAGE, TRUE);
+   MsqWakeQueue(ptirec, QS_SENDMESSAGE, TRUE);
 
    /* We can't access the Message anymore since it could have already been deleted! */
 
@@ -1140,8 +1109,8 @@
       {
          /* Look up if the message has not yet dispatched, if so
             make sure it can't pass a result and it must not set the completion event anymore */
-         Entry = MessageQueue->SentMessagesListHead.Flink;
-         while (Entry != &MessageQueue->SentMessagesListHead)
+         Entry = ptirec->SentMessagesListHead.Flink;
+         while (Entry != &ptirec->SentMessagesListHead)
          {
             if ((PUSER_SENT_MESSAGE) CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry)
                   == Message)
@@ -1157,8 +1126,8 @@
 
          /* Remove from the local dispatching list so the other thread knows,
             it can't pass a result and it must not set the completion event anymore */
-         Entry = ThreadQueue->DispatchingMessagesHead.Flink;
-         while (Entry != &ThreadQueue->DispatchingMessagesHead)
+         Entry = pti->DispatchingMessagesHead.Flink;
+         while (Entry != &pti->DispatchingMessagesHead)
          {
             if ((PUSER_SENT_MESSAGE) CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, DispatchingListEntry)
                   == Message)
@@ -1178,7 +1147,7 @@
 
          TRACE("MsqSendMessage (blocked) timed out 1\n");
       }
-      while (co_MsqDispatchOneSentMessage(ThreadQueue))
+      while (co_MsqDispatchOneSentMessage(ptirec))
          ;
    }
    else
@@ -1186,7 +1155,7 @@
       PVOID WaitObjects[2];
 
       WaitObjects[0] = &CompletionEvent;
-      WaitObjects[1] = ThreadQueue->NewMessages;
+      WaitObjects[1] = pti->pEventQueueServer;
       do
       {
          UserLeaveCo();
@@ -1200,8 +1169,8 @@
          {
             /* Look up if the message has not yet been dispatched, if so
                make sure it can't pass a result and it must not set the completion event anymore */
-            Entry = MessageQueue->SentMessagesListHead.Flink;
-            while (Entry != &MessageQueue->SentMessagesListHead)
+            Entry = ptirec->SentMessagesListHead.Flink;
+            while (Entry != &ptirec->SentMessagesListHead)
             {
                if ((PUSER_SENT_MESSAGE) CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry)
                      == Message)
@@ -1217,8 +1186,8 @@
 
             /* Remove from the local dispatching list so the other thread knows,
                it can't pass a result and it must not set the completion event anymore */
-            Entry = ThreadQueue->DispatchingMessagesHead.Flink;
-            while (Entry != &ThreadQueue->DispatchingMessagesHead)
+            Entry = pti->DispatchingMessagesHead.Flink;
+            while (Entry != &pti->DispatchingMessagesHead)
             {
                if ((PUSER_SENT_MESSAGE) CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, DispatchingListEntry)
                      == Message)
@@ -1239,7 +1208,7 @@
             TRACE("MsqSendMessage timed out 2\n");
             break;
          }
-         while (co_MsqDispatchOneSentMessage(ThreadQueue))
+         while (co_MsqDispatchOneSentMessage(pti))
             ;
       }
       while (NT_SUCCESS(WaitStatus) && STATUS_WAIT_0 != WaitStatus);
@@ -1252,27 +1221,30 @@
 }
 
 VOID FASTCALL
-MsqPostMessage(PUSER_MESSAGE_QUEUE MessageQueue,
+MsqPostMessage(PTHREADINFO pti,
                MSG* Msg,
                BOOLEAN HardwareMessage,
                DWORD MessageBits,
                DWORD dwQEvent)
 {
    PUSER_MESSAGE Message;
+   PUSER_MESSAGE_QUEUE MessageQueue;
 
    if(!(Message = MsqCreateMessage(Msg)))
    {
       return;
    }
 
+   MessageQueue = pti->MessageQueue;
+
    if (dwQEvent)
    {
-       InsertHeadList(&MessageQueue->PostedMessagesListHead,
+       InsertHeadList(&pti->PostedMessagesListHead,
                       &Message->ListEntry);
    }
    else if (!HardwareMessage)
    {
-       InsertTailList(&MessageQueue->PostedMessagesListHead,
+       InsertTailList(&pti->PostedMessagesListHead,
                       &Message->ListEntry);
    }
    else
@@ -1284,15 +1256,15 @@
    Message->dwQEvent = dwQEvent;
    Message->QS_Flags = MessageBits;
    //Message->pti = pti; Fixed in ATI changes. See CORE-6551
-   MsqWakeQueue(MessageQueue, MessageBits, (MessageBits & QS_TIMER ? FALSE : TRUE));
+   MsqWakeQueue(pti, MessageBits, (MessageBits & QS_TIMER ? FALSE : TRUE));
 }
 
 VOID FASTCALL
-MsqPostQuitMessage(PUSER_MESSAGE_QUEUE MessageQueue, ULONG ExitCode)
+MsqPostQuitMessage(PTHREADINFO pti, ULONG ExitCode)
 {
-   MessageQueue->QuitPosted = TRUE;
-   MessageQueue->QuitExitCode = ExitCode;
-   MsqWakeQueue(MessageQueue, QS_POSTMESSAGE|QS_ALLPOSTMESSAGE, TRUE);
+   pti->QuitPosted = TRUE;
+   pti->exitCode = ExitCode;
+   MsqWakeQueue(pti, QS_POSTMESSAGE|QS_ALLPOSTMESSAGE, TRUE);
 }
 
 /***********************************************************************
@@ -1719,7 +1691,7 @@
 }
 
 BOOL APIENTRY
-co_MsqPeekMouseMove(IN PUSER_MESSAGE_QUEUE MessageQueue,
+co_MsqPeekMouseMove(IN PTHREADINFO pti,
                    IN BOOL Remove,
                    IN PWND Window,
                    IN UINT MsgFilterLow,
@@ -1728,7 +1700,7 @@
 {
     BOOL AcceptMessage;
     MSG msg;
-    PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+    PUSER_MESSAGE_QUEUE MessageQueue = pti->MessageQueue;
 
     if(!(MessageQueue->MouseMoved))
         return FALSE;
@@ -1754,7 +1726,7 @@
 
     if(Remove)
     {
-        ClearMsgBitsMask(MessageQueue, QS_MOUSEMOVE);
+        ClearMsgBitsMask(pti, QS_MOUSEMOVE);
         MessageQueue->MouseMoved = FALSE;
     }
 
@@ -1781,7 +1753,7 @@
 }
 
 BOOL APIENTRY
-co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
+co_MsqPeekHardwareMessage(IN PTHREADINFO pti,
                          IN BOOL Remove,
                          IN PWND Window,
                          IN UINT MsgFilterLow,
@@ -1795,7 +1767,7 @@
     PLIST_ENTRY ListHead, CurrentEntry = NULL;
     MSG msg;
     BOOL Ret = FALSE;
-    PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
+    PUSER_MESSAGE_QUEUE MessageQueue = pti->MessageQueue;
 
     if (!filter_contains_hw_range( MsgFilterLow, MsgFilterHigh )) return FALSE;
 
@@ -1843,7 +1815,7 @@
            if (Remove)
            {
                RemoveEntryList(&CurrentMessage->ListEntry);
-               ClearMsgBitsMask(MessageQueue, CurrentMessage->QS_Flags);
+               ClearMsgBitsMask(pti, CurrentMessage->QS_Flags);
                MsqDestroyMessage(CurrentMessage);
            }
 
@@ -1865,7 +1837,7 @@
 }
 
 BOOLEAN APIENTRY
-MsqPeekMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
+MsqPeekMessage(IN PTHREADINFO pti,
                   IN BOOLEAN Remove,
                   IN PWND Window,
                   IN UINT MsgFilterLow,
@@ -1877,25 +1849,12 @@
    PUSER_MESSAGE CurrentMessage;
    PLIST_ENTRY ListHead;
    BOOL Ret = FALSE;
-   PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
 
-   CurrentEntry = MessageQueue->PostedMessagesListHead.Flink;
-   ListHead = &MessageQueue->PostedMessagesListHead;
+   CurrentEntry = pti->PostedMessagesListHead.Flink;
+   ListHead = &pti->PostedMessagesListHead;
 
    if (IsListEmpty(CurrentEntry)) return FALSE;
-
-   if (!MessageQueue->ptiSysLock)
-   {
-      MessageQueue->ptiSysLock = pti;
-      pti->pcti->CTI_flags |= CTI_THREADSYSLOCK;
-   }
-
-   if (MessageQueue->ptiSysLock != pti)
-   {
-      ERR("MsqPeekMessage: Thread Q is locked to another pti!\n");
-      return FALSE;
-   }
-
+   
    CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
                                          ListEntry);
    do
@@ -1920,7 +1879,7 @@
          if (Remove)
          {
              RemoveEntryList(&CurrentMessage->ListEntry);
-             ClearMsgBitsMask(MessageQueue, CurrentMessage->QS_Flags);
+             ClearMsgBitsMask(pti, CurrentMessage->QS_Flags);
              MsqDestroyMessage(CurrentMessage);
          }
          Ret = TRUE;
@@ -1931,18 +1890,16 @@
    }
    while (CurrentEntry != ListHead);
 
-   MessageQueue->ptiSysLock = NULL;
-   pti->pcti->CTI_flags &= ~CTI_THREADSYSLOCK;
    return Ret;
 }
 
 NTSTATUS FASTCALL
-co_MsqWaitForNewMessages(PUSER_MESSAGE_QUEUE MessageQueue, PWND WndFilter,
+co_MsqWaitForNewMessages(PTHREADINFO pti, PWND WndFilter,
                          UINT MsgFilterMin, UINT MsgFilterMax)
 {
    NTSTATUS ret;
    UserLeaveCo();
-   ret = KeWaitForSingleObject( MessageQueue->NewMessages,
+   ret = KeWaitForSingleObject( pti->pEventQueueServer,
                                 UserRequest,
                                 UserMode,
                                 FALSE,
@@ -1952,12 +1909,12 @@
 }
 
 BOOL FASTCALL
-MsqIsHung(PUSER_MESSAGE_QUEUE MessageQueue)
+MsqIsHung(PTHREADINFO pti)
 {
    LARGE_INTEGER LargeTickCount;
 
    KeQueryTickCount(&LargeTickCount);
-   return ((LargeTickCount.u.LowPart - MessageQueue->LastMsgRead) > MSQ_HUNG);
+   return ((LargeTickCount.u.LowPart - pti->timeLast) > MSQ_HUNG);
 }
 
 VOID
@@ -1972,83 +1929,46 @@
 BOOLEAN FASTCALL
 MsqInitializeMessageQueue(PTHREADINFO pti, PUSER_MESSAGE_QUEUE MessageQueue)
 {
-   struct _ETHREAD *Thread;
-   LARGE_INTEGER LargeTickCount;
-   NTSTATUS Status;
-
-   Thread = pti->pEThread;
-   MessageQueue->Thread = Thread;
+   MessageQueue->ptiOwner = pti;
    MessageQueue->CaretInfo = (PTHRDCARETINFO)(MessageQueue + 1);
-   InitializeListHead(&MessageQueue->PostedMessagesListHead);
-   InitializeListHead(&MessageQueue->SentMessagesListHead);
    InitializeListHead(&MessageQueue->HardwareMessagesListHead);
-   InitializeListHead(&MessageQueue->DispatchingMessagesHead);
-   InitializeListHead(&MessageQueue->LocalDispatchingMessagesHead);
-   MessageQueue->QuitPosted = FALSE;
-   MessageQueue->QuitExitCode = 0;
-   KeQueryTickCount(&LargeTickCount);
-   MessageQueue->LastMsgRead = LargeTickCount.u.LowPart;
    MessageQueue->spwndFocus = NULL;
-   MessageQueue->NewMessagesHandle = NULL;
    MessageQueue->iCursorLevel = 0;
    MessageQueue->CursorObject = NULL;
    RtlCopyMemory(MessageQueue->afKeyState, gafAsyncKeyState, sizeof(gafAsyncKeyState));
+   MessageQueue->ptiMouse = pti;
+   MessageQueue->ptiKeyboard = pti;
+   MessageQueue->cThreads++;
 
-   Status = ZwCreateEvent(&MessageQueue->NewMessagesHandle, EVENT_ALL_ACCESS,
-                          NULL, SynchronizationEvent, FALSE);
-   if (!NT_SUCCESS(Status))
-   {
-      return FALSE;
-   }
-
-   Status = ObReferenceObjectByHandle(MessageQueue->NewMessagesHandle, 0,
-                                      ExEventObjectType, KernelMode,
-                                      (PVOID*)&MessageQueue->NewMessages, NULL);
-   if (!NT_SUCCESS(Status))
-   {
-      ZwClose(MessageQueue->NewMessagesHandle);
-      MessageQueue->NewMessagesHandle = NULL;
-      return FALSE;
-   }
-
    return TRUE;
 }
 
 VOID FASTCALL
-MsqCleanupMessageQueue(PTHREADINFO pti)
+MsqCleanupThreadMsgs(PTHREADINFO pti)
 {
-   PUSER_MESSAGE_QUEUE MessageQueue;
    PLIST_ENTRY CurrentEntry;
    PUSER_MESSAGE CurrentMessage;
    PUSER_SENT_MESSAGE CurrentSentMessage;
-
-   MessageQueue = pti->MessageQueue;
-
+   
    /* cleanup posted messages */
-   while (!IsListEmpty(&MessageQueue->PostedMessagesListHead))
+   while (!IsListEmpty(&pti->PostedMessagesListHead))
    {
-      CurrentEntry = RemoveHeadList(&MessageQueue->PostedMessagesListHead);
+      CurrentEntry = RemoveHeadList(&pti->PostedMessagesListHead);
       CurrentMessage = CONTAINING_RECORD(CurrentEntry, USER_MESSAGE,
                                          ListEntry);
       MsqDestroyMessage(CurrentMessage);
    }
 
    /* remove the messages that have not yet been dispatched */
-   while (!IsListEmpty(&MessageQueue->SentMessagesListHead))
+   while (!IsListEmpty(&pti->SentMessagesListHead))
    {
-      CurrentEntry = RemoveHeadList(&MessageQueue->SentMessagesListHead);
+      CurrentEntry = RemoveHeadList(&pti->SentMessagesListHead);
       CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE,
                                              ListEntry);
 
-      /* if it is a callback and this queue is not the sender queue, dereference queue */
-      if ((CurrentSentMessage->CompletionCallback) && (CurrentSentMessage->CallBackSenderQueue != MessageQueue))
-      {
-         IntDereferenceMessageQueue(CurrentSentMessage->CallBackSenderQueue);
-      }
-
       TRACE("Notify the sender and remove a message from the queue that had not been dispatched\n");
       /* Only if the message has a sender was the message in the DispatchingList */
-      if ((CurrentSentMessage->SenderQueue)
+      if ((CurrentSentMessage->ptiSender)
          && (CurrentSentMessage->DispatchingListEntry.Flink != NULL))
       {
          RemoveEntryList(&CurrentSentMessage->DispatchingListEntry);
@@ -2065,33 +1985,19 @@
          if (CurrentSentMessage->Msg.lParam)
             ExFreePool((PVOID)CurrentSentMessage->Msg.lParam);
       }
-
-      /* if the message has a sender */
-      if (CurrentSentMessage->SenderQueue)
-      {
-         /* dereference our and the sender's message queue */
-         IntDereferenceMessageQueue(MessageQueue);
-         IntDereferenceMessageQueue(CurrentSentMessage->SenderQueue);
-      }
-
+      
       /* free the message */
       ExFreePool(CurrentSentMessage);
    }
 
    /* notify senders of dispatching messages. This needs to be cleaned up if e.g.
       ExitThread() was called in a SendMessage() umode callback */
-   while (!IsListEmpty(&MessageQueue->LocalDispatchingMessagesHead))
+   while (!IsListEmpty(&pti->LocalDispatchingMessagesHead))
    {
-      CurrentEntry = RemoveHeadList(&MessageQueue->LocalDispatchingMessagesHead);
+      CurrentEntry = RemoveHeadList(&pti->LocalDispatchingMessagesHead);
       CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE,
                                              ListEntry);
 
-      /* if it is a callback and this queue is not the sender queue, dereference queue */
-      if ((CurrentSentMessage->CompletionCallback) && (CurrentSentMessage->CallBackSenderQueue != MessageQueue))
-      {
-         IntDereferenceMessageQueue(CurrentSentMessage->CallBackSenderQueue);
-      }
-
       /* remove the message from the dispatching list */
       if(CurrentSentMessage->DispatchingListEntry.Flink != NULL)
       {
@@ -2112,22 +2018,14 @@
             ExFreePool((PVOID)CurrentSentMessage->Msg.lParam);
       }
 
-      /* if the message has a sender */
-      if (CurrentSentMessage->SenderQueue)
-      {
-         /* dereference our and the sender's message queue */
-         IntDereferenceMessageQueue(MessageQueue);
-         IntDereferenceMessageQueue(CurrentSentMessage->SenderQueue);
-      }
-
       /* free the message */
       ExFreePool(CurrentSentMessage);
    }
 
    /* tell other threads not to bother returning any info to us */
-   while (! IsListEmpty(&MessageQueue->DispatchingMessagesHead))
+   while (! IsListEmpty(&pti->DispatchingMessagesHead))
    {
-      CurrentEntry = RemoveHeadList(&MessageQueue->DispatchingMessagesHead);
+      CurrentEntry = RemoveHeadList(&pti->DispatchingMessagesHead);
       CurrentSentMessage = CONTAINING_RECORD(CurrentEntry, USER_SENT_MESSAGE,
                                              DispatchingListEntry);
       CurrentSentMessage->CompletionEvent = NULL;
@@ -2144,13 +2042,28 @@
        pti->pcti->fsChangeBits = 0;
    }
 
-   MessageQueue->nCntsQBits[QSRosKey] = 0;
-   MessageQueue->nCntsQBits[QSRosMouseMove] = 0;
-   MessageQueue->nCntsQBits[QSRosMouseButton] = 0;
-   MessageQueue->nCntsQBits[QSRosPostMessage] = 0;
-   MessageQueue->nCntsQBits[QSRosSendMessage] = 0;
-   MessageQueue->nCntsQBits[QSRosHotKey] = 0;
+   pti->nCntsQBits[QSRosKey] = 0;
+   pti->nCntsQBits[QSRosMouseMove] = 0;
+   pti->nCntsQBits[QSRosMouseButton] = 0;
+   pti->nCntsQBits[QSRosPostMessage] = 0;
+   pti->nCntsQBits[QSRosSendMessage] = 0;
+   pti->nCntsQBits[QSRosHotKey] = 0;
 
+}
+ 
+VOID FASTCALL
+MsqCleanupMessageQueue(PTHREADINFO pti)
+{
+   PUSER_MESSAGE_QUEUE MessageQueue;
+
+   MessageQueue = pti->MessageQueue;
+  MessageQueue->cThreads--;
+
+   if (MessageQueue->cThreads)
+   {
+      if (MessageQueue->ptiSysLock == pti) MessageQueue->ptiSysLock = NULL;
+   }
+
    if (MessageQueue->CursorObject)
    {
        PCURICON_OBJECT pCursor = MessageQueue->CursorObject;
@@ -2171,6 +2084,19 @@
 
        UserDereferenceObject(pCursor);
    }
+
+   if (gpqForeground == MessageQueue)
+   {
+      IntSetFocusMessageQueue(NULL);
+   }
+   if (gpqForegroundPrev == MessageQueue)
+   {
+      gpqForegroundPrev = NULL;
+   }
+   if (gpqCursor == MessageQueue)
+   {
+      gpqCursor = NULL;
+   }
 }
 
 PUSER_MESSAGE_QUEUE FASTCALL
@@ -2218,9 +2144,6 @@
    /* clean it up */
    MsqCleanupMessageQueue(pti);
 
-   if (MessageQueue->NewMessagesHandle != NULL)
-      ZwClose(MessageQueue->NewMessagesHandle);
-   MessageQueue->NewMessagesHandle = NULL;
    /* decrease the reference counter, if it hits zero, the queue will be freed */
    IntDereferenceMessageQueue(MessageQueue);
 }
@@ -2276,7 +2199,7 @@
    if (Message->QS_Flags & QS_SMRESULT) return FALSE;
 
    //     SendMessageXxx    || Callback msg and not a notify msg
-   if (Message->SenderQueue || Message->CompletionCallback)
+   if (Message->ptiSender || Message->CompletionCallback)
    {
       Message->lResult = lResult;
       Message->QS_Flags |= QS_SMRESULT;
@@ -2286,9 +2209,12 @@
 }
 
 HWND FASTCALL
-MsqSetStateWindow(PUSER_MESSAGE_QUEUE MessageQueue, ULONG Type, HWND hWnd)
+MsqSetStateWindow(PTHREADINFO pti, ULONG Type, HWND hWnd)
 {
    HWND Prev;
+   PUSER_MESSAGE_QUEUE MessageQueue;
+   
+   MessageQueue = pti->MessageQueue;
 
    switch(Type)
    {
Index: win32ss/user/ntuser/msgqueue.h
===================================================================
--- win32ss/user/ntuser/msgqueue.h	(revision 58773)
+++ win32ss/user/ntuser/msgqueue.h	(working copy)
@@ -6,18 +6,6 @@
 #define MSQ_ISEVENT     2
 #define MSQ_INJECTMODULE 3
 
-#define QSIDCOUNTS 6
-
-typedef enum _QS_ROS_TYPES
-{
-    QSRosKey = 0,
-    QSRosMouseMove,
-    QSRosMouseButton,
-    QSRosPostMessage,
-    QSRosSendMessage,
-    QSRosHotKey,
-}QS_ROS_TYPES,*PQS_ROS_TYPES;
-
 typedef struct _USER_MESSAGE
 {
   LIST_ENTRY ListEntry;
@@ -38,9 +26,10 @@
   PKEVENT CompletionEvent;
   LRESULT* Result;
   LRESULT lResult;
-  struct _USER_MESSAGE_QUEUE* SenderQueue;
-  struct _USER_MESSAGE_QUEUE* CallBackSenderQueue;
+  PTHREADINFO ptiSender;
+  PTHREADINFO ptiReceiver;
   SENDASYNCPROC CompletionCallback;
+  PTHREADINFO ptiCallBackSender;
   ULONG_PTR CompletionCallbackContext;
   /* entry in the dispatching list of the sender's message queue */
   LIST_ENTRY DispatchingListEntry;
@@ -53,13 +42,16 @@
   /* Reference counter, only access this variable with interlocked functions! */
   LONG References;
 
+  PTHREADINFO ptiOwner; // temp..
+  /* Desktop that the message queue is attached to */
+  struct _DESKTOP *Desktop;
+
   PTHREADINFO ptiSysLock;
   /* Owner of the message queue */
-  struct _ETHREAD *Thread;
-  /* Queue of messages sent to the queue. */
-  LIST_ENTRY SentMessagesListHead;
-  /* Queue of messages posted to the queue. */
-  LIST_ENTRY PostedMessagesListHead;
+//  struct _ETHREAD *Thread;
+  PTHREADINFO ptiMouse;
+  PTHREADINFO ptiKeyboard;
+
   /* Queue for hardware messages for the queue. */
   LIST_ENTRY HardwareMessagesListHead;
   /* True if a WM_MOUSEMOVE is pending */
@@ -68,16 +60,6 @@
   MSG MouseMoveMsg;
   /* Last click message for translating double clicks */
   MSG msgDblClk;
-  /* True if a WM_QUIT message is pending. */
-  BOOLEAN QuitPosted;
-  /* The quit exit code. */
-  ULONG QuitExitCode;
-  /* Set if there are new messages specified by WakeMask in any of the queues. */
-  PKEVENT NewMessages;
-  /* Handle for the above event (in the context of the process owning the queue). */
-  HANDLE NewMessagesHandle;
-  /* Last time PeekMessage() was called. */
-  ULONG LastMsgRead;
   /* Current capture window for this queue. */
   PWND spwndCapture;
   /* Current window with focus (ie. receives keyboard input) for this queue. */
@@ -97,13 +79,6 @@
   DWORD QF_flags;
   DWORD cThreads; // Shared message queue counter.
 
-  /* Queue state tracking */
-  // Send list QS_SENDMESSAGE
-  // Post list QS_POSTMESSAGE|QS_HOTKEY|QS_PAINT|QS_TIMER|QS_KEY
-  // Hard list QS_MOUSE|QS_KEY only
-  // Accounting of queue bit sets, the rest are flags. QS_TIMER QS_PAINT counts are handled in thread information.
-  DWORD nCntsQBits[QSIDCOUNTS]; // QS_KEY QS_MOUSEMOVE QS_MOUSEBUTTON QS_POSTMESSAGE QS_SENDMESSAGE QS_HOTKEY
-
   /* Extra message information */
   LPARAM ExtraInfo;
 
@@ -116,13 +91,6 @@
   /* Cursor object */
   PCURICON_OBJECT CursorObject;
 
-  /* Messages that are currently dispatched by other threads */
-  LIST_ENTRY DispatchingMessagesHead;
-  /* Messages that are currently dispatched by this message queue, required for cleanup */
-  LIST_ENTRY LocalDispatchingMessagesHead;
-
-  /* Desktop that the message queue is attached to */
-  struct _DESKTOP *Desktop;
 } USER_MESSAGE_QUEUE, *PUSER_MESSAGE_QUEUE;
 
 #define QF_UPDATEKEYSTATE         0x00000001
@@ -152,17 +120,17 @@
     WM_ASYNC_SETACTIVEWINDOW
 };
 
-BOOL FASTCALL MsqIsHung(PUSER_MESSAGE_QUEUE MessageQueue);
+BOOL FASTCALL MsqIsHung(PTHREADINFO pti);
 VOID CALLBACK HungAppSysTimerProc(HWND,UINT,UINT_PTR,DWORD);
-NTSTATUS FASTCALL co_MsqSendMessage(PUSER_MESSAGE_QUEUE MessageQueue,
+NTSTATUS FASTCALL co_MsqSendMessage(PTHREADINFO ptirec,
            HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam,
            UINT uTimeout, BOOL Block, INT HookMessage, ULONG_PTR *uResult);
 PUSER_MESSAGE FASTCALL MsqCreateMessage(LPMSG Msg);
 VOID FASTCALL MsqDestroyMessage(PUSER_MESSAGE Message);
-VOID FASTCALL MsqPostMessage(PUSER_MESSAGE_QUEUE, MSG*, BOOLEAN, DWORD, DWORD);
-VOID FASTCALL MsqPostQuitMessage(PUSER_MESSAGE_QUEUE MessageQueue, ULONG ExitCode);
+VOID FASTCALL MsqPostMessage(PTHREADINFO, MSG*, BOOLEAN, DWORD, DWORD);
+VOID FASTCALL MsqPostQuitMessage(PTHREADINFO pti, ULONG ExitCode);
 BOOLEAN APIENTRY
-MsqPeekMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
+MsqPeekMessage(IN PTHREADINFO pti,
 	              IN BOOLEAN Remove,
 	              IN PWND Window,
 	              IN UINT MsgFilterLow,
@@ -170,7 +138,7 @@
 	              IN UINT QSflags,
 	              OUT PMSG Message);
 BOOL APIENTRY
-co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
+co_MsqPeekHardwareMessage(IN PTHREADINFO pti,
 	                      IN BOOL Remove,
 	                      IN PWND Window,
 	                      IN UINT MsgFilterLow,
@@ -178,7 +146,7 @@
 	                      IN UINT QSflags,
 	                      OUT MSG* pMsg);
 BOOL APIENTRY
-co_MsqPeekMouseMove(IN PUSER_MESSAGE_QUEUE MessageQueue,
+co_MsqPeekMouseMove(IN PTHREADINFO pti,
                     IN BOOL Remove,
                     IN PWND Window,
                     IN UINT MsgFilterLow,
@@ -186,14 +154,15 @@
                     OUT MSG* pMsg);
 BOOLEAN FASTCALL MsqInitializeMessageQueue(PTHREADINFO, PUSER_MESSAGE_QUEUE);
 PUSER_MESSAGE_QUEUE FASTCALL MsqCreateMessageQueue(PTHREADINFO);
+VOID FASTCALL MsqCleanupThreadMsgs(PTHREADINFO);
 VOID FASTCALL MsqDestroyMessageQueue(PTHREADINFO);
 INIT_FUNCTION NTSTATUS NTAPI MsqInitializeImpl(VOID);
-BOOLEAN FASTCALL co_MsqDispatchOneSentMessage(_In_ PUSER_MESSAGE_QUEUE MessageQueue);
+BOOLEAN FASTCALL co_MsqDispatchOneSentMessage(PTHREADINFO pti);
 NTSTATUS FASTCALL
-co_MsqWaitForNewMessages(PUSER_MESSAGE_QUEUE MessageQueue, PWND WndFilter,
+co_MsqWaitForNewMessages(PTHREADINFO pti, PWND WndFilter,
                       UINT MsgFilterMin, UINT MsgFilterMax);
-VOID FASTCALL MsqIncPaintCountQueue(PUSER_MESSAGE_QUEUE Queue);
-VOID FASTCALL MsqDecPaintCountQueue(PUSER_MESSAGE_QUEUE Queue);
+VOID FASTCALL MsqIncPaintCountQueue(PTHREADINFO);
+VOID FASTCALL MsqDecPaintCountQueue(PTHREADINFO);
 LRESULT FASTCALL co_IntSendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
 LRESULT FASTCALL co_IntPostOrSendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
 LRESULT FASTCALL
@@ -235,13 +204,13 @@
 VOID FASTCALL co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook);
 BOOL FASTCALL MsqIsClkLck(LPMSG Msg, BOOL Remove);
 BOOL FASTCALL MsqIsDblClk(LPMSG Msg, BOOL Remove);
-HWND FASTCALL MsqSetStateWindow(PUSER_MESSAGE_QUEUE MessageQueue, ULONG Type, HWND hWnd);
+HWND FASTCALL MsqSetStateWindow(PTHREADINFO pti, ULONG Type, HWND hWnd);
 BOOL APIENTRY IntInitMessagePumpHook(VOID);
 BOOL APIENTRY IntUninitMessagePumpHook(VOID);
 
 LPARAM FASTCALL MsqSetMessageExtraInfo(LPARAM lParam);
 LPARAM FASTCALL MsqGetMessageExtraInfo(VOID);
-VOID APIENTRY MsqRemoveWindowMessagesFromQueue(PVOID pWindow); /* F*(&$ headers, will be gone in the rewrite! */
+VOID APIENTRY MsqRemoveWindowMessagesFromQueue(PWND pWindow);
 
 #define IntReferenceMessageQueue(MsgQueue) \
   InterlockedIncrement(&(MsgQueue)->References)
@@ -250,9 +219,7 @@
   do { \
     if(InterlockedDecrement(&(MsgQueue)->References) == 0) \
     { \
-      TRACE("Free message queue 0x%p\n", (MsgQueue)); \
-      if ((MsgQueue)->NewMessages != NULL) \
-        ObDereferenceObject((MsgQueue)->NewMessages); \
+      ERR("Free message queue 0x%p\n", (MsgQueue)); \
       ExFreePoolWithTag((MsgQueue), USERTAG_Q); \
     } \
   } while(0)
@@ -289,8 +256,8 @@
 VOID FASTCALL IdlePing(VOID);
 VOID FASTCALL IdlePong(VOID);
 BOOL FASTCALL co_MsqReplyMessage(LRESULT);
-VOID FASTCALL MsqWakeQueue(PUSER_MESSAGE_QUEUE,DWORD,BOOL);
-VOID FASTCALL ClearMsgBitsMask(PUSER_MESSAGE_QUEUE,UINT);
+VOID FASTCALL MsqWakeQueue(PTHREADINFO,DWORD,BOOL);
+VOID FASTCALL ClearMsgBitsMask(PTHREADINFO,UINT);
 
 int UserShowCursor(BOOL bShow);
 PCURICON_OBJECT
Index: win32ss/user/ntuser/painting.c
===================================================================
--- win32ss/user/ntuser/painting.c	(revision 58773)
+++ win32ss/user/ntuser/painting.c	(working copy)
@@ -97,13 +97,12 @@
 VOID FASTCALL
 IntSendSyncPaint(PWND Wnd, ULONG Flags)
 {
-   PTHREADINFO ptiCur;
-   PUSER_MESSAGE_QUEUE MessageQueue;
+   PTHREADINFO ptiCur, ptiWnd;
    PUSER_SENT_MESSAGE Message;
    PLIST_ENTRY Entry;
    BOOL bSend = TRUE;
 
-   MessageQueue = Wnd->head.pti->MessageQueue;
+   ptiWnd = Wnd->head.pti;
    ptiCur = PsGetCurrentThreadWin32Thread();
    /*
       Not the current thread, Wnd is in send Nonclient paint also in send erase background and it is visiable.
@@ -115,10 +114,10 @@
    {
       // For testing, if you see this, break out the Champagne and have a party!
       ERR("SendSyncPaint Wnd in State!\n");
-      if (!IsListEmpty(&MessageQueue->SentMessagesListHead))
+      if (!IsListEmpty(&ptiWnd->SentMessagesListHead))
       {
          // Scan sent queue messages to see if we received sync paint messages.
-         Entry = MessageQueue->SentMessagesListHead.Flink;
+         Entry = ptiWnd->SentMessagesListHead.Flink;
          Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
          do
          {
@@ -133,7 +132,7 @@
             Entry = Message->ListEntry.Flink;
             Message = CONTAINING_RECORD(Entry, USER_SENT_MESSAGE, ListEntry);
          }
-         while (Entry != &MessageQueue->SentMessagesListHead);
+         while (Entry != &ptiWnd->SentMessagesListHead);
       }
       if (bSend)
       {
@@ -270,7 +269,7 @@
             Window->state &= ~WNDS_UPDATEDIRTY;
             Window->hrgnUpdate = NULL;
             if (!(Window->state & WNDS_INTERNALPAINT))
-               MsqDecPaintCountQueue(Window->head.pti->MessageQueue);
+               MsqDecPaintCountQueue(Window->head.pti);
          }
       }
 
@@ -557,9 +556,9 @@
    if (HadPaintMessage != IntIsWindowDirty(Wnd))
    {
       if (HadPaintMessage)
-         MsqDecPaintCountQueue(Wnd->head.pti->MessageQueue);
+         MsqDecPaintCountQueue(Wnd->head.pti);
       else
-         MsqIncPaintCountQueue(Wnd->head.pti->MessageQueue);
+         MsqIncPaintCountQueue(Wnd->head.pti);
    }
    TRACE("IntInvalidateWindows exit\n");
 }
@@ -781,7 +780,7 @@
    {
       PaintWnd->state &= ~WNDS_INTERNALPAINT;
       if (!PaintWnd->hrgnUpdate)
-         MsqDecPaintCountQueue(Thread->MessageQueue);
+         MsqDecPaintCountQueue(Thread);
    }
    PaintWnd->state2 &= ~WNDS2_WMPAINTSENT;
    PaintWnd->state &= ~WNDS_UPDATEDIRTY;
@@ -955,7 +954,7 @@
 
    if (Window->hrgnUpdate != NULL)
    {
-      MsqDecPaintCountQueue(Window->head.pti->MessageQueue);
+      MsqDecPaintCountQueue(Window->head.pti);
       GdiGetClipBox(Ps->hdc, &Ps->rcPaint);
       IntGdiSetRegionOwner(Window->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
       /* The region is part of the dc now and belongs to the process! */
@@ -964,7 +963,7 @@
    else
    {
       if (Window->state & WNDS_INTERNALPAINT)
-         MsqDecPaintCountQueue(Window->head.pti->MessageQueue);
+         MsqDecPaintCountQueue(Window->head.pti);
 
       IntGetClientRect(Window, &Ps->rcPaint);
    }
Index: win32ss/user/ntuser/simplecall.c
===================================================================
--- win32ss/user/ntuser/simplecall.c	(revision 58773)
+++ win32ss/user/ntuser/simplecall.c	(working copy)
@@ -156,7 +156,7 @@
           {
                 PTHREADINFO pti;
                 pti = PsGetCurrentThreadWin32Thread();
-                MsqPostQuitMessage(pti->MessageQueue, Param);
+                MsqPostQuitMessage(pti, Param);
                 RETURN(TRUE);
           }
 
@@ -419,10 +419,9 @@
 
       case TWOPARAM_ROUTINE_SETGUITHRDHANDLE:
          {
-            PUSER_MESSAGE_QUEUE MsgQueue = ((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->MessageQueue;
-
-            ASSERT(MsgQueue);
-            RETURN( (DWORD_PTR)MsqSetStateWindow(MsgQueue, (ULONG)Param1, (HWND)Param2));
+            PTHREADINFO pti = (PTHREADINFO)PsGetCurrentThreadWin32Thread();
+            ASSERT(pti->MessageQueue);
+            RETURN( (DWORD_PTR)MsqSetStateWindow(pti, (ULONG)Param1, (HWND)Param2));
          }
 
       case TWOPARAM_ROUTINE_ENABLEWINDOW:
Index: win32ss/user/ntuser/timer.c
===================================================================
--- win32ss/user/ntuser/timer.c	(revision 58773)
+++ win32ss/user/ntuser/timer.c	(working copy)
@@ -409,7 +409,7 @@
            Msg.wParam  = (WPARAM) pTmr->nID;
            Msg.lParam  = (LPARAM) pTmr->pfn;
 
-           MsqPostMessage(ThreadQueue, &Msg, FALSE, QS_TIMER, 0);
+           MsqPostMessage(pti, &Msg, FALSE, QS_TIMER, 0);
            pTmr->flags &= ~TMRF_READY;
            pti->cTimersReady++;
            Hit = TRUE;
@@ -484,8 +484,8 @@
                 // Set thread message queue for this timer.
                 if (pTmr->pti->MessageQueue)
                 {  // Wakeup thread
-                   ASSERT(pTmr->pti->MessageQueue->NewMessages != NULL);
-                   KeSetEvent(pTmr->pti->MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE);
+                   ASSERT(pTmr->pti->pEventQueueServer != NULL);
+                   KeSetEvent(pTmr->pti->pEventQueueServer, IO_NO_INCREMENT, FALSE);
                 }
              }
           }
Index: win32ss/user/ntuser/win32.h
===================================================================
--- win32ss/user/ntuser/win32.h	(revision 58773)
+++ win32ss/user/ntuser/win32.h	(working copy)
@@ -32,9 +32,9 @@
 #define W32PF_MANUALGUICHECK         (0x02000000)
 #define W32PF_CREATEDWINORDC         (0x04000000)
 #define W32PF_APIHOOKLOADED          (0x08000000)
-/*
-#define QSIDCOUNTS 6
 
+#define QSIDCOUNTS 7
+
 typedef enum _QS_ROS_TYPES
 {
     QSRosKey = 0,
@@ -43,8 +43,9 @@
     QSRosPostMessage,
     QSRosSendMessage,
     QSRosHotKey,
+    QSRosEvent,
 }QS_ROS_TYPES,*PQS_ROS_TYPES;
-*/
+
 extern BOOL ClientPfnInit;
 extern HINSTANCE hModClient;
 extern HANDLE hModuleWin;    // This Win32k Instance.
@@ -65,7 +66,7 @@
 typedef struct _W32THREAD
 {
     PETHREAD pEThread;
-    ULONG RefCount;
+    LONG RefCount;
     PTL ptlW32;
     PVOID pgdiDcattr;
     PVOID pgdiBrushAttr;
@@ -89,13 +90,18 @@
     PCLIENTINFO         pClientInfo;
     FLONG               TIF_flags;
     PUNICODE_STRING     pstrAppName;
-    LIST_ENTRY          psmsSent;        // DispatchingMessagesHead
+    /* Messages that are currently dispatched to other threads */
+    LIST_ENTRY          DispatchingMessagesHead; // psmsSent
     struct _USER_SENT_MESSAGE *pusmCurrent;
-    LIST_ENTRY          psmsReceiveList; // SentMessagesListHead
+    /* Queue of messages sent to the queue. */
+    LIST_ENTRY          SentMessagesListHead;    // psmsReceiveList
+    /* Last time PeekMessage() was called. */
     LONG                timeLast;
     ULONG_PTR           idLast;
+    /* True if a WM_QUIT message is pending. */
     BOOLEAN             QuitPosted;
-    INT                 exitCode;     // QuitExitCode
+    /* The quit exit code. */
+    INT                 exitCode;
     HDESK               hdesk;
     UINT                cPaintsReady; /* Count of paints pending. */
     UINT                cTimersReady; /* Count of timers pending. */
@@ -109,26 +115,32 @@
     LPARAM              lParamHkCurrent;
     WPARAM              wParamHkCurrent;
     struct tagSBTRACK*  pSBTrack;
-    HANDLE              hEventQueueClient; // NewMessagesHandle
-    PKEVENT             pEventQueueServer; // NewMessages
+    /* Set if there are new messages specified by WakeMask in any of the queues. */
+    HANDLE              hEventQueueClient;
+    /* Handle for the above event (in the context of the process owning the queue). */
+    PKEVENT             pEventQueueServer;
     LIST_ENTRY          PtiLink;
     INT                 iCursorLevel;
     POINT               ptLast;
 
-    LIST_ENTRY          mlPost; // PostedMessagesListHead
+    /* Queue of messages posted to the queue. */
+    LIST_ENTRY          PostedMessagesListHead; // mlPost
 
+    UINT                cWindows;
+    UINT                cVisWindows;
     LIST_ENTRY          aphkStart[NB_HOOKS];
     CLIENTTHREADINFO    cti;  // Used only when no Desktop or pcti NULL.
 
     /* ReactOS */
 
-    /* Queue state tracking */
+    /* Thread Queue state tracking */
     // Send list QS_SENDMESSAGE
     // Post list QS_POSTMESSAGE|QS_HOTKEY|QS_PAINT|QS_TIMER|QS_KEY
     // Hard list QS_MOUSE|QS_KEY only
     // Accounting of queue bit sets, the rest are flags. QS_TIMER QS_PAINT counts are handled in thread information.
-    //DWORD nCntsQBits[QSIDCOUNTS]; // QS_KEY QS_MOUSEMOVE QS_MOUSEBUTTON QS_POSTMESSAGE QS_SENDMESSAGE QS_HOTKEY
+    DWORD nCntsQBits[QSIDCOUNTS]; // QS_KEY QS_MOUSEMOVE QS_MOUSEBUTTON QS_POSTMESSAGE QS_SENDMESSAGE QS_HOTKEY
 
+    /* Messages that are currently dispatched by this message queue, required for cleanup */
     LIST_ENTRY LocalDispatchingMessagesHead;
     LIST_ENTRY WindowListHead;
     LIST_ENTRY W32CallbackListHead;
@@ -142,6 +154,22 @@
 
 #include <poppack.h>
 
+
+#define IntReferenceThreadInfo(pti) \
+  InterlockedIncrement(&(pti)->RefCount)
+
+VOID FASTCALL UserDeleteW32Thread(PTHREADINFO);
+
+#define IntDereferenceThreadInfo(pti) \
+  do { \
+    if(InterlockedDecrement(&(pti)->RefCount) == 0) \
+    { \
+      ASSERT(pti->TIF_flags &= (TIF_INCLEANUP|TIF_DONTATTACHQUEUE) == (TIF_INCLEANUP|TIF_DONTATTACHQUEUE)); \
+      UserDeleteW32Thread(pti); \
+    } \
+  } while(0)
+
+
 typedef struct _W32HEAP_USER_MAPPING
 {
     struct _W32HEAP_USER_MAPPING *Next;
@@ -195,9 +223,9 @@
   PTHREADINFO ptiList;
   PTHREADINFO ptiMainThread;
   struct _DESKTOP* rpdeskStartup;
-  PPROCESSINFO ppiNext;
   PCLS pclsPrivateList;
   PCLS pclsPublicList;
+  PPROCESSINFO ppiNext;
   INT cThreads;
   HDESK hdeskStartup;
   DWORD dwhmodLibLoadedMask;
Index: win32ss/user/ntuser/window.c
===================================================================
--- win32ss/user/ntuser/window.c	(revision 58773)
+++ win32ss/user/ntuser/window.c	(working copy)
@@ -3779,7 +3779,7 @@
          break;
 
       case QUERY_WINDOW_ISHUNG:
-         Result = (DWORD)MsqIsHung(pWnd->head.pti->MessageQueue);
+         Result = (DWORD)MsqIsHung(pWnd->head.pti);
          break;
 
       case QUERY_WINDOW_REAL_ID:
