Added WIN_ListParents function and renamed WIN_BuildWinArray into
WIN_ListChildren. Made owner field in WND structure an HWND.

diff --git a/controls/icontitle.c b/controls/icontitle.c
index 6b9dad4..03bb6da 100644
--- a/controls/icontitle.c
+++ b/controls/icontitle.c
@@ -58,12 +58,10 @@
     wndPtr = WIN_FindWndPtr( hWnd );
     if( wndPtr )
     {
-        WND *wnd = WIN_FindWndPtr(owner);
-	wndPtr->owner = wnd;	/* MDI depends on this */
+        wndPtr->owner = owner; /* MDI depends on this */
 	wndPtr->dwStyle &= ~(WS_CAPTION | WS_BORDER);
         if (!IsWindowEnabled(owner)) wndPtr->dwStyle |= WS_DISABLED;
         WIN_ReleaseWndPtr(wndPtr);
-        WIN_ReleaseWndPtr(wnd);
 	return hWnd;
     }
     return 0;
diff --git a/dlls/x11drv/window.c b/dlls/x11drv/window.c
index 4fb4408..1bb66ab 100644
--- a/dlls/x11drv/window.c
+++ b/dlls/x11drv/window.c
@@ -347,9 +347,9 @@
     /* transient for hint */
     if (win->owner)
     {
-        struct x11drv_win_data *owner_data = win->owner->pDriverData;
-        XSetTransientForHint( display, data->whole_window, owner_data->whole_window );
-        group_leader = owner_data->whole_window;
+        Window owner_win = X11DRV_get_whole_window( win->owner );
+        XSetTransientForHint( display, data->whole_window, owner_win );
+        group_leader = owner_win;
     }
     else group_leader = data->whole_window;
 
diff --git a/dlls/x11drv/winpos.c b/dlls/x11drv/winpos.c
index 81004a2..0bfbe3f 100644
--- a/dlls/x11drv/winpos.c
+++ b/dlls/x11drv/winpos.c
@@ -573,7 +573,7 @@
 
         if( hwndInsertAfter != HWND_TOP )
         {
-            if ((list = WIN_BuildWinArray( GetDesktopWindow() )))
+            if ((list = WIN_ListChildren( GetDesktopWindow() )))
             {
                 int i;
                 for (i = 0; list[i]; i++)
@@ -588,7 +588,7 @@
     }
     else if (style & WS_CHILD) return hwndInsertAfter;
 
-    if (!list) list = WIN_BuildWinArray( GetDesktopWindow() );
+    if (!list) list = WIN_ListChildren( GetDesktopWindow() );
     if (list)
     {
         int i;
@@ -604,7 +604,7 @@
                 hwndInsertAfter = list[i];
             }
         }
-        WIN_ReleaseWinArray( list );
+        HeapFree( GetProcessHeap(), 0, list );
     }
 
     return hwndInsertAfter;
diff --git a/include/win.h b/include/win.h
index 9d8ef27..63fe1ba 100644
--- a/include/win.h
+++ b/include/win.h
@@ -25,7 +25,7 @@
     struct tagWND *next;          /* Next sibling */
     struct tagWND *child;         /* First child */
     struct tagWND *parent;        /* Window parent (from CreateWindow) */
-    struct tagWND *owner;         /* Window owner */
+    HWND           owner;         /* Window owner */
     struct tagCLASS *class;       /* Window class */
     HWINDOWPROC    winproc;       /* Window procedure */
     DWORD          dwMagic;       /* Magic number (must be WND_MAGIC) */
@@ -92,8 +92,8 @@
 extern void WIN_DestroyThreadWindows( HWND hwnd );
 extern BOOL WIN_CreateDesktopWindow(void);
 extern BOOL WIN_IsWindowDrawable(WND*, BOOL );
-extern HWND *WIN_BuildWinArray( HWND hwnd );
-extern void WIN_ReleaseWinArray( HWND *wndArray );
+extern HWND *WIN_ListParents( HWND hwnd );
+extern HWND *WIN_ListChildren( HWND hwnd );
 extern BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly );
 
 extern HWND CARET_GetHwnd(void);
diff --git a/windows/dialog.c b/windows/dialog.c
index 985c230..ca15e7f 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -1609,14 +1609,14 @@
 HWND WINAPI GetDlgItem( HWND hwndDlg, INT id )
 {
     int i;
-    HWND *list = WIN_BuildWinArray( hwndDlg );
+    HWND *list = WIN_ListChildren( hwndDlg );
     HWND ret = 0;
 
     if (!list) return 0;
 
     for (i = 0; list[i]; i++) if (GetWindowLongW( list[i], GWL_ID ) == id) break;
     ret = list[i];
-    WIN_ReleaseWinArray( list );
+    HeapFree( GetProcessHeap(), 0, list );
     return ret;
 }
 
diff --git a/windows/mdi.c b/windows/mdi.c
index aea293a..e0fd58f 100644
--- a/windows/mdi.c
+++ b/windows/mdi.c
@@ -141,13 +141,13 @@
     HWND *win_array;
     int i;
 
-    if (!(win_array = WIN_BuildWinArray( hwnd ))) return 0;
+    if (!(win_array = WIN_ListChildren( hwnd ))) return 0;
     for (i = 0; win_array[i]; i++)
     {
         if (GetWindowLongA( win_array[i], GWL_ID ) == id) break;
     }
     ret = win_array[i];
-    WIN_ReleaseWinArray( win_array );
+    HeapFree( GetProcessHeap(), 0, win_array );
     return ret;
 }
 
@@ -282,7 +282,7 @@
     dwStyleMask |= WS_DISABLED | WS_VISIBLE;
     if( !hWnd ) hWnd = clientInfo->hwndActiveChild;
 
-    if (!(list = WIN_BuildWinArray( GetParent(hWnd) ))) return 0;
+    if (!(list = WIN_ListChildren( GetParent(hWnd) ))) return 0;
     i = 0;
     /* start from next after hWnd */
     while (list[i] && list[i] != hWnd) i++;
@@ -304,7 +304,7 @@
         if (bNext) goto found;
     }
  found:
-    WIN_ReleaseWinArray( list );
+    HeapFree( GetProcessHeap(), 0, list );
     return last;
 }
 
@@ -857,7 +857,7 @@
 
     if (ci->nActiveChildren == 0) return 0;
 
-    if (!(win_array = WIN_BuildWinArray( client ))) return 0;
+    if (!(win_array = WIN_ListChildren( client ))) return 0;
 
     /* remove all the windows we don't want */
     for (i = total = 0; win_array[i]; i++)
@@ -890,7 +890,7 @@
                           SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
         }
     }
-    WIN_ReleaseWinArray( win_array );
+    HeapFree( GetProcessHeap(), 0, win_array );
 
     if (has_icons) ArrangeIconicWindows( client );
     return 0;
@@ -910,7 +910,7 @@
 
     if (ci->nActiveChildren == 0) return;
 
-    if (!(win_array = WIN_BuildWinArray( client ))) return;
+    if (!(win_array = WIN_ListChildren( client ))) return;
 
     /* remove all the windows we don't want */
     for (i = total = 0; win_array[i]; i++)
@@ -975,7 +975,7 @@
             x += xsize;
         }
     }
-    WIN_ReleaseWinArray( win_array );
+    HeapFree( GetProcessHeap(), 0, win_array );
     if (has_icons) ArrangeIconicWindows( client );
 }
 
@@ -1948,7 +1948,7 @@
     GetClientRect( hwnd, &clientRect );
     SetRectEmpty( &childRect );
 
-    if ((list = WIN_BuildWinArray( hwnd )))
+    if ((list = WIN_ListChildren( hwnd )))
     {
         int i;
         for (i = 0; list[i]; i++)
@@ -1956,7 +1956,7 @@
             DWORD style = GetWindowLongW( list[i], GWL_STYLE );
             if (style & WS_MAXIMIZE)
             {
-                WIN_ReleaseWinArray( list );
+                HeapFree( GetProcessHeap(), 0, list );
                 ShowScrollBar( hwnd, SB_BOTH, FALSE );
                 return;
             }
@@ -1967,7 +1967,7 @@
                 WIN_ReleaseWndPtr( pWnd );
             }
         }
-        WIN_ReleaseWinArray( list );
+        HeapFree( GetProcessHeap(), 0, list );
     }
     UnionRect( &childRect, &clientRect, &childRect );
 
@@ -2145,11 +2145,11 @@
            HWND hListBox = GetDlgItem(hDlg, MDI_IDC_LISTBOX);
            HWND *list, *sorted_list;
 
-           if (!(list = WIN_BuildWinArray( (HWND)lParam ))) return TRUE;
+           if (!(list = WIN_ListChildren( (HWND)lParam ))) return TRUE;
            if (!(sorted_list = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
                                           sizeof(HWND) * ci->nActiveChildren )))
            {
-               WIN_ReleaseWinArray( list );
+               HeapFree( GetProcessHeap(), 0, list );
                return FALSE;
            }
 
@@ -2159,7 +2159,7 @@
                UINT id = GetWindowLongW( list[i], GWL_ID ) - ci->idFirstChild;
                if (id < ci->nActiveChildren) sorted_list[id] = list[i];
            }
-           WIN_ReleaseWinArray( list );
+           HeapFree( GetProcessHeap(), 0, list );
 
            for (i = 0; i < ci->nActiveChildren; i++)
            {
@@ -2260,13 +2260,13 @@
     HWND *list;
     int i;
 
-    if (!(list = WIN_BuildWinArray( parent ))) return;
+    if (!(list = WIN_ListChildren( parent ))) return;
     for (i = 0; list[i]; i++)
     {
         UINT id = GetWindowLongW( list[i], GWL_ID );
         if (id == pos1) SetWindowLongW( list[i], GWL_ID, pos2 );
         else if (id == pos2) SetWindowLongW( list[i], GWL_ID, pos1 );
     }
-    WIN_ReleaseWinArray( list );
+    HeapFree( GetProcessHeap(), 0, list );
 }
 
diff --git a/windows/painting.c b/windows/painting.c
index 7536d64..ffcd643 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -651,7 +651,7 @@
     if( flags & (RDW_INVALIDATE | RDW_VALIDATE) )
     {
         HWND *list;
-	if( hRgn > 1 && bChildren && (list = WIN_BuildWinArray( wndPtr->hwndSelf )))
+	if( hRgn > 1 && bChildren && (list = WIN_ListChildren( wndPtr->hwndSelf )))
 	{
 	    POINT ptTotal, prevOrigin = {0,0};
             POINT ptClient;
@@ -689,7 +689,7 @@
                 }
                 WIN_ReleaseWndPtr( wnd );
             }
-            WIN_ReleaseWinArray( list );
+            HeapFree( GetProcessHeap(), 0, list );
             OffsetRgn( hRgn, ptTotal.x, ptTotal.y );
             bChildren = 0;
 	}
@@ -700,7 +700,7 @@
     if( bChildren )
     {
         HWND *list;
-        if ((list = WIN_BuildWinArray( wndPtr->hwndSelf )))
+        if ((list = WIN_ListChildren( wndPtr->hwndSelf )))
         {
             INT i;
             for (i = 0; list[i]; i++)
@@ -711,7 +711,7 @@
                     RDW_UpdateRgns( wnd, hRgn, flags, FALSE );
                 WIN_ReleaseWndPtr( wnd );
             }
-            WIN_ReleaseWinArray( list );
+            HeapFree( GetProcessHeap(), 0, list );
         }
     }
 
@@ -820,7 +820,7 @@
     {
         HWND *list, *phwnd;
 
-	if( (list = WIN_BuildWinArray( wndPtr->hwndSelf )) )
+	if( (list = WIN_ListChildren( wndPtr->hwndSelf )) )
 	{
 	    for (phwnd = list; *phwnd; phwnd++)
 	    {
@@ -830,7 +830,7 @@
                     hrgn = RDW_Paint( wndPtr, hrgn, flags, ex );
                 WIN_ReleaseWndPtr(wndPtr);
 	    }
-	    WIN_ReleaseWinArray(list);
+            HeapFree( GetProcessHeap(), 0, list );
 	}
     }
 
diff --git a/windows/user.c b/windows/user.c
index 40b5c91..9380233 100644
--- a/windows/user.c
+++ b/windows/user.c
@@ -224,7 +224,7 @@
 
     /* We have to build a list of all windows first, as in EnumWindows */
 
-    if (!(list = WIN_BuildWinArray( GetDesktopWindow() ))) return FALSE;
+    if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
 
     /* Send a WM_QUERYENDSESSION message to every window */
 
@@ -243,7 +243,7 @@
         if (!IsWindow( *phwnd )) continue;
         SendMessageW( *phwnd, WM_ENDSESSION, result, 0 );
     }
-    WIN_ReleaseWinArray(list);
+    HeapFree( GetProcessHeap(), 0, list );
 
     if (result) ExitKernel16();
     return FALSE;
diff --git a/windows/win.c b/windows/win.c
index 544dddc..a8cc9ad 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -167,53 +167,6 @@
 
 }
 
-/***********************************************************************
- *           WIN_DumpWindow
- *
- * Dump the content of a window structure to stderr.
- */
-void WIN_DumpWindow( HWND hwnd )
-{
-    WND *ptr;
-    char className[80];
-    int i;
-
-    if (!(ptr = WIN_FindWndPtr( hwnd )))
-    {
-        WARN("%04x is not a window handle\n", hwnd );
-        return;
-    }
-
-    if (!GetClassNameA( hwnd, className, sizeof(className ) ))
-        strcpy( className, "#NULL#" );
-
-    TRACE("Window %04x (%p):\n", hwnd, ptr );
-    DPRINTF( "next=%p  child=%p  parent=%p  owner=%p  class=%p '%s'\n"
-             "inst=%04x  taskQ=%04x  updRgn=%04x  active=%04x dce=%p  idmenu=%08x\n"
-             "style=%08lx  exstyle=%08lx  wndproc=%08x  text='%s'\n"
-             "client=%d,%d-%d,%d  window=%d,%d-%d,%d"
-             "sysmenu=%04x  flags=%04x  props=%p  vscroll=%p  hscroll=%p\n",
-             ptr->next, ptr->child, ptr->parent, ptr->owner,
-             ptr->class, className, ptr->hInstance, ptr->hmemTaskQ,
-             ptr->hrgnUpdate, ptr->hwndLastActive, ptr->dce, ptr->wIDmenu,
-             ptr->dwStyle, ptr->dwExStyle, (UINT)ptr->winproc,
-             ptr->text ? debugstr_w(ptr->text) : "",
-             ptr->rectClient.left, ptr->rectClient.top, ptr->rectClient.right,
-             ptr->rectClient.bottom, ptr->rectWindow.left, ptr->rectWindow.top,
-             ptr->rectWindow.right, ptr->rectWindow.bottom, ptr->hSysMenu,
-             ptr->flags, ptr->pProp, ptr->pVScroll, ptr->pHScroll );
-
-    if (ptr->cbWndExtra)
-    {
-        DPRINTF( "extra bytes:" );
-        for (i = 0; i < ptr->cbWndExtra; i++)
-            DPRINTF( " %02x", *((BYTE*)ptr->wExtra+i) );
-        DPRINTF( "\n" );
-    }
-    DPRINTF( "\n" );
-    WIN_ReleaseWndPtr(ptr);
-}
-
 
 /***********************************************************************
  *           WIN_UnlinkWindow
@@ -428,7 +381,7 @@
     HWND *list;
     int i;
 
-    if (!(list = WIN_BuildWinArray( hwnd ))) return;
+    if (!(list = WIN_ListChildren( hwnd ))) return;
     for (i = 0; list[i]; i++)
     {
         if (!IsWindow( list[i] )) continue;
@@ -437,7 +390,7 @@
         else
             WIN_DestroyThreadWindows( list[i] );
     }
-    WIN_ReleaseWinArray( list );
+    HeapFree( GetProcessHeap(), 0, list );
 }
 
 /***********************************************************************
@@ -470,7 +423,7 @@
     pWndDesktop->next              = NULL;
     pWndDesktop->child             = NULL;
     pWndDesktop->parent            = NULL;
-    pWndDesktop->owner             = NULL;
+    pWndDesktop->owner             = 0;
     pWndDesktop->class             = class;
     pWndDesktop->dwMagic           = WND_MAGIC;
     pWndDesktop->hwndSelf          = hwndDesktop;
@@ -675,19 +628,16 @@
     if ((cs->style & WS_CHILD) && cs->hwndParent)
     {
         wndPtr->parent = WIN_FindWndPtr( cs->hwndParent );
-        wndPtr->owner  = NULL;
+        wndPtr->owner  = 0;
         WIN_ReleaseWndPtr(wndPtr->parent);
     }
     else
     {
         wndPtr->parent = pWndDesktop;
         if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf))
-            wndPtr->owner = NULL;
+            wndPtr->owner = 0;
         else
-        {
-            wndPtr->owner = WIN_FindWndPtr( GetAncestor( cs->hwndParent, GA_ROOT ));
-            WIN_ReleaseWndPtr(wndPtr->owner);
-	}
+            wndPtr->owner = GetAncestor( cs->hwndParent, GA_ROOT );
     }
     
 
@@ -1062,7 +1012,7 @@
         HWND* pWndArray;
         int i;
 
-        if (!(pWndArray = WIN_BuildWinArray( hwnd ))) return;
+        if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
 
         /* start from the end (FIXME: is this needed?) */
         for (i = 0; pWndArray[i]; i++) ;
@@ -1071,7 +1021,7 @@
         {
             if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
         }
-        WIN_ReleaseWinArray( pWndArray );
+        HeapFree( GetProcessHeap(), 0, pWndArray );
     }
     else
       WARN("\tdestroyed itself while in WM_DESTROY!\n");
@@ -1158,31 +1108,40 @@
     {
       for (;;)
       {
-        WND *siblingPtr = WIN_LockWndPtr(wndPtr->parent->child);  /* First sibling */
-        while (siblingPtr)
-        {
-            if (siblingPtr->owner == wndPtr)
-	    {
-               if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
-                   break;
-               else 
-                   siblingPtr->owner = NULL;
-	    }
-            WIN_UpdateWndPtr(&siblingPtr,siblingPtr->next);
-        }
-        if (siblingPtr)
-        {
-            DestroyWindow( siblingPtr->hwndSelf );
-            WIN_ReleaseWndPtr(siblingPtr);
-        }
-        else break;
+          int i, got_one = 0;
+          HWND *list = WIN_ListChildren( wndPtr->parent->hwndSelf );
+          if (list)
+          {
+              for (i = 0; list[i]; i++)
+              {
+                  WND *siblingPtr = WIN_FindWndPtr( list[i] );
+                  if (!siblingPtr) continue;
+                  if (siblingPtr->owner == hwnd)
+                  {
+                      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;
       }
 
       WINPOS_ActivateOtherWindow(wndPtr->hwndSelf);
 
-      if( wndPtr->owner &&
-	  wndPtr->owner->hwndLastActive == wndPtr->hwndSelf )
-	  wndPtr->owner->hwndLastActive = wndPtr->owner->hwndSelf;
+      if (wndPtr->owner)
+      {
+          WND *owner = WIN_FindWndPtr( wndPtr->owner );
+          if (owner->hwndLastActive == hwnd) owner->hwndLastActive = wndPtr->owner;
+          WIN_ReleaseWndPtr( owner );
+      }
     }
 
       /* Send destroy messages */
@@ -1278,7 +1237,7 @@
         if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
     }
 
-    if (!(list = WIN_BuildWinArray( parent )))
+    if (!(list = WIN_ListChildren( parent )))
     {
         if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
         return 0;
@@ -1301,7 +1260,7 @@
         if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
     }
     retvalue = list[i];
-    WIN_ReleaseWinArray( list );
+    HeapFree( GetProcessHeap(), 0, list );
     if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
 
     /* In this case we need to check whether other processes
@@ -2046,19 +2005,16 @@
 {
     WND *wndPtr;
     HWND retvalue = 0;
-    
-    if(!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
-    if ((!(wndPtr->dwStyle & (WS_POPUP|WS_CHILD))))
-	goto end;
 
-    WIN_UpdateWndPtr(&wndPtr,((wndPtr->dwStyle & WS_CHILD) ? wndPtr->parent : wndPtr->owner));
-    if (wndPtr)
-        retvalue = wndPtr->hwndSelf;
-
-end:
-    WIN_ReleaseWndPtr(wndPtr);
+    if ((wndPtr = WIN_FindWndPtr(hwnd)))
+    {
+        if (wndPtr->dwStyle & WS_CHILD)
+            retvalue = wndPtr->parent->hwndSelf;
+        else if (wndPtr->dwStyle & WS_POPUP)
+            retvalue = wndPtr->owner;
+        WIN_ReleaseWndPtr(wndPtr);
+    }
     return retvalue;
-    
 }
 
 
@@ -2087,7 +2043,11 @@
         while (wndPtr->parent->hwndSelf != GetDesktopWindow())
             WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
         while (wndPtr->owner)
-            WIN_UpdateWndPtr( &wndPtr, wndPtr->owner );
+        {
+            WND *ptr = WIN_FindWndPtr( wndPtr->owner );
+            WIN_ReleaseWndPtr( wndPtr );
+            wndPtr = ptr;
+        }
         break;
     }
     ret = wndPtr->hwndSelf;
@@ -2189,19 +2149,15 @@
  */
 BOOL WINAPI IsChild( HWND parent, HWND child )
 {
-    WND * wndPtr = WIN_FindWndPtr( child );
-    while (wndPtr && wndPtr->parent)
-    {
-        WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
-        if (wndPtr->hwndSelf == GetDesktopWindow()) break;
-        if (wndPtr->hwndSelf == parent)
-        {
-            WIN_ReleaseWndPtr(wndPtr);
-            return TRUE;
-        }
-    }
-    WIN_ReleaseWndPtr(wndPtr);
-    return FALSE;
+    HWND *list = WIN_ListParents( child );
+    int i;
+    BOOL ret;
+
+    if (!list) return FALSE;
+    for (i = 0; list[i]; i++) if (list[i] == parent) break;
+    ret = (list[i] != 0);
+    HeapFree( GetProcessHeap(), 0, list );
+    return ret;
 }
 
 
@@ -2219,19 +2175,16 @@
  */
 BOOL WINAPI IsWindowVisible( HWND hwnd )
 {
+    HWND *list;
     BOOL retval;
-    WND *wndPtr = WIN_FindWndPtr( hwnd );
-    while (wndPtr && wndPtr->parent)
-    {
-        if (!(wndPtr->dwStyle & WS_VISIBLE))
-    {
-            WIN_ReleaseWndPtr(wndPtr);
-            return FALSE;
-        }
-        WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
-    }
-    retval = (wndPtr && (wndPtr->dwStyle & WS_VISIBLE));
-    WIN_ReleaseWndPtr(wndPtr);
+    int i;
+
+    if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
+    if (!(list = WIN_ListParents( hwnd ))) return TRUE;
+    for (i = 0; list[i]; i++)
+        if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
+    retval = !list[i];
+    HeapFree( GetProcessHeap(), 0, list );
     return retval;
 }
 
@@ -2245,13 +2198,21 @@
  */
 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
 {
-  if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
-  if ((wnd->dwStyle & WS_MINIMIZE) &&
-       icon && GetClassLongA( wnd->hwndSelf, GCL_HICON ))  return FALSE;
-  for(wnd = wnd->parent; wnd; wnd = wnd->parent)
-    if( wnd->dwStyle & WS_MINIMIZE ||
-      !(wnd->dwStyle & WS_VISIBLE) ) break;
-  return (wnd == NULL);
+    HWND *list;
+    BOOL retval;
+    int i;
+
+    if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
+    if ((wnd->dwStyle & WS_MINIMIZE) &&
+        icon && GetClassLongA( wnd->hwndSelf, GCL_HICON ))  return FALSE;
+
+    if (!(list = WIN_ListParents( wnd->hwndSelf ))) return TRUE;
+    for (i = 0; list[i]; i++)
+        if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
+            break;
+    retval = !list[i];
+    HeapFree( GetProcessHeap(), 0, list );
+    return retval;
 }
 
 
@@ -2340,7 +2301,7 @@
         goto end;
 	
     case GW_OWNER:
-        retval = wndPtr->owner ? wndPtr->owner->hwndSelf : 0;
+        retval = wndPtr->owner;
         goto end;
 
     case GW_CHILD:
@@ -2378,7 +2339,7 @@
 {
     int count = 0;
     WND *pWnd;
-    HWND *win_array = WIN_BuildWinArray( GetDesktopWindow() );
+    HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
 
     if (!win_array) return TRUE;
 
@@ -2422,7 +2383,7 @@
         }
         WIN_ReleaseWndPtr( pWnd );
     }
-    WIN_ReleaseWinArray( win_array );
+    HeapFree( GetProcessHeap(), 0, win_array );
 
     return TRUE;
 }
@@ -2443,7 +2404,7 @@
 {
     int count = 0;
     WND *pWnd;
-    HWND *win_array = WIN_BuildWinArray(GetDesktopWindow());
+    HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
 
     if (!win_array) return TRUE;
 
@@ -2482,7 +2443,7 @@
         }
         WIN_ReleaseWndPtr( pWnd );
     }
-    WIN_ReleaseWinArray( win_array );
+    HeapFree( GetProcessHeap(), 0, win_array );
     return TRUE;
 }
 
@@ -2512,15 +2473,56 @@
 
 
 /*******************************************************************
- *           WIN_BuildWinArray
+ *           WIN_ListParents
  *
- * Build an array of pointers to the children of a given window.
- * The array must be freed with WIN_ReleaseWinArray. Return NULL
- * when no windows are found.
+ * Build an array of all parents of a given window, starting with
+ * the immediate parent. The array must be freed with HeapFree.
+ * Returns NULL if window is a top-level window.
  */
-HWND *WIN_BuildWinArray( HWND hwnd )
+HWND *WIN_ListParents( HWND hwnd )
 {
-    /* Future: this function will lock all windows associated with this array */
+    WND *parent, *wndPtr = WIN_FindWndPtr( hwnd );
+    HWND *list = NULL;
+    UINT i, count = 0;
+
+    /* First count the windows */
+
+    if (!wndPtr) return NULL;
+
+    parent = wndPtr->parent;
+    while (parent && parent->hwndSelf != GetDesktopWindow())
+    {
+        count++;
+        parent = parent->parent;
+    }
+
+    if (count)
+    {
+        if ((list = HeapAlloc( GetProcessHeap(), 0, sizeof(HWND) * (count + 1) )))
+        {
+            parent = wndPtr->parent;
+            for (i = 0; i < count; i++)
+            {
+                list[i] = parent->hwndSelf;
+                parent = parent->parent;
+            }
+            list[i] = 0;
+        }
+    }
+
+    WIN_ReleaseWndPtr( wndPtr );
+    return list;
+}
+
+
+/*******************************************************************
+ *           WIN_ListChildren
+ *
+ * Build an array of the children of a given window. The array must be
+ * freed with HeapFree. Returns NULL when no windows are found.
+ */
+HWND *WIN_ListChildren( HWND hwnd )
+{
     WND *pWnd, *wndPtr = WIN_FindWndPtr( hwnd );
     HWND *list, *phwnd;
     UINT count = 0;
@@ -2557,13 +2559,6 @@
     return list;
 }
 
-/*******************************************************************
- *           WIN_ReleaseWinArray
- */
-void WIN_ReleaseWinArray(HWND *wndArray)
-{
-    if (wndArray) HeapFree( GetProcessHeap(), 0, wndArray );
-}
 
 /*******************************************************************
  *		EnumWindows (USER32.@)
@@ -2578,7 +2573,7 @@
     /* unpleasant side-effects, for instance if the callback */
     /* function changes the Z-order of the windows.          */
 
-    if (!(list = WIN_BuildWinArray( GetDesktopWindow() ))) return FALSE;
+    if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
 
     /* Now call the callback function for every window */
 
@@ -2590,7 +2585,7 @@
         if (!(ret = lpEnumFunc( list[i], lParam ))) break;
     }
     WIN_RestoreWndsLock(iWndsLocks);
-    WIN_ReleaseWinArray(list);
+    HeapFree( GetProcessHeap(), 0, list );
     return ret;
 }
 
@@ -2615,7 +2610,7 @@
     HWND *list;
     int i, iWndsLocks;
 
-    if (!(list = WIN_BuildWinArray( GetDesktopWindow() ))) return FALSE;
+    if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
 
     /* Now call the callback function for every window */
 
@@ -2626,7 +2621,7 @@
         if (!func( list[i], lParam )) break;
     }
     WIN_RestoreWndsLock(iWndsLocks);
-    WIN_ReleaseWinArray(list);
+    HeapFree( GetProcessHeap(), 0, list );
     return TRUE;
 }
 
@@ -2648,14 +2643,14 @@
         /* skip owned windows */
         if (GetWindow( *list, GW_OWNER )) continue;
         /* Build children list first */
-        childList = WIN_BuildWinArray( *list );
+        childList = WIN_ListChildren( *list );
 
         ret = func( *list, lParam );
 
         if (childList)
         {
             if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
-            WIN_ReleaseWinArray(childList);
+            HeapFree( GetProcessHeap(), 0, childList );
         }
         if (!ret) return FALSE;
     }
@@ -2671,11 +2666,11 @@
     HWND *list;
     int iWndsLocks;
 
-    if (!(list = WIN_BuildWinArray( parent ))) return FALSE;
+    if (!(list = WIN_ListChildren( parent ))) return FALSE;
     iWndsLocks = WIN_SuspendWndsLock();
     WIN_EnumChildWindows( list, func, lParam );
     WIN_RestoreWndsLock(iWndsLocks);
-    WIN_ReleaseWinArray(list);
+    HeapFree( GetProcessHeap(), 0, list );
     return TRUE;
 }
 
@@ -2696,7 +2691,7 @@
 {
     int i;
     BOOL retvalue;
-    HWND *list = WIN_BuildWinArray( GetDesktopWindow() );
+    HWND *list = WIN_ListChildren( GetDesktopWindow() );
 
     if (!list) return FALSE;
     for (i = 0; list[i]; i++)
@@ -2704,7 +2699,7 @@
         if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
     }
     retvalue = (list[i] != 0);
-    WIN_ReleaseWinArray( list );
+    HeapFree( GetProcessHeap(), 0, list );
     return retvalue;
 }
 
diff --git a/windows/winpos.c b/windows/winpos.c
index ed7843e..8a9be5e 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -553,7 +553,7 @@
 
     GetClientRect( hwndParent, &rect );
     if (!PtInRect( &rect, pt )) return 0;
-    if (!(list = WIN_BuildWinArray( hwndParent ))) return 0;
+    if (!(list = WIN_ListChildren( hwndParent ))) return 0;
 
     for (i = 0; list[i] && !retvalue; i++)
     {
@@ -571,7 +571,7 @@
         }
         WIN_ReleaseWndPtr( wnd );
     }
-    WIN_ReleaseWinArray( list );
+    HeapFree( GetProcessHeap(), 0, list );
     if (!retvalue) retvalue = hwndParent;
     return retvalue;
 }
@@ -1523,7 +1523,7 @@
         DWORD old_thread = GetWindowThreadProcessId( hwndPrevActive, NULL );
         DWORD new_thread = GetWindowThreadProcessId( hwndActive, NULL );
 
-        if ((list = WIN_BuildWinArray( GetDesktopWindow() )))
+        if ((list = WIN_ListChildren( GetDesktopWindow() )))
         {
             for (phwnd = list; *phwnd; phwnd++)
             {
@@ -1531,12 +1531,12 @@
                 if (GetWindowThreadProcessId( *phwnd, NULL ) == old_thread)
                     SendMessageW( *phwnd, WM_ACTIVATEAPP, 0, new_thread );
             }
-            WIN_ReleaseWinArray(list);
+            HeapFree( GetProcessHeap(), 0, list );
         }
 
 	hActiveQueue = hNewActiveQueue;
 
-        if ((list = WIN_BuildWinArray( GetDesktopWindow() )))
+        if ((list = WIN_ListChildren( GetDesktopWindow() )))
         {
             for (phwnd = list; *phwnd; phwnd++)
             {
@@ -1544,7 +1544,7 @@
                 if (GetWindowThreadProcessId( *phwnd, NULL ) == new_thread)
                     SendMessageW( *phwnd, WM_ACTIVATEAPP, 1, old_thread );
             }
-            WIN_ReleaseWinArray(list);
+            HeapFree( GetProcessHeap(), 0, list );
         }
         
 	if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
@@ -1625,6 +1625,7 @@
     WND *pWnd;
     HWND hwndActive = 0;
     HWND hwndTo = 0;
+    HWND owner;
 
     /* Get current active window from the active queue */
     if ( hActiveQueue )
@@ -1648,10 +1649,11 @@
         return 0;
     }
 
-    if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
-        !WINPOS_CanActivate((hwndTo = GetAncestor( pWnd->owner->hwndSelf, GA_ROOT ))) )
+    owner = GetWindow( hwnd, GW_OWNER );
+    if( !(pWnd->dwStyle & WS_POPUP) || !owner ||
+        !WINPOS_CanActivate((hwndTo = GetAncestor( owner, GA_ROOT ))) )
     {
-        HWND tmp = GetAncestor( pWnd->hwndSelf, GA_ROOT );
+        HWND tmp = GetAncestor( hwnd, GA_ROOT );
         hwndTo = hwndPrevActive;
 
         while( !WINPOS_CanActivate(hwndTo) )