Added WIN_GetRectangles function.
Fixed WindowFromPoint to work accross processes.

diff --git a/include/win.h b/include/win.h
index d1679a6..7b8cdd6 100644
--- a/include/win.h
+++ b/include/win.h
@@ -92,6 +92,7 @@
 extern LONG WIN_SetStyle( HWND hwnd, LONG style );
 extern LONG WIN_SetExStyle( HWND hwnd, LONG style );
 extern void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient );
+extern BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient );
 extern LRESULT WIN_DestroyWindow( HWND hwnd );
 extern void WIN_DestroyThreadWindows( HWND hwnd );
 extern BOOL WIN_CreateDesktopWindow(void);
diff --git a/windows/win.c b/windows/win.c
index cf39d3f..c3cce5a 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -569,6 +569,52 @@
 
 
 /***********************************************************************
+ *           WIN_GetRectangles
+ *
+ * Get the window and client rectangles.
+ */
+BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
+{
+    WND *win = WIN_GetPtr( hwnd );
+    BOOL ret = TRUE;
+
+    if (!win) return FALSE;
+    if (win == WND_OTHER_PROCESS)
+    {
+        SERVER_START_REQ( get_window_rectangles )
+        {
+            req->handle = hwnd;
+            if ((ret = !wine_server_call( req )))
+            {
+                if (rectWindow)
+                {
+                    rectWindow->left   = reply->window.left;
+                    rectWindow->top    = reply->window.top;
+                    rectWindow->right  = reply->window.right;
+                    rectWindow->bottom = reply->window.bottom;
+                }
+                if (rectClient)
+                {
+                    rectClient->left   = reply->client.left;
+                    rectClient->top    = reply->client.top;
+                    rectClient->right  = reply->client.right;
+                    rectClient->bottom = reply->client.bottom;
+                }
+            }
+        }
+        SERVER_END_REQ;
+    }
+    else
+    {
+        if (rectWindow) *rectWindow = win->rectWindow;
+        if (rectClient) *rectClient = win->rectClient;
+        WIN_ReleasePtr( win );
+    }
+    return ret;
+}
+
+
+/***********************************************************************
  *           WIN_DestroyWindow
  *
  * Destroy storage associated to a window. "Internals" p.358
diff --git a/windows/winpos.c b/windows/winpos.c
index bb7e48d..e44a2b3 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -173,32 +173,7 @@
  */
 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
 {
-    BOOL ret;
-    WND *wndPtr = WIN_GetPtr( hwnd );
-
-    if (!wndPtr) return FALSE;
-
-    if (wndPtr != WND_OTHER_PROCESS)
-    {
-        *rect = wndPtr->rectWindow;
-        WIN_ReleasePtr( wndPtr );
-        ret = TRUE;
-    }
-    else
-    {
-        SERVER_START_REQ( get_window_rectangles )
-        {
-            req->handle = hwnd;
-            if ((ret = !wine_server_call_err( req )))
-            {
-                rect->left   = reply->window.left;
-                rect->top    = reply->window.top;
-                rect->right  = reply->window.right;
-                rect->bottom = reply->window.bottom;
-            }
-        }
-        SERVER_END_REQ;
-    }
+    BOOL ret = WIN_GetRectangles( hwnd, rect, NULL );
     if (ret)
     {
         MapWindowPoints( GetAncestor( hwnd, GA_PARENT ), 0, (POINT *)rect, 2 );
@@ -292,31 +267,14 @@
 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
 {
     BOOL ret;
-    WND *wndPtr = WIN_GetPtr( hwnd );
 
-    rect->left = rect->top = rect->right = rect->bottom = 0;
-    if (!wndPtr) return FALSE;
-
-    if (wndPtr != WND_OTHER_PROCESS)
+    rect->right = rect->bottom = 0;
+    if ((ret = WIN_GetRectangles( hwnd, NULL, rect )))
     {
-        rect->right  = wndPtr->rectClient.right - wndPtr->rectClient.left;
-        rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
-        WIN_ReleasePtr( wndPtr );
-        ret = TRUE;
+        rect->right -= rect->left;
+        rect->bottom -= rect->top;
     }
-    else
-    {
-        SERVER_START_REQ( get_window_rectangles )
-        {
-            req->handle = hwnd;
-            if ((ret = !wine_server_call_err( req )))
-            {
-                rect->right  = reply->client.right - reply->client.left;
-                rect->bottom = reply->client.bottom - reply->client.top;
-            }
-        }
-        SERVER_END_REQ;
-    }
+    rect->left = rect->top = 0;
     return ret;
 }
 
@@ -351,57 +309,64 @@
 static HWND find_child_from_point( HWND parent, POINT pt, INT *hittest, LPARAM lparam )
 {
     int i, res;
+    LONG style, exstyle;
+    RECT rectWindow, rectClient;
     WND *wndPtr;
     HWND *list = WIN_ListChildren( parent );
 
     if (!list) return 0;
     for (i = 0; list[i]; i++)
     {
-        if (!(wndPtr = WIN_FindWndPtr( list[i] ))) continue;
         /* If point is in window, and window is visible, and it  */
         /* is enabled (or it's a top-level window), then explore */
         /* its children. Otherwise, go to the next window.       */
 
-        if (!(wndPtr->dwStyle & WS_VISIBLE)) goto next;  /* not visible -> skip */
-        if ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD | WS_DISABLED)) == (WS_CHILD | WS_DISABLED))
-            goto next;  /* disabled child -> skip */
-        if ((wndPtr->dwExStyle & (WS_EX_LAYERED | WS_EX_TRANSPARENT)) == (WS_EX_LAYERED | WS_EX_TRANSPARENT))
-            goto next;  /* transparent -> skip */
-        if (wndPtr->hrgnWnd)
+        style = GetWindowLongW( list[i], GWL_STYLE );
+        if (!(style & WS_VISIBLE)) continue;  /* not visible -> skip */
+        if ((style & (WS_POPUP | WS_CHILD | WS_DISABLED)) == (WS_CHILD | WS_DISABLED))
+            continue;  /* disabled child -> skip */
+        exstyle = GetWindowLongW( list[i], GWL_EXSTYLE );
+        if ((exstyle & (WS_EX_LAYERED | WS_EX_TRANSPARENT)) == (WS_EX_LAYERED | WS_EX_TRANSPARENT))
+            continue;  /* transparent -> skip */
+
+        if (!WIN_GetRectangles( list[i], &rectWindow, &rectClient )) continue;
+        if (!PtInRect( &rectWindow, pt )) continue;  /* not in window -> skip */
+
+        /* FIXME: check window region for other processes too */
+        if ((wndPtr = WIN_GetPtr( list[i] )) && wndPtr != WND_OTHER_PROCESS)
         {
-            if (!PtInRegion( wndPtr->hrgnWnd, pt.x - wndPtr->rectWindow.left,
-                             pt.y - wndPtr->rectWindow.top ))
-                goto next;  /* point outside window region -> skip */
+            if (wndPtr->hrgnWnd && !PtInRegion( wndPtr->hrgnWnd,
+                                                pt.x - rectWindow.left, pt.y - rectWindow.top ))
+            {
+                WIN_ReleasePtr( wndPtr );
+                continue;  /* point outside window region -> skip */
+            }
+            WIN_ReleasePtr( wndPtr );
         }
-        else if (!PtInRect( &wndPtr->rectWindow, pt )) goto next;  /* not in window -> skip */
 
         /* If window is minimized or disabled, return at once */
-        if (wndPtr->dwStyle & WS_MINIMIZE)
+        if (style & WS_MINIMIZE)
         {
-            WIN_ReleaseWndPtr( wndPtr );
             *hittest = HTCAPTION;
             return list[i];
         }
-        if (wndPtr->dwStyle & WS_DISABLED)
+        if (style & WS_DISABLED)
         {
-            WIN_ReleaseWndPtr( wndPtr );
             *hittest = HTERROR;
             return list[i];
         }
 
         /* If point is in client area, explore children */
-        if (PtInRect( &wndPtr->rectClient, pt ))
+        if (PtInRect( &rectClient, pt ))
         {
             POINT new_pt;
             HWND ret;
 
-            new_pt.x = pt.x - wndPtr->rectClient.left;
-            new_pt.y = pt.y - wndPtr->rectClient.top;
-            WIN_ReleaseWndPtr( wndPtr );
+            new_pt.x = pt.x - rectClient.left;
+            new_pt.y = pt.y - rectClient.top;
             if ((ret = find_child_from_point( list[i], new_pt, hittest, lparam )))
                 return ret;
         }
-        else WIN_ReleaseWndPtr( wndPtr );
 
         /* Now it's inside window, send WM_NCCHITTEST (if same thread) */
         if (!WIN_IsCurrentThread( list[i] ))
@@ -414,10 +379,7 @@
             *hittest = res;  /* Found the window */
             return list[i];
         }
-        continue;  /* continue search with next sibling */
-
-    next:
-        WIN_ReleaseWndPtr( wndPtr );
+        /* continue search with next sibling */
     }
     return 0;
 }
@@ -430,40 +392,36 @@
  */
 HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest )
 {
-    WND *wndScope;
     POINT xy = pt;
     int res;
+    LONG style;
 
     TRACE("scope %04x %ld,%ld\n", hwndScope, pt.x, pt.y);
 
     if (!hwndScope) hwndScope = GetDesktopWindow();
-    if (!(wndScope = WIN_FindWndPtr( hwndScope ))) return 0;
-    hwndScope = wndScope->hwndSelf;  /* make it a full handle */
+    style = GetWindowLongW( hwndScope, GWL_STYLE );
 
     *hittest = HTERROR;
-    if( wndScope->dwStyle & WS_DISABLED )
+    if (style & WS_DISABLED) return 0;
+
+    MapWindowPoints( GetDesktopWindow(), GetAncestor( hwndScope, GA_PARENT ), &xy, 1 );
+
+    if (!(style & WS_MINIMIZE))
     {
-        WIN_ReleaseWndPtr(wndScope);
-        return 0;
-    }
-
-    if (wndScope->parent)
-        MapWindowPoints( GetDesktopWindow(), wndScope->parent, &xy, 1 );
-
-    if (!(wndScope->dwStyle & WS_MINIMIZE) && PtInRect( &wndScope->rectClient, xy ))
-    {
-        HWND ret;
-
-        xy.x -= wndScope->rectClient.left;
-        xy.y -= wndScope->rectClient.top;
-        WIN_ReleaseWndPtr( wndScope );
-        if ((ret = find_child_from_point( hwndScope, xy, hittest, MAKELONG( pt.x, pt.y ) )))
+        RECT rectClient;
+        if (WIN_GetRectangles( hwndScope, NULL, &rectClient ) && PtInRect( &rectClient, xy ))
         {
-            TRACE( "found child %x\n", ret );
-            return ret;
+            HWND ret;
+
+            xy.x -= rectClient.left;
+            xy.y -= rectClient.top;
+            if ((ret = find_child_from_point( hwndScope, xy, hittest, MAKELONG( pt.x, pt.y ) )))
+            {
+                TRACE( "found child %x\n", ret );
+                return ret;
+            }
         }
     }
-    else WIN_ReleaseWndPtr( wndScope );
 
     /* If nothing found, try the scope window */
     if (!WIN_IsCurrentThread( hwndScope ))
@@ -512,28 +470,29 @@
     HWND *list;
     int i;
     RECT rect;
-    HWND retvalue = 0;
+    HWND retvalue;
 
     GetClientRect( hwndParent, &rect );
     if (!PtInRect( &rect, pt )) return 0;
     if (!(list = WIN_ListChildren( hwndParent ))) return 0;
 
-    for (i = 0; list[i] && !retvalue; i++)
+    for (i = 0; list[i]; i++)
     {
-        WND *wnd = WIN_FindWndPtr( list[i] );
-        if (!wnd) continue;
-        if (PtInRect( &wnd->rectWindow, pt ))
+        if (!WIN_GetRectangles( list[i], &rect, NULL )) continue;
+        if (!PtInRect( &rect, pt )) continue;
+        if (uFlags & (CWP_SKIPINVISIBLE|CWP_SKIPDISABLED))
         {
-            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];
+            LONG style = GetWindowLongW( list[i], GWL_STYLE );
+            if ((uFlags & CWP_SKIPINVISIBLE) && !(style & WS_VISIBLE)) continue;
+            if ((uFlags & CWP_SKIPDISABLED) && (style & WS_DISABLED)) continue;
         }
-        WIN_ReleaseWndPtr( wnd );
+        if (uFlags & CWP_SKIPTRANSPARENT)
+        {
+            if (GetWindowLongW( list[i], GWL_EXSTYLE ) & WS_EX_TRANSPARENT) continue;
+        }
+        break;
     }
+    retvalue = list[i];
     HeapFree( GetProcessHeap(), 0, list );
     if (!retvalue) retvalue = hwndParent;
     return retvalue;