Added internal Wine messages to perform SetWindowPos, ShowWindow and
SetParent in the correct thread.
Replace QUEUE_IsExitingQueue by USER_IsExitingThread.
Store window rectangles in the server.
Prevent DestroyWindow on windows not belonging to the current thread.

diff --git a/controls/icontitle.c b/controls/icontitle.c
index c048092..f3f62c4 100644
--- a/controls/icontitle.c
+++ b/controls/icontitle.c
@@ -43,7 +43,6 @@
  */
 HWND ICONTITLE_Create( HWND owner )
 {
-    WND* wndPtr;
     HWND hWnd;
     HINSTANCE instance = GetWindowLongA( owner, GWL_HINSTANCE );
     LONG style = WS_CLIPSIBLINGS;
@@ -57,10 +56,9 @@
 	hWnd = CreateWindowExA( 0, ICONTITLE_CLASS_ATOM, NULL,
                                 style, 0, 0, 1, 1,
                                 owner, 0, instance, NULL );
-    if (!(wndPtr = WIN_GetPtr( hWnd ))) return 0;
-    wndPtr->owner = owner; /* MDI depends on this */
-    wndPtr->dwStyle &= ~(WS_CAPTION | WS_BORDER);
-    WIN_ReleasePtr(wndPtr);
+    WIN_SetOwner( hWnd, owner );  /* MDI depends on this */
+    SetWindowLongW( hWnd, GWL_STYLE,
+                    GetWindowLongW( hWnd, GWL_STYLE ) & ~(WS_CAPTION | WS_BORDER) );
     return hWnd;
 }
 
diff --git a/dlls/ttydrv/wnd.c b/dlls/ttydrv/wnd.c
index 7cf4cec..d375c29 100644
--- a/dlls/ttydrv/wnd.c
+++ b/dlls/ttydrv/wnd.c
@@ -566,9 +566,36 @@
       /* Send WM_NCCALCSIZE message to get new client area */
     if( (winpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
     {
-         WINPOS_SendNCCalcSize( winpos->hwnd, TRUE, &newWindowRect,
-                                &wndPtr->rectWindow, &wndPtr->rectClient,
-                                winpos, &newClientRect );
+        NCCALCSIZE_PARAMS params;
+        WINDOWPOS winposCopy;
+
+        params.rgrc[0] = newWindowRect;
+        params.rgrc[1] = wndPtr->rectWindow;
+        params.rgrc[2] = wndPtr->rectClient;
+        params.lppos = &winposCopy;
+        winposCopy = *winpos;
+
+        SendMessageW( winpos->hwnd, WM_NCCALCSIZE, TRUE, (LPARAM)&params );
+
+        TRACE( "%d,%d-%d,%d\n", params.rgrc[0].left, params.rgrc[0].top,
+               params.rgrc[0].right, params.rgrc[0].bottom );
+
+        /* If the application send back garbage, ignore it */
+        if (params.rgrc[0].left <= params.rgrc[0].right &&
+            params.rgrc[0].top <= params.rgrc[0].bottom)
+            newClientRect = params.rgrc[0];
+
+         /* FIXME: WVR_ALIGNxxx */
+
+        if( newClientRect.left != wndPtr->rectClient.left ||
+            newClientRect.top != wndPtr->rectClient.top )
+            winpos->flags &= ~SWP_NOCLIENTMOVE;
+
+        if( (newClientRect.right - newClientRect.left !=
+             wndPtr->rectClient.right - wndPtr->rectClient.left) ||
+            (newClientRect.bottom - newClientRect.top !=
+             wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
+            winpos->flags &= ~SWP_NOCLIENTSIZE;
     }
 
     if(!(winpos->flags & SWP_NOZORDER) && winpos->hwnd != winpos->hwndInsertAfter)
@@ -579,8 +606,7 @@
 
     /* FIXME: actually do something with WVR_VALIDRECTS */
 
-    wndPtr->rectWindow = newWindowRect;
-    wndPtr->rectClient = newClientRect;
+    WIN_SetRectangles( winpos->hwnd, &newWindowRect, &newClientRect );
 
     if( winpos->flags & SWP_SHOWWINDOW )
     {
diff --git a/dlls/user/message.c b/dlls/user/message.c
index 8c59896..04cd9ab 100644
--- a/dlls/user/message.c
+++ b/dlls/user/message.c
@@ -533,6 +533,10 @@
         if (lparam) return sizeof(BOOL);
         return 0;
 
+    case WM_WINE_SETWINDOWPOS:
+        push_data( data, (WINDOWPOS *)lparam, sizeof(WINDOWPOS) );
+        return 0;
+
     /* these contain an HFONT */
     case WM_SETFONT:
     case WM_GETFONT:
@@ -644,6 +648,7 @@
         break;
     case WM_WINDOWPOSCHANGING:
     case WM_WINDOWPOSCHANGED:
+    case WM_WINE_SETWINDOWPOS:
         minsize = sizeof(WINDOWPOS);
         break;
     case WM_COPYDATA:
@@ -1073,6 +1078,30 @@
 
 
 /***********************************************************************
+ *           handle_internal_message
+ *
+ * Handle an internal Wine message instead of calling the window proc.
+ */
+static LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
+{
+    switch(msg)
+    {
+    case WM_WINE_SETWINDOWPOS:
+        return USER_Driver.pSetWindowPos( (WINDOWPOS *)lparam );
+    case WM_WINE_SHOWWINDOW:
+        return USER_Driver.pShowWindow( hwnd, wparam );
+    case WM_WINE_DESTROYWINDOW:
+        return WIN_DestroyWindow( hwnd );
+    case WM_WINE_SETPARENT:
+        return (LRESULT)WIN_SetParent( hwnd, (HWND)wparam );
+    default:
+        FIXME( "unknown internal message %x\n", msg );
+        return 0;
+    }
+}
+
+
+/***********************************************************************
  *           call_window_proc
  *
  * Call a window procedure and the corresponding hooks.
@@ -1082,7 +1111,7 @@
     LRESULT result;
     WNDPROC winproc;
 
-    /* FIXME: should check for exiting queue */
+    if (msg & 0x80000000) return handle_internal_message( hwnd, msg, wparam, lparam );
 
     /* first the WH_CALLWNDPROC hook */
     if (HOOK_IsHooked( WH_CALLWNDPROC ))
@@ -1308,8 +1337,6 @@
     unsigned int res;
     int timeout = -1;
 
-    /* FIXME: should check for exiting queue */
-
     if (info->type != MSG_NOTIFY &&
         info->type != MSG_CALLBACK &&
         info->type != MSG_POSTED &&
@@ -1489,7 +1516,9 @@
 
     SPY_EnterMessage( SPY_SENDMESSAGE, hwnd, msg, wparam, lparam );
 
-    dest_tid = GetWindowThreadProcessId( hwnd, &dest_pid );
+    if (!(dest_tid = GetWindowThreadProcessId( hwnd, &dest_pid ))) return 0;
+
+    if (USER_IsExitingThread( dest_tid )) return 0;
 
     if (dest_tid == GetCurrentThreadId())
     {
@@ -1535,7 +1564,9 @@
 
     SPY_EnterMessage( SPY_SENDMESSAGE, hwnd, msg, wparam, lparam );
 
-    dest_tid = GetWindowThreadProcessId( hwnd, &dest_pid );
+    if (!(dest_tid = GetWindowThreadProcessId( hwnd, &dest_pid ))) return 0;
+
+    if (USER_IsExitingThread( dest_tid )) return 0;
 
     if (dest_tid == GetCurrentThreadId())
     {
@@ -1624,7 +1655,9 @@
         return TRUE;
     }
 
-    dest_tid = GetWindowThreadProcessId( hwnd, NULL );
+    if (!(dest_tid = GetWindowThreadProcessId( hwnd, NULL ))) return FALSE;
+
+    if (USER_IsExitingThread( dest_tid )) return TRUE;
 
     if (dest_tid == GetCurrentThreadId())
     {
@@ -1676,7 +1709,9 @@
         return TRUE;
     }
 
-    dest_tid = GetWindowThreadProcessId( hwnd, NULL );
+    if (!(dest_tid = GetWindowThreadProcessId( hwnd, NULL ))) return FALSE;
+
+    if (USER_IsExitingThread( dest_tid )) return TRUE;
 
     if (dest_tid == GetCurrentThreadId())
     {
@@ -1740,6 +1775,7 @@
 BOOL WINAPI PostMessageW( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
 {
     struct send_message_info info;
+    DWORD dest_tid;
 
     if (is_pointer_message( msg ))
     {
@@ -1758,7 +1794,11 @@
         EnumWindows( broadcast_message_callback, (LPARAM)&info );
         return TRUE;
     }
-    return put_message_in_queue( GetWindowThreadProcessId( hwnd, NULL ), &info, NULL );
+    if (!(dest_tid = GetWindowThreadProcessId( hwnd, NULL ))) return FALSE;
+
+    if (USER_IsExitingThread( dest_tid )) return TRUE;
+
+    return put_message_in_queue( dest_tid, &info, NULL );
 }
 
 
@@ -1783,6 +1823,7 @@
         SetLastError( ERROR_INVALID_PARAMETER );
         return FALSE;
     }
+    if (USER_IsExitingThread( thread )) return TRUE;
 
     info.type   = MSG_POSTED;
     info.hwnd   = 0;
diff --git a/dlls/user/user_main.c b/dlls/user/user_main.c
index c16bb6c..a4fa027 100644
--- a/dlls/user/user_main.c
+++ b/dlls/user/user_main.c
@@ -34,8 +34,10 @@
 WORD USER_HeapSel = 0;  /* USER heap selector */
 
 static HMODULE graphics_driver;
+static DWORD exiting_thread_id;
 
 extern void COMM_Init(void);
+extern void WDML_NotifyThreadDetach(void);
 
 #define GET_USER_FUNC(name) USER_Driver.p##name = (void*)GetProcAddress( graphics_driver, #name )
 
@@ -257,20 +259,29 @@
 
 
 /**********************************************************************
- *           thread
+ *           USER_IsExitingThread
+ */
+BOOL USER_IsExitingThread( DWORD tid )
+{
+    return (tid == exiting_thread_id);
+}
+
+
+/**********************************************************************
+ *           thread_detach
  */
 static void thread_detach(void)
 {
     HQUEUE16 hQueue = GetThreadQueue16( 0 );
 
-    extern void WDML_NotifyThreadDetach(void);
+    exiting_thread_id = GetCurrentThreadId();
+
     WDML_NotifyThreadDetach();
 
     if (hQueue)
     {
         TIMER_RemoveQueueTimers( hQueue );
         HOOK_FreeQueueHooks();
-        QUEUE_SetExitingQueue( hQueue );
         WIN_DestroyThreadWindows( GetDesktopWindow() );
         QUEUE_DeleteMsgQueue();
     }
@@ -290,6 +301,7 @@
             CURSORICON_FreeModuleIcons( hModule );
         }
     }
+    exiting_thread_id = 0;
 }
 
 
diff --git a/dlls/x11drv/window.c b/dlls/x11drv/window.c
index b9023c7..380912e 100644
--- a/dlls/x11drv/window.c
+++ b/dlls/x11drv/window.c
@@ -872,7 +872,7 @@
     rect = wndPtr->rectWindow;
     SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rect );
     if (rect.left > rect.right || rect.top > rect.bottom) rect = wndPtr->rectWindow;
-    wndPtr->rectClient = rect;
+    WIN_SetRectangles( hwnd, &wndPtr->rectWindow, &rect );
     X11DRV_sync_client_window_position( display, wndPtr );
     X11DRV_register_window( display, hwnd, data );
 
@@ -1005,18 +1005,14 @@
 {
     Display *display = thread_display();
     WND *wndPtr;
-    DWORD dwStyle;
     HWND retvalue;
 
-    if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
-
-    dwStyle = wndPtr->dwStyle;
-
-    if (!parent) parent = GetDesktopWindow();
-
     /* Windows hides the window first, then shows it again
      * including the WM_SHOWWINDOW messages and all */
-    if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
+    BOOL was_visible = ShowWindow( hwnd, SW_HIDE );
+
+    if (!IsWindow( parent )) return 0;
+    if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
 
     retvalue = wndPtr->parent;  /* old parent */
     if (parent != retvalue)
@@ -1027,7 +1023,7 @@
 
         if (parent != GetDesktopWindow()) /* a child window */
         {
-            if (!(dwStyle & WS_CHILD))
+            if (!(wndPtr->dwStyle & WS_CHILD))
             {
                 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
                 if (menu) DestroyMenu( menu );
@@ -1041,15 +1037,14 @@
                          data->whole_rect.left, data->whole_rect.top );
         wine_tsx11_unlock();
     }
-    WIN_ReleaseWndPtr( wndPtr );
+    WIN_ReleasePtr( wndPtr );
 
     /* SetParent additionally needs to make hwnd the topmost window
        in the x-order and send the expected WM_WINDOWPOSCHANGING and
        WM_WINDOWPOSCHANGED notification messages. 
     */
     SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
-                  SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
-                  ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
+                  SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
     /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
      * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
 
diff --git a/dlls/x11drv/winpos.c b/dlls/x11drv/winpos.c
index ba7e4fa..5409293 100644
--- a/dlls/x11drv/winpos.c
+++ b/dlls/x11drv/winpos.c
@@ -523,7 +523,7 @@
     if (!(pWinpos->flags & SWP_NOSENDCHANGING))
         SendMessageA( pWinpos->hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
 
-    if (!(wndPtr = WIN_FindWndPtr( pWinpos->hwnd ))) return FALSE;
+    if (!(wndPtr = WIN_GetPtr( pWinpos->hwnd )) || wndPtr == WND_OTHER_PROCESS) return FALSE;
 
     /* Calculate new position and size */
 
@@ -547,43 +547,69 @@
                                     pWinpos->y - wndPtr->rectWindow.top );
     }
     pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
-    WIN_ReleaseWndPtr( wndPtr );
+    WIN_ReleasePtr( wndPtr );
     return TRUE;
 }
 
 /***********************************************************************
  *           SWP_DoNCCalcSize
  */
-static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
-                              RECT* pNewWindowRect, RECT* pNewClientRect )
+static UINT SWP_DoNCCalcSize( WINDOWPOS* pWinpos, RECT* pNewWindowRect, RECT* pNewClientRect )
 {
     UINT wvrFlags = 0;
+    WND *wndPtr;
+
+    if (!(wndPtr = WIN_GetPtr( pWinpos->hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
 
       /* Send WM_NCCALCSIZE message to get new client area */
     if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
     {
-         wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
-                                    &wndPtr->rectWindow, &wndPtr->rectClient,
-                                    pWinpos, pNewClientRect );
+        NCCALCSIZE_PARAMS params;
+        WINDOWPOS winposCopy;
+
+        params.rgrc[0] = *pNewWindowRect;
+        params.rgrc[1] = wndPtr->rectWindow;
+        params.rgrc[2] = wndPtr->rectClient;
+        params.lppos = &winposCopy;
+        winposCopy = *pWinpos;
+        WIN_ReleasePtr( wndPtr );
+
+        wvrFlags = SendMessageW( pWinpos->hwnd, WM_NCCALCSIZE, TRUE, (LPARAM)&params );
+
+        TRACE( "%d,%d-%d,%d\n", params.rgrc[0].left, params.rgrc[0].top,
+               params.rgrc[0].right, params.rgrc[0].bottom );
+
+        /* If the application send back garbage, ignore it */
+        if (params.rgrc[0].left <= params.rgrc[0].right &&
+            params.rgrc[0].top <= params.rgrc[0].bottom)
+            *pNewClientRect = params.rgrc[0];
+
          /* FIXME: WVR_ALIGNxxx */
 
-         if( pNewClientRect->left != wndPtr->rectClient.left ||
-             pNewClientRect->top != wndPtr->rectClient.top )
-             pWinpos->flags &= ~SWP_NOCLIENTMOVE;
+        if (!(wndPtr = WIN_GetPtr( pWinpos->hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
 
-         if( (pNewClientRect->right - pNewClientRect->left !=
-              wndPtr->rectClient.right - wndPtr->rectClient.left) ||
-             (pNewClientRect->bottom - pNewClientRect->top !=
-              wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
-             pWinpos->flags &= ~SWP_NOCLIENTSIZE;
+        if( pNewClientRect->left != wndPtr->rectClient.left ||
+            pNewClientRect->top != wndPtr->rectClient.top )
+            pWinpos->flags &= ~SWP_NOCLIENTMOVE;
+
+        if( (pNewClientRect->right - pNewClientRect->left !=
+             wndPtr->rectClient.right - wndPtr->rectClient.left) ||
+            (pNewClientRect->bottom - pNewClientRect->top !=
+             wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
+            pWinpos->flags &= ~SWP_NOCLIENTSIZE;
     }
     else
-      if( !(pWinpos->flags & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
-                                             pNewClientRect->top != wndPtr->rectClient.top) )
+    {
+        if (!(pWinpos->flags & SWP_NOMOVE) &&
+            (pNewClientRect->left != wndPtr->rectClient.left ||
+             pNewClientRect->top != wndPtr->rectClient.top))
             pWinpos->flags &= ~SWP_NOCLIENTMOVE;
+    }
+    WIN_ReleasePtr( wndPtr );
     return wvrFlags;
 }
 
+
 /***********************************************************************
  *           SWP_DoOwnedPopups
  *
@@ -783,7 +809,7 @@
 
     /* Common operations */
 
-    wvrFlags = SWP_DoNCCalcSize( wndPtr, winpos, &newWindowRect, &newClientRect );
+    wvrFlags = SWP_DoNCCalcSize( winpos, &newWindowRect, &newClientRect );
 
     if(!(winpos->flags & SWP_NOZORDER) && winpos->hwnd != winpos->hwndInsertAfter)
     {
@@ -816,8 +842,7 @@
 
     /* FIXME: actually do something with WVR_VALIDRECTS */
 
-    wndPtr->rectWindow = newWindowRect;
-    wndPtr->rectClient = newClientRect;
+    WIN_SetRectangles( winpos->hwnd, &newWindowRect, &newClientRect );
 
     if (winpos->flags & SWP_SHOWWINDOW) wndPtr->dwStyle |= WS_VISIBLE;
     else if (winpos->flags & SWP_HIDEWINDOW)
@@ -993,7 +1018,7 @@
 
 UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect )
 {
-    WND *wndPtr = WIN_FindWndPtr( hwnd );
+    WND *wndPtr;
     UINT swpFlags = 0;
     POINT size;
     WINDOWPLACEMENT wpl;
@@ -1003,90 +1028,87 @@
     wpl.length = sizeof(wpl);
     GetWindowPlacement( hwnd, &wpl );
 
+    if (HOOK_CallHooksA( WH_CBT, HCBT_MINMAX, (WPARAM)hwnd, cmd ))
+        return SWP_NOSIZE | SWP_NOMOVE;
+
+    if (IsIconic( hwnd ))
+    {
+        if (cmd == SW_MINIMIZE) return SWP_NOSIZE | SWP_NOMOVE;
+        if (!SendMessageA( hwnd, WM_QUERYOPEN, 0, 0 )) return SWP_NOSIZE | SWP_NOMOVE;
+        swpFlags |= SWP_NOCOPYBITS;
+    }
+
+    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
+
     size.x = wndPtr->rectWindow.left;
     size.y = wndPtr->rectWindow.top;
 
-    if (!HOOK_CallHooksA(WH_CBT, HCBT_MINMAX, (WPARAM)wndPtr->hwndSelf, cmd))
+    switch( cmd )
     {
+    case SW_MINIMIZE:
+        if( wndPtr->dwStyle & WS_MAXIMIZE)
+        {
+            wndPtr->flags |= WIN_RESTORE_MAX;
+            wndPtr->dwStyle &= ~WS_MAXIMIZE;
+        }
+        else
+            wndPtr->flags &= ~WIN_RESTORE_MAX;
+        wndPtr->dwStyle |= WS_MINIMIZE;
+
+        X11DRV_set_iconic_state( wndPtr );
+
+        wpl.ptMinPosition = WINPOS_FindIconPos( wndPtr, wpl.ptMinPosition );
+
+        SetRect( rect, wpl.ptMinPosition.x, wpl.ptMinPosition.y,
+                 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
+        swpFlags |= SWP_NOCOPYBITS;
+        break;
+
+    case SW_MAXIMIZE:
+        WINPOS_GetMinMaxInfo( hwnd, &size, &wpl.ptMaxPosition, NULL, NULL );
+
         if( wndPtr->dwStyle & WS_MINIMIZE )
         {
-            if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
-            {
-                swpFlags = SWP_NOSIZE | SWP_NOMOVE;
-                goto done;
-            }
-            swpFlags |= SWP_NOCOPYBITS;
+            wndPtr->dwStyle &= ~WS_MINIMIZE;
+            WINPOS_ShowIconTitle( hwnd, FALSE );
+            X11DRV_set_iconic_state( wndPtr );
         }
-        switch( cmd )
-        {
-        case SW_MINIMIZE:
-            if( wndPtr->dwStyle & WS_MAXIMIZE)
-            {
-                wndPtr->flags |= WIN_RESTORE_MAX;
-                wndPtr->dwStyle &= ~WS_MAXIMIZE;
-            }
-            else
-                wndPtr->flags &= ~WIN_RESTORE_MAX;
-            wndPtr->dwStyle |= WS_MINIMIZE;
+        wndPtr->dwStyle |= WS_MAXIMIZE;
 
+        SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, size.x, size.y );
+        break;
+
+    case SW_RESTORE:
+        if( wndPtr->dwStyle & WS_MINIMIZE )
+        {
+            wndPtr->dwStyle &= ~WS_MINIMIZE;
+            WINPOS_ShowIconTitle( hwnd, FALSE );
             X11DRV_set_iconic_state( wndPtr );
 
-            wpl.ptMinPosition = WINPOS_FindIconPos( wndPtr, wpl.ptMinPosition );
-
-            SetRect( rect, wpl.ptMinPosition.x, wpl.ptMinPosition.y,
-                     GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
-            swpFlags |= SWP_NOCOPYBITS;
-            break;
-
-        case SW_MAXIMIZE:
-            WINPOS_GetMinMaxInfo( hwnd, &size, &wpl.ptMaxPosition, NULL, NULL );
-
-            if( wndPtr->dwStyle & WS_MINIMIZE )
+            if( wndPtr->flags & WIN_RESTORE_MAX)
             {
-                wndPtr->dwStyle &= ~WS_MINIMIZE;
-                WINPOS_ShowIconTitle( hwnd, FALSE );
-                X11DRV_set_iconic_state( wndPtr );
+                /* Restore to maximized position */
+                WINPOS_GetMinMaxInfo( hwnd, &size, &wpl.ptMaxPosition, NULL, NULL);
+                wndPtr->dwStyle |= WS_MAXIMIZE;
+                SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, size.x, size.y );
+                break;
             }
-            wndPtr->dwStyle |= WS_MAXIMIZE;
-
-            SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, size.x, size.y );
-            break;
-
-        case SW_RESTORE:
-            if( wndPtr->dwStyle & WS_MINIMIZE )
-            {
-                wndPtr->dwStyle &= ~WS_MINIMIZE;
-                WINPOS_ShowIconTitle( hwnd, FALSE );
-                X11DRV_set_iconic_state( wndPtr );
-
-                if( wndPtr->flags & WIN_RESTORE_MAX)
-                {
-                    /* Restore to maximized position */
-                    WINPOS_GetMinMaxInfo( hwnd, &size, &wpl.ptMaxPosition, NULL, NULL);
-                    wndPtr->dwStyle |= WS_MAXIMIZE;
-                    SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, size.x, size.y );
-                    break;
-                }
-            }
-            else
-                if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
-                {
-                    swpFlags = (UINT16)(-1);
-                    goto done;
-                }
-                else wndPtr->dwStyle &= ~WS_MAXIMIZE;
-
-            /* Restore to normal position */
-
-            *rect = wpl.rcNormalPosition;
-            rect->right -= rect->left;
-            rect->bottom -= rect->top;
-
-            break;
         }
-    } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
+        else
+        {
+            if (!(wndPtr->dwStyle & WS_MAXIMIZE)) break;
+            wndPtr->dwStyle &= ~WS_MAXIMIZE;
+        }
 
- done:
+        /* Restore to normal position */
+
+        *rect = wpl.rcNormalPosition;
+        rect->right -= rect->left;
+        rect->bottom -= rect->top;
+
+        break;
+    }
+
     WIN_ReleaseWndPtr( wndPtr );
     return swpFlags;
 }
diff --git a/include/queue.h b/include/queue.h
index baf84ff..394e34f 100644
--- a/include/queue.h
+++ b/include/queue.h
@@ -69,8 +69,6 @@
 extern MESSAGEQUEUE *QUEUE_Current(void);
 extern MESSAGEQUEUE *QUEUE_Lock( HQUEUE16 hQueue );
 extern void QUEUE_Unlock( MESSAGEQUEUE *queue );
-extern BOOL QUEUE_IsExitingQueue( HQUEUE16 hQueue );
-extern void QUEUE_SetExitingQueue( HQUEUE16 hQueue );
 extern void QUEUE_DeleteMsgQueue(void);
 
 #endif  /* __WINE_QUEUE_H */
diff --git a/include/user.h b/include/user.h
index 6b9dd35..b1aab08 100644
--- a/include/user.h
+++ b/include/user.h
@@ -35,7 +35,14 @@
 
 typedef VOID CALLBACK (*LPMOUSE_EVENT_PROC)(DWORD,DWORD,DWORD,DWORD,DWORD);
 
-struct tagWND;
+/* internal messages codes */
+enum wine_internal_message
+{
+    WM_WINE_DESTROYWINDOW = 0x80000000,
+    WM_WINE_SETWINDOWPOS,
+    WM_WINE_SHOWWINDOW,
+    WM_WINE_SETPARENT
+};
 
 typedef struct tagUSER_DRIVER {
     /* keyboard functions */
@@ -99,6 +106,8 @@
 extern void USER_Unlock(void);
 extern void USER_CheckNotLock(void);
 
+extern BOOL USER_IsExitingThread( DWORD tid );
+
 VOID WINAPI MOUSE_Enable(LPMOUSE_EVENT_PROC lpMouseEventProc);
 VOID WINAPI MOUSE_Disable(VOID);
 
diff --git a/include/win.h b/include/win.h
index dcd7ed0..81c3df7 100644
--- a/include/win.h
+++ b/include/win.h
@@ -88,12 +88,16 @@
 extern HWND WIN_IsCurrentThread( HWND hwnd );
 extern void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter );
 extern void WIN_UnlinkWindow( HWND hwnd );
+extern void WIN_SetOwner( HWND hwnd, HWND owner );
+extern void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient );
 extern HWND WIN_FindWinToRepaint( HWND hwnd );
+extern LRESULT WIN_DestroyWindow( HWND hwnd );
 extern void WIN_DestroyThreadWindows( HWND hwnd );
 extern BOOL WIN_CreateDesktopWindow(void);
 extern BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL );
 extern HWND *WIN_ListParents( HWND hwnd );
 extern HWND *WIN_ListChildren( HWND hwnd );
+extern HWND WIN_SetParent( HWND hwnd, HWND parent );
 extern BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly );
 
 inline static HWND WIN_GetFullHandle( HWND hwnd )
diff --git a/include/winpos.h b/include/winpos.h
index 25f8948..0ca4a31 100644
--- a/include/winpos.h
+++ b/include/winpos.h
@@ -28,10 +28,6 @@
 extern BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse,
                                       BOOL fChangeFocus );
 extern BOOL WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg );
-extern LONG WINPOS_SendNCCalcSize(HWND hwnd, BOOL calcValidRect,
-                                  RECT *newWindowRect, RECT *oldWindowRect,
-                                  RECT *oldClientRect, WINDOWPOS *winpos,
-                                  RECT *newClientRect );
 extern LONG WINPOS_HandleWindowPosChanging16(HWND hwnd, struct tagWINDOWPOS16 *winpos);
 extern LONG WINPOS_HandleWindowPosChanging(HWND hwnd, WINDOWPOS *winpos);
 extern HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest );
diff --git a/windows/dce.c b/windows/dce.c
index c8e1688..b6f6e66 100644
--- a/windows/dce.c
+++ b/windows/dce.c
@@ -144,11 +144,9 @@
 void DCE_FreeWindowDCE( HWND hwnd )
 {
     DCE *pDCE;
-    WND *pWnd = WIN_FindWndPtr( hwnd );
+    WND *pWnd = WIN_GetPtr( hwnd );
 
     pDCE = firstDCE;
-    hwnd = pWnd->hwndSelf;  /* make it a full handle */
-
     while( pDCE )
     {
 	if( pDCE->hwndCurrent == hwnd )
@@ -189,8 +187,7 @@
 	}
 	pDCE = pDCE->next;
     }
-    
-    WIN_ReleaseWndPtr( pWnd );
+    WIN_ReleasePtr( pWnd );
 }
 
 
@@ -359,14 +356,19 @@
     DWORD 	dcxFlags = 0;
     BOOL	bUpdateVisRgn = TRUE;
     BOOL	bUpdateClipOrigin = FALSE;
-    HWND parent;
+    HWND parent, full;
 
     TRACE("hwnd %04x, hrgnClip %04x, flags %08x\n", 
           hwnd, hrgnClip, (unsigned)flags);
 
     if (!hwnd) hwnd = GetDesktopWindow();
-    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
-    hwnd = wndPtr->hwndSelf;  /* make it a full handle */
+    if (!(full = WIN_IsCurrentProcess( hwnd )) && full != GetDesktopWindow())
+    {
+        FIXME( "not supported yet on other process window %x\n", full );
+        return 0;
+    }
+    hwnd = full;
+    if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
 
     /* fixup flags */
 
@@ -494,7 +496,7 @@
 
     TRACE("(%04x,%04x,0x%lx): returning %04x\n", hwnd, hrgnClip, flags, hdc);
 END:
-    WIN_ReleaseWndPtr(wndPtr);
+    WIN_ReleasePtr(wndPtr);
     return hdc;
 }
 
diff --git a/windows/painting.c b/windows/painting.c
index 6c854fe..450d8af 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -306,11 +306,20 @@
     BOOL bIcon;
     HRGN hrgnUpdate;
     RECT clipRect, clientRect;
-    WND *wndPtr = WIN_FindWndPtr( hwnd );
-    if (!wndPtr) return 0;
+    HWND full_handle;
+    WND *wndPtr;
 
-    bIcon = (wndPtr->dwStyle & WS_MINIMIZE && GetClassLongA(hwnd, GCL_HICON));
+    if (!(full_handle = WIN_IsCurrentThread( hwnd )))
+    {
+        if (IsWindow(hwnd))
+            FIXME( "window %x belongs to other thread\n", hwnd );
+        return 0;
+    }
+    hwnd = full_handle;
 
+    bIcon = (IsIconic(hwnd) && GetClassLongA(hwnd, GCL_HICON));
+
+    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
     wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
 
     /* send WM_NCPAINT and make sure hrgnUpdate is a valid rgn handle */
@@ -320,7 +329,7 @@
      * Make sure the window is still a window. All window locks are suspended
      * when the WM_NCPAINT is sent.
      */
-    if (!IsWindow(wndPtr->hwndSelf))
+    if (!IsWindow( hwnd ))
     {
         WIN_ReleaseWndPtr(wndPtr);
         return 0;
@@ -336,7 +345,7 @@
 
     TRACE("hrgnUpdate = %04x, \n", hrgnUpdate);
 
-    if (GetClassLongA(wndPtr->hwndSelf, GCL_STYLE) & CS_PARENTDC)
+    if (GetClassLongA( hwnd, GCL_STYLE ) & CS_PARENTDC)
     {
         /* Don't clip the output to the update region for CS_PARENTDC window */
 	if( hrgnUpdate ) 
diff --git a/windows/queue.c b/windows/queue.c
index 0e788c2..1829d6c 100644
--- a/windows/queue.c
+++ b/windows/queue.c
@@ -24,7 +24,6 @@
 DEFAULT_DEBUG_CHANNEL(msg);
 
 
-static HQUEUE16 hExitingQueue = 0;
 static PERQUEUEDATA *pQDataWin16 = NULL;  /* Global perQData for Win16 tasks */
 
 HQUEUE16 hActiveQueue = 0;
@@ -325,24 +324,6 @@
 
 
 /***********************************************************************
- *	     QUEUE_IsExitingQueue
- */
-BOOL QUEUE_IsExitingQueue( HQUEUE16 hQueue )
-{
-    return (hExitingQueue && (hQueue == hExitingQueue));
-}
-
-
-/***********************************************************************
- *	     QUEUE_SetExitingQueue
- */
-void QUEUE_SetExitingQueue( HQUEUE16 hQueue )
-{
-    hExitingQueue = hQueue;
-}
-
-
-/***********************************************************************
  *           QUEUE_CreateMsgQueue
  *
  * Creates a message queue. Doesn't link it into queue list!
@@ -417,7 +398,6 @@
     msgQueue->magic = 0;
 
     if( hActiveQueue == hQueue ) hActiveQueue = 0;
-    if (hExitingQueue == hQueue) hExitingQueue = 0;
 
     HeapLock( GetProcessHeap() );  /* FIXME: a bit overkill */
 
diff --git a/windows/win.c b/windows/win.c
index 106a60c..970bf0e 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -175,6 +175,18 @@
 }
 
 
+/*******************************************************************
+ *           send_parent_notify
+ */
+static void send_parent_notify( HWND hwnd, UINT msg )
+{
+    if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
+    if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
+    SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
+                  MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
+}
+
+
 /***********************************************************************
  *           WIN_GetPtr
  *
@@ -351,6 +363,14 @@
 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
 {
     BOOL ret;
+    WND *wndPtr = WIN_GetPtr( hwnd );
+
+    if (!wndPtr) return;
+    if (wndPtr == WND_OTHER_PROCESS)
+    {
+        if (IsWindow(hwnd)) ERR(" cannot link other process window %x\n", hwnd );
+        return;
+    }
 
     SERVER_START_REQ( link_window )
     {
@@ -360,19 +380,71 @@
         ret = !SERVER_CALL_ERR();
     }
     SERVER_END_REQ;
-    if (ret && parent)
+    if (ret && parent) wndPtr->parent = WIN_GetFullHandle(parent);
+    WIN_ReleasePtr( wndPtr );
+}
+
+
+/***********************************************************************
+ *           WIN_SetOwner
+ *
+ * Change the owner of a window.
+ */
+void WIN_SetOwner( HWND hwnd, HWND owner )
+{
+    WND *win = WIN_FindWndPtr( hwnd );
+    if (win)
     {
-        WND *wndPtr = WIN_FindWndPtr( hwnd );
-        if (wndPtr)
-        {
-            wndPtr->parent = WIN_GetFullHandle(parent);
-            WIN_ReleaseWndPtr( wndPtr );
-        }
+        win->owner = owner;
+        WIN_ReleaseWndPtr( win );
     }
 }
 
 
 /***********************************************************************
+ *           WIN_SetRectangles
+ *
+ * Set the window and client rectangles.
+ */
+void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
+{
+    WND *win = WIN_GetPtr( hwnd );
+    BOOL ret;
+
+    if (!win) return;
+    if (win == WND_OTHER_PROCESS)
+    {
+        if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %x\n", hwnd );
+        return;
+    }
+    SERVER_START_REQ( set_window_rectangles )
+    {
+        req->handle        = hwnd;
+        req->window.left   = rectWindow->left;
+        req->window.top    = rectWindow->top;
+        req->window.right  = rectWindow->right;
+        req->window.bottom = rectWindow->bottom;
+        req->client.left   = rectClient->left;
+        req->client.top    = rectClient->top;
+        req->client.right  = rectClient->right;
+        req->client.bottom = rectClient->bottom;
+        ret = !SERVER_CALL();
+    }
+    SERVER_END_REQ;
+    if (ret)
+    {
+        win->rectWindow = *rectWindow;
+        win->rectClient = *rectClient;
+
+        TRACE( "win %x window (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", hwnd,
+               rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
+               rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
+    }
+    WIN_ReleasePtr( win );
+}
+
+
+/***********************************************************************
  *           find_child_to_repaint
  *
  * Find a window that needs repaint among the children of the specified window.
@@ -481,18 +553,28 @@
  *
  * Destroy storage associated to a window. "Internals" p.358
  */
-static void WIN_DestroyWindow( HWND hwnd )
+LRESULT WIN_DestroyWindow( HWND hwnd )
 {
     WND *wndPtr;
     HWND *list;
 
     TRACE("%04x\n", hwnd );
 
+    if (!(hwnd = WIN_IsCurrentThread( hwnd )))
+    {
+        ERR( "window doesn't belong to current thread\n" );
+        return 0;
+    }
+
     /* free child windows */
     if ((list = WIN_ListChildren( hwnd )))
     {
         int i;
-        for (i = 0; list[i]; i++) WIN_DestroyWindow( list[i] );
+        for (i = 0; list[i]; i++)
+        {
+            if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
+            else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
+        }
         HeapFree( GetProcessHeap(), 0, list );
     }
 
@@ -517,7 +599,7 @@
 
     TIMER_RemoveWindowTimers( hwnd );
 
-    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
+    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
     wndPtr->hmemTaskQ = 0;
 
     if (!(wndPtr->dwStyle & WS_CHILD))
@@ -538,6 +620,7 @@
     wndPtr->class = NULL;
     wndPtr->dwMagic = 0;  /* Mark it as invalid */
     WIN_ReleaseWndPtr( wndPtr );
+    return 0;
 }
 
 /***********************************************************************
@@ -576,10 +659,10 @@
     WNDPROC winproc;
     DCE *dce;
     CREATESTRUCTA cs;
+    RECT rect;
 
     TRACE("Creating desktop window\n");
 
-
     if (!WINPOS_CreateInternalPosAtom() ||
         !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
                                    &wndExtra, &winproc, &clsStyle, &dce )))
@@ -595,11 +678,6 @@
     pWndDesktop->owner             = 0;
     pWndDesktop->class             = class;
     pWndDesktop->hInstance         = 0;
-    pWndDesktop->rectWindow.left   = 0;
-    pWndDesktop->rectWindow.top    = 0;
-    pWndDesktop->rectWindow.right  = GetSystemMetrics(SM_CXSCREEN);
-    pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
-    pWndDesktop->rectClient        = pWndDesktop->rectWindow;
     pWndDesktop->text              = NULL;
     pWndDesktop->hmemTaskQ         = 0;
     pWndDesktop->hrgnUpdate        = 0;
@@ -625,13 +703,16 @@
     cs.hwndParent     = 0;
     cs.x              = 0;
     cs.y              = 0;
-    cs.cx             = pWndDesktop->rectWindow.right;
-    cs.cy             = pWndDesktop->rectWindow.bottom;
+    cs.cx             = GetSystemMetrics( SM_CXSCREEN );
+    cs.cy             = GetSystemMetrics( SM_CYSCREEN );
     cs.style          = pWndDesktop->dwStyle;
     cs.dwExStyle      = pWndDesktop->dwExStyle;
     cs.lpszName       = NULL;
     cs.lpszClass      = DESKTOP_CLASS_ATOM;
 
+    SetRect( &rect, 0, 0, cs.cx, cs.cy );
+    WIN_SetRectangles( hwndDesktop, &rect, &rect );
+
     if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
 
     pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
@@ -721,6 +802,7 @@
     INT wndExtra;
     DWORD clsStyle;
     WNDPROC winproc;
+    RECT rect;
     DCE *dce;
     BOOL unicode = (type == WIN_PROC_32W);
 
@@ -867,11 +949,8 @@
 
     /* Initialize the dimensions before sending WM_GETMINMAXINFO */
 
-    wndPtr->rectWindow.left   = cs->x;
-    wndPtr->rectWindow.top    = cs->y;
-    wndPtr->rectWindow.right  = cs->x + cs->cx;
-    wndPtr->rectWindow.bottom = cs->y + cs->cy;
-    wndPtr->rectClient        = wndPtr->rectWindow;
+    SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy );
+    WIN_SetRectangles( hwnd, &rect, &rect );
 
     /* Send the WM_GETMINMAXINFO message and fix the size if needed */
 
@@ -887,11 +966,8 @@
     if (cs->cx < 0) cs->cx = 0;
     if (cs->cy < 0) cs->cy = 0;
 
-    wndPtr->rectWindow.left   = cs->x;
-    wndPtr->rectWindow.top    = cs->y;
-    wndPtr->rectWindow.right  = cs->x + cs->cx;
-    wndPtr->rectWindow.bottom = cs->y + cs->cy;
-    wndPtr->rectClient        = wndPtr->rectWindow;
+    SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy );
+    WIN_SetRectangles( hwnd, &rect, &rect );
 
     /* Set the window menu */
 
@@ -923,17 +999,13 @@
         return 0;
     }
 
-    if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
-    {
-        /* Notify the parent window only */
+    /* Notify the parent window only */
 
-        SendMessageA( wndPtr->parent, WM_PARENTNOTIFY,
-                      MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
-        if( !IsWindow(hwnd) )
-        {
-            hwnd = 0;
-            goto end;
-        }
+    send_parent_notify( hwnd, WM_CREATE );
+    if( !IsWindow(hwnd) )
+    {
+        hwnd = 0;
+        goto end;
     }
 
     if (cs->style & WS_VISIBLE)
@@ -1188,17 +1260,17 @@
  */
 BOOL WINAPI DestroyWindow( HWND hwnd )
 {
-    WND * wndPtr;
-    BOOL retvalue;
+    BOOL is_child;
     HWND h;
 
-    hwnd = WIN_GetFullHandle( hwnd );
+    if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
+    {
+        SetLastError( ERROR_ACCESS_DENIED );
+        return FALSE;
+    }
+
     TRACE("(%04x)\n", hwnd);
 
-    /* Initialization */
-
-    if (hwnd == GetDesktopWindow()) return FALSE;   /* Can't destroy desktop */
-
     /* Look whether the focus is within the tree of windows we will
      * be destroying.
      */
@@ -1214,25 +1286,20 @@
 
     if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
 
-    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
-    if (!(wndPtr->dwStyle & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
+    is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
+
+    if (is_child)
+    {
+        if (!USER_IsExitingThread( GetCurrentThreadId() ))
+            send_parent_notify( hwnd, WM_DESTROY );
+    }
+    else if (!GetWindow( hwnd, GW_OWNER ))
     {
         HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
         /* FIXME: clean up palette - see "Internals" p.352 */
     }
 
-    if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
-	if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
-	{
-	    /* Notify the parent window only */
-            SendMessageA( wndPtr->parent, WM_PARENTNOTIFY,
-                          MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
-            if( !IsWindow(hwnd) )
-            {
-                retvalue = TRUE;
-                goto end;
-            }
-	}
+    if (!IsWindow(hwnd)) return TRUE;
 
     if (USER_Driver.pResetSelectionOwner)
         USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
@@ -1240,77 +1307,62 @@
       /* Hide the window */
 
     ShowWindow( hwnd, SW_HIDE );
-    if (!IsWindow(hwnd))
-    {
-        retvalue = TRUE;
-        goto end;
-    }
+    if (!IsWindow(hwnd)) return TRUE;
 
       /* Recursively destroy owned windows */
 
-    if( !(wndPtr->dwStyle & WS_CHILD) )
+    if (!is_child)
     {
         HWND owner;
 
-      for (;;)
-      {
-          int i, got_one = 0;
-          HWND *list = WIN_ListChildren( wndPtr->parent );
-          if (list)
-          {
-              for (i = 0; list[i]; i++)
-              {
-                  WND *siblingPtr;
-                  if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
-                  if (!(siblingPtr = WIN_FindWndPtr( list[i] ))) continue;
-                  if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
-                  {
-                      WIN_ReleaseWndPtr( siblingPtr );
-                      DestroyWindow( list[i] );
-                      got_one = 1;
-                      continue;
-                  }
-                  else siblingPtr->owner = 0;
-                  WIN_ReleaseWndPtr( siblingPtr );
-              }
-              HeapFree( GetProcessHeap(), 0, list );
-          }
-          if (!got_one) break;
-      }
+        for (;;)
+        {
+            int i, got_one = 0;
+            HWND *list = WIN_ListChildren( GetDesktopWindow() );
+            if (list)
+            {
+                for (i = 0; list[i]; i++)
+                {
+                    if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
+                    if (WIN_IsCurrentThread( list[i] ))
+                    {
+                        DestroyWindow( list[i] );
+                        got_one = 1;
+                        continue;
+                    }
+                    WIN_SetOwner( list[i], 0 );
+                }
+                HeapFree( GetProcessHeap(), 0, list );
+            }
+            if (!got_one) break;
+        }
 
-      WINPOS_ActivateOtherWindow( hwnd );
+        WINPOS_ActivateOtherWindow( hwnd );
 
-      if ((owner = GetWindow( hwnd, GW_OWNER )))
-      {
-          WND *ptr = WIN_FindWndPtr( owner );
-          if (ptr)
-          {
-              if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner;
-              WIN_ReleaseWndPtr( ptr );
-          }
-      }
+        if ((owner = GetWindow( hwnd, GW_OWNER )))
+        {
+            WND *ptr = WIN_FindWndPtr( owner );
+            if (ptr)
+            {
+                if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner;
+                WIN_ReleaseWndPtr( ptr );
+            }
+        }
     }
 
       /* Send destroy messages */
 
     WIN_SendDestroyMsg( hwnd );
-    if (!IsWindow(hwnd))
-    {
-        retvalue = TRUE;
-        goto end;
-    }
+    if (!IsWindow( hwnd )) return TRUE;
 
       /* Unlink now so we won't bother with the children later on */
 
-    if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
+    WIN_UnlinkWindow( hwnd );
 
       /* Destroy the window storage */
 
     WIN_DestroyWindow( hwnd );
-    retvalue = TRUE;
-end:
-    WIN_ReleaseWndPtr(wndPtr);
-    return retvalue;
+    return TRUE;
 }
 
 
@@ -1319,20 +1371,9 @@
  */
 BOOL WINAPI CloseWindow( HWND hwnd )
 {
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
-    BOOL retvalue;
-
-    if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
-    {
-        retvalue = FALSE;
-        goto end;
-    }
+    if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
     ShowWindow( hwnd, SW_MINIMIZE );
-    retvalue = TRUE;
-end:
-    WIN_ReleaseWndPtr(wndPtr);
-    return retvalue;
-
+    return TRUE;
 }
 
 
@@ -1523,14 +1564,7 @@
  */
 BOOL WINAPI IsWindowEnabled(HWND hWnd)
 {
-    WND * wndPtr;
-    BOOL retvalue;
-
-    if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
-    retvalue = !(wndPtr->dwStyle & WS_DISABLED);
-    WIN_ReleaseWndPtr(wndPtr);
-    return retvalue;
-
+    return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
 }
 
 
@@ -2114,34 +2148,25 @@
 
 
 /*****************************************************************
- *		SetParent (USER32.@)
+ *		WIN_SetParent
+ *
+ * Implementation of SetParent, runs in the thread owning the window.
  */
-HWND WINAPI SetParent( HWND hwnd, HWND parent )
+HWND WIN_SetParent( HWND hwnd, HWND parent )
 {
     WND *wndPtr;
-    DWORD dwStyle;
     HWND retvalue;
-
-    if (!parent) parent = GetDesktopWindow();
-    else parent = WIN_GetFullHandle( parent );
-
-    /* sanity checks */
-    if (WIN_GetFullHandle(hwnd) == GetDesktopWindow() || !IsWindow( parent ))
-    {
-        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
-        return 0;
-    }
+    BOOL was_visible;
 
     if (USER_Driver.pSetParent)
         return USER_Driver.pSetParent( hwnd, parent );
 
-    if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
-
-    dwStyle = wndPtr->dwStyle;
-
     /* Windows hides the window first, then shows it again
      * including the WM_SHOWWINDOW messages and all */
-    if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
+    was_visible = ShowWindow( hwnd, SW_HIDE );
+
+    if (!IsWindow( parent )) return 0;
+    if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
 
     retvalue = wndPtr->parent;  /* old parent */
     if (parent != retvalue)
@@ -2150,28 +2175,55 @@
 
         if (parent != GetDesktopWindow()) /* a child window */
         {
-            if (!(dwStyle & WS_CHILD))
+            if (!(wndPtr->dwStyle & WS_CHILD))
             {
                 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
                 if (menu) DestroyMenu( menu );
             }
         }
     }
-    WIN_ReleaseWndPtr( wndPtr );
+    WIN_ReleasePtr( wndPtr );
 
     /* SetParent additionally needs to make hwnd the topmost window
        in the x-order and send the expected WM_WINDOWPOSCHANGING and
        WM_WINDOWPOSCHANGED notification messages.
     */
     SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
-                  SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
-                  ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
+                  SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
     /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
      * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
     return retvalue;
 }
 
 
+/*****************************************************************
+ *		SetParent (USER32.@)
+ */
+HWND WINAPI SetParent( HWND hwnd, HWND parent )
+{
+    HWND full_handle;
+
+    if (!parent) parent = GetDesktopWindow();
+    else parent = WIN_GetFullHandle( parent );
+
+    if (!IsWindow( parent ))
+    {
+        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+        return 0;
+    }
+
+    if ((full_handle = WIN_IsCurrentThread( hwnd )))
+        return WIN_SetParent( full_handle, parent );
+
+    if ((full_handle = WIN_GetFullHandle(hwnd)) == GetDesktopWindow())
+    {
+        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+        return 0;
+    }
+    return SendMessageW( full_handle, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
+}
+
+
 /*******************************************************************
  *		IsChild (USER32.@)
  */
diff --git a/windows/winpos.c b/windows/winpos.c
index 1969780..64e11fe 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -11,6 +11,7 @@
 #include "wingdi.h"
 #include "winerror.h"
 #include "wine/winuser16.h"
+#include "wine/server.h"
 #include "controls.h"
 #include "user.h"
 #include "region.h"
@@ -83,7 +84,9 @@
 {
     LPINTERNALPOS lpPos;
     MESSAGEQUEUE *pMsgQ = 0;
-    WND *wndPtr = WIN_FindWndPtr( hwnd );
+    WND *wndPtr = WIN_GetPtr( hwnd );
+
+    if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return;
 
     lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
 
@@ -92,7 +95,7 @@
     if ( !pMsgQ )
     {
         WARN("\tMessage queue not found. Exiting!\n" );
-        WIN_ReleaseWndPtr( wndPtr );
+        WIN_ReleasePtr( wndPtr );
         return;
     }
 
@@ -112,8 +115,7 @@
     }
 
     QUEUE_Unlock( pMsgQ );
-    WIN_ReleaseWndPtr( wndPtr );
-    return;
+    WIN_ReleasePtr( wndPtr );
 }
 
 /***********************************************************************
@@ -169,16 +171,41 @@
 /***********************************************************************
  *		GetWindowRect (USER32.@)
  */
-BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect ) 
+BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
 {
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
+    BOOL ret;
+    WND *wndPtr = WIN_GetPtr( hwnd );
+
     if (!wndPtr) return FALSE;
-    *rect = wndPtr->rectWindow;
-    WIN_ReleaseWndPtr(wndPtr);
-    MapWindowPoints( GetAncestor( hwnd, GA_PARENT ), 0, (POINT *)rect, 2 );
-    TRACE("hwnd %04x (%d,%d)-(%d,%d)\n",
-	  hwnd, rect->left, rect->top, rect->right, rect->bottom);
-    return TRUE;
+
+    if (wndPtr != WND_OTHER_PROCESS)
+    {
+        *rect = wndPtr->rectWindow;
+        WIN_ReleasePtr( wndPtr );
+        ret = TRUE;
+    }
+    else
+    {
+        SERVER_START_REQ( get_window_rectangles )
+        {
+            req->handle = hwnd;
+            if ((ret = !SERVER_CALL_ERR()))
+            {
+                rect->left   = req->window.left;
+                rect->top    = req->window.top;
+                rect->right  = req->window.right;
+                rect->bottom = req->window.bottom;
+            }
+        }
+        SERVER_END_REQ;
+    }
+    if (ret)
+    {
+        MapWindowPoints( GetAncestor( hwnd, GA_PARENT ), 0, (POINT *)rect, 2 );
+        TRACE( "hwnd %04x (%d,%d)-(%d,%d)\n",
+               hwnd, rect->left, rect->top, rect->right, rect->bottom);
+    }
+    return ret;
 }
 
 
@@ -246,19 +273,35 @@
 /***********************************************************************
  *		GetClientRect (USER32.@)
  */
-BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect ) 
+BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
 {
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
+    BOOL ret;
+    WND *wndPtr = WIN_GetPtr( hwnd );
 
     rect->left = rect->top = rect->right = rect->bottom = 0;
     if (!wndPtr) return FALSE;
-    rect->right  = wndPtr->rectClient.right - wndPtr->rectClient.left;
-    rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
 
-    WIN_ReleaseWndPtr(wndPtr);
-    TRACE("hwnd %04x (%d,%d)-(%d,%d)\n",
-	  hwnd, rect->left, rect->top, rect->right, rect->bottom);
-    return TRUE;
+    if (wndPtr != WND_OTHER_PROCESS)
+    {
+        rect->right  = wndPtr->rectClient.right - wndPtr->rectClient.left;
+        rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
+        WIN_ReleasePtr( wndPtr );
+        ret = TRUE;
+    }
+    else
+    {
+        SERVER_START_REQ( get_window_rectangles )
+        {
+            req->handle = hwnd;
+            if ((ret = !SERVER_CALL_ERR()))
+            {
+                rect->right  = req->client.right - req->client.left;
+                rect->bottom = req->client.bottom - req->client.top;
+            }
+        }
+        SERVER_END_REQ;
+    }
+    return ret;
 }
 
 
@@ -316,8 +359,6 @@
         }
         else if (!PtInRect( &wndPtr->rectWindow, pt )) goto next;  /* not in window -> skip */
 
-        TRACE( "%ld,%ld is inside %04x\n", pt.x, pt.y, list[i] );
-
         /* If window is minimized or disabled, return at once */
         if (wndPtr->dwStyle & WS_MINIMIZE)
         {
@@ -401,7 +442,10 @@
         xy.y -= wndScope->rectClient.top;
         WIN_ReleaseWndPtr( wndScope );
         if ((ret = find_child_from_point( hwndScope, xy, hittest, MAKELONG( pt.x, pt.y ) )))
+        {
+            TRACE( "found child %x\n", ret );
             return ret;
+        }
     }
     else WIN_ReleaseWndPtr( wndScope );
 
@@ -409,15 +453,18 @@
     if (!WIN_IsCurrentThread( hwndScope ))
     {
         *hittest = HTCLIENT;
+        TRACE( "returning %x\n", hwndScope );
         return hwndScope;
     }
     res = SendMessageA( hwndScope, WM_NCHITTEST, 0, MAKELONG( pt.x, pt.y ) );
     if (res != HTTRANSPARENT)
     {
         *hittest = res;  /* Found the window */
+        TRACE( "returning %x\n", hwndScope );
         return hwndScope;
     }
     *hittest = HTNOWHERE;
+    TRACE( "nothing found\n" );
     return 0;
 }
 
@@ -483,59 +530,67 @@
  * Calculate the offset between the origin of the two windows. Used
  * to implement MapWindowPoints.
  */
-static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
-                                 POINT *offset )
+static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, POINT *offset )
 {
-    WND * wndPtr = 0;
-    HWND *list;
-    int i;
+    WND * wndPtr;
 
     offset->x = offset->y = 0;
-    if (hwndFrom == hwndTo ) return;
 
-      /* Translate source window origin to screen coords */
+    /* Translate source window origin to screen coords */
     if (hwndFrom)
     {
-        if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
+        HWND hwnd = hwndFrom;
+
+        while (hwnd)
         {
-            ERR("bad hwndFrom = %04x\n",hwndFrom);
-            return;
-        }
-        if ((list = WIN_ListParents( hwndFrom )))
-        {
-            for (i = 0; list[i]; i++)
+            if (hwnd == hwndTo) return;
+            if (!(wndPtr = WIN_GetPtr( hwnd )))
             {
-                offset->x += wndPtr->rectClient.left;
-                offset->y += wndPtr->rectClient.top;
-                WIN_ReleaseWndPtr( wndPtr );
-                if (!(wndPtr = WIN_FindWndPtr( list[i] ))) break;
+                ERR( "bad hwndFrom = %04x\n", hwnd );
+                return;
             }
-            HeapFree( GetProcessHeap(), 0, list );
+            if (wndPtr == WND_OTHER_PROCESS) goto other_process;
+            offset->x += wndPtr->rectClient.left;
+            offset->y += wndPtr->rectClient.top;
+            hwnd = wndPtr->parent;
+            WIN_ReleasePtr( wndPtr );
         }
-        WIN_ReleaseWndPtr(wndPtr);
     }
 
-      /* Translate origin to destination window coords */
+    /* Translate origin to destination window coords */
     if (hwndTo)
     {
-        if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
+        HWND hwnd = hwndTo;
+
+        while (hwnd)
         {
-            ERR("bad hwndTo = %04x\n", hwndTo );
-            return;
-        }
-        if ((list = WIN_ListParents( hwndTo )))
-        {
-            for (i = 0; list[i]; i++)
+            if (!(wndPtr = WIN_GetPtr( hwnd )))
             {
-                offset->x -= wndPtr->rectClient.left;
-                offset->y -= wndPtr->rectClient.top;
-                WIN_ReleaseWndPtr( wndPtr );
-                if (!(wndPtr = WIN_FindWndPtr( list[i] ))) break;
+                ERR( "bad hwndTo = %04x\n", hwnd );
+                return;
             }
-            HeapFree( GetProcessHeap(), 0, list );
+            if (wndPtr == WND_OTHER_PROCESS) goto other_process;
+            offset->x -= wndPtr->rectClient.left;
+            offset->y -= wndPtr->rectClient.top;
+            hwnd = wndPtr->parent;
+            WIN_ReleasePtr( wndPtr );
         }
-        WIN_ReleaseWndPtr(wndPtr);
     }
+    return;
+
+ other_process:  /* one of the parents may belong to another process, do it the hard way */
+    offset->x = offset->y = 0;
+    SERVER_START_REQ( get_windows_offset )
+    {
+        req->from = hwndFrom;
+        req->to   = hwndTo;
+        if (!SERVER_CALL())
+        {
+            offset->x = req->x;
+            offset->y = req->y;
+        }
+    }
+    SERVER_END_REQ;
 }
 
 
@@ -560,12 +615,11 @@
 /*******************************************************************
  *		MapWindowPoints (USER32.@)
  */
-INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
-                               LPPOINT lppt, UINT count )
+INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo, LPPOINT lppt, UINT count )
 {
     POINT offset;
 
-    WINPOS_GetWinOffset( WIN_GetFullHandle(hwndFrom), WIN_GetFullHandle(hwndTo), &offset );
+    WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
     while (count--)
     {
 	lppt->x += offset.x;
@@ -581,12 +635,7 @@
  */
 BOOL WINAPI IsIconic(HWND hWnd)
 {
-    BOOL retvalue;
-    WND * wndPtr = WIN_FindWndPtr(hWnd);
-    if (wndPtr == NULL) return FALSE;
-    retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
-    WIN_ReleaseWndPtr(wndPtr);
-    return retvalue;
+    return (GetWindowLongW( hWnd, GWL_STYLE ) & WS_MINIMIZE) != 0;
 }
 
 
@@ -595,12 +644,7 @@
  */
 BOOL WINAPI IsZoomed(HWND hWnd)
 {
-    BOOL retvalue;
-    WND * wndPtr = WIN_FindWndPtr(hWnd);
-    if (wndPtr == NULL) return FALSE;
-    retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
-    WIN_ReleaseWndPtr(wndPtr);
-    return retvalue;
+    return (GetWindowLongW( hWnd, GWL_STYLE ) & WS_MAXIMIZE) != 0;
 }
 
 
@@ -780,8 +824,7 @@
 /***********************************************************************
  *           WINPOS_InitInternalPos
  */
-static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt, 
-					     LPRECT restoreRect )
+static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt, const RECT *restoreRect )
 {
     LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
                                                       atomInternalPos );
@@ -948,7 +991,11 @@
  */
 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
 {
-    return USER_Driver.pShowWindow( hwnd, cmd );
+    HWND full_handle;
+
+    if ((full_handle = WIN_IsCurrentThread( hwnd )))
+        return USER_Driver.pShowWindow( full_handle, cmd );
+    return SendMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 );
 }
 
 
@@ -1360,7 +1407,6 @@
 BOOL WINPOS_ActivateOtherWindow(HWND hwnd)
 {
     BOOL bRet = 0;
-    WND *pWnd;
     HWND hwndActive = 0;
     HWND hwndTo = 0;
     HWND owner;
@@ -1376,21 +1422,16 @@
         }
     }
 
-    pWnd = WIN_FindWndPtr( hwnd );
-    hwnd = pWnd->hwndSelf;
+    if (!(hwnd = WIN_IsCurrentThread( hwnd ))) return 0;
 
     if( hwnd == hwndPrevActive )
         hwndPrevActive = 0;
 
-    if( hwndActive != hwnd &&
-        ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
-    {
-        WIN_ReleaseWndPtr( pWnd );
+    if( hwndActive != hwnd && (hwndActive || USER_IsExitingThread( GetCurrentThreadId() )))
         return 0;
-    }
 
-    owner = GetWindow( hwnd, GW_OWNER );
-    if( !(pWnd->dwStyle & WS_POPUP) || !owner ||
+    if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_POPUP) ||
+        !(owner = GetWindow( hwnd, GW_OWNER )) ||
         !WINPOS_CanActivate((hwndTo = GetAncestor( owner, GA_ROOT ))) )
     {
         HWND tmp = GetAncestor( hwnd, GA_ROOT );
@@ -1403,7 +1444,6 @@
             if( !hwndTo ) break;
         }
     }
-    WIN_ReleaseWndPtr( pWnd );
 
     bRet = WINPOS_SetActiveWindow( hwndTo, FALSE, TRUE );
 
@@ -1452,45 +1492,6 @@
 
 
 /***********************************************************************
- *           WINPOS_SendNCCalcSize
- *
- * Send a WM_NCCALCSIZE message to a window.
- * All parameters are read-only except newClientRect.
- * oldWindowRect, oldClientRect and winpos must be non-NULL only
- * when calcValidRect is TRUE.
- */
-LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
-                            RECT *newWindowRect, RECT *oldWindowRect,
-                            RECT *oldClientRect, WINDOWPOS *winpos,
-                            RECT *newClientRect )
-{
-    NCCALCSIZE_PARAMS params;
-    WINDOWPOS winposCopy;
-    LONG result;
-
-    params.rgrc[0] = *newWindowRect;
-    if (calcValidRect)
-    {
-        winposCopy = *winpos;
-	params.rgrc[1] = *oldWindowRect;
-	params.rgrc[2] = *oldClientRect;
-	params.lppos = &winposCopy;
-    }
-    result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
-                             (LPARAM)&params );
-    TRACE("%d,%d-%d,%d\n",
-                 params.rgrc[0].left, params.rgrc[0].top,
-                 params.rgrc[0].right, params.rgrc[0].bottom );
-
-    /* If the application send back garbage, ignore it */
-    if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
-        *newClientRect = params.rgrc[0];
-
-    return result;
-}
-
-
-/***********************************************************************
  *           WINPOS_HandleWindowPosChanging16
  *
  * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
@@ -1557,7 +1558,8 @@
     winpos.cx = cx;
     winpos.cy = cy;
     winpos.flags = flags;
-    return USER_Driver.pSetWindowPos( &winpos );
+    if (WIN_IsCurrentThread( hwnd )) return USER_Driver.pSetWindowPos( &winpos );
+    return SendMessageW( winpos.hwnd, WM_WINE_SETWINDOWPOS, 0, (LPARAM)&winpos );
 }
 
 
@@ -1599,31 +1601,13 @@
     DWP *pDWP;
     int i;
     HDWP newhdwp = hdwp,retvalue;
-    /* HWND parent; */
-    WND *pWnd;
 
     hwnd = WIN_GetFullHandle( hwnd );
     if (hwnd == GetDesktopWindow()) return 0;
 
     if (!(pDWP = USER_HEAP_LIN_ADDR( hdwp ))) return 0;
 
-    if (!(pWnd = WIN_FindWndPtr( hwnd ))) return 0;
-
-/* Numega Bounds Checker Demo dislikes the following code.
-   In fact, I've not been able to find any "same parent" requirement in any docu
-   [AM 980509]
- */
-#if 0
-    /* All the windows of a DeferWindowPos() must have the same parent */
-    parent = pWnd->parent->hwndSelf;
-    if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
-    else if (parent != pDWP->hwndParent)
-    {
-        USER_HEAP_FREE( hdwp );
-        retvalue = 0;
-        goto END;
-    }
-#endif
+    USER_Lock();
 
     for (i = 0; i < pDWP->actualCount; i++)
     {
@@ -1638,7 +1622,7 @@
             {
                 pDWP->winPos[i].x = x;
                 pDWP->winPos[i].y = y;
-            }                
+            }
             if (!(flags & SWP_NOSIZE))
             {
                 pDWP->winPos[i].cx = cx;
@@ -1676,7 +1660,7 @@
     pDWP->actualCount++;
     retvalue = newhdwp;
 END:
-    WIN_ReleaseWndPtr(pWnd);
+    USER_Unlock();
     return retvalue;
 }
 
diff --git a/windows/x11drv/event.c b/windows/x11drv/event.c
index 8eb9910..e567a7c 100644
--- a/windows/x11drv/event.c
+++ b/windows/x11drv/event.c
@@ -1200,7 +1200,6 @@
   LPDRAGINFO16          lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
   SEGPTR		spDragInfo = K32WOWGlobalLock16(hDragInfo);
   Window		w_aux_root, w_aux_child;
-  WND*			pDropWnd;
   WND*                  pWnd;
   
   if( !lpDragInfo || !spDragInfo ) return;
@@ -1224,76 +1223,73 @@
       bAccept = DRAG_QueryUpdate( hWnd, spDragInfo, TRUE );
       x = lpDragInfo->pt.x; y = lpDragInfo->pt.y;
     }
-  pDropWnd = WIN_FindWndPtr( lpDragInfo->hScope );
   WIN_ReleaseWndPtr(pWnd);
   
   GlobalFree16( hDragInfo );
-  
-  if( bAccept )
-    {
-      TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
-			    dndSelection, 0, 65535, FALSE,
-			    AnyPropertyType, &u.atom_aux, (int *) &u.pt_aux.y,
-			    &data_length, &aux_long, &p_data);
-      
-      if( !aux_long && p_data)	/* don't bother if > 64K */
-	{
-	  signed char *p = (signed char*) p_data;
-	  char *p_drop;
-	  
-	  aux_long = 0; 
-	  while( *p )	/* calculate buffer size */
-	    {
-	      p_drop = p;
-	      if((u.i = *p) != -1 ) 
-		{
-		  INT len = GetShortPathNameA( p, NULL, 0 );
-		  if (len) aux_long += len + 1;
-		  else *p = -1;
-		}
-	      p += strlen(p) + 1;
-	    }
-	  if( aux_long && aux_long < 65535 )
-	    {
-	      HDROP                 hDrop;
-	      DROPFILES *lpDrop;
-	      
-	      aux_long += sizeof(DROPFILES) + 1;
-	      hDrop = GlobalAlloc( GMEM_SHARE, aux_long );
-	      lpDrop = (DROPFILES*)GlobalLock( hDrop );
-	      
-	      if( lpDrop )
-		{
-		  lpDrop->pFiles = sizeof(DROPFILES);
-		  lpDrop->pt.x = x;
-		  lpDrop->pt.y = y;
-		  lpDrop->fNC =
-		    ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left)  ||
-		      y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top)    ||
-		      x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
-		      y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
-                  lpDrop->fWide = FALSE;
-		  p_drop = (char *)(lpDrop + 1);
-		  p = p_data;
-		  while(*p)
-		    {
-		      if( *p != -1 )	/* use only "good" entries */
-			{
-                          GetShortPathNameA( p, p_drop, 65535 );
-                          p_drop += strlen( p_drop ) + 1;
-			}
-		      p += strlen(p) + 1;
-		    }
-		  *p_drop = '\0';
-		  PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
-		}
-	    }
-	}
-      if( p_data ) TSXFree(p_data);  
-      
-    } /* WS_EX_ACCEPTFILES */
 
-  WIN_ReleaseWndPtr(pDropWnd);
+    if (!bAccept) return;
+
+    TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
+                          dndSelection, 0, 65535, FALSE,
+                          AnyPropertyType, &u.atom_aux, (int *) &u.pt_aux.y,
+                          &data_length, &aux_long, &p_data);
+
+    if( !aux_long && p_data)  /* don't bother if > 64K */
+    {
+        signed char *p = (signed char*) p_data;
+        char *p_drop;
+
+        aux_long = 0;
+        while( *p )  /* calculate buffer size */
+        {
+            p_drop = p;
+            if((u.i = *p) != -1 )
+            {
+                INT len = GetShortPathNameA( p, NULL, 0 );
+                if (len) aux_long += len + 1;
+                else *p = -1;
+            }
+            p += strlen(p) + 1;
+        }
+        if( aux_long && aux_long < 65535 )
+        {
+            HDROP                 hDrop;
+            DROPFILES *lpDrop;
+
+            aux_long += sizeof(DROPFILES) + 1;
+            hDrop = GlobalAlloc( GMEM_SHARE, aux_long );
+            lpDrop = (DROPFILES*)GlobalLock( hDrop );
+
+            if( lpDrop )
+            {
+                WND *pDropWnd = WIN_FindWndPtr( lpDragInfo->hScope );
+                lpDrop->pFiles = sizeof(DROPFILES);
+                lpDrop->pt.x = x;
+                lpDrop->pt.y = y;
+                lpDrop->fNC =
+                    ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left)  ||
+                      y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top)    ||
+                      x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) ||
+                      y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
+                lpDrop->fWide = FALSE;
+                WIN_ReleaseWndPtr(pDropWnd);
+                p_drop = (char *)(lpDrop + 1);
+                p = p_data;
+                while(*p)
+                {
+                    if( *p != -1 ) /* use only "good" entries */
+                    {
+                        GetShortPathNameA( p, p_drop, 65535 );
+                        p_drop += strlen( p_drop ) + 1;
+                    }
+                    p += strlen(p) + 1;
+                }
+                *p_drop = '\0';
+                PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
+            }
+        }
+    }
+    if( p_data ) TSXFree(p_data);
 }
 
 /**********************************************************************
@@ -1306,8 +1302,6 @@
  */
 static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
 {
-  WND           *pDropWnd;
-  WND           *pWnd;
   unsigned long	data_length;
   unsigned long	aux_long, drop_len = 0;
   unsigned char	*p_data = NULL; /* property data */
@@ -1322,14 +1316,7 @@
     Window      w_aux;
   }		u; /* unused */
 
-  pWnd = WIN_FindWndPtr(hWnd);
-
-  if (!(pWnd->dwExStyle & WS_EX_ACCEPTFILES))
-  {
-    WIN_ReleaseWndPtr(pWnd);
-    return;
-  }
-  WIN_ReleaseWndPtr(pWnd);
+  if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return;
 
   TSXGetWindowProperty( event->display, DefaultRootWindow(event->display),
 			dndSelection, 0, 65535, FALSE,
@@ -1362,13 +1349,12 @@
       TSXQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
 		       &x, &y, &u.i, &u.i, &u.i);
 
-      pDropWnd = WIN_FindWndPtr( hWnd );
-      
       drop_len += sizeof(DROPFILES) + 1;
       hDrop = GlobalAlloc( GMEM_SHARE, drop_len );
       lpDrop = (DROPFILES *) GlobalLock( hDrop );
 
       if( lpDrop ) {
+          WND *pDropWnd = WIN_FindWndPtr( hWnd );
 	  lpDrop->pFiles = sizeof(DROPFILES);
 	  lpDrop->pt.x = (INT)x;
 	  lpDrop->pt.y = (INT)y;
@@ -1379,6 +1365,7 @@
 	      y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) );
 	  lpDrop->fWide = FALSE;
 	  p_drop = (char*)(lpDrop + 1);
+          WIN_ReleaseWndPtr(pDropWnd);
       }
 
       /* create message content */
@@ -1411,7 +1398,6 @@
         GlobalUnlock(hDrop);
         PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
       }
-      WIN_ReleaseWndPtr(pDropWnd);
     }
     if( p_data ) TSXFree(p_data);  
   }