diff --git a/dlls/ttydrv/wnd.c b/dlls/ttydrv/wnd.c
index 13a01e9cfdcd53279a07aa561f0d0b7dcf429efc..2db3ec41bbf0342390d2f1715382b4948ee3832e 100644
--- a/dlls/ttydrv/wnd.c
+++ b/dlls/ttydrv/wnd.c
@@ -127,7 +127,7 @@ static BOOL DCE_GetVisRect( WND *wndPtr, BOOL clientArea, RECT *lprect )
         INT xoffset = lprect->left;
         INT yoffset = lprect->top;
 
-        while ((wndPtr = WIN_LockWndPtr(wndPtr->parent)))
+        while ((wndPtr = WIN_FindWndPtr( GetAncestor(wndPtr->hwndSelf,GA_PARENT) )))
         {
             if ( (wndPtr->dwStyle & (WS_ICONIC | WS_VISIBLE)) != WS_VISIBLE )
             {
@@ -175,27 +175,28 @@ fail:
  * adding to the clip region the intersection of the target rectangle
  * with an offset window rectangle.
  */
-static BOOL DCE_AddClipRects( WND *pWndStart, WND *pWndEnd,
-                              HRGN hrgnClip, LPRECT lpRect, int x, int y )
+static BOOL DCE_AddClipRects( HWND start, HWND end, HRGN hrgnClip, LPRECT lpRect, int x, int y )
 {
     RECT rect;
+    WND *pWnd;
 
-    for (WIN_LockWndPtr(pWndStart); (pWndStart && (pWndStart != pWndEnd)); WIN_UpdateWndPtr(&pWndStart,pWndStart->next))
+    for (pWnd = WIN_FindWndPtr(start); (pWnd && (pWnd->hwndSelf != end)); WIN_UpdateWndPtr(&pWnd,pWnd->next))
     {
-        if( !(pWndStart->dwStyle & WS_VISIBLE) ) continue;
+        if( !(pWnd->dwStyle & WS_VISIBLE) ) continue;
 
-        rect.left = pWndStart->rectWindow.left + x;
-        rect.top = pWndStart->rectWindow.top + y;
-        rect.right = pWndStart->rectWindow.right + x;
-        rect.bottom = pWndStart->rectWindow.bottom + y;
+        rect.left = pWnd->rectWindow.left + x;
+        rect.top = pWnd->rectWindow.top + y;
+        rect.right = pWnd->rectWindow.right + x;
+        rect.bottom = pWnd->rectWindow.bottom + y;
 
         if( IntersectRect( &rect, &rect, lpRect ))
         {
             if(!REGION_UnionRectWithRgn( hrgnClip, &rect )) break;
         }
     }
-    WIN_ReleaseWndPtr(pWndStart);
-    return (pWndStart == pWndEnd);
+    start = pWnd->hwndSelf;
+    WIN_ReleaseWndPtr(pWnd);
+    return (start == end);
 }
 
 
@@ -242,7 +243,7 @@ static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags )
                     else
                         xoffset = yoffset = 0;
 
-                    DCE_AddClipRects( wndPtr->child, NULL, hrgnClip, &rect, xoffset, yoffset );
+                    DCE_AddClipRects( wndPtr->child->hwndSelf, 0, hrgnClip, &rect, xoffset, yoffset );
                 }
 
                 /* We may need to clip children of child window, if a window with PARENTDC
@@ -267,7 +268,7 @@ static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags )
                     xoffset += childWnd->rectClient.left;
                     yoffset += childWnd->rectClient.top;
 
-                    DCE_AddClipRects( childWnd->child, NULL, hrgnClip,
+                    DCE_AddClipRects( childWnd->child->hwndSelf, 0, hrgnClip,
                                       &rect, xoffset, yoffset );
                 }
 
@@ -286,8 +287,8 @@ static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags )
                 }
 
                 if (flags & DCX_CLIPSIBLINGS && wndPtr->parent )
-                    DCE_AddClipRects( wndPtr->parent->child,
-                                      wndPtr, hrgnClip, &rect, xoffset, yoffset );
+                    DCE_AddClipRects( GetWindow( wndPtr->hwndSelf, GW_HWNDFIRST ),
+                                      wndPtr->hwndSelf, hrgnClip, &rect, xoffset, yoffset );
 
                 /* Clip siblings of all ancestors that have the
                  * WS_CLIPSIBLINGS style
@@ -295,13 +296,15 @@ static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags )
 
                 while (wndPtr->parent)
                 {
-                    WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
+                    WND *ptr = WIN_FindWndPtr( wndPtr->parent );
+                    WIN_ReleaseWndPtr( wndPtr );
+                    wndPtr = ptr;
                     xoffset -= wndPtr->rectClient.left;
                     yoffset -= wndPtr->rectClient.top;
                     if(wndPtr->dwStyle & WS_CLIPSIBLINGS && wndPtr->parent)
                     {
-                        DCE_AddClipRects( wndPtr->parent->child, wndPtr,
-                                          hrgnClip, &rect, xoffset, yoffset );
+                        DCE_AddClipRects( GetWindow( wndPtr->hwndSelf, GW_HWNDFIRST ),
+                                          wndPtr->hwndSelf, hrgnClip, &rect, xoffset, yoffset );
                     }
                 }
 
@@ -364,7 +367,7 @@ BOOL TTYDRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags )
     {
         if (flags & DCX_PARENTCLIP)
         {
-            WND *parentPtr = WIN_LockWndPtr(wndPtr->parent);
+            WND *parentPtr = WIN_FindWndPtr( wndPtr->parent );
 
             if( wndPtr->dwStyle & WS_VISIBLE && !(parentPtr->dwStyle & WS_MINIMIZE) )
             {
@@ -534,7 +537,10 @@ BOOL TTYDRV_SetWindowPos( WINDOWPOS *winpos )
     }
 
     if( winpos->hwndInsertAfter == HWND_TOP )
-        winpos->flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
+    {
+        if (GetWindow( wndPtr->hwndSelf, GW_HWNDFIRST ) == wndPtr->hwndSelf)
+            winpos->flags |= SWP_NOZORDER;
+    }
     else
         if( winpos->hwndInsertAfter == HWND_BOTTOM )
             winpos->flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
@@ -583,14 +589,11 @@ BOOL TTYDRV_SetWindowPos( WINDOWPOS *winpos )
 
     if( !(winpos->flags & SWP_NOREDRAW) )
     {
-        RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
+        RedrawWindow( wndPtr->parent, NULL, 0,
                       RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN );
-        if (wndPtr->parent->hwndSelf == GetDesktopWindow() ||
-            wndPtr->parent->parent->hwndSelf == GetDesktopWindow())
-        {
-            RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
+        if (wndPtr->parent == GetDesktopWindow())
+            RedrawWindow( wndPtr->parent, NULL, 0,
                           RDW_ERASENOW | RDW_NOCHILDREN );
-        }
     }
 
     if (!(winpos->flags & SWP_NOACTIVATE))
diff --git a/dlls/x11drv/window.c b/dlls/x11drv/window.c
index 524ba99a0bbf3e8b28620bda2e0fdc33716c37ca..b1a59059b94908ae18f1b50ebe2cf6219c6bfd1e 100644
--- a/dlls/x11drv/window.c
+++ b/dlls/x11drv/window.c
@@ -76,8 +76,7 @@ inline static BOOL is_window_managed( WND *win )
  */
 inline static BOOL is_window_top_level( WND *win )
 {
-    return (root_window == DefaultRootWindow(gdi_display) &&
-            win->parent->hwndSelf == GetDesktopWindow());
+    return (root_window == DefaultRootWindow(gdi_display) && win->parent == GetDesktopWindow());
 }
 
 
@@ -633,7 +632,7 @@ static Window create_whole_window( Display *display, WND *win )
     if (!(cx = rect.right - rect.left)) cx = 1;
     if (!(cy = rect.bottom - rect.top)) cy = 1;
 
-    parent = get_client_window( win->parent );
+    parent = X11DRV_get_client_window( win->parent );
 
     wine_tsx11_lock();
 
@@ -887,9 +886,9 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode )
            (unsigned int)data->whole_window, (unsigned int)data->client_window );
 
     if ((wndPtr->dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
-        WIN_LinkWindow( hwnd, wndPtr->parent->hwndSelf, HWND_BOTTOM );
+        WIN_LinkWindow( hwnd, wndPtr->parent, HWND_BOTTOM );
     else
-        WIN_LinkWindow( hwnd, wndPtr->parent->hwndSelf, HWND_TOP );
+        WIN_LinkWindow( hwnd, wndPtr->parent, HWND_TOP );
 
     WIN_ReleaseWndPtr( wndPtr );
 
@@ -1009,7 +1008,7 @@ HWND X11DRV_SetParent( HWND hwnd, HWND parent )
      * including the WM_SHOWWINDOW messages and all */
     if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
 
-    retvalue = wndPtr->parent->hwndSelf;  /* old parent */
+    retvalue = wndPtr->parent;  /* old parent */
     if (parent != retvalue)
     {
         struct x11drv_win_data *data = wndPtr->pDriverData;
diff --git a/dlls/x11drv/winpos.c b/dlls/x11drv/winpos.c
index 0d4c286f2652061451660be947e75b0e19ea14a0..218186ad54297d0f426f93750952b14204c83459 100644
--- a/dlls/x11drv/winpos.c
+++ b/dlls/x11drv/winpos.c
@@ -59,37 +59,48 @@ DEFAULT_DEBUG_CHANNEL(x11drv);
  *
  * Clip all children of a given window out of the visible region
  */
-static int clip_children( WND *win, WND *last, HRGN hrgn, int whole_window )
+static int clip_children( HWND parent, HWND last, HRGN hrgn, int whole_window )
 {
+    HWND *list;
     WND *ptr;
     HRGN rectRgn;
-    int x, y, ret = SIMPLEREGION;
+    int i, x, y, ret = SIMPLEREGION;
 
     /* first check if we have anything to do */
-    for (ptr = win->child; ptr && ptr != last; ptr = ptr->next)
-        if (ptr->dwStyle & WS_VISIBLE) break;
-    if (!ptr || ptr == last) return ret; /* no children to clip */
+    if (!(list = WIN_ListChildren( parent ))) return ret;
+    for (i = 0; list[i] && list[i] != last; i++)
+        if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE) break;
+    if (!list[i] || list[i] == last) goto done; /* no children to clip */
 
     if (whole_window)
     {
+        WND *win = WIN_FindWndPtr( parent );
         x = win->rectWindow.left - win->rectClient.left;
         y = win->rectWindow.top - win->rectClient.top;
+        WIN_ReleaseWndPtr( win );
     }
     else x = y = 0;
 
     rectRgn = CreateRectRgn( 0, 0, 0, 0 );
-    while (ptr && ptr != last)
+
+    for ( ; list[i] && list[i] != last; i++)
     {
+        if (!(ptr = WIN_FindWndPtr( list[i] ))) continue;
         if (ptr->dwStyle & WS_VISIBLE)
         {
             SetRectRgn( rectRgn, ptr->rectWindow.left + x, ptr->rectWindow.top + y,
                         ptr->rectWindow.right + x, ptr->rectWindow.bottom + y );
             if ((ret = CombineRgn( hrgn, hrgn, rectRgn, RGN_DIFF )) == NULLREGION)
+            {
+                WIN_ReleaseWndPtr( ptr );
                 break;  /* no need to go on, region is empty */
+            }
         }
-        ptr = ptr->next;
+        WIN_ReleaseWndPtr( ptr );
     }
     DeleteObject( rectRgn );
+ done:
+    HeapFree( GetProcessHeap(), 0, list );
     return ret;
 }
 
@@ -99,7 +110,7 @@ static int clip_children( WND *win, WND *last, HRGN hrgn, int whole_window )
  *
  * Compute the visible region of a window
  */
-static HRGN get_visible_region( WND *win, WND *top, UINT flags, int mode )
+static HRGN get_visible_region( WND *win, HWND top, UINT flags, int mode )
 {
     HRGN rgn;
     RECT rect;
@@ -118,7 +129,7 @@ static HRGN get_visible_region( WND *win, WND *top, UINT flags, int mode )
     }
 
     if (flags & DCX_PARENTCLIP)
-        GetClientRect( win->parent->hwndSelf, &rect );
+        GetClientRect( win->parent, &rect );
     else if (flags & DCX_WINDOW)
         rect = data->whole_rect;
     else
@@ -132,12 +143,12 @@ static HRGN get_visible_region( WND *win, WND *top, UINT flags, int mode )
     if ((flags & DCX_CLIPCHILDREN) && (mode != ClipByChildren))
     {
         /* we need to clip children by hand */
-        if (clip_children( win, NULL, rgn, (flags & DCX_WINDOW) ) == NULLREGION) return rgn;
+        if (clip_children( win->hwndSelf, 0, rgn, (flags & DCX_WINDOW) ) == NULLREGION) return rgn;
     }
 
-    if (top && top != win)  /* need to clip siblings of ancestors */
+    if (top && top != win->hwndSelf)  /* need to clip siblings of ancestors */
     {
-        WND *ptr = win;
+        WND *parent, *ptr = WIN_LockWndPtr( win );
         HRGN tmp = 0;
 
         OffsetRgn( rgn, xoffset, yoffset );
@@ -145,10 +156,12 @@ static HRGN get_visible_region( WND *win, WND *top, UINT flags, int mode )
         {
             if (ptr->dwStyle & WS_CLIPSIBLINGS)
             {
-                if (clip_children( ptr->parent, ptr, rgn, FALSE ) == NULLREGION) break;
+                if (clip_children( ptr->parent, ptr->hwndSelf, rgn, FALSE ) == NULLREGION) break;
             }
-            if (ptr == top) break;
-            ptr = ptr->parent;
+            if (ptr->hwndSelf == top) break;
+            if (!(parent = WIN_FindWndPtr( ptr->parent ))) break;
+            WIN_ReleaseWndPtr( ptr );
+            ptr = parent;
             /* clip to parent client area */
             if (tmp) SetRectRgn( tmp, 0, 0, ptr->rectClient.right - ptr->rectClient.left,
                                  ptr->rectClient.bottom - ptr->rectClient.top );
@@ -159,6 +172,7 @@ static HRGN get_visible_region( WND *win, WND *top, UINT flags, int mode )
             xoffset += ptr->rectClient.left;
             yoffset += ptr->rectClient.top;
         }
+        WIN_ReleaseWndPtr( ptr );
         /* make it relative to the target window again */
         OffsetRgn( rgn, -xoffset, -yoffset );
         if (tmp) DeleteObject( tmp );
@@ -180,7 +194,7 @@ static int get_covered_region( WND *win, HRGN rgn )
 {
     HRGN tmp;
     int ret;
-    WND *ptr = win;
+    WND *parent, *ptr = WIN_LockWndPtr( win );
     int xoffset = 0, yoffset = 0;
 
     tmp = CreateRectRgn( 0, 0, 0, 0 );
@@ -193,13 +207,16 @@ static int get_covered_region( WND *win, HRGN rgn )
     {
         if (!(ptr->dwStyle & WS_CLIPSIBLINGS))
         {
-            if (clip_children( ptr->parent, ptr, tmp, FALSE ) == NULLREGION) break;
+            if (clip_children( ptr->parent, ptr->hwndSelf, tmp, FALSE ) == NULLREGION) break;
         }
-        if (!(ptr = ptr->parent)) break;
+        if (!(parent = WIN_FindWndPtr( ptr->parent ))) break;
+        WIN_ReleaseWndPtr( ptr );
+        ptr = parent;
         OffsetRgn( tmp, ptr->rectClient.left, ptr->rectClient.top );
         xoffset += ptr->rectClient.left;
         yoffset += ptr->rectClient.top;
     }
+    WIN_ReleaseWndPtr( ptr );
     /* make it relative to the target window again */
     OffsetRgn( tmp, -xoffset, -yoffset );
 
@@ -215,44 +232,58 @@ static int get_covered_region( WND *win, HRGN rgn )
  *
  * Expose a region of a given window.
  */
-static void expose_window( WND *win, RECT *rect, HRGN rgn, int flags )
+static void expose_window( HWND hwnd, RECT *rect, HRGN rgn, int flags )
 {
-    WND *ptr, *top;
-    int xoffset = 0, yoffset = 0;
+    POINT offset;
+    HWND top = 0;
+    HWND *list;
+    int i;
 
     /* find the top most parent that doesn't clip children or siblings and
      * invalidate the area on its parent, including all children */
-    top = NULL;
-    for (ptr = win; ptr && ptr->parent; ptr = ptr->parent)
+    if ((list = WIN_ListParents( hwnd )))
     {
-        if (!(ptr->dwStyle & WS_CLIPSIBLINGS)) top = ptr;
-        if (!(ptr->parent->dwStyle & WS_CLIPCHILDREN)) top = ptr;
-    }
+        HWND current = hwnd;
+        LONG style = GetWindowLongW( hwnd, GWL_STYLE );
+        for (i = 0; list[i] && list[i] != GetDesktopWindow(); i++)
+        {
+            if (!(style & WS_CLIPSIBLINGS)) top = current;
+            style = GetWindowLongW( list[i], GWL_STYLE );
+            if (!(style & WS_CLIPCHILDREN)) top = current;
+            current = list[i];
+        }
 
-    if (top)
-    {
-        if (top->parent && top->parent->hwndSelf != GetDesktopWindow()) top = top->parent;
-        flags &= ~RDW_FRAME;  /* parent will invalidate children frame anyway */
-        flags |= RDW_ALLCHILDREN;
+        if (top)
+        {
+            /* find the parent of the top window, reusing the parent list */
+            if (top == hwnd) i = 0;
+            else
+            {
+                for (i = 0; list[i]; i++) if (list[i] == top) break;
+                if (list[i] && list[i+1]) i++;
+            }
+            if (list[i] != GetDesktopWindow()) top = list[i];
+            flags &= ~RDW_FRAME;  /* parent will invalidate children frame anyway */
+            flags |= RDW_ALLCHILDREN;
+        }
+        HeapFree( GetProcessHeap(), 0, list );
     }
-    else top = win;
+
+    if (!top) top = hwnd;
 
     /* make coords relative to top */
-    for (ptr = win; ptr != top; ptr = ptr->parent)
-    {
-        xoffset += ptr->rectClient.left;
-        yoffset += ptr->rectClient.top;
-    }
+    offset.x = offset.y = 0;
+    MapWindowPoints( hwnd, top, &offset, 1 );
 
     if (rect)
     {
-        OffsetRect( rect, xoffset, yoffset );
-        RedrawWindow( top->hwndSelf, rect, 0, flags );
+        OffsetRect( rect, offset.x, offset.y );
+        RedrawWindow( top, rect, 0, flags );
     }
     else
     {
-        OffsetRgn( rgn, xoffset, yoffset );
-        RedrawWindow( top->hwndSelf, NULL, rgn, flags );
+        OffsetRgn( rgn, offset.x, offset.y );
+        RedrawWindow( top, NULL, rgn, flags );
     }
 }
 
@@ -327,7 +358,7 @@ static void expose_covered_window_area( WND *win, const RECT *old_client_rect, B
     if (ret != NULLREGION)
     {
         if (get_covered_region( win, hrgn ) != NULLREGION)
-            expose_window( win, NULL, hrgn,
+            expose_window( win->hwndSelf, NULL, hrgn,
                            RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN );
     }
 
@@ -362,9 +393,9 @@ void X11DRV_Expose( HWND hwnd, XExposeEvent *event )
         /* make position relative to client area instead of window */
         OffsetRect( &rect, -data->client_rect.left, -data->client_rect.top );
     }
-
-    expose_window( win, &rect, 0, flags );
     WIN_ReleaseWndPtr( win );
+
+    expose_window( hwnd, &rect, 0, flags );
 }
 
 
@@ -377,49 +408,53 @@ void X11DRV_Expose( HWND hwnd, XExposeEvent *event )
 BOOL X11DRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags )
 {
     WND *win = WIN_FindWndPtr( hwnd );
-    WND *ptr, *top;
+    HWND top = 0;
     X11DRV_WND_DATA *data = win->pDriverData;
     Drawable drawable;
     BOOL visible;
-    int org_x, org_y, mode = IncludeInferiors;
+    POINT org;
+    int mode = IncludeInferiors;
 
     /* don't clip siblings if using parent clip region */
     if (flags & DCX_PARENTCLIP) flags &= ~DCX_CLIPSIBLINGS;
 
     /* find the top parent in the hierarchy that isn't clipping siblings */
-    top = NULL;
     visible = (win->dwStyle & WS_VISIBLE) != 0;
 
     if (visible)
     {
-        for (ptr = win->parent; ptr && ptr->parent; ptr = ptr->parent)
+        HWND *list = WIN_ListParents( hwnd );
+        if (list)
         {
-            if (!(ptr->dwStyle & WS_VISIBLE))
+            int i;
+            for (i = 0; list[i] != GetDesktopWindow(); i++)
             {
-                visible = FALSE;
-                top = NULL;
-                break;
+                LONG style = GetWindowLongW( list[i], GWL_STYLE );
+                if (!(style & WS_VISIBLE))
+                {
+                    visible = FALSE;
+                    top = 0;
+                    break;
+                }
+                if (!(style & WS_CLIPSIBLINGS)) top = list[i];
             }
-            if (!(ptr->dwStyle & WS_CLIPSIBLINGS)) top = ptr;
+            HeapFree( GetProcessHeap(), 0, list );
         }
-        if (!top && visible && !(flags & DCX_CLIPSIBLINGS)) top = win;
+        if (!top && visible && !(flags & DCX_CLIPSIBLINGS)) top = hwnd;
     }
 
     if (top)
     {
-        org_x = org_y = 0;
+        HWND parent = GetAncestor( top, GA_PARENT );
+        org.x = org.y = 0;
         if (flags & DCX_WINDOW)
         {
-            org_x = win->rectWindow.left - win->rectClient.left;
-            org_y = win->rectWindow.top - win->rectClient.top;
-        }
-        for (ptr = win; ptr != top->parent; ptr = ptr->parent)
-        {
-            org_x += ptr->rectClient.left;
-            org_y += ptr->rectClient.top;
+            org.x = win->rectWindow.left - win->rectClient.left;
+            org.y = win->rectWindow.top - win->rectClient.top;
         }
+        MapWindowPoints( hwnd, parent, &org, 1 );
         /* have to use the parent so that we include siblings */
-        if (top->parent) drawable = get_client_window( top->parent );
+        if (parent) drawable = X11DRV_get_client_window( parent );
         else drawable = root_window;
     }
     else
@@ -427,25 +462,25 @@ BOOL X11DRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags )
         if (IsIconic( hwnd ))
         {
             drawable = data->icon_window ? data->icon_window : data->whole_window;
-            org_x = 0;
-            org_y = 0;
+            org.x = 0;
+            org.y = 0;
         }
         else if (flags & DCX_WINDOW)
         {
             drawable = data->whole_window;
-            org_x = win->rectWindow.left - data->whole_rect.left;
-            org_y = win->rectWindow.top - data->whole_rect.top;
+            org.x = win->rectWindow.left - data->whole_rect.left;
+            org.y = win->rectWindow.top - data->whole_rect.top;
         }
         else
         {
             drawable = data->client_window;
-            org_x = 0;
-            org_y = 0;
+            org.x = 0;
+            org.y = 0;
             if (flags & DCX_CLIPCHILDREN) mode = ClipByChildren;  /* can use X11 clipping */
         }
     }
 
-    X11DRV_SetDrawable( hdc, drawable, mode, org_x, org_y );
+    X11DRV_SetDrawable( hdc, drawable, mode, org.x, org.y );
 
     if (flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN) ||
         SetHookFlags16( hdc, DCHF_VALIDATEVISRGN ))  /* DC was dirty */
@@ -462,7 +497,7 @@ BOOL X11DRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags )
                             (flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF );
 
             /* make it relative to the drawable origin */
-            OffsetRgn( visRgn, org_x, org_y );
+            OffsetRgn( visRgn, org.x, org.y );
         }
         else visRgn = CreateRectRgn( 0, 0, 0, 0 );
 
@@ -893,9 +928,10 @@ BOOL X11DRV_SetWindowPos( WINDOWPOS *winpos )
 static POINT WINPOS_FindIconPos( WND* wndPtr, POINT pt )
 {
     RECT rectParent;
+    HWND *list;
     short x, y, xspacing, yspacing;
 
-    GetClientRect( wndPtr->parent->hwndSelf, &rectParent );
+    GetClientRect( wndPtr->parent, &rectParent );
     if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
         (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
         return pt;  /* The icon already has a suitable position */
@@ -903,34 +939,48 @@ static POINT WINPOS_FindIconPos( WND* wndPtr, POINT pt )
     xspacing = GetSystemMetrics(SM_CXICONSPACING);
     yspacing = GetSystemMetrics(SM_CYICONSPACING);
 
+    list = WIN_ListChildren( wndPtr->parent );
     y = rectParent.bottom;
     for (;;)
     {
         x = rectParent.left;
         do
         {
-              /* Check if another icon already occupies this spot */
-            WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
-            while (childPtr)
+            /* Check if another icon already occupies this spot */
+            /* FIXME: this is completely inefficient */
+            if (list)
             {
-                if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
+                int i;
+                WND *childPtr;
+
+                for (i = 0; list[i]; i++)
                 {
+                    if (list[i] == wndPtr->hwndSelf) continue;
+                    if (!IsIconic( list[i] )) continue;
+                    if (!(childPtr = WIN_FindWndPtr( list[i] ))) continue;
                     if ((childPtr->rectWindow.left < x + xspacing) &&
                         (childPtr->rectWindow.right >= x) &&
                         (childPtr->rectWindow.top <= y) &&
                         (childPtr->rectWindow.bottom > y - yspacing))
+                    {
+                        WIN_ReleaseWndPtr( childPtr );
                         break;  /* There's a window in there */
+                    }
+                    WIN_ReleaseWndPtr( childPtr );
+                }
+                if (list[i])
+                {
+                    /* found something here, try next spot */
+                    x += xspacing;
+                    continue;
                 }
-                WIN_UpdateWndPtr(&childPtr,childPtr->next);
-            }
-            WIN_ReleaseWndPtr(childPtr);
-            if (!childPtr) /* No window was found, so it's OK for us */
-            {
-                pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
-                pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
-                return pt;
             }
-            x += xspacing;
+
+            /* No window was found, so it's OK for us */
+            pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
+            pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
+            return pt;
+
         } while(x <= rectParent.right-xspacing);
         y -= yspacing;
     }
@@ -1990,35 +2040,42 @@ void X11DRV_SysCommandSizeMove( HWND hwnd, WPARAM wParam )
  */
 void X11DRV_ForceWindowRaise( HWND hwnd )
 {
+    int i = 0;
+    HWND *list;
     XWindowChanges winChanges;
     Display *display = thread_display();
-    WND *wndPrev, *wndPtr = WIN_FindWndPtr( hwnd );
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
 
     if (!wndPtr) return;
 
     if ((wndPtr->dwExStyle & WS_EX_MANAGED) ||
-        wndPtr->parent->hwndSelf != GetDesktopWindow() ||
+        wndPtr->parent != GetDesktopWindow() ||
         IsRectEmpty( &wndPtr->rectWindow ) ||
         !get_whole_window(wndPtr))
     {
         WIN_ReleaseWndPtr( wndPtr );
         return;
     }
+    WIN_ReleaseWndPtr( wndPtr );
 
     /* Raise all windows up to wndPtr according to their Z order.
      * (it would be easier with sibling-related Below but it doesn't
      * work very well with SGI mwm for instance)
      */
     winChanges.stack_mode = Above;
-    while (wndPtr)
+    if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return;
+    while (list[i] && list[i] != hwnd) i++;
+    if (list[i])
     {
-        if (!IsRectEmpty( &wndPtr->rectWindow ) && get_whole_window(wndPtr))
-            TSXReconfigureWMWindow( display, get_whole_window(wndPtr), 0,
-                                    CWStackMode, &winChanges );
-        wndPrev = wndPtr->parent->child;
-        if (wndPrev == wndPtr) break;
-        while (wndPrev && (wndPrev->next != wndPtr)) wndPrev = wndPrev->next;
-        WIN_UpdateWndPtr( &wndPtr, wndPrev );
+        for ( ; i >= 0; i--)
+        {
+            WND *ptr = WIN_FindWndPtr( list[i] );
+            if (!ptr) continue;
+            if (!IsRectEmpty( &ptr->rectWindow ) && get_whole_window(ptr))
+                TSXReconfigureWMWindow( display, get_whole_window(ptr), 0,
+                                        CWStackMode, &winChanges );
+            WIN_ReleaseWndPtr( ptr );
+        }
     }
-    WIN_ReleaseWndPtr( wndPtr );
+    HeapFree( GetProcessHeap(), 0, list );
 }
diff --git a/include/win.h b/include/win.h
index 42577afb3be17222a8f149da70f9907dbdc8387e..829e075f657573369108a48a4d2711554da7a6f9 100644
--- a/include/win.h
+++ b/include/win.h
@@ -24,7 +24,7 @@ typedef struct tagWND
 {
     struct tagWND *next;          /* Next sibling */
     struct tagWND *child;         /* First child */
-    struct tagWND *parent;        /* Window parent (from CreateWindow) */
+    HWND           parent;        /* Window parent */
     HWND           owner;         /* Window owner */
     struct tagCLASS *class;       /* Window class */
     HWINDOWPROC    winproc;       /* Window procedure */
diff --git a/windows/win.c b/windows/win.c
index 440bbdff292d9bf8e80035d1b4b5a675bdc98ca9..86fe6a51b299f5854ee51d707b22d81f13a28cd5 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -406,14 +406,16 @@ void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
     /* first unlink it if it is linked */
     if (wndPtr->parent)
     {
-        ppWnd = &wndPtr->parent->child;
+        WND *ptr = WIN_FindWndPtr( wndPtr->parent );
+        ppWnd = &ptr->child;
         while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
         if (*ppWnd) *ppWnd = wndPtr->next;
+        WIN_ReleaseWndPtr( ptr );
     }
 
     if (parentPtr)
     {
-        wndPtr->parent = parentPtr;
+        wndPtr->parent = parentPtr->hwndSelf;
         if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
         {
             ppWnd = &parentPtr->child;  /* Point to first sibling hwnd */
@@ -622,7 +624,7 @@ BOOL WIN_CreateDesktopWindow(void)
     pWndDesktop->tid               = 0;  /* nobody owns the desktop */
     pWndDesktop->next              = NULL;
     pWndDesktop->child             = NULL;
-    pWndDesktop->parent            = NULL;
+    pWndDesktop->parent            = 0;
     pWndDesktop->owner             = 0;
     pWndDesktop->class             = class;
     pWndDesktop->hInstance         = 0;
@@ -777,7 +779,16 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
             WARN("Bad parent %04x\n", cs->hwndParent );
 	    return 0;
 	}
-        if (cs->style & WS_CHILD) parent = cs->hwndParent;
+        if (cs->style & WS_CHILD)
+        {
+            parent = WIN_GetFullHandle(cs->hwndParent);
+            if (!WIN_IsCurrentProcess(parent))
+            {
+                FIXME( "creating child window of %x in other process not supported yet\n",
+                       parent );
+                return 0;
+            }
+        }
         else owner = GetAncestor( cs->hwndParent, GA_ROOT );
     }
     else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP))
@@ -831,9 +842,7 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
     wndPtr->next  = NULL;
     wndPtr->child = NULL;
     wndPtr->owner = owner;
-    wndPtr->parent = WIN_FindWndPtr( parent );
-    WIN_ReleaseWndPtr(wndPtr->parent);
-
+    wndPtr->parent         = parent;
     wndPtr->class          = classPtr;
     wndPtr->winproc        = winproc;
     wndPtr->hInstance      = cs->hInstance;
@@ -964,7 +973,7 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
     {
         /* Notify the parent window only */
 
-        SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
+        SendMessageA( wndPtr->parent, WM_PARENTNOTIFY,
                       MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
         if( !IsWindow(hwnd) )
         {
@@ -1262,8 +1271,8 @@ BOOL WINAPI DestroyWindow( HWND hwnd )
 	if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
 	{
 	    /* Notify the parent window only */
-	    SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
-			    MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
+            SendMessageA( wndPtr->parent, WM_PARENTNOTIFY,
+                          MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
             if( !IsWindow(hwnd) )
             {
                 retvalue = TRUE;
@@ -1292,7 +1301,7 @@ BOOL WINAPI DestroyWindow( HWND hwnd )
       for (;;)
       {
           int i, got_one = 0;
-          HWND *list = WIN_ListChildren( wndPtr->parent->hwndSelf );
+          HWND *list = WIN_ListChildren( wndPtr->parent );
           if (list)
           {
               for (i = 0; list[i]; i++)
@@ -2092,7 +2101,7 @@ HWND WINAPI GetParent( HWND hwnd )
     if ((wndPtr = WIN_FindWndPtr(hwnd)))
     {
         if (wndPtr->dwStyle & WS_CHILD)
-            retvalue = wndPtr->parent->hwndSelf;
+            retvalue = wndPtr->parent;
         else if (wndPtr->dwStyle & WS_POPUP)
             retvalue = wndPtr->owner;
         WIN_ReleaseWndPtr(wndPtr);
@@ -2107,34 +2116,42 @@ HWND WINAPI GetParent( HWND hwnd )
 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
 {
     HWND ret = 0;
-    WND *wndPtr;
+    size_t size = (type == GA_PARENT) ? sizeof(user_handle_t) : REQUEST_MAX_VAR_SIZE;
 
-    if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
-    if (wndPtr->hwndSelf == GetDesktopWindow()) goto done;
-
-    switch(type)
-    {
-    case GA_PARENT:
-        WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
-        break;
-    case GA_ROOT:
-        while (wndPtr->parent->hwndSelf != GetDesktopWindow())
-            WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
-        break;
-    case GA_ROOTOWNER:
-        while (wndPtr->parent->hwndSelf != GetDesktopWindow())
-            WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
-        while (wndPtr && wndPtr->owner)
+    SERVER_START_VAR_REQ( get_window_parents, size )
+    {
+        req->handle = hwnd;
+        if (!SERVER_CALL())
         {
-            WND *ptr = WIN_FindWndPtr( wndPtr->owner );
-            WIN_ReleaseWndPtr( wndPtr );
-            wndPtr = ptr;
+            user_handle_t *data = server_data_ptr(req);
+            int count = server_data_size(req) / sizeof(*data);
+            if (count)
+            {
+                switch(type)
+                {
+                case GA_PARENT:
+                    ret = data[0];
+                    break;
+                case GA_ROOT:
+                case GA_ROOTOWNER:
+                    if (count > 1) ret = data[count - 2];  /* get the one before the desktop */
+                    else ret = WIN_GetFullHandle( hwnd );
+                    break;
+                }
+            }
+        }
+    }
+    SERVER_END_VAR_REQ;
+
+    if (ret && type == GA_ROOTOWNER)
+    {
+        for (;;)
+        {
+            HWND owner = GetWindow( ret, GW_OWNER );
+            if (!owner) break;
+            ret = owner;
         }
-        break;
     }
-    ret = wndPtr ? wndPtr->hwndSelf : 0;
- done:
-    WIN_ReleaseWndPtr( wndPtr );
     return ret;
 }
 
@@ -2169,7 +2186,7 @@ HWND WINAPI SetParent( HWND hwnd, HWND parent )
      * including the WM_SHOWWINDOW messages and all */
     if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
 
-    retvalue = wndPtr->parent->hwndSelf;  /* old parent */
+    retvalue = wndPtr->parent;  /* old parent */
     if (parent != retvalue)
     {
         WIN_LinkWindow( hwnd, parent, HWND_TOP );
diff --git a/windows/winpos.c b/windows/winpos.c
index 285f5b5308ad211a7e8881aaaa2b117377d5c286..34522236bbebaf54efb9b9b0efd8cbd6d0ccf769 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -309,7 +309,7 @@ HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest )
     }
 
     if (wndScope->parent)
-        MapWindowPoints( GetDesktopWindow(), wndScope->parent->hwndSelf, &xy, 1 );
+        MapWindowPoints( GetDesktopWindow(), wndScope->parent, &xy, 1 );
 
     if (xy.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
         xy.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom ||
@@ -401,7 +401,7 @@ hittest:
 
         /* Restart the search from the next sibling */
         WIN_UpdateWndPtr(&wndPtr,wndTmp->next);
-        hwnd_ret = wndTmp->parent ? wndTmp->parent->hwndSelf : 0;
+        hwnd_ret = wndTmp->parent;
         WIN_ReleaseWndPtr( wndTmp );
     }
 
@@ -477,6 +477,8 @@ static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
                                  POINT *offset )
 {
     WND * wndPtr = 0;
+    HWND *list;
+    int i;
 
     offset->x = offset->y = 0;
     if (hwndFrom == hwndTo ) return;
@@ -489,11 +491,16 @@ static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
             ERR("bad hwndFrom = %04x\n",hwndFrom);
             return;
         }
-        while (wndPtr->parent)
+        if ((list = WIN_ListParents( hwndFrom )))
         {
-            offset->x += wndPtr->rectClient.left;
-            offset->y += wndPtr->rectClient.top;
-            WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
+            for (i = 0; list[i]; i++)
+            {
+                offset->x += wndPtr->rectClient.left;
+                offset->y += wndPtr->rectClient.top;
+                WIN_ReleaseWndPtr( wndPtr );
+                if (!(wndPtr = WIN_FindWndPtr( list[i] ))) break;
+            }
+            HeapFree( GetProcessHeap(), 0, list );
         }
         WIN_ReleaseWndPtr(wndPtr);
     }
@@ -506,12 +513,17 @@ static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
             ERR("bad hwndTo = %04x\n", hwndTo );
             return;
         }
-        while (wndPtr->parent)
+        if ((list = WIN_ListParents( hwndTo )))
         {
-            offset->x -= wndPtr->rectClient.left;
-            offset->y -= wndPtr->rectClient.top;
-            WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
-        }    
+            for (i = 0; list[i]; i++)
+            {
+                offset->x -= wndPtr->rectClient.left;
+                offset->y -= wndPtr->rectClient.top;
+                WIN_ReleaseWndPtr( wndPtr );
+                if (!(wndPtr = WIN_FindWndPtr( list[i] ))) break;
+            }
+            HeapFree( GetProcessHeap(), 0, list );
+        }
         WIN_ReleaseWndPtr(wndPtr);
     }
 }