Implemented GetAncestor and removed WIN_GetTopParent.
Removed a few more accesses to the WND structure.

diff --git a/windows/dce.c b/windows/dce.c
index b7bb024..d206458 100644
--- a/windows/dce.c
+++ b/windows/dce.c
@@ -143,7 +143,7 @@
  *
  * Remove owned DCE and reset unreleased cache DCEs.
  */
-void DCE_FreeWindowDCE( WND* pWnd )
+void DCE_FreeWindowDCE( HWND hwnd )
 {
     DCE *pDCE;
 
@@ -152,14 +152,16 @@
 
     while( pDCE )
     {
-	if( pDCE->hwndCurrent == pWnd->hwndSelf )
+	if( pDCE->hwndCurrent == hwnd )
 	{
+            WND *pWnd = WIN_FindWndPtr( hwnd );
 	    if( pDCE == pWnd->dce ) /* owned or Class DCE*/
 	    {
                 if (pWnd->clsStyle & CS_OWNDC)	/* owned DCE*/
 		{
                     pDCE = DCE_FreeDCE( pDCE );
                     pWnd->dce = NULL;
+                    WIN_ReleaseWndPtr( pWnd );
                     continue;
                 }
 		else if( pDCE->DCXflags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN) )	/* Class DCE*/
@@ -188,6 +190,7 @@
 		pDCE->DCXflags |= DCX_DCEEMPTY;
 		pDCE->hwndCurrent = 0;
 	    }
+            WIN_ReleaseWndPtr( pWnd );
 	}
 	pDCE = pDCE->next;
     }
@@ -257,17 +260,17 @@
  * an ancestor and whose client rect intersects with specified update
  * rectangle. In addition, pWnd->parent DCEs may need to be updated if
  * DCX_CLIPCHILDREN flag is set.  */
-BOOL DCE_InvalidateDCE(WND* pWnd, const RECT* pRectUpdate)
+BOOL DCE_InvalidateDCE(HWND hwnd, const RECT* pRectUpdate)
 {
-    WND* wndScope = WIN_LockWndPtr(pWnd->parent);
+    HWND hwndScope = GetAncestor( hwnd, GA_PARENT );
     BOOL bRet = FALSE;
 
-    if( wndScope )
+    if( hwndScope )
     {
 	DCE *dce;
 
 	TRACE("scope hwnd = %04x, (%i,%i - %i,%i)\n",
-		     wndScope->hwndSelf, pRectUpdate->left,pRectUpdate->top,
+		     hwndScope, pRectUpdate->left,pRectUpdate->top,
 		     pRectUpdate->right,pRectUpdate->bottom);
 	if(TRACE_ON(dc)) 
 	  DCE_DumpCache();
@@ -276,72 +279,66 @@
 
 	for (dce = firstDCE; (dce); dce = dce->next)
 	{
-	    if( !(dce->DCXflags & DCX_DCEEMPTY) )
-	    {
-		WND* wndCurrent = WIN_FindWndPtr(dce->hwndCurrent);
+            WND* wndCurrent;
+            HWND tmp;
+            INT xoffset = 0, yoffset = 0;
 
-		if( wndCurrent )
-		{
-		    WND* wnd = NULL;
-		    INT xoffset = 0, yoffset = 0;
+            if (dce->DCXflags & DCX_DCEEMPTY) continue;
+            if ((dce->hwndCurrent == hwndScope) && !(dce->DCXflags & DCX_CLIPCHILDREN))
+                continue;  /* child window positions don't bother us */
+            if (!(wndCurrent = WIN_FindWndPtr(dce->hwndCurrent))) continue;
 
-                    if( (wndCurrent == wndScope) && !(dce->DCXflags & DCX_CLIPCHILDREN) )
-                    {
-			/* child window positions don't bother us */
-                        WIN_ReleaseWndPtr(wndCurrent);
-                        continue;
+            /* check if DCE window is within the z-order scope */
+
+            for (tmp = dce->hwndCurrent; tmp; tmp = GetAncestor( tmp, GA_PARENT ))
+            {
+                if (tmp == hwndScope )
+                {
+                    RECT wndRect;
+
+                    wndRect = wndCurrent->rectWindow;
+
+                    OffsetRect( &wndRect, xoffset - wndCurrent->rectClient.left, 
+                                yoffset - wndCurrent->rectClient.top);
+
+                    if (hwnd == wndCurrent->hwndSelf ||
+                        IntersectRect( &wndRect, &wndRect, pRectUpdate ))
+                    { 
+                        if( !(dce->DCXflags & DCX_DCEBUSY) )
+                        {
+                            /* Don't bother with visible regions of unused DCEs */
+
+                            TRACE("\tpurged %08x dce [%04x]\n", 
+                                  (unsigned)dce, wndCurrent->hwndSelf);
+
+                            dce->hwndCurrent = 0;
+                            dce->DCXflags &= DCX_CACHE;
+                            dce->DCXflags |= DCX_DCEEMPTY;
+                        }
+                        else
+                        {
+                            /* Set dirty bits in the hDC and DCE structs */
+
+                            TRACE("\tfixed up %08x dce [%04x]\n", 
+                                  (unsigned)dce, wndCurrent->hwndSelf);
+
+                            dce->DCXflags |= DCX_DCEDIRTY;
+                            SetHookFlags16(dce->hDC, DCHF_INVALIDATEVISRGN);
+                            bRet = TRUE;
+                        }
                     }
-
-		    /* check if DCE window is within the z-order scope */
-
-		    for( wnd = WIN_LockWndPtr(wndCurrent); wnd; WIN_UpdateWndPtr(&wnd,wnd->parent))
-		    {
-			if( wnd == wndScope )
-		 	{
-			    RECT wndRect;
-
-			    wndRect = wndCurrent->rectWindow;
-
-			    OffsetRect( &wndRect, xoffset - wndCurrent->rectClient.left, 
-						    yoffset - wndCurrent->rectClient.top);
-
-			    if (pWnd == wndCurrent ||
-				IntersectRect( &wndRect, &wndRect, pRectUpdate ))
-			    { 
-				if( !(dce->DCXflags & DCX_DCEBUSY) )
-				{
-				    /* Don't bother with visible regions of unused DCEs */
-
-				    TRACE("\tpurged %08x dce [%04x]\n", 
-						(unsigned)dce, wndCurrent->hwndSelf);
-
-				    dce->hwndCurrent = 0;
-				    dce->DCXflags &= DCX_CACHE;
-				    dce->DCXflags |= DCX_DCEEMPTY;
-				}
-				else
-				{
-				    /* Set dirty bits in the hDC and DCE structs */
-
-				    TRACE("\tfixed up %08x dce [%04x]\n", 
-						(unsigned)dce, wndCurrent->hwndSelf);
-
-				    dce->DCXflags |= DCX_DCEDIRTY;
-				    SetHookFlags16(dce->hDC, DCHF_INVALIDATEVISRGN);
-				    bRet = TRUE;
-				}
-			    }
-                            WIN_ReleaseWndPtr(wnd);
-			    break;
-			}
-			xoffset += wnd->rectClient.left;
-			yoffset += wnd->rectClient.top;
-		    }
-		}
-                WIN_ReleaseWndPtr(wndCurrent);
-	    }
+                    break;
+                }
+                else
+                {
+                    WND* wnd = WIN_FindWndPtr( tmp );
+                    xoffset += wnd->rectClient.left;
+                    yoffset += wnd->rectClient.top;
+                    WIN_ReleaseWndPtr( wnd );
+                }
+            }
+            WIN_ReleaseWndPtr(wndCurrent);
 	} /* dce list */
-        WIN_ReleaseWndPtr(wndScope);
     }
     return bRet;
 }
@@ -353,24 +350,22 @@
  *  Translate given region from the wnd client to the DC coordinates
  *  and add it to the clipping region.
  */
-INT DCE_ExcludeRgn( HDC hDC, WND* wnd, HRGN hRgn )
+INT DCE_ExcludeRgn( HDC hDC, HWND hwnd, HRGN hRgn )
 {
   POINT  pt = {0, 0};
   DCE     *dce = firstDCE;
 
   while (dce && (dce->hDC != hDC)) dce = dce->next;
-  if( dce )
+  if (!dce) return ERROR;
+
+  MapWindowPoints( hwnd, dce->hwndCurrent, &pt, 1);
+  if( dce->DCXflags & DCX_WINDOW )
   {
-      MapWindowPoints( wnd->hwndSelf, dce->hwndCurrent, &pt, 1);
-      if( dce->DCXflags & DCX_WINDOW )
-      { 
-	  wnd = WIN_FindWndPtr(dce->hwndCurrent);
-	  pt.x += wnd->rectClient.left - wnd->rectWindow.left;
-	  pt.y += wnd->rectClient.top - wnd->rectWindow.top;
-          WIN_ReleaseWndPtr(wnd);
-      }
+      WND *wnd = WIN_FindWndPtr(dce->hwndCurrent);
+      pt.x += wnd->rectClient.left - wnd->rectWindow.left;
+      pt.y += wnd->rectClient.top - wnd->rectWindow.top;
+      WIN_ReleaseWndPtr(wnd);
   }
-  else return ERROR;
   OffsetRgn(hRgn, pt.x, pt.y);
 
   return ExtSelectClipRgn( hDC, hRgn, RGN_DIFF );
@@ -401,6 +396,7 @@
     DWORD 	dcxFlags = 0;
     BOOL	bUpdateVisRgn = TRUE;
     BOOL	bUpdateClipOrigin = FALSE;
+    HWND parent;
 
     TRACE("hwnd %04x, hrgnClip %04x, flags %08x\n", 
           hwnd, hrgnClip, (unsigned)flags);
@@ -431,7 +427,8 @@
 
     if (flags & DCX_WINDOW) flags &= ~DCX_CLIPCHILDREN;
 
-    if (!wndPtr->parent || (wndPtr->parent->hwndSelf == GetDesktopWindow()))
+    parent = GetAncestor( hwnd, GA_PARENT );
+    if (!parent || (parent == GetDesktopWindow()))
         flags = (flags & ~DCX_PARENTCLIP) | DCX_CLIPSIBLINGS;
 
     /* it seems parent clip is ignored when clipping siblings or children */
@@ -439,11 +436,11 @@
 
     if( flags & DCX_PARENTCLIP )
     {
-        if( (wndPtr->dwStyle & WS_VISIBLE) && (wndPtr->parent->dwStyle & WS_VISIBLE) )
+        LONG parent_style = GetWindowLongW( parent, GWL_STYLE );
+        if( (wndPtr->dwStyle & WS_VISIBLE) && (parent_style & WS_VISIBLE) )
         {
             flags &= ~DCX_CLIPCHILDREN;
-            if( wndPtr->parent->dwStyle & WS_CLIPSIBLINGS )
-                flags |= DCX_CLIPSIBLINGS;
+            if (parent_style & WS_CLIPSIBLINGS) flags |= DCX_CLIPSIBLINGS;
         }
     }
 
diff --git a/windows/defwnd.c b/windows/defwnd.c
index 6b60957..f15d43e 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -162,14 +162,14 @@
     WND *wndPtr = WIN_FindWndPtr( hwnd );
     BOOL bVisible = wndPtr->dwStyle & WS_VISIBLE;
 
-    TRACE("%04x %i\n", wndPtr->hwndSelf, (wParam!=0) );
+    TRACE("%04x %i\n", hwnd, (wParam!=0) );
 
     if( wParam )
     {
 	if( !bVisible )
 	{
 	    wndPtr->dwStyle |= WS_VISIBLE;
-	    DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow );
+            DCE_InvalidateDCE( hwnd, &wndPtr->rectWindow );
 	}
     }
     else if( bVisible )
@@ -177,8 +177,8 @@
 	if( wndPtr->dwStyle & WS_MINIMIZE ) wParam = RDW_VALIDATE;
 	else wParam = RDW_ALLCHILDREN | RDW_VALIDATE;
 
-	RedrawWindow( wndPtr->hwndSelf, NULL, 0, wParam );
-	DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow );
+        RedrawWindow( hwnd, NULL, 0, wParam );
+        DCE_InvalidateDCE( hwnd, &wndPtr->rectWindow );
 	wndPtr->dwStyle &= ~WS_VISIBLE;
     }
     WIN_ReleaseWndPtr( wndPtr );
@@ -520,7 +520,7 @@
 
 	    if( wParam == VK_F4 )	/* try to close the window */
 	    {
-                HWND top = WIN_GetTopParent( hwnd );
+                HWND top = GetAncestor( hwnd, GA_ROOT );
                 if (!(GetClassLongW( top, GCL_STYLE ) & CS_NOCLOSE))
                     PostMessageW( top, WM_SYSCOMMAND, SC_CLOSE, 0 );
 	    }
@@ -537,7 +537,7 @@
 	/* Press and release F10 or ALT */
 	if (((wParam == VK_MENU) && iMenuSysKey) ||
             ((wParam == VK_F10) && iF10Key))
-              SendMessageW( WIN_GetTopParent(hwnd), WM_SYSCOMMAND, SC_KEYMENU, 0L );
+              SendMessageW( GetAncestor( hwnd, GA_ROOT ), WM_SYSCOMMAND, SC_KEYMENU, 0L );
 	iMenuSysKey = iF10Key = 0;
         break;
 
diff --git a/windows/dialog.c b/windows/dialog.c
index 7b863e6..985c230 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -100,14 +100,13 @@
  * Helper function for modal dialogs to enable again the
  * owner of the dialog box.
  */
-void DIALOG_EnableOwner( HWND hOwner, BOOL ownerWasEnabled)
+void DIALOG_EnableOwner( HWND hOwner )
 {
     /* Owner must be a top-level window */
     if (hOwner)
-        hOwner = WIN_GetTopParent( hOwner );
+        hOwner = GetAncestor( hOwner, GA_ROOT );
     if (!hOwner) return;
-    if (ownerWasEnabled)
-        EnableWindow( hOwner, TRUE );
+    EnableWindow( hOwner, TRUE );
 }
 
 
@@ -121,7 +120,7 @@
 {
     /* Owner must be a top-level window */
     if (hOwner)
-        hOwner = WIN_GetTopParent( hOwner );
+        hOwner = GetAncestor( hOwner, GA_ROOT );
     if (!hOwner) return FALSE;
     if (IsWindowEnabled( hOwner ))
     {
@@ -841,8 +840,7 @@
     {
 	if (hFont) DeleteObject( hFont );
 	if (hMenu) DestroyMenu( hMenu );
-        if (modal)
-            DIALOG_EnableOwner(owner, ownerEnabled);
+        if (modal && ownerEnabled) DIALOG_EnableOwner(owner);
 	return 0;
     }
     wndPtr = WIN_FindWndPtr( hwnd );
@@ -904,8 +902,7 @@
     }
     WIN_ReleaseWndPtr(wndPtr);
     if( IsWindow(hwnd) ) DestroyWindow( hwnd );
-    if (modal)
-        DIALOG_EnableOwner(owner, ownerEnabled);
+    if (modal && ownerEnabled) DIALOG_EnableOwner(owner);
     return 0;
 }
 
@@ -1044,7 +1041,7 @@
     DIALOGINFO * dlgInfo;
     MSG msg;
     INT retval;
-    HWND ownerMsg = WIN_GetTopParent( owner );
+    HWND ownerMsg = GetAncestor( owner, GA_ROOT );
 
     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return -1;
     dlgInfo = (DIALOGINFO *)wndPtr->wExtra;
@@ -1075,7 +1072,7 @@
             if (dlgInfo->flags & DF_END) break;
         }
     }
-    DIALOG_EnableOwner( owner, (dlgInfo->flags & DF_OWNERENABLED) );
+    if (dlgInfo->flags & DF_OWNERENABLED) DIALOG_EnableOwner( owner );
     retval = dlgInfo->idResult; 
     WIN_ReleaseWndPtr(wndPtr);
     DestroyWindow( hwnd );
@@ -1242,6 +1239,7 @@
     WND * wndPtr = WIN_FindWndPtr( hwnd );
     BOOL wasEnabled = TRUE;
     DIALOGINFO * dlgInfo;
+    HWND owner;
 
     TRACE("%04x %d\n", hwnd, retval );
 
@@ -1257,14 +1255,15 @@
         dlgInfo->flags |= DF_END;
         wasEnabled = (dlgInfo->flags & DF_OWNERENABLED);
     }
+    WIN_ReleaseWndPtr(wndPtr);
 
-    if(wndPtr->owner)
-       DIALOG_EnableOwner( wndPtr->owner->hwndSelf, wasEnabled );
- 
+    if (wasEnabled && (owner = GetWindow( hwnd, GW_OWNER )))
+        DIALOG_EnableOwner( owner );
+
     /* Windows sets the focus to the dialog itself in EndDialog */
 
     if (IsChild(hwnd, GetFocus()))
-       SetFocus(wndPtr->hwndSelf);
+       SetFocus( hwnd );
 
     /* Don't have to send a ShowWindow(SW_HIDE), just do
        SetWindowPos with SWP_HIDEWINDOW as done in Windows */
@@ -1272,7 +1271,6 @@
     SetWindowPos(hwnd, (HWND)0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE
                  | SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW);
 
-    WIN_ReleaseWndPtr(wndPtr);
     /* unblock dialog loop */
     PostMessageA(hwnd, WM_NULL, 0, 0); 
     return TRUE;
@@ -1286,89 +1284,76 @@
 {
     HWND hwndControl = hwnd;
     HWND hwndNext;
-    WND *wndPtr;
-    BOOL RetVal = FALSE;
     INT dlgCode;
+    WCHAR buffer[128];
 
-        do
+    do
+    {
+        DWORD style = GetWindowLongW( hwndControl, GWL_STYLE );
+        if ((style & (WS_VISIBLE | WS_DISABLED)) == WS_VISIBLE)
         {
-            wndPtr = WIN_FindWndPtr( hwndControl );
-            if ( (wndPtr != NULL) && 
-                 ((wndPtr->dwStyle & (WS_VISIBLE | WS_DISABLED)) == WS_VISIBLE) )
+            dlgCode = SendMessageA( hwndControl, WM_GETDLGCODE, 0, 0 );
+            if ( (dlgCode & (DLGC_BUTTON | DLGC_STATIC)) &&
+                 GetWindowTextW( hwndControl, buffer, sizeof(buffer)/sizeof(WCHAR) ))
             {
-                dlgCode = SendMessageA( hwndControl, WM_GETDLGCODE, 0, 0 );
-                if ( (dlgCode & (DLGC_BUTTON | DLGC_STATIC)) && 
-                     (wndPtr->text!=NULL))
+                /* find the accelerator key */
+                LPWSTR p = buffer - 2;
+                char a_char = vKey;
+                WCHAR w_char = 0;
+
+                do
                 {
-                    /* find the accelerator key */
-                    LPWSTR p = wndPtr->text - 2;
-		    char a_char = vKey;
-		    WCHAR w_char = 0;
-
-                    do
-                    {
-                        p = strchrW( p + 2, '&' );
-                    }
-                    while (p != NULL && p[1] == '&');
-
-                    /* and check if it's the one we're looking for */
-		    MultiByteToWideChar(CP_ACP, 0, &a_char, 1, &w_char, 1);
-                    if (p != NULL && toupperW( p[1] ) == toupperW( w_char ) )
-                    {
-                        if ((dlgCode & DLGC_STATIC) || 
-                            (wndPtr->dwStyle & 0x0f) == BS_GROUPBOX )
-                        {
-                            /* set focus to the control */
-                            SendMessageA( hwndDlg, WM_NEXTDLGCTL,
-                                    hwndControl, 1);
-                            /* and bump it on to next */
-                            SendMessageA( hwndDlg, WM_NEXTDLGCTL, 0, 0);
-                        }
-                        else if (dlgCode & DLGC_BUTTON)
-                        {
-                            /* send BM_CLICK message to the control */
-                            SendMessageA( hwndControl, BM_CLICK, 0, 0 );
-                        }
-
-                        RetVal = TRUE;
-			WIN_ReleaseWndPtr(wndPtr);
-                        break;
-                    }
+                    p = strchrW( p + 2, '&' );
                 }
-		hwndNext = GetWindow( hwndControl, GW_CHILD );
-            }
-	    else
-	    {
-		hwndNext = 0;
-	    }
-            WIN_ReleaseWndPtr(wndPtr);
-	    if (!hwndNext)
-	    {
-	        hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
-	    }
-	    while (!hwndNext && hwndControl)
-	    {
-		hwndControl = GetParent( hwndControl );
-		if (hwndControl == hwndDlg)
-		{
-		    if(hwnd==hwndDlg){  /* prevent endless loop */
-		        hwndNext=hwnd;
-			break;
-		    }
-		    hwndNext = GetWindow( hwndDlg, GW_CHILD );
-		}
-		else
-		{
-		    hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
-		}
-	    }
-            hwndControl = hwndNext;
-        }
-        while (hwndControl && (hwndControl != hwnd));
+                while (p != NULL && p[1] == '&');
 
-    return RetVal;
+                /* and check if it's the one we're looking for */
+                MultiByteToWideChar(CP_ACP, 0, &a_char, 1, &w_char, 1);
+                if (p != NULL && toupperW( p[1] ) == toupperW( w_char ) )
+                {
+                    if ((dlgCode & DLGC_STATIC) || (style & 0x0f) == BS_GROUPBOX )
+                    {
+                        /* set focus to the control */
+                        SendMessageA( hwndDlg, WM_NEXTDLGCTL, hwndControl, 1);
+                        /* and bump it on to next */
+                        SendMessageA( hwndDlg, WM_NEXTDLGCTL, 0, 0);
+                    }
+                    else if (dlgCode & DLGC_BUTTON)
+                    {
+                        /* send BM_CLICK message to the control */
+                        SendMessageA( hwndControl, BM_CLICK, 0, 0 );
+                    }
+                    return TRUE;
+                }
+            }
+            hwndNext = GetWindow( hwndControl, GW_CHILD );
+        }
+        else hwndNext = 0;
+
+        if (!hwndNext) hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
+
+        while (!hwndNext && hwndControl)
+        {
+            hwndControl = GetParent( hwndControl );
+            if (hwndControl == hwndDlg)
+            {
+                if(hwnd==hwndDlg)   /* prevent endless loop */
+                {
+                    hwndNext=hwnd;
+                    break;
+                }
+                hwndNext = GetWindow( hwndDlg, GW_CHILD );
+            }
+            else
+                hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
+        }
+        hwndControl = hwndNext;
+    }
+    while (hwndControl && (hwndControl != hwnd));
+
+    return FALSE;
 }
- 
+
 /***********************************************************************
  *           DIALOG_FindMsgDestination
  *
@@ -1596,47 +1581,25 @@
  */
 INT16 WINAPI GetDlgCtrlID16( HWND16 hwnd )
 {
-    WND *wndPtr = WIN_FindWndPtr(hwnd);
-    INT16 retvalue;
-    
-    if (!wndPtr) return 0;
-
-    retvalue = wndPtr->wIDmenu;
-    WIN_ReleaseWndPtr(wndPtr);
-    return retvalue;
+    return GetDlgCtrlID( hwnd );
 }
- 
+
 
 /***********************************************************************
  *		GetDlgCtrlID (USER32.@)
  */
 INT WINAPI GetDlgCtrlID( HWND hwnd )
 {
-    INT retvalue;
-    WND *wndPtr = WIN_FindWndPtr(hwnd);
-    if (!wndPtr) return 0;
-    retvalue = wndPtr->wIDmenu;
-    WIN_ReleaseWndPtr(wndPtr);
-    return retvalue;
+    return GetWindowLongW( hwnd, GWL_ID );
 }
- 
+
 
 /***********************************************************************
  *		GetDlgItem (USER.91)
  */
 HWND16 WINAPI GetDlgItem16( HWND16 hwndDlg, INT16 id )
 {
-    WND *pWnd;
-
-    if (!(pWnd = WIN_FindWndPtr( hwndDlg ))) return 0;
-    for (WIN_UpdateWndPtr(&pWnd,pWnd->child); pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
-        if (pWnd->wIDmenu == (UINT16)id)
-        {
-            HWND16 retvalue = pWnd->hwndSelf;
-            WIN_ReleaseWndPtr(pWnd);
-            return retvalue;
-        }
-    return 0;
+    return GetDlgItem( hwndDlg, id );
 }
 
 
@@ -1645,17 +1608,16 @@
  */
 HWND WINAPI GetDlgItem( HWND hwndDlg, INT id )
 {
-    WND *pWnd;
+    int i;
+    HWND *list = WIN_BuildWinArray( hwndDlg );
+    HWND ret = 0;
 
-    if (!(pWnd = WIN_FindWndPtr( hwndDlg ))) return 0;
-    for (WIN_UpdateWndPtr(&pWnd,pWnd->child); pWnd;WIN_UpdateWndPtr(&pWnd,pWnd->next))
-        if (pWnd->wIDmenu == (UINT16)id)
-        {
-            HWND retvalue = pWnd->hwndSelf;
-            WIN_ReleaseWndPtr(pWnd);
-            return retvalue;
-        }
-    return 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 );
+    return ret;
 }
 
 
@@ -1989,11 +1951,7 @@
 HWND WINAPI GetNextDlgGroupItem( HWND hwndDlg, HWND hwndCtrl,
                                      BOOL fPrevious )
 {
-    WND *pWnd = NULL,
-        *pWndLast = NULL,
-        *pWndCtrl = NULL,
-        *pWndDlg = NULL;
-    HWND retvalue;
+    HWND hwnd, retvalue;
 
     if(hwndCtrl)
     {
@@ -2003,71 +1961,44 @@
             hwndDlg = GetParent(hwndCtrl);
     }
 
-    if (!(pWndDlg = WIN_FindWndPtr( hwndDlg ))) return 0;
     if (hwndCtrl)
     {
-        if (!(pWndCtrl = WIN_FindWndPtr( hwndCtrl )))
-    {
-            retvalue = 0;
-            goto END;
-        }
         /* Make sure hwndCtrl is a top-level child */
-        while (pWndCtrl->parent && (pWndCtrl->parent != pWndDlg))
-            WIN_UpdateWndPtr(&pWndCtrl,pWndCtrl->parent);
-        if (pWndCtrl->parent != pWndDlg)
-        {
-            retvalue = 0;
-            goto END;
-        }
+        HWND parent = GetParent( hwndCtrl );
+        while (parent && parent != hwndDlg) parent = GetParent(parent);
+        if (parent != hwndDlg) return 0;
     }
     else
     {
         /* No ctrl specified -> start from the beginning */
-        if (!(pWndCtrl = WIN_LockWndPtr(pWndDlg->child)))
-        {
-            retvalue = 0;
-            goto END;
-        }
-        if (fPrevious)
-            while (pWndCtrl->next) WIN_UpdateWndPtr(&pWndCtrl,pWndCtrl->next);
+        if (!(hwndCtrl = GetWindow( hwndDlg, GW_CHILD ))) return 0;
+        if (fPrevious) hwndCtrl = GetWindow( hwndCtrl, GW_HWNDLAST );
     }
 
-    pWndLast = WIN_LockWndPtr(pWndCtrl);
-    pWnd = WIN_LockWndPtr(pWndCtrl->next);
-
+    retvalue = hwndCtrl;
+    hwnd = GetWindow( hwndCtrl, GW_HWNDNEXT );
     while (1)
     {
-        if (!pWnd || (pWnd->dwStyle & WS_GROUP))
+        if (!hwnd || (GetWindowLongW( hwnd, GWL_STYLE ) & WS_GROUP))
         {
             /* Wrap-around to the beginning of the group */
-            WND *pWndTemp;
+            HWND tmp;
 
-            WIN_UpdateWndPtr( &pWnd, pWndDlg->child );
-            for ( pWndTemp = WIN_LockWndPtr( pWnd ); 
-                  pWndTemp;
-                  WIN_UpdateWndPtr( &pWndTemp, pWndTemp->next) )
+            hwnd = GetWindow( hwndDlg, GW_CHILD );
+            for (tmp = hwnd; tmp; tmp = GetWindow( tmp, GW_HWNDNEXT ) )
             {
-                if (pWndTemp->dwStyle & WS_GROUP) WIN_UpdateWndPtr( &pWnd, pWndTemp );
-                if (pWndTemp == pWndCtrl) break;
+                if (GetWindowLongW( tmp, GWL_STYLE ) & WS_GROUP) hwnd = tmp;
+                if (tmp == hwndCtrl) break;
             }
-            WIN_ReleaseWndPtr( pWndTemp );
         }
-        if (pWnd == pWndCtrl) break;
-	if ((pWnd->dwStyle & WS_VISIBLE) && !(pWnd->dwStyle & WS_DISABLED))
-	{
-            WIN_UpdateWndPtr(&pWndLast,pWnd);
+        if (hwnd == hwndCtrl) break;
+        if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_VISIBLE|WS_DISABLED)) == WS_VISIBLE)
+        {
+            retvalue = hwnd;
 	    if (!fPrevious) break;
 	}
-        WIN_UpdateWndPtr(&pWnd,pWnd->next);
+        hwnd = GetWindow( hwnd, GW_HWNDNEXT );
     }
-    retvalue = pWndLast->hwndSelf;
-
-    WIN_ReleaseWndPtr(pWndLast);
-    WIN_ReleaseWndPtr(pWnd);
-END:
-    WIN_ReleaseWndPtr(pWndCtrl);
-    WIN_ReleaseWndPtr(pWndDlg);
-
     return retvalue;
 }
 
diff --git a/windows/focus.c b/windows/focus.c
index 4820429..57582d5 100644
--- a/windows/focus.c
+++ b/windows/focus.c
@@ -59,39 +59,40 @@
 HWND WINAPI SetFocus( HWND hwnd )
 {
     HWND hWndFocus = 0, hwndTop = hwnd;
-    WND *wndPtr = WIN_FindWndPtr( hwnd );
     MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
-    BOOL16 bRet = 0;
+    BOOL bRet = 0;
 
     /* Get the messageQ for the current thread */
     if (!(pCurMsgQ = QUEUE_Current()))
     {
         WARN("\tCurrent message queue not found. Exiting!\n" );
-        goto CLEANUP;
+        return 0;
     }
 
-    if (wndPtr)
+    if (hwnd)
     {
-	  /* Check if we can set the focus to this window */
+        /* Check if we can set the focus to this window */
+        WND *wndPtr;
 
-	while ( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD  )
-	{
-	    if ( wndPtr->dwStyle & ( WS_MINIMIZE | WS_DISABLED) )
-		 goto CLEANUP;
-            WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
-            if (!wndPtr) goto CLEANUP;
-	    hwndTop = wndPtr->hwndSelf;
-	}
+        for (;;)
+        {
+            HWND parent;
+            LONG style = GetWindowLongW( hwndTop, GWL_STYLE );
+            if (style & (WS_MINIMIZE | WS_DISABLED)) return 0;
+            parent = GetAncestor( hwndTop, GA_PARENT );
+            if (!parent || parent == GetDesktopWindow()) break;
+            hwndTop = parent;
+        }
 
-        /* definitely at the top window now */
-        if ( wndPtr->dwStyle & ( WS_MINIMIZE | WS_DISABLED) ) goto CLEANUP;
+        if (!(wndPtr = WIN_FindWndPtr( hwndTop ))) return 0;
 
         /* Retrieve the message queue associated with this window */
         pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
+        WIN_ReleaseWndPtr( wndPtr );
         if ( !pMsgQ )
         {
             WARN("\tMessage queue not found. Exiting!\n" );
-            goto CLEANUP;
+            return 0;
         }
 
         /* Make sure that message queue for the window we are setting focus to
@@ -133,7 +134,7 @@
     else /* NULL hwnd passed in */
     {
         if( HOOK_CallHooksA( WH_CBT, HCBT_SETFOCUS, 0, (LPARAM)hWndFocus ) )
-            goto CLEANUP;
+            return 0;
 
         /* Get the current focus from the perQ data of the current message Q */
         hWndFocus = PERQDATA_GetFocusWnd( pCurMsgQ->pQData );
@@ -150,7 +151,6 @@
     if ( pMsgQ )
         QUEUE_Unlock( pMsgQ );
 
-    WIN_ReleaseWndPtr(wndPtr);
     return bRet ? hWndFocus : 0;
 }
 
diff --git a/windows/mdi.c b/windows/mdi.c
index feb2430..aea293a 100644
--- a/windows/mdi.c
+++ b/windows/mdi.c
@@ -193,25 +193,24 @@
 /**********************************************************************
  *			MDI_MenuModifyItem
  */
-static BOOL MDI_MenuModifyItem( HWND client, HWND hWndChild )
+static void MDI_MenuModifyItem( HWND client, HWND hWndChild )
 {
-    static const WCHAR format[] = {'%','d',' ',0};
-
     MDICLIENTINFO *clientInfo = get_client_info( client );
     WCHAR buffer[128];
     UINT n, id;
-    BOOL bRet;
 
-    if (!clientInfo || !clientInfo->hWindowMenu) return FALSE;
+    if (!clientInfo || !clientInfo->hWindowMenu) return;
 
     id = GetWindowLongA( hWndChild, GWL_ID );
-    n = wsprintfW(buffer, format, id - clientInfo->idFirstChild + 1);
-    GetWindowTextW( hWndChild, buffer + n, sizeof(buffer)/sizeof(WCHAR) - n );
+    if (id >= clientInfo->idFirstChild + MDI_MOREWINDOWSLIMIT) return;
+    buffer[0] = '&';
+    buffer[1] = '1' + id - clientInfo->idFirstChild;
+    buffer[2] = ' ';
+    GetWindowTextW( hWndChild, buffer + 3, sizeof(buffer)/sizeof(WCHAR) - 3 );
 
-    n    = GetMenuState(clientInfo->hWindowMenu, id, MF_BYCOMMAND);
-    bRet = ModifyMenuW(clientInfo->hWindowMenu, id, MF_BYCOMMAND | MF_STRING, id, buffer );
+    n = GetMenuState(clientInfo->hWindowMenu, id, MF_BYCOMMAND);
+    ModifyMenuW(clientInfo->hWindowMenu, id, MF_BYCOMMAND | MF_STRING, id, buffer );
     CheckMenuItem(clientInfo->hWindowMenu, id, n & MF_CHECKED);
-    return bRet;
 }
 
 /**********************************************************************
@@ -276,28 +275,37 @@
 static HWND MDI_GetWindow(MDICLIENTINFO *clientInfo, HWND hWnd, BOOL bNext,
                             DWORD dwStyleMask )
 {
-    WND *wndPtr, *pWnd, *pWndLast = NULL;
-    
+    int i;
+    HWND *list;
+    HWND last = 0;
+
     dwStyleMask |= WS_DISABLED | WS_VISIBLE;
     if( !hWnd ) hWnd = clientInfo->hwndActiveChild;
 
-    if( !(wndPtr = WIN_FindWndPtr(hWnd)) ) return 0;
+    if (!(list = WIN_BuildWinArray( GetParent(hWnd) ))) return 0;
+    i = 0;
+    /* start from next after hWnd */
+    while (list[i] && list[i] != hWnd) i++;
+    if (list[i]) i++;
 
-    for ( pWnd = WIN_LockWndPtr(wndPtr->next); ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
+    for ( ; list[i]; i++)
     {
-        if (!pWnd ) WIN_UpdateWndPtr(&pWnd,wndPtr->parent->child);
-
-        if ( pWnd == wndPtr ) break; /* went full circle */
-
-        if (!pWnd->owner && (pWnd->dwStyle & dwStyleMask) == WS_VISIBLE )
-        {
-	    pWndLast = pWnd;
-	    if ( bNext ) break;
-        }
+        if (GetWindow( list[i], GW_OWNER )) continue;
+        if ((GetWindowLongW( list[i], GWL_STYLE ) & dwStyleMask) != WS_VISIBLE) continue;
+        last = list[i];
+        if (bNext) goto found;
     }
-    WIN_ReleaseWndPtr(wndPtr);
-    WIN_ReleaseWndPtr(pWnd);
-    return pWndLast ? pWndLast->hwndSelf : 0;
+    /* now restart from the beginning */
+    for (i = 0; list[i] && list[i] != hWnd; i++)
+    {
+        if (GetWindow( list[i], GW_OWNER )) continue;
+        if ((GetWindowLongW( list[i], GWL_STYLE ) & dwStyleMask) != WS_VISIBLE) continue;
+        last = list[i];
+        if (bNext) goto found;
+    }
+ found:
+    WIN_ReleaseWinArray( list );
+    return last;
 }
 
 /**********************************************************************
@@ -775,7 +783,9 @@
         /* The window to be activated must be displayed in the "Windows" menu */
         if (id >= clientInfo->idFirstChild + MDI_MOREWINDOWSLIMIT)
         {
-            MDI_SwapMenuItems( GetParent(child), id, clientInfo->idFirstChild + MDI_MOREWINDOWSLIMIT - 1);
+            MDI_SwapMenuItems( GetParent(child),
+                               id, clientInfo->idFirstChild + MDI_MOREWINDOWSLIMIT - 1);
+            id = clientInfo->idFirstChild + MDI_MOREWINDOWSLIMIT - 1;
             MDI_MenuModifyItem( GetParent(child), child );
         }
 
@@ -1129,7 +1139,7 @@
     WCHAR   lpBuffer[MDI_MAXTITLELENGTH+1];
     MDICLIENTINFO *ci = get_client_info( hClient );
 
-    TRACE("repaint %i, frameText %s\n", repaint, (lpTitle)?debugstr_w(lpTitle):"NULL");
+    TRACE("repaint %i, frameText %s\n", repaint, debugstr_w(lpTitle));
 
     if (!ci) return;
 
@@ -1149,42 +1159,30 @@
 
     if (ci->frameTitle)
     {
-	WND* childWnd = WIN_FindWndPtr( ci->hwndChildMaximized );     
-
-	if( childWnd && childWnd->text )
+	if (ci->hwndChildMaximized)
 	{
 	    /* combine frame title and child title if possible */
 
 	    static const WCHAR lpBracket[]  = {' ','-',' ','[',0};
 	    static const WCHAR lpBracket2[]  = {']',0};
 	    int	i_frame_text_length = strlenW(ci->frameTitle);
-	    int	i_child_text_length = strlenW(childWnd->text);
 
 	    lstrcpynW( lpBuffer, ci->frameTitle, MDI_MAXTITLELENGTH);
 
 	    if( i_frame_text_length + 6 < MDI_MAXTITLELENGTH )
             {
 		strcatW( lpBuffer, lpBracket );
-
-		if( i_frame_text_length + i_child_text_length + 6 < MDI_MAXTITLELENGTH )
-		{
-		    strcatW( lpBuffer, childWnd->text );
-		    strcatW( lpBuffer, lpBracket2 );
-		}
-		else
-		{
-		    lstrcpynW( lpBuffer + i_frame_text_length + 4, 
-				 childWnd->text, MDI_MAXTITLELENGTH - i_frame_text_length - 5 );
-		    strcatW( lpBuffer, lpBracket2 );
-		}
-	    }
+                if (GetWindowTextW( ci->hwndChildMaximized, lpBuffer + i_frame_text_length + 4,
+                                    MDI_MAXTITLELENGTH - i_frame_text_length - 5 ))
+                    strcatW( lpBuffer, lpBracket2 );
+                else
+                    lpBuffer[i_frame_text_length] = 0;  /* remove bracket */
+            }
 	}
 	else
 	{
             lstrcpynW(lpBuffer, ci->frameTitle, MDI_MAXTITLELENGTH+1 );
 	}
-        WIN_ReleaseWndPtr(childWnd);
-
     }
     else
 	lpBuffer[0] = '\0';
@@ -1514,7 +1512,7 @@
                     HWND childHwnd;
                     if (id - ci->idFirstChild == MDI_MOREWINDOWSLIMIT)
                         /* User chose "More Windows..." */
-                        childHwnd = MDI_MoreWindowsDialog(hwnd);
+                        childHwnd = MDI_MoreWindowsDialog(hwndMDIClient);
                     else
                         /* User chose one of the windows listed in the "Windows" menu */
                         childHwnd = MDI_GetChildByID(hwndMDIClient,id);
@@ -1945,24 +1943,32 @@
     SCROLLINFO info;
     RECT childRect, clientRect;
     INT  vmin, vmax, hmin, hmax, vpos, hpos;
-    WND *pWnd;
+    HWND *list;
 
-    if (!(pWnd = WIN_FindWndPtr( hwnd ))) return;
     GetClientRect( hwnd, &clientRect );
     SetRectEmpty( &childRect );
 
-    for ( WIN_UpdateWndPtr(&pWnd,pWnd->child); pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next))
+    if ((list = WIN_BuildWinArray( hwnd )))
     {
-	  if( pWnd->dwStyle & WS_MAXIMIZE )
-	  {
-              WIN_ReleaseWndPtr(pWnd);
-	      ShowScrollBar(hwnd, SB_BOTH, FALSE);
-	      return;
-	  }
-          if( pWnd->dwStyle & WS_VISIBLE )
-              UnionRect( &childRect, &pWnd->rectWindow, &childRect );
-    } 
-    WIN_ReleaseWndPtr(pWnd);
+        int i;
+        for (i = 0; list[i]; i++)
+        {
+            DWORD style = GetWindowLongW( list[i], GWL_STYLE );
+            if (style & WS_MAXIMIZE)
+            {
+                WIN_ReleaseWinArray( list );
+                ShowScrollBar( hwnd, SB_BOTH, FALSE );
+                return;
+            }
+            if (style & WS_VISIBLE)
+            {
+                WND *pWnd = WIN_FindWndPtr( list[i] );
+                UnionRect( &childRect, &pWnd->rectWindow, &childRect );
+                WIN_ReleaseWndPtr( pWnd );
+            }
+        }
+        WIN_ReleaseWinArray( list );
+    }
     UnionRect( &childRect, &clientRect, &childRect );
 
     hmin = childRect.left;
@@ -2132,28 +2138,38 @@
     {
        case WM_INITDIALOG:
        {
-           WND  *pWnd;
            UINT widest       = 0;
            UINT length;
            UINT i;
-           WND  *pParentWnd  = (WND *)WIN_FindWndPtr(lParam);
-           MDICLIENTINFO *ci = (MDICLIENTINFO*)pParentWnd->wExtra;
+           MDICLIENTINFO *ci = get_client_info( (HWND)lParam );
            HWND hListBox = GetDlgItem(hDlg, MDI_IDC_LISTBOX);
+           HWND *list, *sorted_list;
+
+           if (!(list = WIN_BuildWinArray( (HWND)lParam ))) return TRUE;
+           if (!(sorted_list = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+                                          sizeof(HWND) * ci->nActiveChildren )))
+           {
+               WIN_ReleaseWinArray( list );
+               return FALSE;
+           }
 
            /* Fill the list, sorted by id... */
+           for (i = 0; list[i]; i++)
+           {
+               UINT id = GetWindowLongW( list[i], GWL_ID ) - ci->idFirstChild;
+               if (id < ci->nActiveChildren) sorted_list[id] = list[i];
+           }
+           WIN_ReleaseWinArray( list );
+
            for (i = 0; i < ci->nActiveChildren; i++)
            {
+               WCHAR buffer[128];
 
-               /* Find the window with the current ID */
-               for (pWnd = WIN_LockWndPtr(pParentWnd->child); pWnd; WIN_UpdateWndPtr(&pWnd, pWnd->next))
-                   if (pWnd->wIDmenu == ci->idFirstChild + i)
-                       break;
-
-               SendMessageW(hListBox, LB_ADDSTRING, 0, (LPARAM) pWnd->text);
-               SendMessageW(hListBox, LB_SETITEMDATA, i, (LPARAM) pWnd);
-               length = strlenW(pWnd->text);
-               WIN_ReleaseWndPtr(pWnd);
-
+               if (!GetWindowTextW( sorted_list[i], buffer, sizeof(buffer)/sizeof(WCHAR) ))
+                   continue;
+               SendMessageW(hListBox, LB_ADDSTRING, 0, (LPARAM)buffer );
+               SendMessageW(hListBox, LB_SETITEMDATA, i, (LPARAM)sorted_list[i] );
+               length = strlenW(buffer);  /* FIXME: should use GetTextExtentPoint */
                if (length > widest)
                    widest = length;
            }
@@ -2168,6 +2184,9 @@
        case WM_COMMAND:
            switch (LOWORD(wParam))
            {
+                default:
+                    if (HIWORD(wParam) != LBN_DBLCLK) break;
+                    /* fall through */
                 case IDOK:
                 {
                     /*  windows are sorted by menu ID, so we must return the
@@ -2175,32 +2194,14 @@
                      */
                     HWND hListBox     = GetDlgItem(hDlg, MDI_IDC_LISTBOX);
                     UINT index        = SendMessageW(hListBox, LB_GETCURSEL, 0, 0);
-                    WND *pWnd         = (WND *)SendMessageW(hListBox, LB_GETITEMDATA, index, 0);
+                    HWND hwnd         = SendMessageW(hListBox, LB_GETITEMDATA, index, 0);
 
-                    EndDialog(hDlg, pWnd->hwndSelf);
+                    EndDialog(hDlg, hwnd);
                     return TRUE;
                 }
                 case IDCANCEL:
                     EndDialog(hDlg, 0);
                     return TRUE;
-
-                default:
-                    switch (HIWORD(wParam))
-                    {
-                        case LBN_DBLCLK:
-                        {
-                            /*  windows are sorted by menu ID, so we must return the
-                             *  window associated to the given id
-                             */
-                            HWND hListBox     = GetDlgItem(hDlg, MDI_IDC_LISTBOX);
-                            UINT index        = SendMessageW(hListBox, LB_GETCURSEL, 0, 0);
-                            WND *pWnd         = (WND *)SendMessageW(hListBox, LB_GETITEMDATA, index, 0);
-
-                            EndDialog(hDlg, pWnd->hwndSelf);
-                            return TRUE;
-                        }
-                    }
-                    break;
            }
            break;
     }
@@ -2256,17 +2257,16 @@
 
 static void MDI_SwapMenuItems(HWND parent, UINT pos1, UINT pos2)
 {
-    WND *pWnd;
+    HWND *list;
+    int i;
 
-    pWnd = WIN_FindWndPtr( GetWindow( parent, GW_CHILD ) );
-    while (pWnd)
+    if (!(list = WIN_BuildWinArray( parent ))) return;
+    for (i = 0; list[i]; i++)
     {
-        if (pWnd->wIDmenu == pos1)
-            pWnd->wIDmenu = pos2;
-        else
-            if (pWnd->wIDmenu == pos2)
-                pWnd->wIDmenu = pos1;
-        WIN_UpdateWndPtr(&pWnd,pWnd->next);
+        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 );
 }
 
diff --git a/windows/message.c b/windows/message.c
index 99a276c..2134854 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -433,7 +433,7 @@
         (raw_message == WM_RBUTTONDOWN) ||
         (raw_message == WM_MBUTTONDOWN))
     {
-        HWND hwndTop = WIN_GetTopParent( msg->hwnd );
+        HWND hwndTop = GetAncestor( msg->hwnd, GA_ROOT );
 
         /* Send the WM_PARENTNOTIFY,
          * note that even for double/nonclient clicks
diff --git a/windows/nonclient.c b/windows/nonclient.c
index 65a3f2e..172e122 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -1787,7 +1787,7 @@
         NC_GetInsideRect( hwnd, rect );
         OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
         if (wndPtr->dwStyle & WS_CHILD)
-            ClientToScreen( wndPtr->parent->hwndSelf, (POINT *)rect );
+            ClientToScreen( GetParent(hwnd), (POINT *)rect );
         if (TWEAK_WineLook == WIN31_LOOK) {
             rect->right = rect->left + GetSystemMetrics(SM_CXSIZE);
             rect->bottom = rect->top + GetSystemMetrics(SM_CYSIZE);
@@ -2065,7 +2065,7 @@
     {
     case HTCAPTION:
         {
-            HWND top = WIN_GetTopParent(hwnd);
+            HWND top = GetAncestor( hwnd, GA_ROOT );
 
             if( WINPOS_SetActiveWindow(top, TRUE, TRUE) || (GetActiveWindow() == top) )
                 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
@@ -2187,8 +2187,11 @@
 
     TRACE("Handling WM_SYSCOMMAND %x %ld,%ld\n", wParam, pt.x, pt.y );
 
-    if (wndPtr->parent && (uCommand != SC_KEYMENU))
-        ScreenToClient( wndPtr->parent->hwndSelf, &pt );
+    if (uCommand != SC_KEYMENU)
+    {
+        HWND parent = GetAncestor( hwnd, GA_PARENT );
+        if (parent != GetDesktopWindow()) ScreenToClient( parent, &pt );
+    }
 
     switch (uCommand)
     {
diff --git a/windows/painting.c b/windows/painting.c
index 6f73fe1..7536d64 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -96,12 +96,8 @@
  *              RDW_Paint() method.
  * 
  */
-static BOOL WIN_HaveToDelayNCPAINT(
-  WND* wndPtr, 
-  UINT uncFlags)
+static BOOL WIN_HaveToDelayNCPAINT( HWND hwnd, UINT uncFlags)
 {
-  WND* parentWnd = NULL;
-
   /*
    * Test the shortcut first. (duh)
    */
@@ -122,22 +118,16 @@
    * that doesn't have the WS_CLIPCHILDREN style and that
    * has an invalid region. 
    */
-  parentWnd = WIN_LockWndPtr(wndPtr->parent);
-
-  while (parentWnd!=NULL)
+  while ((hwnd = GetAncestor( hwnd, GA_PARENT )))
   {
-    if ( ((parentWnd->dwStyle & WS_CLIPCHILDREN) == 0) &&
-	 (parentWnd->hrgnUpdate != 0) )
-    {
-      WIN_ReleaseWndPtr(parentWnd);
-      return TRUE;
-    }
-
-    WIN_UpdateWndPtr(&parentWnd, parentWnd->parent);    
+      WND* parentWnd = WIN_FindWndPtr( hwnd );
+      if (!(parentWnd->dwStyle & WS_CLIPCHILDREN) && parentWnd->hrgnUpdate)
+      {
+          WIN_ReleaseWndPtr( parentWnd );
+          return TRUE;
+      }
+      WIN_ReleaseWndPtr( parentWnd );
   }
-
-  WIN_ReleaseWndPtr(parentWnd);
-
   return FALSE;
 }
 
@@ -188,7 +178,7 @@
      * If the window's non-client area needs to be painted, 
      */
     if ( ( wnd->flags & WIN_NEEDS_NCPAINT ) &&
-	 !WIN_HaveToDelayNCPAINT(wnd, uncFlags) )
+	 !WIN_HaveToDelayNCPAINT(wnd->hwndSelf, uncFlags) )
     {
 	    RECT r2, r3;
 
@@ -495,7 +485,7 @@
  */
 static void RDW_ValidateParent(WND *wndChild)
 {
-    WND *wndParent = WIN_LockWndPtr(wndChild->parent);
+    HWND parent;
     HRGN hrg;
 
     if (wndChild->hrgnUpdate == 1 ) {
@@ -508,7 +498,10 @@
     } else
         hrg = wndChild->hrgnUpdate;
 
-    while ((wndParent) && (wndParent->hwndSelf != GetDesktopWindow()) ) {
+    parent = GetAncestor( wndChild->hwndSelf, GA_PARENT );
+    while (parent && parent != GetDesktopWindow())
+    {
+        WND *wndParent = WIN_FindWndPtr( parent );
         if (!(wndParent->dwStyle & WS_CLIPCHILDREN))
         {
             if (wndParent->hrgnUpdate != 0)
@@ -536,10 +529,10 @@
                 OffsetRgn( hrg, -ptOffset.x, -ptOffset.y );
             }
         }
-        WIN_UpdateWndPtr(&wndParent, wndParent->parent);    
+        WIN_ReleaseWndPtr( wndParent );
+        parent = GetAncestor( parent, GA_PARENT );
     }
     if (hrg != wndChild->hrgnUpdate) DeleteObject( hrg );
-    WIN_ReleaseWndPtr(wndParent);
 }
 
 /***********************************************************************
@@ -559,8 +552,8 @@
      */
 
     BOOL bHadOne =  wndPtr->hrgnUpdate && hRgn;
-    BOOL bChildren =  ( wndPtr->child && !(flags & RDW_NOCHILDREN) && !(wndPtr->dwStyle & WS_MINIMIZE) 
-			&& ((flags & RDW_ALLCHILDREN) || !(wndPtr->dwStyle & WS_CLIPCHILDREN)) );
+    BOOL bChildren =  (!(flags & RDW_NOCHILDREN) && !(wndPtr->dwStyle & WS_MINIMIZE) &&
+                       ((flags & RDW_ALLCHILDREN) || !(wndPtr->dwStyle & WS_CLIPCHILDREN)) );
     RECT r;
 
     r.left = 0;
@@ -657,43 +650,48 @@
 
     if( flags & (RDW_INVALIDATE | RDW_VALIDATE) )
     {
-	if( hRgn > 1 && bChildren )
+        HWND *list;
+	if( hRgn > 1 && bChildren && (list = WIN_BuildWinArray( wndPtr->hwndSelf )))
 	{
-            WND* wnd = wndPtr->child;
 	    POINT ptTotal, prevOrigin = {0,0};
             POINT ptClient;
+            INT i;
 
             ptClient.x = wndPtr->rectClient.left - wndPtr->rectWindow.left;
             ptClient.y = wndPtr->rectClient.top - wndPtr->rectWindow.top;
 
-            for( ptTotal.x = ptTotal.y = 0; wnd; wnd = wnd->next )
+            for(i = ptTotal.x = ptTotal.y = 0; list[i]; i++)
             {
+                WND *wnd = WIN_FindWndPtr( list[i] );
+                if (!wnd) continue;
                 if( wnd->dwStyle & WS_VISIBLE )
                 {
-		    POINT ptOffset;
+                    POINT ptOffset;
 
                     r.left = wnd->rectWindow.left + ptClient.x;
                     r.right = wnd->rectWindow.right + ptClient.x;
                     r.top = wnd->rectWindow.top + ptClient.y;
                     r.bottom = wnd->rectWindow.bottom + ptClient.y;
 
-		    ptOffset.x = r.left - prevOrigin.x; 
-		    ptOffset.y = r.top - prevOrigin.y;
+                    ptOffset.x = r.left - prevOrigin.x;
+                    ptOffset.y = r.top - prevOrigin.y;
                     OffsetRect( &r, -ptTotal.x, -ptTotal.y );
 
                     if( RectInRegion( hRgn, &r ) )
                     {
                         OffsetRgn( hRgn, -ptOffset.x, -ptOffset.y );
                         RDW_UpdateRgns( wnd, hRgn, flags, FALSE );
-			prevOrigin.x = r.left + ptTotal.x;
-			prevOrigin.y = r.top + ptTotal.y;
+                        prevOrigin.x = r.left + ptTotal.x;
+                        prevOrigin.y = r.top + ptTotal.y;
                         ptTotal.x += ptOffset.x;
                         ptTotal.y += ptOffset.y;
                     }
                 }
+                WIN_ReleaseWndPtr( wnd );
             }
+            WIN_ReleaseWinArray( list );
             OffsetRgn( hRgn, ptTotal.x, ptTotal.y );
-	    bChildren = 0;
+            bChildren = 0;
 	}
     }
 
@@ -701,10 +699,20 @@
 
     if( bChildren )
     {
-	WND* wnd;
-	for( wnd = wndPtr->child; wnd; wnd = wnd->next )
-	     if( wnd->dwStyle & WS_VISIBLE )
-		 RDW_UpdateRgns( wnd, hRgn, flags, FALSE );
+        HWND *list;
+        if ((list = WIN_BuildWinArray( wndPtr->hwndSelf )))
+        {
+            INT i;
+            for (i = 0; list[i]; i++)
+            {
+                WND *wnd = WIN_FindWndPtr( list[i] );
+                if (!wnd) continue;
+                if( wnd->dwStyle & WS_VISIBLE )
+                    RDW_UpdateRgns( wnd, hRgn, flags, FALSE );
+                WIN_ReleaseWndPtr( wnd );
+            }
+            WIN_ReleaseWinArray( list );
+        }
     }
 
 end:
@@ -762,7 +770,7 @@
      * Check if this window should delay it's processing of WM_NCPAINT.
      * See WIN_HaveToDelayNCPAINT for a description of the mechanism
      */
-    if ((ex & RDW_EX_DELAY_NCPAINT) || WIN_HaveToDelayNCPAINT(wndPtr, 0) )
+    if ((ex & RDW_EX_DELAY_NCPAINT) || WIN_HaveToDelayNCPAINT(wndPtr->hwndSelf, 0) )
 	ex |= RDW_EX_DELAY_NCPAINT;
 
     if (flags & RDW_UPDATENOW)
@@ -807,8 +815,8 @@
 
       /* ... and its child windows */
 
-    if( wndPtr->child && !(flags & RDW_NOCHILDREN) && !(wndPtr->dwStyle & WS_MINIMIZE) 
-	&& ((flags & RDW_ALLCHILDREN) || !(wndPtr->dwStyle & WS_CLIPCHILDREN)) )
+    if(!(flags & RDW_NOCHILDREN) && !(wndPtr->dwStyle & WS_MINIMIZE) &&
+       ((flags & RDW_ALLCHILDREN) || !(wndPtr->dwStyle & WS_CLIPCHILDREN)) )
     {
         HWND *list, *phwnd;
 
@@ -1209,7 +1217,7 @@
 
 	/* do ugly coordinate translations in dce.c */
 
-	ret = DCE_ExcludeRgn( hdc, wndPtr, hrgn );
+	ret = DCE_ExcludeRgn( hdc, hwnd, hrgn );
 	DeleteObject( hrgn );
         WIN_ReleaseWndPtr(wndPtr);
 	return ret;
diff --git a/windows/win.c b/windows/win.c
index e070ab8..544dddc 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -406,7 +406,7 @@
 	wndPtr->hSysMenu = 0;
     }
     USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
-    DCE_FreeWindowDCE( wndPtr );    /* Always do this to catch orphaned DCs */ 
+    DCE_FreeWindowDCE( wndPtr->hwndSelf );    /* Always do this to catch orphaned DCs */
     WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
     CLASS_RemoveWindow( wndPtr->class );
     wndPtr->class = NULL;
@@ -423,34 +423,21 @@
  * Destroy all children of 'wnd' owned by the current thread.
  * Return TRUE if something was done.
  */
-BOOL WIN_DestroyThreadWindows( HWND hwnd )
+void WIN_DestroyThreadWindows( HWND hwnd )
 {
-    BOOL ret = FALSE;
-    WND *wnd = WIN_FindWndPtr( hwnd );
+    HWND *list;
+    int i;
 
-    if (!wnd) return FALSE;
-    while (wnd->child)
+    if (!(list = WIN_BuildWinArray( hwnd ))) return;
+    for (i = 0; list[i]; i++)
     {
-        WND *tmp = WIN_LockWndPtr(wnd->child);
-        ret = FALSE;
-        while (tmp)
-        {
-            if (GetWindowThreadProcessId( tmp->hwndSelf, NULL ) == GetCurrentThreadId())
-            {
-                DestroyWindow( tmp->hwndSelf );
-                ret = TRUE;
-                break;
-            }
-            if (tmp->child && WIN_DestroyThreadWindows( tmp->hwndSelf ))
-                ret = TRUE;
-            else
-                WIN_UpdateWndPtr(&tmp,tmp->next);
-        }
-        WIN_ReleaseWndPtr(tmp);
-        if (!ret) break;
+        if (!IsWindow( list[i] )) continue;
+        if (GetWindowThreadProcessId( list[i], NULL ) == GetCurrentThreadId())
+            DestroyWindow( list[i] );
+        else
+            WIN_DestroyThreadWindows( list[i] );
     }
-    WIN_ReleaseWndPtr( wnd );
-    return ret;
+    WIN_ReleaseWinArray( list );
 }
 
 /***********************************************************************
@@ -698,10 +685,8 @@
             wndPtr->owner = NULL;
         else
         {
-            WND *tmpWnd = WIN_FindWndPtr(cs->hwndParent);
-            wndPtr->owner = WIN_GetTopParentPtr(tmpWnd);
+            wndPtr->owner = WIN_FindWndPtr( GetAncestor( cs->hwndParent, GA_ROOT ));
             WIN_ReleaseWndPtr(wndPtr->owner);
-            WIN_ReleaseWndPtr(tmpWnd);
 	}
     }
     
@@ -1053,92 +1038,40 @@
     return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
 }
 
+
 /***********************************************************************
  *           WIN_SendDestroyMsg
  */
-static void WIN_SendDestroyMsg( WND* pWnd )
+static void WIN_SendDestroyMsg( HWND hwnd )
 {
-    if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret();
+    if( CARET_GetHwnd() == hwnd) DestroyCaret();
     if (USER_Driver.pResetSelectionOwner)
-        USER_Driver.pResetSelectionOwner( pWnd->hwndSelf, TRUE );
+        USER_Driver.pResetSelectionOwner( hwnd, TRUE );
 
     /*
      * Send the WM_DESTROY to the window.
      */
-    SendMessageA( pWnd->hwndSelf, WM_DESTROY, 0, 0);
+    SendMessageA( hwnd, WM_DESTROY, 0, 0);
 
     /*
      * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
      * make sure that the window still exists when we come back.
      */
-    if (IsWindow(pWnd->hwndSelf))
+    if (IsWindow(hwnd))
     {
-      HWND* pWndArray = NULL;
-      WND*  pChild    = NULL;
-      int   nKidCount = 0;
+        HWND* pWndArray;
+        int i;
 
-      /*
-       * Now, if the window has kids, we have to send WM_DESTROY messages 
-       * recursively to it's kids. It seems that those calls can also
-       * trigger re-entrant calls to DestroyWindow for the kids so we must 
-       * protect against corruption of the list of siblings. We first build
-       * a list of HWNDs representing all the kids.
-       */
-      pChild = WIN_LockWndPtr(pWnd->child);
-      while( pChild )
-      {
-	nKidCount++;
-	WIN_UpdateWndPtr(&pChild,pChild->next);
-      }
+        if (!(pWndArray = WIN_BuildWinArray( hwnd ))) return;
 
-      /*
-       * If there are no kids, we're done.
-       */
-      if (nKidCount==0)
-	return;
+        /* start from the end (FIXME: is this needed?) */
+        for (i = 0; pWndArray[i]; i++) ;
 
-      pWndArray = HeapAlloc(GetProcessHeap(), 0, nKidCount*sizeof(HWND));
-
-      /*
-       * Sanity check
-       */
-      if (pWndArray==NULL)
-	return;
-
-      /*
-       * Now, enumerate all the kids in a list, since we wait to make the SendMessage
-       * call, our linked list of siblings should be safe.
-       */
-      nKidCount = 0;
-      pChild = WIN_LockWndPtr(pWnd->child);
-      while( pChild )
-      {
-	pWndArray[nKidCount] = pChild->hwndSelf;
-	nKidCount++;
-	WIN_UpdateWndPtr(&pChild,pChild->next);
-      }
-
-      /*
-       * Now that we have a list, go through that list again and send the destroy
-       * message to those windows. We are using the HWND to retrieve the
-       * WND pointer so we are effectively checking that all the kid windows are
-       * still valid before sending the message.
-       */
-      while (nKidCount>0)
-      {
-	pChild = WIN_FindWndPtr(pWndArray[--nKidCount]);
-
-	if (pChild!=NULL)
-	{
-	  WIN_SendDestroyMsg( pChild );
-	  WIN_ReleaseWndPtr(pChild);	  
-	}
-      }
-
-      /*
-       * Cleanup
-       */
-      HeapFree(GetProcessHeap(), 0, pWndArray);
+        while (--i >= 0)
+        {
+            if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
+        }
+        WIN_ReleaseWinArray( pWndArray );
     }
     else
       WARN("\tdestroyed itself while in WM_DESTROY!\n");
@@ -1162,46 +1095,29 @@
     WND * wndPtr;
     BOOL retvalue;
     HWND h;
-    BOOL bFocusSet = FALSE;
 
     TRACE("(%04x)\n", hwnd);
 
     /* Initialization */
 
     if (hwnd == GetDesktopWindow()) return FALSE;   /* Can't destroy desktop */
-    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
 
     /* Look whether the focus is within the tree of windows we will
      * be destroying.
      */
-    h = GetFocus16();
-    while (h && (GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
+    h = GetFocus();
+    if (h == hwnd || IsChild( hwnd, h ))
     {
-	if (h == hwnd)
-	{
-	    SetFocus(GetParent(h));
-	    bFocusSet = TRUE;
-	    break;
-	}
-	h = GetParent(h);
-    }
-    /* If the focus is on the window we will destroy and it has no parent,
-     * set the focus to 0.
-     */
-    if (! bFocusSet && (h == hwnd))
-    {                   
-	if (!(GetWindowLongA(h,GWL_STYLE) & WS_CHILD))
-	    SetFocus(0);
+        HWND parent = GetAncestor( hwnd, GA_PARENT );
+        if (parent == GetDesktopWindow()) parent = 0;
+        SetFocus( parent );
     }
 
       /* Call hooks */
 
-    if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) )
-    {
-        retvalue = FALSE;
-        goto end;
-    }
+    if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, hwnd, 0L) ) return FALSE;
 
+    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
     if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner)
     {
         HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, hwnd, 0L );
@@ -1271,7 +1187,7 @@
 
       /* Send destroy messages */
 
-    WIN_SendDestroyMsg( wndPtr );
+    WIN_SendDestroyMsg( hwnd );
     if (!IsWindow(hwnd))
     {
         retvalue = TRUE;
@@ -1348,70 +1264,50 @@
  *
  * Implementation of FindWindow() and FindWindowEx().
  */
-static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className,
-                              LPCWSTR title )
+static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
 {
-    WND *pWnd;
+    HWND *list;
     HWND retvalue;
+    int i = 0, len = 0;
+    WCHAR *buffer = NULL;
+
+    if (!parent) parent = GetDesktopWindow();
+    if (title)
+    {
+        len = strlenW(title) + 1;  /* one extra char to check for chars beyond the end */
+        if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
+    }
+
+    if (!(list = WIN_BuildWinArray( parent )))
+    {
+        if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
+        return 0;
+    }
 
     if (child)
     {
-        if (!(pWnd = WIN_FindWndPtr( child ))) return 0;
-        if (parent)
-        {
-            if (!pWnd->parent || (pWnd->parent->hwndSelf != parent))
-            {
-                retvalue = 0;
-                goto end;
-            }
-        }
-        else if (pWnd->parent != pWndDesktop)
-        {
-            retvalue = 0;
-            goto end;
-        }
-        WIN_UpdateWndPtr(&pWnd,pWnd->next);
-    }
-    else
-    {
-        if (!(pWnd = parent ? WIN_FindWndPtr(parent) : WIN_LockWndPtr(pWndDesktop)))
-        {
-            retvalue = 0;
-            goto end;
-        }
-        WIN_UpdateWndPtr(&pWnd,pWnd->child);
-    }
-    if (!pWnd)
-    {
-        retvalue = 0;
-        goto end;
+        while (list[i] && list[i] != child) i++;
+        if (!list[i]) return 0;
+        i++;  /* start from next window */
     }
 
-    for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
+    for ( ; list[i]; i++)
     {
-        if (className && (GetClassWord(pWnd->hwndSelf, GCW_ATOM) != className))
+        if (className && (GetClassWord(list[i], GCW_ATOM) != className))
             continue;  /* Not the right class */
 
         /* Now check the title */
-
-        if (!title)
-        {
-            retvalue = pWnd->hwndSelf;
-            goto end;
-        }
-        if (pWnd->text && !strcmpW( pWnd->text, title ))
-        {
-            retvalue = pWnd->hwndSelf;
-            goto end;
-        }
+        if (!title) break;
+        if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
     }
-    retvalue = 0;
+    retvalue = list[i];
+    WIN_ReleaseWinArray( list );
+    if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
+
     /* In this case we need to check whether other processes
        own a window with the given paramters on the Desktop,
        but we don't, so let's at least warn about it */
-    FIXME("Returning 0 without checking other processes\n");
-end:
-    WIN_ReleaseWndPtr(pWnd);
+    if (!retvalue) FIXME("Returning 0 without checking other processes\n");
     return retvalue;
 }
 
@@ -2165,38 +2061,38 @@
     
 }
 
-/*****************************************************************
- *         WIN_GetTopParent
- *
- * Get the top-level parent for a child window.
- * returns a locked pointer
- */
-WND* WIN_GetTopParentPtr( WND* pWnd )
-{
-    WND *tmpWnd = WIN_LockWndPtr(pWnd);
-    
-    while( tmpWnd && (tmpWnd->dwStyle & WS_CHILD))
-    {
-        WIN_UpdateWndPtr(&tmpWnd,tmpWnd->parent);
-    }
-    return tmpWnd;
-}
 
 /*****************************************************************
- *         WIN_GetTopParent
- *
- * Get the top-level parent for a child window.
+ *		GetAncestor (USER32.@)
  */
-HWND WIN_GetTopParent( HWND hwnd )
+HWND WINAPI GetAncestor( HWND hwnd, UINT type )
 {
-    HWND retvalue;
-    WND *tmpPtr = WIN_FindWndPtr(hwnd);
-    WND *wndPtr = WIN_GetTopParentPtr (tmpPtr );
-    
-    retvalue = wndPtr ? wndPtr->hwndSelf : 0;
-    WIN_ReleaseWndPtr(tmpPtr);
-    WIN_ReleaseWndPtr(wndPtr);
-    return retvalue;
+    HWND ret;
+    WND *wndPtr, *parent;
+
+    if (hwnd == GetDesktopWindow()) return 0;
+    if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
+    parent = wndPtr->parent;
+
+    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->owner)
+            WIN_UpdateWndPtr( &wndPtr, wndPtr->owner );
+        break;
+    }
+    ret = wndPtr->hwndSelf;
+    WIN_ReleaseWndPtr( wndPtr );
+    return ret;
 }
 
 
@@ -2481,6 +2377,7 @@
 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
 {
     int count = 0;
+    WND *pWnd;
     HWND *win_array = WIN_BuildWinArray( GetDesktopWindow() );
 
     if (!win_array) return TRUE;
@@ -2491,10 +2388,10 @@
     while (win_array[count]) count++;
     while (--count >= 0)
     {
-        WND *pWnd = WIN_FindWndPtr( win_array[count] );
-        if (!pWnd) continue;
+        if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
+        if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
 
-        if (pWnd->owner && (pWnd->owner->hwndSelf == owner) && (pWnd->dwStyle & WS_POPUP))
+        if (pWnd->dwStyle & WS_POPUP)
         {
             if (fShow)
             {
@@ -2545,7 +2442,7 @@
 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
 {
     int count = 0;
-
+    WND *pWnd;
     HWND *win_array = WIN_BuildWinArray(GetDesktopWindow());
 
     if (!win_array) return TRUE;
@@ -2553,10 +2450,10 @@
     while (win_array[count]) count++;
     while (--count >= 0)
     {
-        WND *pWnd = WIN_FindWndPtr( win_array[count] );
-        if (!pWnd) continue;
+        if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
+        if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
 
-        if (pWnd->owner && (pWnd->owner->hwndSelf == owner) && (pWnd->dwStyle & WS_POPUP))
+        if (pWnd->dwStyle & WS_POPUP)
         {
             if (fShow)
             {
@@ -2797,21 +2694,17 @@
  */
 BOOL WINAPI AnyPopup(void)
 {
-    WND *wndPtr = WIN_LockWndPtr(pWndDesktop->child);
+    int i;
     BOOL retvalue;
-    
-    while (wndPtr)
+    HWND *list = WIN_BuildWinArray( GetDesktopWindow() );
+
+    if (!list) return FALSE;
+    for (i = 0; list[i]; i++)
     {
-        if (wndPtr->owner && (wndPtr->dwStyle & WS_VISIBLE))
-        {
-            retvalue = TRUE;
-            goto end;
-	}
-        WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
+        if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
     }
-    retvalue = FALSE;
-end:
-    WIN_ReleaseWndPtr(wndPtr);
+    retvalue = (list[i] != 0);
+    WIN_ReleaseWinArray( list );
     return retvalue;
 }
 
diff --git a/windows/winpos.c b/windows/winpos.c
index 19e0a15..ed7843e 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -187,13 +187,13 @@
  */
 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect ) 
 {
-    WND * wndPtr = WIN_FindWndPtr( hwnd ); 
-    if (!wndPtr) return;
-    
-    CONV_RECT32TO16( &wndPtr->rectWindow, rect );
-    if (wndPtr->parent)
-	MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
-    WIN_ReleaseWndPtr(wndPtr);
+    RECT rect32;
+
+    GetWindowRect( hwnd, &rect32 );
+    rect->left   = rect32.left;
+    rect->top    = rect32.top;
+    rect->right  = rect32.right;
+    rect->bottom = rect32.bottom;
 }
 
 
@@ -202,13 +202,11 @@
  */
 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect ) 
 {
-    WND * wndPtr = WIN_FindWndPtr( hwnd ); 
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
     if (!wndPtr) return FALSE;
-    
     *rect = wndPtr->rectWindow;
-    if (wndPtr->parent)
-	MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
     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;
@@ -528,38 +526,7 @@
  */
 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
 {
-    /* pt is in the client coordinates */
-
-    WND* wnd = WIN_FindWndPtr(hwndParent);
-    RECT rect;
-    HWND retvalue;
-
-    if( !wnd ) return 0;
-
-    /* get client rect fast */
-    rect.top = rect.left = 0;
-    rect.right = wnd->rectClient.right - wnd->rectClient.left;
-    rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
-
-    if (!PtInRect( &rect, pt ))
-    {
-        retvalue = 0;
-        goto end;
-    }
-    WIN_UpdateWndPtr(&wnd,wnd->child);
-    while ( wnd )
-    {
-        if (PtInRect( &wnd->rectWindow, pt ))
-        {
-            retvalue = wnd->hwndSelf;
-            goto end;
-        }
-        WIN_UpdateWndPtr(&wnd,wnd->next);
-    }
-    retvalue = hwndParent;
-end:
-    WIN_ReleaseWndPtr(wnd);
-    return retvalue;
+    return ChildWindowFromPointEx( hwndParent, pt, CWP_ALL );
 }
 
 /*******************************************************************
@@ -576,50 +543,36 @@
 /*******************************************************************
  *		ChildWindowFromPointEx (USER32.@)
  */
-HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
-		UINT uFlags)
+HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt, UINT uFlags)
 {
     /* pt is in the client coordinates */
-
-    WND* wnd = WIN_FindWndPtr(hwndParent);
+    HWND *list;
+    int i;
     RECT rect;
-    HWND retvalue;
+    HWND retvalue = 0;
 
-    if( !wnd ) return 0;
+    GetClientRect( hwndParent, &rect );
+    if (!PtInRect( &rect, pt )) return 0;
+    if (!(list = WIN_BuildWinArray( hwndParent ))) return 0;
 
-    /* get client rect fast */
-    rect.top = rect.left = 0;
-    rect.right = wnd->rectClient.right - wnd->rectClient.left;
-    rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
-
-    if (!PtInRect( &rect, pt ))
+    for (i = 0; list[i] && !retvalue; i++)
     {
-        retvalue = 0;
-        goto end;
+        WND *wnd = WIN_FindWndPtr( list[i] );
+        if (!wnd) continue;
+        if (PtInRect( &wnd->rectWindow, pt ))
+        {
+            if ( (uFlags & CWP_SKIPINVISIBLE) &&
+                 !(wnd->dwStyle & WS_VISIBLE) );
+            else if ( (uFlags & CWP_SKIPDISABLED) &&
+                      (wnd->dwStyle & WS_DISABLED) );
+            else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
+                      (wnd->dwExStyle & WS_EX_TRANSPARENT) );
+            else retvalue = list[i];
+        }
+        WIN_ReleaseWndPtr( wnd );
     }
-    WIN_UpdateWndPtr(&wnd,wnd->child);
-
-    while ( wnd )
-    {
-        if (PtInRect( &wnd->rectWindow, pt )) {
-		if ( (uFlags & CWP_SKIPINVISIBLE) && 
-				!(wnd->dwStyle & WS_VISIBLE) );
-		else if ( (uFlags & CWP_SKIPDISABLED) && 
-				(wnd->dwStyle & WS_DISABLED) );
-		else if ( (uFlags & CWP_SKIPTRANSPARENT) && 
-				(wnd->dwExStyle & WS_EX_TRANSPARENT) );
-		else
-                {
-                    retvalue = wnd->hwndSelf;
-                    goto end;
-	        }
-                
-	}
-	WIN_UpdateWndPtr(&wnd,wnd->next);
-    }
-    retvalue = hwndParent;
-end:
-    WIN_ReleaseWndPtr(wnd);
+    WIN_ReleaseWinArray( list );
+    if (!retvalue) retvalue = hwndParent;
     return retvalue;
 }
 
@@ -787,11 +740,10 @@
 /*******************************************************************
  *         WINPOS_CanActivate
  */
-static BOOL WINPOS_CanActivate(WND* pWnd)
+static BOOL WINPOS_CanActivate(HWND hwnd)
 {
-    if( pWnd && ( (pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
-       == WS_VISIBLE ) ) return TRUE;
-    return FALSE;
+    if (!hwnd) return FALSE;
+    return ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_DISABLED|WS_VISIBLE|WS_CHILD)) == WS_VISIBLE);
 }
 
 
@@ -1601,11 +1553,8 @@
     if (hWnd)
     {
         /* walk up to the first unowned window */
-        wndTemp = WIN_LockWndPtr(wndPtr);
-        while (wndTemp->owner)
-        {
-            WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
-        }
+        HWND tmp = GetAncestor( hWnd, GA_ROOTOWNER );
+        wndTemp = WIN_FindWndPtr( tmp );
         /* and set last active owned popup */
         wndTemp->hwndLastActive = hWnd;
 
@@ -1625,7 +1574,7 @@
         {
             HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
 
-            if ( hOldFocus && WIN_GetTopParent( hOldFocus ) != hwndActive )
+            if ( hOldFocus && GetAncestor( hOldFocus, GA_ROOT ) != hwndActive )
                 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus, 
                                    (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
                                    0 : hwndActive );
@@ -1673,8 +1622,9 @@
 BOOL WINPOS_ActivateOtherWindow(HWND hwnd)
 {
     BOOL bRet = 0;
-    WND *pWnd, *pWndTo = NULL;
+    WND *pWnd;
     HWND hwndActive = 0;
+    HWND hwndTo = 0;
 
     /* Get current active window from the active queue */
     if ( hActiveQueue )
@@ -1699,27 +1649,21 @@
     }
 
     if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
-        !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
+        !WINPOS_CanActivate((hwndTo = GetAncestor( pWnd->owner->hwndSelf, GA_ROOT ))) )
     {
-        WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
+        HWND tmp = GetAncestor( pWnd->hwndSelf, GA_ROOT );
+        hwndTo = hwndPrevActive;
 
-        WIN_ReleaseWndPtr(pWndTo);
-        pWndTo = WIN_FindWndPtr(hwndPrevActive);
-
-        while( !WINPOS_CanActivate(pWndTo) )
+        while( !WINPOS_CanActivate(hwndTo) )
         {
             /* by now owned windows should've been taken care of */
-            WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
-            WIN_UpdateWndPtr(&pWndPtr,pWndTo);
-            if( !pWndTo ) break;
+            tmp = hwndTo = GetWindow( tmp, GW_HWNDNEXT );
+            if( !hwndTo ) break;
         }
-        WIN_ReleaseWndPtr(pWndPtr);
     }
     WIN_ReleaseWndPtr( pWnd );
 
-    bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
-
-    if( pWndTo ) WIN_ReleaseWndPtr(pWndTo);
+    bRet = WINPOS_SetActiveWindow( hwndTo, FALSE, TRUE );
 
     hwndPrevActive = 0;
     return bRet;
diff --git a/windows/x11drv/clipboard.c b/windows/x11drv/clipboard.c
index 293e518..83e7205 100644
--- a/windows/x11drv/clipboard.c
+++ b/windows/x11drv/clipboard.c
@@ -353,7 +353,7 @@
     /*
      * Query the selection owner for the TARGETS property
      */
-    w = X11DRV_get_top_window(hWnd);
+    w = X11DRV_get_whole_window( GetAncestor(hWnd,GA_ROOT) );
 
     aTargets = TSXInternAtom(display, "TARGETS", False);
 
@@ -892,7 +892,8 @@
     if ( !(selectionAcquired == (S_PRIMARY | S_CLIPBOARD)) )
     {
         Atom xaClipboard = TSXInternAtom(display, _CLIPBOARD, False);
-        owner = X11DRV_get_top_window( hWndClipWindow ? hWndClipWindow : AnyPopup() );
+        owner = X11DRV_get_whole_window( GetAncestor( hWndClipWindow ? hWndClipWindow : AnyPopup(),
+                                                      GA_ROOT ) );
 
         /* Grab PRIMARY selection if not owned */
         if ( !(selectionAcquired & S_PRIMARY) )
@@ -1047,7 +1048,7 @@
     {
 	XEvent xe;
         Atom propRequest;
-	Window w = X11DRV_get_top_window(hWnd);
+	Window w = X11DRV_get_whole_window( GetAncestor( hWnd, GA_ROOT ));
 
         /* Map the format ID requested to an X selection property.
          * If the format is in the cache, use the atom associated
diff --git a/windows/x11drv/event.c b/windows/x11drv/event.c
index 3541f68..3071d99 100644
--- a/windows/x11drv/event.c
+++ b/windows/x11drv/event.c
@@ -386,16 +386,15 @@
         x -= data->client_rect.left;
         y -= data->client_rect.top;
     }
-    while (win->parent && win->parent->hwndSelf != GetDesktopWindow())
-    {
-        x += win->rectClient.left;
-        y += win->rectClient.top;
-        WIN_UpdateWndPtr( &win, win->parent );
-    }
-    pt->x = x + win->rectClient.left;
-    pt->y = y + win->rectClient.top;
-    *hwnd = win->hwndSelf;
     WIN_ReleaseWndPtr( win );
+
+    pt->x = x;
+    pt->y = y;
+    if (*hwnd != GetDesktopWindow())
+    {
+        ClientToScreen( *hwnd, pt );
+        *hwnd = GetAncestor( *hwnd, GA_ROOT );
+    }
 }