Removed the MESSAGEQUEUE structure, and store the corresponding
information directly in the TEB, in the Win32ClientInfo field.

diff --git a/dlls/kernel/task.c b/dlls/kernel/task.c
index 628e4d8..37e9ba0 100644
--- a/dlls/kernel/task.c
+++ b/dlls/kernel/task.c
@@ -1021,16 +1021,8 @@
  */
 HQUEUE16 WINAPI SetTaskQueue16( HTASK16 hTask, HQUEUE16 hQueue )
 {
-    HQUEUE16 hPrev;
-    TDB *pTask;
-
-    if (!hTask) hTask = GetCurrentTask();
-    if (!(pTask = TASK_GetPtr( hTask ))) return 0;
-
-    hPrev = pTask->hQueue;
-    pTask->hQueue = hQueue;
-
-    return hPrev;
+    FIXME( "stub, should not get called\n" );
+    return 0xbeef;
 }
 
 
@@ -1039,11 +1031,8 @@
  */
 HQUEUE16 WINAPI GetTaskQueue16( HTASK16 hTask )
 {
-    TDB *pTask;
-
-    if (!hTask) hTask = GetCurrentTask();
-    if (!(pTask = TASK_GetPtr( hTask ))) return 0;
-    return pTask->hQueue;
+    FIXME( "stub, should not get called\n" );
+    return 0xbeef;
 }
 
 /***********************************************************************
@@ -1051,17 +1040,8 @@
  */
 HQUEUE16 WINAPI SetThreadQueue16( DWORD thread, HQUEUE16 hQueue )
 {
-    HQUEUE16 oldQueue = NtCurrentTeb()->queue;
-
-    if (thread && thread != GetCurrentThreadId())
-    {
-        FIXME( "not supported on other thread %04lx\n", thread );
-        return 0;
-    }
-    NtCurrentTeb()->queue = hQueue;
-    if ( GetTaskQueue16( NtCurrentTeb()->htask16 ) == oldQueue )
-        SetTaskQueue16( NtCurrentTeb()->htask16, hQueue );
-    return oldQueue;
+    FIXME( "stub, should not get called\n" );
+    return 0xbeef;
 }
 
 /***********************************************************************
@@ -1069,12 +1049,8 @@
  */
 HQUEUE16 WINAPI GetThreadQueue16( DWORD thread )
 {
-    if (thread && thread != GetCurrentThreadId())
-    {
-        FIXME( "not supported on other thread %04lx\n", thread );
-        return 0;
-    }
-    return NtCurrentTeb()->queue;
+    FIXME( "stub, should not get called\n" );
+    return 0xbeef;
 }
 
 /***********************************************************************
@@ -1082,10 +1058,7 @@
  */
 VOID WINAPI SetFastQueue16( DWORD thread, HQUEUE16 hQueue )
 {
-    if (!thread || thread == GetCurrentThreadId())
-        NtCurrentTeb()->queue = hQueue;
-    else
-        FIXME( "not supported on other thread %04lx\n", thread );
+    FIXME( "stub, should not get called\n" );
 }
 
 /***********************************************************************
@@ -1093,10 +1066,8 @@
  */
 HQUEUE16 WINAPI GetFastQueue16( void )
 {
-    HQUEUE16 ret = NtCurrentTeb()->queue;
-
-    if (!ret) FIXME("(): should initialize thread-local queue, expect failure!\n" );
-    return ret;
+    FIXME( "stub, should not get called\n" );
+    return 0xbeef;
 }
 
 /***********************************************************************
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index 13d6f9d..712e3c3 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -262,7 +262,6 @@
     teb->ClientId.UniqueProcess = (HANDLE)GetCurrentProcessId();
     teb->ClientId.UniqueThread  = (HANDLE)tid;
 
-    teb->exit_code   = STILL_ACTIVE;
     teb->request_fd  = request_pipe[1];
     teb->reply_fd    = -1;
     teb->wait_fd[0]  = -1;
diff --git a/dlls/user/Makefile.in b/dlls/user/Makefile.in
index ff5a009..d03ef7d 100644
--- a/dlls/user/Makefile.in
+++ b/dlls/user/Makefile.in
@@ -17,7 +17,6 @@
 C_SRCS = \
 	$(TOPOBJDIR)/windows/driver.c \
 	$(TOPOBJDIR)/windows/multimon.c \
-	$(TOPOBJDIR)/windows/queue.c \
 	$(TOPOBJDIR)/windows/syscolor.c \
 	$(TOPOBJDIR)/windows/user.c \
 	button.c \
diff --git a/dlls/user/cursoricon.c b/dlls/user/cursoricon.c
index a55bd49..b18f551 100644
--- a/dlls/user/cursoricon.c
+++ b/dlls/user/cursoricon.c
@@ -1378,7 +1378,7 @@
 
     /* Check whether destroying active cursor */
 
-    if ( QUEUE_Current()->cursor == HICON_32(handle) )
+    if ( get_user_thread_info()->cursor == HICON_32(handle) )
     {
         WARN_(cursor)("Destroying active cursor!\n" );
         SetCursor( 0 );
@@ -1483,15 +1483,15 @@
  */
 HCURSOR WINAPI SetCursor( HCURSOR hCursor /* [in] Handle of cursor to show */ )
 {
-    MESSAGEQUEUE *queue = QUEUE_Current();
+    struct user_thread_info *thread_info = get_user_thread_info();
     HCURSOR hOldCursor;
 
-    if (hCursor == queue->cursor) return hCursor;  /* No change */
+    if (hCursor == thread_info->cursor) return hCursor;  /* No change */
     TRACE_(cursor)("%p\n", hCursor );
-    hOldCursor = queue->cursor;
-    queue->cursor = hCursor;
+    hOldCursor = thread_info->cursor;
+    thread_info->cursor = hCursor;
     /* Change the cursor shape only if it is visible */
-    if (queue->cursor_count >= 0 && USER_Driver.pSetCursor)
+    if (thread_info->cursor_count >= 0 && USER_Driver.pSetCursor)
     {
         USER_Driver.pSetCursor( (CURSORICONINFO*)GlobalLock16(HCURSOR_16(hCursor)) );
         GlobalUnlock16(HCURSOR_16(hCursor));
@@ -1504,24 +1504,24 @@
  */
 INT WINAPI ShowCursor( BOOL bShow )
 {
-    MESSAGEQUEUE *queue = QUEUE_Current();
+    struct user_thread_info *thread_info = get_user_thread_info();
 
-    TRACE_(cursor)("%d, count=%d\n", bShow, queue->cursor_count );
+    TRACE_(cursor)("%d, count=%d\n", bShow, thread_info->cursor_count );
 
     if (bShow)
     {
-        if (++queue->cursor_count == 0 && USER_Driver.pSetCursor) /* Show it */
+        if (++thread_info->cursor_count == 0 && USER_Driver.pSetCursor) /* Show it */
         {
-            USER_Driver.pSetCursor((CURSORICONINFO*)GlobalLock16(HCURSOR_16(queue->cursor)));
-            GlobalUnlock16(HCURSOR_16(queue->cursor));
+            USER_Driver.pSetCursor((CURSORICONINFO*)GlobalLock16(HCURSOR_16(thread_info->cursor)));
+            GlobalUnlock16(HCURSOR_16(thread_info->cursor));
         }
     }
     else
     {
-        if (--queue->cursor_count == -1 && USER_Driver.pSetCursor) /* Hide it */
+        if (--thread_info->cursor_count == -1 && USER_Driver.pSetCursor) /* Hide it */
             USER_Driver.pSetCursor( NULL );
     }
-    return queue->cursor_count;
+    return thread_info->cursor_count;
 }
 
 /***********************************************************************
@@ -1529,7 +1529,7 @@
  */
 HCURSOR WINAPI GetCursor(void)
 {
-    return QUEUE_Current()->cursor;
+    return get_user_thread_info()->cursor;
 }
 
 
diff --git a/dlls/user/hook.c b/dlls/user/hook.c
index 8823fce..7625fdd 100644
--- a/dlls/user/hook.c
+++ b/dlls/user/hook.c
@@ -324,7 +324,7 @@
  */
 LRESULT HOOK_CallHooks( INT id, INT code, WPARAM wparam, LPARAM lparam, BOOL unicode )
 {
-    MESSAGEQUEUE *queue = QUEUE_Current();
+    struct user_thread_info *thread_info = get_user_thread_info();
     HOOKPROC proc = NULL;
     HHOOK handle = 0;
     DWORD pid = 0, tid = 0;
@@ -334,7 +334,6 @@
 
     USER_CheckNotLock();
 
-    if (!queue) return 0;
     SERVER_START_REQ( start_hook_chain )
     {
         req->id = id;
@@ -380,10 +379,10 @@
 
         if (!module[0] || (proc = get_hook_proc( proc, module )) != NULL)
         {
-            HHOOK prev = queue->hook;
-            queue->hook = handle;
+            HHOOK prev = thread_info->hook;
+            thread_info->hook = handle;
             ret = call_hook( proc, id, code, wparam, lparam, unicode, unicode_hook );
-            queue->hook = prev;
+            thread_info->hook = prev;
         }
 
     }
@@ -492,7 +491,7 @@
  */
 LRESULT WINAPI CallNextHookEx( HHOOK hhook, INT code, WPARAM wparam, LPARAM lparam )
 {
-    MESSAGEQUEUE *queue = QUEUE_Current();
+    struct user_thread_info *thread_info = get_user_thread_info();
     HOOKPROC proc = NULL;
     WCHAR module[MAX_PATH];
     HHOOK handle = 0;
@@ -501,11 +500,9 @@
     BOOL prev_unicode = FALSE, next_unicode = FALSE;
     LRESULT ret = 0;
 
-    if (!queue) return 0;
-
     SERVER_START_REQ( get_next_hook )
     {
-        req->handle = queue->hook;
+        req->handle = thread_info->hook;
         req->event = EVENT_MIN;
         wine_server_set_reply( req, module, sizeof(module)-sizeof(WCHAR) );
         if (!wine_server_call_err( req ))
@@ -550,10 +547,10 @@
 
         if (!module[0] || (proc = get_hook_proc( proc, module )) != NULL)
         {
-            HHOOK prev = queue->hook;
-            queue->hook = handle;
+            HHOOK prev = thread_info->hook;
+            thread_info->hook = handle;
             ret = call_hook( proc, id, code, wparam, lparam, prev_unicode, next_unicode );
-            queue->hook = prev;
+            thread_info->hook = prev;
         }
     }
     return ret;
diff --git a/dlls/user/hook16.c b/dlls/user/hook16.c
index 073d91df..ab7a0fc 100644
--- a/dlls/user/hook16.c
+++ b/dlls/user/hook16.c
@@ -110,7 +110,7 @@
  */
 static LRESULT call_hook_16( INT id, INT code, WPARAM wp, LPARAM lp )
 {
-    struct hook16_queue_info *info = QUEUE_Current()->hook16_info;
+    struct hook16_queue_info *info = get_user_thread_info()->hook16_info;
     WORD args[4];
     LRESULT ret;
     INT prev_id = info->id;
@@ -348,12 +348,11 @@
  */
 HHOOK WINAPI SetWindowsHookEx16( INT16 id, HOOKPROC16 proc, HINSTANCE16 hInst, HTASK16 hTask )
 {
-    MESSAGEQUEUE *queue = QUEUE_Current();
+    struct user_thread_info *thread_info = get_user_thread_info();
     struct hook16_queue_info *info;
     HHOOK hook;
     int index = id - WH_MINHOOK;
 
-    if (!queue) return 0;
     if (id < WH_MINHOOK || id > WH_MAXHOOK16) return 0;
     if (!hook_procs[index])
     {
@@ -367,10 +366,10 @@
         return 0;
     }
 
-    if (!(info = queue->hook16_info))
+    if (!(info = thread_info->hook16_info))
     {
         if (!(info = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*info) ))) return 0;
-        queue->hook16_info = info;
+        thread_info->hook16_info = info;
     }
     if (info->hook[index])
     {
@@ -389,12 +388,11 @@
  */
 BOOL16 WINAPI UnhookWindowsHook16( INT16 id, HOOKPROC16 proc )
 {
-    MESSAGEQUEUE *queue = QUEUE_Current();
     struct hook16_queue_info *info;
     int index = id - WH_MINHOOK;
 
     if (id < WH_MINHOOK || id > WH_MAXHOOK16) return FALSE;
-    if (!queue || !(info = queue->hook16_info)) return FALSE;
+    if (!(info = get_user_thread_info()->hook16_info)) return FALSE;
     if (info->proc[index] != proc) return FALSE;
     if (!UnhookWindowsHookEx( info->hook[index] )) return FALSE;
     info->hook[index] = 0;
@@ -408,11 +406,10 @@
  */
 BOOL16 WINAPI UnhookWindowsHookEx16( HHOOK hhook )
 {
-    MESSAGEQUEUE *queue = QUEUE_Current();
     struct hook16_queue_info *info;
     int index;
 
-    if (!queue || !(info = queue->hook16_info)) return FALSE;
+    if (!(info = get_user_thread_info()->hook16_info)) return FALSE;
     for (index = 0; index < NB_HOOKS16; index++)
     {
         if (info->hook[index] == hhook)
@@ -472,11 +469,10 @@
  */
 LRESULT WINAPI CallNextHookEx16( HHOOK hhook, INT16 code, WPARAM16 wparam, LPARAM lparam )
 {
-    MESSAGEQUEUE *queue = QUEUE_Current();
     struct hook16_queue_info *info;
     LRESULT ret = 0;
 
-    if (!queue || !(info = queue->hook16_info)) return 0;
+    if (!(info = get_user_thread_info()->hook16_info)) return 0;
 
     switch (info->id)
     {
diff --git a/dlls/user/input.c b/dlls/user/input.c
index ab60cd0..2499073 100644
--- a/dlls/user/input.c
+++ b/dlls/user/input.c
@@ -138,10 +138,8 @@
  */
 BOOL WINAPI GetCursorInfo( PCURSORINFO pci )
 {
-    MESSAGEQUEUE *queue = QUEUE_Current();
-
     if (!pci) return 0;
-    if (queue->cursor_count >= 0) pci->flags = CURSOR_SHOWING;
+    if (get_user_thread_info()->cursor_count >= 0) pci->flags = CURSOR_SHOWING;
     else pci->flags = 0;
     GetCursorPos(&pci->ptScreenPos);
     return 1;
diff --git a/dlls/user/message.c b/dlls/user/message.c
index d4d5e42..1be9873 100644
--- a/dlls/user/message.c
+++ b/dlls/user/message.c
@@ -1486,14 +1486,14 @@
 static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam,
                                  BOOL unicode, BOOL same_thread )
 {
+    struct user_thread_info *thread_info = get_user_thread_info();
     LRESULT result = 0;
     WNDPROC winproc;
     CWPSTRUCT cwp;
     CWPRETSTRUCT cwpret;
-    MESSAGEQUEUE *queue = QUEUE_Current();
 
-    if (queue->recursion_count > MAX_SENDMSG_RECURSION) return 0;
-    queue->recursion_count++;
+    if (thread_info->recursion_count > MAX_SENDMSG_RECURSION) return 0;
+    thread_info->recursion_count++;
 
     if (msg & 0x80000000)
     {
@@ -1529,7 +1529,7 @@
     cwpret.hwnd    = hwnd;
     HOOK_CallHooks( WH_CALLWNDPROCRET, HC_ACTION, same_thread, (LPARAM)&cwpret, unicode );
  done:
-    queue->recursion_count--;
+    thread_info->recursion_count--;
     return result;
 }
 
@@ -1903,7 +1903,7 @@
 {
     LRESULT result;
     ULONG_PTR extra_info = 0;
-    MESSAGEQUEUE *queue = QUEUE_Current();
+    struct user_thread_info *thread_info = get_user_thread_info();
     struct received_message_info info, *old_info;
     unsigned int hw_id = 0;  /* id of previous hardware message */
 
@@ -2023,10 +2023,10 @@
                 TRACE("dropping msg %x\n", info.msg.message );
                 goto next;  /* ignore it */
             }
-            queue->GetMessagePosVal = MAKELONG( info.msg.pt.x, info.msg.pt.y );
+            thread_info->GetMessagePosVal = MAKELONG( info.msg.pt.x, info.msg.pt.y );
             /* fall through */
         case MSG_POSTED:
-            queue->GetMessageExtraInfoVal = extra_info;
+            thread_info->GetMessageExtraInfoVal = extra_info;
 	    if (info.msg.message >= WM_DDE_FIRST && info.msg.message <= WM_DDE_LAST)
 	    {
 		if (!unpack_dde_message( info.msg.hwnd, info.msg.message, &info.msg.wParam,
@@ -2044,12 +2044,12 @@
         }
 
         /* if we get here, we have a sent message; call the window procedure */
-        old_info = queue->receive_info;
-        queue->receive_info = &info;
+        old_info = thread_info->receive_info;
+        thread_info->receive_info = &info;
         result = call_window_proc( info.msg.hwnd, info.msg.message, info.msg.wParam,
                                    info.msg.lParam, (info.type != MSG_ASCII), FALSE );
         reply_message( &info, result, TRUE );
-        queue->receive_info = old_info;
+        thread_info->receive_info = old_info;
     next:
         HeapFree( GetProcessHeap(), 0, buffer );
     }
@@ -2069,15 +2069,38 @@
 
 
 /***********************************************************************
+ *           get_server_queue_handle
+ *
+ * Get a handle to the server message queue for the current thread.
+ */
+static HANDLE get_server_queue_handle(void)
+{
+    struct user_thread_info *thread_info = get_user_thread_info();
+    HANDLE ret;
+
+    if (!(ret = thread_info->server_queue))
+    {
+        SERVER_START_REQ( get_msg_queue )
+        {
+            wine_server_call( req );
+            ret = reply->handle;
+        }
+        SERVER_END_REQ;
+        thread_info->server_queue = ret;
+        if (!ret) ERR( "Cannot get server thread queue\n" );
+    }
+    return ret;
+}
+
+
+/***********************************************************************
  *           wait_message_reply
  *
  * Wait until a sent message gets replied to.
  */
 static void wait_message_reply( UINT flags )
 {
-    MESSAGEQUEUE *queue;
-
-    if (!(queue = QUEUE_Current())) return;
+    HANDLE server_queue = get_server_queue_handle();
 
     for (;;)
     {
@@ -2110,10 +2133,10 @@
         ReleaseThunkLock( &dwlc );
 
         if (USER_Driver.pMsgWaitForMultipleObjectsEx)
-            res = USER_Driver.pMsgWaitForMultipleObjectsEx( 1, &queue->server_queue,
+            res = USER_Driver.pMsgWaitForMultipleObjectsEx( 1, &server_queue,
                                                             INFINITE, QS_ALLINPUT, 0 );
         else
-            res = WaitForSingleObject( queue->server_queue, INFINITE );
+            res = WaitForSingleObject( server_queue, INFINITE );
 
         if (dwlc) RestoreThunkLock( dwlc );
     }
@@ -2534,8 +2557,7 @@
  */
 BOOL WINAPI ReplyMessage( LRESULT result )
 {
-    MESSAGEQUEUE *queue = QUEUE_Current();
-    struct received_message_info *info = queue->receive_info;
+    struct received_message_info *info = get_user_thread_info()->receive_info;
 
     if (!info) return FALSE;
     reply_message( info, result, FALSE );
@@ -2557,8 +2579,7 @@
  */
 DWORD WINAPI InSendMessageEx( LPVOID reserved )
 {
-    MESSAGEQUEUE *queue = QUEUE_Current();
-    struct received_message_info *info = queue->receive_info;
+    struct received_message_info *info = get_user_thread_info()->receive_info;
 
     if (info) return info->flags;
     return ISMEX_NOSEND;
@@ -2661,7 +2682,7 @@
  */
 BOOL WINAPI PeekMessageW( MSG *msg_out, HWND hwnd, UINT first, UINT last, UINT flags )
 {
-    MESSAGEQUEUE *queue;
+    struct user_thread_info *thread_info = get_user_thread_info();
     MSG msg;
 
     USER_CheckNotLock();
@@ -2694,12 +2715,9 @@
         else break;
     }
 
-    if ((queue = QUEUE_Current()))
-    {
-        queue->GetMessageTimeVal = msg.time;
-        msg.pt.x = LOWORD( queue->GetMessagePosVal );
-        msg.pt.y = HIWORD( queue->GetMessagePosVal );
-    }
+    thread_info->GetMessageTimeVal = msg.time;
+    msg.pt.x = LOWORD( thread_info->GetMessagePosVal );
+    msg.pt.y = HIWORD( thread_info->GetMessagePosVal );
 
     HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, flags & PM_REMOVE, (LPARAM)&msg, TRUE );
 
@@ -2733,7 +2751,7 @@
  */
 BOOL WINAPI GetMessageW( MSG *msg, HWND hwnd, UINT first, UINT last )
 {
-    MESSAGEQUEUE *queue = QUEUE_Current();
+    HANDLE server_queue = get_server_queue_handle();
     int mask = QS_POSTMESSAGE | QS_SENDMESSAGE;  /* Always selected */
 
     if (first || last)
@@ -2769,15 +2787,15 @@
         if (changed_bits & mask) continue;
         if (wake_bits & QS_SENDMESSAGE) continue;
 
-        TRACE( "(%04x) mask=%08x, bits=%08x, changed=%08x, waiting\n",
-               queue->self, mask, wake_bits, changed_bits );
+        TRACE( "(%04lx) mask=%08x, bits=%08x, changed=%08x, waiting\n",
+               GetCurrentThreadId(), mask, wake_bits, changed_bits );
 
         ReleaseThunkLock( &dwlc );
         if (USER_Driver.pMsgWaitForMultipleObjectsEx)
-            USER_Driver.pMsgWaitForMultipleObjectsEx( 1, &queue->server_queue, INFINITE,
+            USER_Driver.pMsgWaitForMultipleObjectsEx( 1, &server_queue, INFINITE,
                                                       QS_ALLINPUT, 0 );
         else
-            WaitForSingleObject( queue->server_queue, INFINITE );
+            WaitForSingleObject( server_queue, INFINITE );
         if (dwlc) RestoreThunkLock( dwlc );
     }
 
@@ -3008,10 +3026,7 @@
  */
 DWORD WINAPI GetMessagePos(void)
 {
-    MESSAGEQUEUE *queue;
-
-    if (!(queue = QUEUE_Current())) return 0;
-    return queue->GetMessagePosVal;
+    return get_user_thread_info()->GetMessagePosVal;
 }
 
 
@@ -3032,10 +3047,7 @@
  */
 LONG WINAPI GetMessageTime(void)
 {
-    MESSAGEQUEUE *queue;
-
-    if (!(queue = QUEUE_Current())) return 0;
-    return queue->GetMessageTimeVal;
+    return get_user_thread_info()->GetMessageTimeVal;
 }
 
 
@@ -3045,10 +3057,7 @@
  */
 LPARAM WINAPI GetMessageExtraInfo(void)
 {
-    MESSAGEQUEUE *queue;
-
-    if (!(queue = QUEUE_Current())) return 0;
-    return queue->GetMessageExtraInfoVal;
+    return get_user_thread_info()->GetMessageExtraInfoVal;
 }
 
 
@@ -3057,12 +3066,9 @@
  */
 LPARAM WINAPI SetMessageExtraInfo(LPARAM lParam)
 {
-    MESSAGEQUEUE *queue;
-    LONG old_value;
-
-    if (!(queue = QUEUE_Current())) return 0;
-    old_value = queue->GetMessageExtraInfoVal;
-    queue->GetMessageExtraInfoVal = lParam;
+    struct user_thread_info *thread_info = get_user_thread_info();
+    LONG old_value = thread_info->GetMessageExtraInfoVal;
+    thread_info->GetMessageExtraInfoVal = lParam;
     return old_value;
 }
 
@@ -3088,7 +3094,6 @@
 {
     HANDLE handles[MAXIMUM_WAIT_OBJECTS];
     DWORD i, ret, lock;
-    MESSAGEQUEUE *msgQueue;
 
     if (count > MAXIMUM_WAIT_OBJECTS-1)
     {
@@ -3096,8 +3101,6 @@
         return WAIT_FAILED;
     }
 
-    if (!(msgQueue = QUEUE_Current())) return WAIT_FAILED;
-
     /* set the queue mask */
     SERVER_START_REQ( set_queue_mask )
     {
@@ -3110,7 +3113,7 @@
 
     /* Add the thread event to the handle list */
     for (i = 0; i < count; i++) handles[i] = pHandles[i];
-    handles[count] = msgQueue->server_queue;
+    handles[count] = get_server_queue_handle();
 
     ReleaseThunkLock( &lock );
     if (USER_Driver.pMsgWaitForMultipleObjectsEx)
diff --git a/dlls/user/message.h b/dlls/user/message.h
index ecbbde4..b03ffd0 100644
--- a/dlls/user/message.h
+++ b/dlls/user/message.h
@@ -27,34 +27,8 @@
 #include "winbase.h"
 #include "wine/windef16.h"
 
-struct received_message_info;
-struct hook16_queue_info;
-
-/* Message queue */
-typedef struct tagMESSAGEQUEUE
-{
-  HQUEUE16  self;                   /* Handle to self (was: reserved) */
-  HANDLE    server_queue;           /* Handle to server-side queue */
-  DWORD     recursion_count;        /* Counter to prevent infinite SendMessage recursion */
-  HHOOK     hook;                   /* Current hook */
-  struct received_message_info *receive_info; /* Info about message being currently received */
-  struct hook16_queue_info *hook16_info;      /* Opaque pointer for 16-bit hook support */
-
-  DWORD     GetMessageTimeVal;      /* Value for GetMessageTime */
-  DWORD     GetMessagePosVal;       /* Value for GetMessagePos */
-  DWORD     GetMessageExtraInfoVal; /* Value for GetMessageExtraInfo */
-
-  HCURSOR   cursor;                 /* current cursor */
-  INT       cursor_count;           /* cursor show count */
-} MESSAGEQUEUE;
-
-
 #define MAX_SENDMSG_RECURSION  64
 
-/* queue.c */
-extern MESSAGEQUEUE *QUEUE_Current(void);
-extern void QUEUE_DeleteMsgQueue(void);
-
 /* message.c */
 extern LRESULT MSG_SendInternalMessageTimeout( DWORD dest_pid, DWORD dest_tid,
                                                UINT msg, WPARAM wparam, LPARAM lparam,
diff --git a/dlls/user/user16.c b/dlls/user/user16.c
index 9865994..020765a 100644
--- a/dlls/user/user16.c
+++ b/dlls/user/user16.c
@@ -1097,6 +1097,16 @@
 }
 
 
+/***********************************************************************
+ *		InitThreadInput   (USER.409)
+ */
+HQUEUE16 WINAPI InitThreadInput16( WORD unknown, WORD flags )
+{
+    /* nothing to do here */
+    return 0xbeef;
+}
+
+
 /*******************************************************************
  *         InsertMenu    (USER.410)
  */
diff --git a/dlls/user/user_main.c b/dlls/user/user_main.c
index 70be706..9a63756 100644
--- a/dlls/user/user_main.c
+++ b/dlls/user/user_main.c
@@ -239,9 +239,6 @@
     /* Initialize message spying */
     if (!SPY_Init()) return FALSE;
 
-    /* Create message queue of initial thread */
-    InitThreadInput16( 0, 0 );
-
     /* Create desktop window */
     if (!WIN_CreateDesktopWindow()) return FALSE;
 
@@ -268,7 +265,7 @@
     WDML_NotifyThreadDetach();
 
     WIN_DestroyThreadWindows( GetDesktopWindow() );
-    QUEUE_DeleteMsgQueue();
+    CloseHandle( get_user_thread_info()->server_queue );
 
     exiting_thread_id = 0;
 }
diff --git a/dlls/user/user_private.h b/dlls/user/user_private.h
index 4b85db8..711f88b 100644
--- a/dlls/user/user_private.h
+++ b/dlls/user/user_private.h
@@ -26,6 +26,8 @@
 #include "winbase.h"
 #include "wingdi.h"
 #include "winuser.h"
+#include "winreg.h"
+#include "winternl.h"
 #include "local.h"
 
 extern WORD USER_HeapSel;
@@ -119,6 +121,31 @@
 
 extern USER_DRIVER USER_Driver;
 
+struct received_message_info;
+struct hook16_queue_info;
+
+/* this is the structure stored in TEB->Win32ClientInfo */
+/* no attempt is made to keep the layout compatible with the Windows one */
+struct user_thread_info
+{
+    HANDLE                        server_queue;           /* 00 Handle to server-side queue */
+    DWORD                         recursion_count;        /* 04 SendMessage recursion counter */
+    HHOOK                         hook;                   /* 08 Current hook */
+    struct received_message_info *receive_info;           /* 0c Message being currently received */
+    struct hook16_queue_info     *hook16_info;            /* 10 Opaque pointer for 16-bit hook support */
+    DWORD                         GetMessageTimeVal;      /* 14 Value for GetMessageTime */
+    DWORD                         GetMessagePosVal;       /* 18 Value for GetMessagePos */
+    DWORD                         GetMessageExtraInfoVal; /* 1c Value for GetMessageExtraInfo */
+    HCURSOR                       cursor;                 /* 20 Current cursor */
+    INT                           cursor_count;           /* 24 Cursor show count */
+                                                          /* 28-7c Available for more data */
+};
+
+static inline struct user_thread_info *get_user_thread_info(void)
+{
+    return (struct user_thread_info *)NtCurrentTeb()->Win32ClientInfo;
+}
+
 extern HMODULE user32_module;
 extern DWORD USER16_AlertableWait;
 extern HBRUSH SYSCOLOR_55AABrush;
diff --git a/dlls/user/wnd16.c b/dlls/user/wnd16.c
index 170f67b..1042a5a 100644
--- a/dlls/user/wnd16.c
+++ b/dlls/user/wnd16.c
@@ -20,10 +20,10 @@
 
 #include "wine/winuser16.h"
 #include "wownt32.h"
-#include "user_private.h"
 #include "win.h"
 #include "winproc.h"
 #include "stackframe.h"
+#include "user_private.h"
 
 /* handle <--> handle16 conversions */
 #define HANDLE_16(h32)		(LOWORD(h32))
diff --git a/include/thread.h b/include/thread.h
index 3548547..baaf6c1 100644
--- a/include/thread.h
+++ b/include/thread.h
@@ -63,35 +63,15 @@
     NT_TIB       Tib;            /* 12-  00 Thread information block */
     PVOID        EnvironmentPointer; /* 12-  1c EnvironmentPointer (win95: tib flags + win16 mutex count) */
     CLIENT_ID    ClientId;       /* -2-  20 Process and thread id (win95: debug context) */
-    HQUEUE16     queue;          /* 1!-  28 Message queue (NT: DWORD ActiveRpcHandle)*/
-    WORD         pad1;           /* --n  2a */
-    PVOID        ThreadLocalStoragePointer; /* 1--  2c Pointer to TLS array */
-    PEB         *Peb;            /* 12-  30 owning process PEB */
-    DWORD        LastErrorValue; /* -2-  34 Last error code */
-    DWORD        exit_code;      /* 1--  38 Termination status */
-    WORD         teb_sel;        /* 1--  3c Selector to TEB */
-    WORD         emu_sel;        /* 1-n  3e 80387 emulator selector */
-    DWORD        unknown1;       /* --n  40 */
-    DWORD        unknown2;       /* --n  44 */
-    DWORD        unknown3;       /* --n  48 */
-    int          thread_errno;   /* --3  4c Per-thread errno (was: ring0_thread) */
-    int          thread_h_errno; /* --3  50 Per-thread h_errno (was: ptr to tdbx structure) */
-    void        *stack_base;     /* 1-n  54 Stack base (unused) */
-    void        *exit_stack;     /* 1-n  58 Exit stack */
-    void        *emu_data;       /* --n  5c Related to 80387 emulation */
-    DWORD        last_error;     /* 1--  60 Last error code */
-    HANDLE       debug_cb;       /* 1-n  64 Debugger context block */
-    DWORD        debug_thread;   /* 1-n  68 Thread debugging this one (?) */
-    void        *pcontext;       /* 1-n  6c Thread register context */
-    DWORD        cur_stack;      /* --3  70 Current stack (was: unknown) */
-    DWORD        ThunkConnect;   /* 1-n  74 */
-    DWORD        NegStackBase;   /* 1-n  78 */
-    WORD         current_ss;     /* 1-n  7c Another 16-bit stack selector */
-    WORD         pad2;           /* --n  7e */
-    void        *ss_table;       /* --n  80 Pointer to info about 16-bit stack */
-    WORD         stack_sel;      /* --3  84 16-bit stack selector */
-    HTASK16      htask16;        /* --3  86 Win16 task handle */
-    DWORD        pad4[15];       /* --n  88 */
+    PVOID        ActiveRpcHandle;              /* 028 */
+    PVOID        ThreadLocalStoragePointer;    /* 02c Pointer to TLS array */
+    PEB         *Peb;                          /* 030 owning process PEB */
+    DWORD        LastErrorValue;               /* 034 Last error code */
+    ULONG        CountOfOwnedCriticalSections; /* 038 */
+    PVOID        CsrClientThread;              /* 03c */
+    PVOID        Win32ThreadInfo;              /* 040 */
+    ULONG        Win32ClientInfo[0x1f];        /* 044 */
+    PVOID        WOW32Reserved;                /* 0c0 */
     ULONG        CurrentLocale;  /* -2-  C4 */
     DWORD        pad5[48];       /* --n  C8 */
     DWORD        delta_priority; /* 1-n 188 Priority delta */
@@ -105,7 +85,8 @@
 
     /* The following are Wine-specific fields (NT: GDI stuff) */
     UINT         code_page;      /* --3 1fc Thread code page */
-    DWORD        unused[2];      /* --3 200 Was server buffer */
+    DWORD        cur_stack;      /* --3 200 Current stack */
+    DWORD        teb_sel;        /* --3 204 Selector to TEB */
     DWORD        gs_sel;         /* --3 208 %gs selector for this thread */
     int          request_fd;     /* --3 20c fd for sending server requests */
     int          reply_fd;       /* --3 210 fd for receiving server replies */
@@ -117,10 +98,12 @@
     DWORD        dpmi_vif;       /* --3 22c Protected mode virtual interrupt flag */
     DWORD        vm86_pending;   /* --3 230 Data for vm86 mode */
     void        *vm86_ptr;       /* --3 234 Data for vm86 mode */
+    WORD         stack_sel;      /* --3 238 16-bit stack selector */
+    HTASK16      htask16;        /* --3 23a Win16 task handle */
     /* here is plenty space for wine specific fields (don't forget to change pad6!!) */
 
     /* the following are nt specific fields */
-    DWORD        pad6[623];                  /* --n 238 */
+    DWORD        pad6[622];                  /* --n 23c */
     ULONG        LastStatusValue;            /* -2- bf4 */
     UNICODE_STRING StaticUnicodeString;      /* -2- bf8 used by advapi32 */
     WCHAR        StaticUnicodeBuffer[261];   /* -2- c00 used by advapi32 */
diff --git a/windows/queue.c b/windows/queue.c
deleted file mode 100644
index af60eae..0000000
--- a/windows/queue.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Message queues related functions
- *
- * Copyright 1993, 1994 Alexandre Julliard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "config.h"
-#include "wine/port.h"
-
-#include <stdarg.h>
-#include <string.h>
-#include <signal.h>
-#include <assert.h>
-#include "windef.h"
-#include "winbase.h"
-#include "wingdi.h"
-#include "winerror.h"
-#include "wine/winbase16.h"
-#include "wine/winuser16.h"
-#include "message.h"
-#include "win.h"
-#include "user_private.h"
-#include "thread.h"
-#include "wine/debug.h"
-#include "wine/server.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(msg);
-
-
-/***********************************************************************
- *           QUEUE_CreateMsgQueue
- *
- * Creates a message queue. Doesn't link it into queue list!
- */
-static HQUEUE16 QUEUE_CreateMsgQueue(void)
-{
-    HQUEUE16 hQueue;
-    HANDLE handle;
-    MESSAGEQUEUE * msgQueue;
-
-    TRACE_(msg)("(): Creating message queue...\n");
-
-    if (!(hQueue = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT,
-                                  sizeof(MESSAGEQUEUE) )))
-        return 0;
-
-    msgQueue = (MESSAGEQUEUE *) GlobalLock16( hQueue );
-    if ( !msgQueue )
-        return 0;
-
-    SERVER_START_REQ( get_msg_queue )
-    {
-        wine_server_call_err( req );
-        handle = reply->handle;
-    }
-    SERVER_END_REQ;
-    if (!handle)
-    {
-        ERR_(msg)("Cannot get thread queue\n");
-        GlobalFree16( hQueue );
-        return 0;
-    }
-    msgQueue->server_queue = handle;
-    msgQueue->self = hQueue;
-    return hQueue;
-}
-
-
-/***********************************************************************
- *	     QUEUE_Current
- *
- * Get the current thread queue, creating it if required.
- * QUEUE_Unlock is not needed since the queue can only be deleted by
- * the current thread anyway.
- */
-MESSAGEQUEUE *QUEUE_Current(void)
-{
-    HQUEUE16 hQueue = NtCurrentTeb()->queue;
-
-    if (!hQueue)
-    {
-        if (!(hQueue = QUEUE_CreateMsgQueue())) return NULL;
-        SetThreadQueue16( 0, hQueue );
-    }
-
-    return GlobalLock16( hQueue );
-}
-
-
-
-/***********************************************************************
- *	     QUEUE_DeleteMsgQueue
- *
- * Delete a message queue.
- */
-void QUEUE_DeleteMsgQueue(void)
-{
-    HQUEUE16 hQueue = NtCurrentTeb()->queue;
-    MESSAGEQUEUE * msgQueue;
-
-    if (!hQueue) return;  /* thread doesn't have a queue */
-
-    TRACE("(): Deleting message queue %04x\n", hQueue);
-
-    if (!(msgQueue = GlobalLock16( hQueue )))
-    {
-        ERR("invalid thread queue\n");
-        return;
-    }
-
-    SetThreadQueue16( 0, 0 );
-    CloseHandle( msgQueue->server_queue );
-    GlobalFree16( hQueue );
-}
-
-
-/***********************************************************************
- *		InitThreadInput   (USER.409)
- */
-HQUEUE16 WINAPI InitThreadInput16( WORD unknown, WORD flags )
-{
-    MESSAGEQUEUE *queue = QUEUE_Current();
-    return queue ? queue->self : 0;
-}