Store in the server all the window information accessible with
Get/SetWindowLong.

diff --git a/controls/scroll.c b/controls/scroll.c
index 55b330d..6f83cd3 100644
--- a/controls/scroll.c
+++ b/controls/scroll.c
@@ -1714,10 +1714,8 @@
 BOOL SCROLL_ShowScrollBar( HWND hwnd, INT nBar, 
 			     BOOL fShowH, BOOL fShowV )
 {
-    WND *wndPtr = WIN_FindWndPtr( hwnd );
-    BOOL retvalue = FALSE;
+    LONG style = GetWindowLongW( hwnd, GWL_STYLE );
 
-    if (!wndPtr) return FALSE;
     TRACE("hwnd=%04x bar=%d horz=%d, vert=%d\n",
                     hwnd, nBar, fShowH, fShowV );
 
@@ -1725,20 +1723,19 @@
     {
     case SB_CTL:
         ShowWindow( hwnd, fShowH ? SW_SHOW : SW_HIDE );
-        retvalue = TRUE;
-        goto END;
+        return TRUE;
 
     case SB_BOTH:
     case SB_HORZ:
         if (fShowH)
         {
-            fShowH = !(wndPtr->dwStyle & WS_HSCROLL);
-            wndPtr->dwStyle |= WS_HSCROLL;
+            fShowH = !(style & WS_HSCROLL);
+            style |= WS_HSCROLL;
         }
         else  /* hide it */
         {
-            fShowH = (wndPtr->dwStyle & WS_HSCROLL);
-            wndPtr->dwStyle &= ~WS_HSCROLL;
+            fShowH = (style & WS_HSCROLL);
+            style &= ~WS_HSCROLL;
         }
         if( nBar == SB_HORZ ) {
             fShowV = FALSE;
@@ -1749,35 +1746,30 @@
     case SB_VERT:
         if (fShowV)
         {
-            fShowV = !(wndPtr->dwStyle & WS_VSCROLL);
-            wndPtr->dwStyle |= WS_VSCROLL;
+            fShowV = !(style & WS_VSCROLL);
+            style |= WS_VSCROLL;
         }
 	else  /* hide it */
         {
-            fShowV = (wndPtr->dwStyle & WS_VSCROLL);
-            wndPtr->dwStyle &= ~WS_VSCROLL;
+            fShowV = (style & WS_VSCROLL);
+            style &= ~WS_VSCROLL;
         }
         if ( nBar == SB_VERT )
            fShowH = FALSE;
         break;
 
     default:
-        retvalue = FALSE;  /* Nothing to do! */
-        goto END;
+        return FALSE;  /* Nothing to do! */
     }
 
     if( fShowH || fShowV ) /* frame has been changed, let the window redraw itself */
     {
+        WIN_SetStyle( hwnd, style );
 	SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE
                     | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
-        retvalue = TRUE;
-        goto END;
+        return TRUE;
     }
-
-    retvalue = FALSE; /* no frame changes */
-END:
-    WIN_ReleaseWndPtr(wndPtr);
-    return retvalue;
+    return FALSE; /* no frame changes */
 }
 
 
diff --git a/dlls/ttydrv/wnd.c b/dlls/ttydrv/wnd.c
index d375c29..47e4f4e 100644
--- a/dlls/ttydrv/wnd.c
+++ b/dlls/ttydrv/wnd.c
@@ -609,13 +609,9 @@
     WIN_SetRectangles( winpos->hwnd, &newWindowRect, &newClientRect );
 
     if( winpos->flags & SWP_SHOWWINDOW )
-    {
-        wndPtr->dwStyle |= WS_VISIBLE;
-    }
+        WIN_SetStyle( winpos->hwnd, wndPtr->dwStyle | WS_VISIBLE );
     else if( winpos->flags & SWP_HIDEWINDOW )
-    {
-        wndPtr->dwStyle &= ~WS_VISIBLE;
-    }
+        WIN_SetStyle( winpos->hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
 
     /* ------------------------------------------------------------------------ FINAL */
 
diff --git a/dlls/user/message.c b/dlls/user/message.c
index a9608cb..14f458f 100644
--- a/dlls/user/message.c
+++ b/dlls/user/message.c
@@ -1084,16 +1084,21 @@
  */
 static LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
 {
+    if (hwnd == GetDesktopWindow()) return 0;
     switch(msg)
     {
+    case WM_WINE_DESTROYWINDOW:
+        return WIN_DestroyWindow( hwnd );
     case WM_WINE_SETWINDOWPOS:
         return USER_Driver.pSetWindowPos( (WINDOWPOS *)lparam );
     case WM_WINE_SHOWWINDOW:
-        return USER_Driver.pShowWindow( hwnd, wparam );
-    case WM_WINE_DESTROYWINDOW:
-        return WIN_DestroyWindow( hwnd );
+        return ShowWindow( hwnd, wparam );
     case WM_WINE_SETPARENT:
-        return (LRESULT)WIN_SetParent( hwnd, (HWND)wparam );
+        return (LRESULT)SetParent( hwnd, (HWND)wparam );
+    case WM_WINE_SETWINDOWLONG:
+        return (LRESULT)SetWindowLongW( hwnd, wparam, lparam );
+    case WM_WINE_ENABLEWINDOW:
+        return EnableWindow( hwnd, wparam );
     default:
         FIXME( "unknown internal message %x\n", msg );
         return 0;
diff --git a/dlls/user/user_main.c b/dlls/user/user_main.c
index 92dc3f5..006e74c 100644
--- a/dlls/user/user_main.c
+++ b/dlls/user/user_main.c
@@ -87,7 +87,6 @@
     GET_USER_FUNC(CreateWindow);
     GET_USER_FUNC(DestroyWindow);
     GET_USER_FUNC(GetDC);
-    GET_USER_FUNC(EnableWindow);
     GET_USER_FUNC(ForceWindowRaise);
     GET_USER_FUNC(MsgWaitForMultipleObjectsEx);
     GET_USER_FUNC(ScrollDC);
diff --git a/dlls/x11drv/window.c b/dlls/x11drv/window.c
index bf5d0fa..8307062 100644
--- a/dlls/x11drv/window.c
+++ b/dlls/x11drv/window.c
@@ -22,6 +22,7 @@
 #include "debugtools.h"
 #include "x11drv.h"
 #include "win.h"
+#include "winpos.h"
 #include "dce.h"
 #include "options.h"
 
@@ -106,8 +107,8 @@
     BOOL is_top_level = is_window_top_level( win );
     BOOL managed = is_top_level && is_window_managed( win );
 
-    if (managed) win->dwExStyle |= WS_EX_MANAGED;
-    else win->dwExStyle &= ~WS_EX_MANAGED;
+    if (managed) WIN_SetExStyle( win->hwndSelf, win->dwExStyle | WS_EX_MANAGED );
+    else WIN_SetExStyle( win->hwndSelf, win->dwExStyle & ~WS_EX_MANAGED );
 
     attr->override_redirect = !managed;
     attr->colormap          = X11DRV_PALETTE_PaletteXColormap;
@@ -833,13 +834,17 @@
     data->hWMIconBitmap = 0;
     data->hWMIconMask   = 0;
 
-    wndPtr = WIN_FindWndPtr( hwnd );
+    wndPtr = WIN_GetPtr( hwnd );
     wndPtr->pDriverData = data;
 
+    /* initialize the dimensions before sending WM_GETMINMAXINFO */
+    SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy );
+    WIN_SetRectangles( hwnd, &rect, &rect );
+
     if (!wndPtr->parent)
     {
         create_desktop( display, wndPtr, cs );
-        WIN_ReleaseWndPtr( wndPtr );
+        WIN_ReleasePtr( wndPtr );
         return TRUE;
     }
 
@@ -847,11 +852,30 @@
     if (!create_client_window( display, wndPtr )) goto failed;
     TSXSync( display, False );
 
-    WIN_ReleaseWndPtr( wndPtr );
-
     SetPropA( hwnd, whole_window_atom, (HANDLE)data->whole_window );
     SetPropA( hwnd, client_window_atom, (HANDLE)data->client_window );
 
+    /* Send the WM_GETMINMAXINFO message and fix the size if needed */
+    if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
+    {
+        POINT maxSize, maxPos, minTrack, maxTrack;
+
+        WIN_ReleasePtr( wndPtr );
+        WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
+        if (maxSize.x < cs->cx) cs->cx = maxSize.x;
+        if (maxSize.y < cs->cy) cs->cy = maxSize.y;
+        if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
+        if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
+        if (cs->cx < 0) cs->cx = 0;
+        if (cs->cy < 0) cs->cy = 0;
+
+        if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
+        SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy );
+        WIN_SetRectangles( hwnd, &rect, &rect );
+        X11DRV_sync_whole_window_position( display, wndPtr, 0 );
+    }
+    WIN_ReleasePtr( wndPtr );
+
     /* send WM_NCCREATE */
     TRACE( "hwnd %x cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cs->cx, cs->cy );
     if (unicode)
@@ -860,17 +884,20 @@
         ret = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
     if (!ret)
     {
-        X11DRV_DestroyWindow( hwnd );
+        WARN("aborted by WM_xxCREATE!\n");
         return FALSE;
     }
 
-    if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
+    if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
 
     sync_window_style( display, wndPtr );
 
     /* send WM_NCCALCSIZE */
     rect = wndPtr->rectWindow;
+    WIN_ReleasePtr( wndPtr );
     SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rect );
+
+    if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
     if (rect.left > rect.right || rect.top > rect.bottom) rect = wndPtr->rectWindow;
     WIN_SetRectangles( hwnd, &wndPtr->rectWindow, &rect );
     X11DRV_sync_client_window_position( display, wndPtr );
@@ -892,7 +919,7 @@
     else
         WIN_LinkWindow( hwnd, wndPtr->parent, HWND_TOP );
 
-    WIN_ReleaseWndPtr( wndPtr );
+    WIN_ReleasePtr( wndPtr );
 
     if (unicode)
         ret = (SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs ) != -1);
@@ -902,7 +929,6 @@
     if (!ret)
     {
         WIN_UnlinkWindow( hwnd );
-        X11DRV_DestroyWindow( hwnd );
         return FALSE;
     }
 
@@ -932,7 +958,7 @@
 
         RECT newPos;
         UINT swFlag = (wndPtr->dwStyle & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
-        wndPtr->dwStyle &= ~(WS_MAXIMIZE | WS_MINIMIZE);
+        WIN_SetStyle( hwnd, wndPtr->dwStyle & ~(WS_MAXIMIZE | WS_MINIMIZE) );
         WINPOS_MinMaximize( hwnd, swFlag, &newPos );
         swFlag = ((wndPtr->dwStyle & WS_CHILD) || GetActiveWindow())
             ? SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED
@@ -946,8 +972,8 @@
 
 
  failed:
-    X11DRV_DestroyWindow( wndPtr->hwndSelf );
-    WIN_ReleaseWndPtr( wndPtr );
+    X11DRV_DestroyWindow( hwnd );
+    if (wndPtr) WIN_ReleasePtr( wndPtr );
     return FALSE;
 }
 
@@ -1052,78 +1078,6 @@
 }
 
 
-/*******************************************************************
- *		EnableWindow   (X11DRV.@)
- */
-BOOL X11DRV_EnableWindow( HWND hwnd, BOOL enable )
-{
-    Display *display = thread_display();
-    XWMHints *wm_hints;
-    WND *wndPtr;
-    BOOL retvalue;
-
-    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
-    hwnd = wndPtr->hwndSelf;  /* make it a full handle */
-
-    retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
-
-    if (enable && (wndPtr->dwStyle & WS_DISABLED))
-    {
-        /* Enable window */
-        wndPtr->dwStyle &= ~WS_DISABLED;
-
-        if (wndPtr->dwExStyle & WS_EX_MANAGED)
-        {
-            wine_tsx11_lock();
-            if (!(wm_hints = XGetWMHints( display, get_whole_window(wndPtr) )))
-                wm_hints = XAllocWMHints();
-            if (wm_hints)
-            {
-                wm_hints->flags |= InputHint;
-                wm_hints->input = TRUE;
-                XSetWMHints( display, get_whole_window(wndPtr), wm_hints );
-                XFree(wm_hints);
-            }
-            wine_tsx11_unlock();
-        }
-
-        SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
-    }
-    else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
-    {
-        SendMessageA( wndPtr->hwndSelf, WM_CANCELMODE, 0, 0 );
-
-        /* Disable window */
-        wndPtr->dwStyle |= WS_DISABLED;
-
-        if (wndPtr->dwExStyle & WS_EX_MANAGED)
-        {
-            wine_tsx11_lock();
-            if (!(wm_hints = XGetWMHints( display, get_whole_window(wndPtr) )))
-                wm_hints = XAllocWMHints();
-            if (wm_hints)
-            {
-                wm_hints->flags |= InputHint;
-                wm_hints->input = FALSE;
-                XSetWMHints( display, get_whole_window(wndPtr), wm_hints );
-                XFree(wm_hints);
-            }
-            wine_tsx11_unlock();
-        }
-
-        if (hwnd == GetFocus())
-            SetFocus( 0 );  /* A disabled window can't have the focus */
-
-        if (hwnd == GetCapture())
-            ReleaseCapture();  /* A disabled window can't capture the mouse */
-
-        SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
-    }
-    WIN_ReleaseWndPtr(wndPtr);
-    return retvalue;
-}
-
-
 /*****************************************************************
  *		SetFocus   (X11DRV.@)
  *
diff --git a/dlls/x11drv/winpos.c b/dlls/x11drv/winpos.c
index 5409293..6301e08 100644
--- a/dlls/x11drv/winpos.c
+++ b/dlls/x11drv/winpos.c
@@ -14,6 +14,7 @@
 #include "winbase.h"
 #include "wingdi.h"
 #include "winuser.h"
+#include "winerror.h"
 
 #include "x11drv.h"
 #include "hook.h"
@@ -407,7 +408,7 @@
  */
 BOOL X11DRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags )
 {
-    WND *win = WIN_FindWndPtr( hwnd );
+    WND *win = WIN_GetPtr( hwnd );
     HWND top = 0;
     X11DRV_WND_DATA *data = win->pDriverData;
     Drawable drawable;
@@ -505,7 +506,7 @@
         DeleteObject( visRgn );
     }
 
-    WIN_ReleaseWndPtr( win );
+    WIN_ReleasePtr( win );
     return TRUE;
 }
 
@@ -675,10 +676,14 @@
 /* fix redundant flags and values in the WINDOWPOS structure */
 static BOOL fixup_flags( WINDOWPOS *winpos )
 {
-    WND *wndPtr = WIN_FindWndPtr( winpos->hwnd );
+    WND *wndPtr = WIN_GetPtr( winpos->hwnd );
     BOOL ret = TRUE;
 
-    if (!wndPtr) return FALSE;
+    if (!wndPtr || wndPtr == WND_OTHER_PROCESS)
+    {
+        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+        return FALSE;
+    }
     winpos->hwnd = wndPtr->hwndSelf;  /* make it a full handle */
 
     if (wndPtr->dwStyle & WS_VISIBLE) winpos->flags &= ~SWP_SHOWWINDOW;
@@ -723,25 +728,20 @@
     /* hwndInsertAfter must be a sibling of the window */
     if ((winpos->hwndInsertAfter != HWND_TOP) && (winpos->hwndInsertAfter != HWND_BOTTOM))
     {
-        WND* wnd = WIN_FindWndPtr(winpos->hwndInsertAfter);
-        if (wnd)
+        winpos->hwndInsertAfter = WIN_GetFullHandle( winpos->hwndInsertAfter );
+        if (GetAncestor( winpos->hwndInsertAfter, GA_PARENT ) != wndPtr->parent) ret = FALSE;
+        else
         {
-            winpos->hwndInsertAfter = wnd->hwndSelf;  /* make it a full handle */
-            if (wnd->parent != wndPtr->parent) ret = FALSE;
-            else
-            {
-                /* don't need to change the Zorder of hwnd if it's already inserted
-                 * after hwndInsertAfter or when inserting hwnd after itself.
-                 */
-                if ((winpos->hwnd == winpos->hwndInsertAfter) ||
-                    (winpos->hwnd == GetWindow( winpos->hwndInsertAfter, GW_HWNDNEXT )))
-                    winpos->flags |= SWP_NOZORDER;
-            }
-            WIN_ReleaseWndPtr(wnd);
+            /* don't need to change the Zorder of hwnd if it's already inserted
+             * after hwndInsertAfter or when inserting hwnd after itself.
+             */
+            if ((winpos->hwnd == winpos->hwndInsertAfter) ||
+                (winpos->hwnd == GetWindow( winpos->hwndInsertAfter, GW_HWNDNEXT )))
+                winpos->flags |= SWP_NOZORDER;
         }
     }
  done:
-    WIN_ReleaseWndPtr(wndPtr);
+    WIN_ReleasePtr( wndPtr );
     return ret;
 }
 
@@ -754,18 +754,51 @@
 void X11DRV_SetWindowStyle( HWND hwnd, LONG oldStyle )
 {
     Display *display = thread_display();
-    WND *wndPtr = WIN_FindWndPtr( hwnd );
-    if (!wndPtr) return;
+    WND *wndPtr;
+    LONG changed;
 
-    if ((wndPtr->dwStyle & WS_VISIBLE) && (!(oldStyle & WS_VISIBLE)))
+    if (hwnd == GetDesktopWindow()) return;
+    if (!(wndPtr = WIN_GetPtr( hwnd ))) return;
+    if (wndPtr == WND_OTHER_PROCESS) return;
+
+    changed = wndPtr->dwStyle ^ oldStyle;
+
+    if (changed & WS_VISIBLE)
     {
         if (!IsRectEmpty( &wndPtr->rectWindow ))
         {
-            TRACE( "mapping win %x\n", hwnd );
-            TSXMapWindow( display, get_whole_window(wndPtr) );
+            if (wndPtr->dwStyle & WS_VISIBLE)
+            {
+                TRACE( "mapping win %x\n", hwnd );
+                TSXMapWindow( display, get_whole_window(wndPtr) );
+            }
+            else
+            {
+                TRACE( "unmapping win %x\n", hwnd );
+                TSXUnmapWindow( display, get_whole_window(wndPtr) );
+            }
         }
     }
-    WIN_ReleaseWndPtr(wndPtr);
+
+    if (changed & WS_DISABLED)
+    {
+        if (wndPtr->dwExStyle & WS_EX_MANAGED)
+        {
+            XWMHints *wm_hints;
+            wine_tsx11_lock();
+            if (!(wm_hints = XGetWMHints( display, get_whole_window(wndPtr) )))
+                wm_hints = XAllocWMHints();
+            if (wm_hints)
+            {
+                wm_hints->flags |= InputHint;
+                wm_hints->input = !(wndPtr->dwStyle & WS_DISABLED);
+                XSetWMHints( display, get_whole_window(wndPtr), wm_hints );
+                XFree(wm_hints);
+            }
+            wine_tsx11_unlock();
+        }
+    }
+    WIN_ReleasePtr(wndPtr);
 }
 
 
@@ -844,37 +877,26 @@
 
     WIN_SetRectangles( winpos->hwnd, &newWindowRect, &newClientRect );
 
-    if (winpos->flags & SWP_SHOWWINDOW) wndPtr->dwStyle |= WS_VISIBLE;
-    else if (winpos->flags & SWP_HIDEWINDOW)
-    {
-        /* clear the update region */
-        RedrawWindow( winpos->hwnd, NULL, 0, RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE |
-                                             RDW_NOINTERNALPAINT | RDW_ALLCHILDREN );
-        wndPtr->dwStyle &= ~WS_VISIBLE;
-    }
-
     if (get_whole_window(wndPtr))  /* don't do anything if X window not created yet */
     {
         Display *display = thread_display();
 
-        wine_tsx11_lock();
         if (!(winpos->flags & SWP_SHOWWINDOW) && (winpos->flags & SWP_HIDEWINDOW))
         {
-            if (!IsRectEmpty( &oldWindowRect ))
-            {
-                XUnmapWindow( display, get_whole_window(wndPtr) );
-                TRACE( "unmapping win %x\n", winpos->hwnd );
-            }
-            else TRACE( "not unmapping zero size win %x\n", winpos->hwnd );
+            WIN_SetStyle( winpos->hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
+            /* clear the update region */
+//            RedrawWindow( winpos->hwnd, NULL, 0, RDW_VALIDATE | RDW_NOFRAME |
+//                          RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_ALLCHILDREN );
         }
         else if ((wndPtr->dwStyle & WS_VISIBLE) &&
                  !IsRectEmpty( &oldWindowRect ) && IsRectEmpty( &newWindowRect ))
         {
             /* resizing to zero size -> unmap */
             TRACE( "unmapping zero size win %x\n", winpos->hwnd );
-            XUnmapWindow( display, get_whole_window(wndPtr) );
+            TSXUnmapWindow( display, get_whole_window(wndPtr) );
         }
 
+        wine_tsx11_lock();
         if (bChangePos)
             X11DRV_sync_whole_window_position( display, wndPtr, !(winpos->flags & SWP_NOZORDER) );
         else
@@ -893,12 +915,7 @@
         }
         if (winpos->flags & SWP_SHOWWINDOW)
         {
-            if (!IsRectEmpty( &newWindowRect ))
-            {
-                XMapWindow( display, get_whole_window(wndPtr) );
-                TRACE( "mapping win %x\n", winpos->hwnd );
-            }
-            else TRACE( "not mapping win %x, size is zero\n", winpos->hwnd );
+            WIN_SetStyle( winpos->hwnd, wndPtr->dwStyle | WS_VISIBLE );
         }
         else if ((wndPtr->dwStyle & WS_VISIBLE) &&
                  IsRectEmpty( &oldWindowRect ) && !IsRectEmpty( &newWindowRect ))
@@ -910,6 +927,13 @@
         XFlush( display );  /* FIXME: should not be necessary */
         wine_tsx11_unlock();
     }
+    else  /* no X window, simply toggle the window style */
+    {
+        if (winpos->flags & SWP_SHOWWINDOW)
+            WIN_SetStyle( winpos->hwnd, wndPtr->dwStyle | WS_VISIBLE );
+        else if (winpos->flags & SWP_HIDEWINDOW)
+            WIN_SetStyle( winpos->hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
+    }
 
     /* manually expose the areas that X won't expose because they are still covered by something */
 
@@ -1021,6 +1045,7 @@
     WND *wndPtr;
     UINT swpFlags = 0;
     POINT size;
+    LONG old_style;
     WINDOWPLACEMENT wpl;
 
     TRACE("0x%04x %u\n", hwnd, cmd );
@@ -1046,14 +1071,10 @@
     switch( cmd )
     {
     case SW_MINIMIZE:
-        if( wndPtr->dwStyle & WS_MAXIMIZE)
-        {
-            wndPtr->flags |= WIN_RESTORE_MAX;
-            wndPtr->dwStyle &= ~WS_MAXIMIZE;
-        }
-        else
-            wndPtr->flags &= ~WIN_RESTORE_MAX;
-        wndPtr->dwStyle |= WS_MINIMIZE;
+        if( wndPtr->dwStyle & WS_MAXIMIZE) wndPtr->flags |= WIN_RESTORE_MAX;
+        else wndPtr->flags &= ~WIN_RESTORE_MAX;
+
+        WIN_SetStyle( hwnd, (wndPtr->dwStyle & ~WS_MAXIMIZE) | WS_MINIMIZE );
 
         X11DRV_set_iconic_state( wndPtr );
 
@@ -1067,21 +1088,19 @@
     case SW_MAXIMIZE:
         WINPOS_GetMinMaxInfo( hwnd, &size, &wpl.ptMaxPosition, NULL, NULL );
 
-        if( wndPtr->dwStyle & WS_MINIMIZE )
+        old_style = WIN_SetStyle( hwnd, (wndPtr->dwStyle & ~WS_MINIMIZE) | WS_MAXIMIZE );
+        if (old_style & WS_MINIMIZE)
         {
-            wndPtr->dwStyle &= ~WS_MINIMIZE;
             WINPOS_ShowIconTitle( hwnd, FALSE );
             X11DRV_set_iconic_state( wndPtr );
         }
-        wndPtr->dwStyle |= WS_MAXIMIZE;
-
         SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, size.x, size.y );
         break;
 
     case SW_RESTORE:
-        if( wndPtr->dwStyle & WS_MINIMIZE )
+        old_style = WIN_SetStyle( hwnd, wndPtr->dwStyle & ~(WS_MINIMIZE|WS_MAXIMIZE) );
+        if (old_style & WS_MINIMIZE)
         {
-            wndPtr->dwStyle &= ~WS_MINIMIZE;
             WINPOS_ShowIconTitle( hwnd, FALSE );
             X11DRV_set_iconic_state( wndPtr );
 
@@ -1089,16 +1108,12 @@
             {
                 /* Restore to maximized position */
                 WINPOS_GetMinMaxInfo( hwnd, &size, &wpl.ptMaxPosition, NULL, NULL);
-                wndPtr->dwStyle |= WS_MAXIMIZE;
+                WIN_SetStyle( hwnd, wndPtr->dwStyle | WS_MAXIMIZE );
                 SetRect( rect, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, size.x, size.y );
                 break;
             }
         }
-        else
-        {
-            if (!(wndPtr->dwStyle & WS_MAXIMIZE)) break;
-            wndPtr->dwStyle &= ~WS_MAXIMIZE;
-        }
+        else if (!(old_style & WS_MAXIMIZE)) break;
 
         /* Restore to normal position */
 
@@ -1250,7 +1265,7 @@
     HWND hwndFocus = GetFocus();
     WND *win;
 
-    if (!(win = WIN_FindWndPtr( hwnd ))) return;
+    if (!(win = WIN_GetPtr( hwnd ))) return;
 
     if ((win->dwStyle & WS_VISIBLE) &&
         (win->dwStyle & WS_MINIMIZE) &&
@@ -1260,16 +1275,7 @@
         unsigned int width, height, border, depth;
         Window root, top;
         RECT rect;
-
-        DCE_InvalidateDCE( hwnd, &win->rectWindow );
-        win->dwStyle &= ~WS_MINIMIZE;
-        win->dwStyle |= WS_VISIBLE;
-        WIN_InternalShowOwnedPopups( hwnd, TRUE, TRUE );
-
-        if (win->flags & WIN_RESTORE_MAX)
-            win->dwStyle |= WS_MAXIMIZE;
-        else
-            win->dwStyle &= ~WS_MAXIMIZE;
+        LONG style = (win->dwStyle & ~(WS_MINIMIZE|WS_MAXIMIZE)) | WS_VISIBLE;
 
         /* FIXME: hack */
         wine_tsx11_lock();
@@ -1283,12 +1289,19 @@
         rect.bottom = y + height;
         X11DRV_X_to_window_rect( win, &rect );
 
+        DCE_InvalidateDCE( hwnd, &win->rectWindow );
+
+        if (win->flags & WIN_RESTORE_MAX) style |= WS_MAXIMIZE;
+        WIN_SetStyle( hwnd, style );
+        WIN_ReleasePtr( win );
+
+        WIN_InternalShowOwnedPopups( hwnd, TRUE, TRUE );
         SendMessageA( hwnd, WM_SHOWWINDOW, SW_RESTORE, 0 );
         SetWindowPos( hwnd, 0, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top,
                       SWP_NOZORDER | SWP_WINE_NOHOSTMOVE );
     }
+    else WIN_ReleasePtr( win );
     if (hwndFocus && IsChild( hwnd, hwndFocus )) X11DRV_SetFocus(hwndFocus);  /* FIXME */
-    WIN_ReleaseWndPtr( win );
 }
 
 
@@ -1299,28 +1312,26 @@
 {
     WND *win;
 
-    if (!(win = WIN_FindWndPtr( hwnd ))) return;
+    if (!(win = WIN_GetPtr( hwnd ))) return;
 
     if ((win->dwStyle & WS_VISIBLE) && (win->dwExStyle & WS_EX_MANAGED))
     {
+        if (win->dwStyle & WS_MAXIMIZE)
+            win->flags |= WIN_RESTORE_MAX;
+        else
+            win->flags &= ~WIN_RESTORE_MAX;
+
+        WIN_SetStyle( hwnd, (win->dwStyle & ~WS_MAXIMIZE) | WS_MINIMIZE );
+        WIN_ReleasePtr( win );
+
         EndMenu();
         SendMessageA( hwnd, WM_SHOWWINDOW, SW_MINIMIZE, 0 );
-
-        win->flags &= ~WIN_RESTORE_MAX;
-        win->dwStyle |= WS_MINIMIZE;
-
-        if (win->dwStyle & WS_MAXIMIZE)
-        {
-            win->flags |= WIN_RESTORE_MAX;
-            win->dwStyle &= ~WS_MAXIMIZE;
-        }
-
         SetWindowPos( hwnd, 0, 0, 0, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON),
                       SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_WINE_NOHOSTMOVE );
 
         WIN_InternalShowOwnedPopups( hwnd, FALSE, TRUE );
     }
-    WIN_ReleaseWndPtr( win );
+    else WIN_ReleasePtr( win );
 }
 
 
@@ -1538,23 +1549,26 @@
  *
  * Assign specified region to window (for non-rectangular windows)
  */
-BOOL X11DRV_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw )
+int X11DRV_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw )
 {
-    RECT rect;
-    WND *wndPtr = WIN_FindWndPtr(hwnd);
-    int ret = FALSE;
+    WND *wndPtr;
 
-    if (!wndPtr) return FALSE;
+    if ((wndPtr = WIN_GetPtr( hwnd )) == WND_OTHER_PROCESS)
+    {
+        if (IsWindow( hwnd ))
+            FIXME( "not supported on other process window %x\n", hwnd );
+        wndPtr = NULL;
+    }
+    if (!wndPtr)
+    {
+        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+        return FALSE;
+    }
 
     if (wndPtr->hrgnWnd == hrgn)
     {
-        ret = TRUE;
-        goto done;
-    }
-
-    if (hrgn) /* verify that region really exists */
-    {
-        if (GetRgnBox( hrgn, &rect ) == ERROR) goto done;
+        WIN_ReleasePtr( wndPtr );
+        return TRUE;
     }
 
     if (wndPtr->hrgnWnd)
@@ -1584,8 +1598,11 @@
                 DWORD size;
                 DWORD dwBufferSize = GetRegionData(hrgn, 0, NULL);
                 PRGNDATA pRegionData = HeapAlloc(GetProcessHeap(), 0, dwBufferSize);
-                if (!pRegionData) goto done;
-
+                if (!pRegionData)
+                {
+                    WIN_ReleasePtr( wndPtr );
+                    return TRUE;
+                }
                 GetRegionData(hrgn, dwBufferSize, pRegionData);
                 size = pRegionData->rdh.nCount;
                 x_offset = wndPtr->rectWindow.left - data->whole_rect.left;
@@ -1624,12 +1641,9 @@
     }
 #endif  /* HAVE_LIBXSHAPE */
 
+    WIN_ReleasePtr( wndPtr );
     if (redraw) RedrawWindow( hwnd, NULL, 0, RDW_FRAME | RDW_INVALIDATE | RDW_ERASE );
-    ret = TRUE;
-
- done:
-    WIN_ReleaseWndPtr(wndPtr);
-    return ret;
+    return TRUE;
 }
 
 
diff --git a/dlls/x11drv/x11drv.spec b/dlls/x11drv/x11drv.spec
index 2c3efaf..25ee1f9 100644
--- a/dlls/x11drv/x11drv.spec
+++ b/dlls/x11drv/x11drv.spec
@@ -78,7 +78,6 @@
 @ cdecl CreateWindow(long ptr long) X11DRV_CreateWindow
 @ cdecl DestroyWindow(long) X11DRV_DestroyWindow
 @ cdecl GetDC(long long long long) X11DRV_GetDC
-@ cdecl EnableWindow(long long) X11DRV_EnableWindow
 @ cdecl ForceWindowRaise(long) X11DRV_ForceWindowRaise
 @ cdecl MsgWaitForMultipleObjectsEx(long ptr long long long) X11DRV_MsgWaitForMultipleObjectsEx
 @ cdecl ScrollDC(long long long ptr ptr long ptr) X11DRV_ScrollDC
diff --git a/include/user.h b/include/user.h
index fb5603d..baf99db 100644
--- a/include/user.h
+++ b/include/user.h
@@ -38,7 +38,9 @@
     WM_WINE_DESTROYWINDOW = 0x80000000,
     WM_WINE_SETWINDOWPOS,
     WM_WINE_SHOWWINDOW,
-    WM_WINE_SETPARENT
+    WM_WINE_SETPARENT,
+    WM_WINE_SETWINDOWLONG,
+    WM_WINE_ENABLEWINDOW
 };
 
 /* internal SendInput codes (FIXME) */
@@ -79,7 +81,6 @@
     BOOL   (*pCreateWindow)(HWND,CREATESTRUCTA*,BOOL);
     BOOL   (*pDestroyWindow)(HWND);
     BOOL   (*pGetDC)(HWND,HDC,HRGN,DWORD);
-    BOOL   (*pEnableWindow)(HWND,BOOL);
     void   (*pForceWindowRaise)(HWND);
     DWORD  (*pMsgWaitForMultipleObjectsEx)(DWORD,const HANDLE*,DWORD,DWORD,DWORD);
     BOOL   (*pScrollDC)(HDC,INT,INT,const RECT*,const RECT*,HRGN,LPRECT);
@@ -87,7 +88,7 @@
     void   (*pSetFocus)(HWND);
     HWND   (*pSetParent)(HWND,HWND);
     BOOL   (*pSetWindowPos)(WINDOWPOS *);
-    BOOL   (*pSetWindowRgn)(HWND,HRGN,BOOL);
+    int    (*pSetWindowRgn)(HWND,HRGN,BOOL);
     HICON  (*pSetWindowIcon)(HWND,HICON,BOOL);
     void   (*pSetWindowStyle)(HWND,DWORD);
     BOOL   (*pSetWindowText)(HWND,LPCWSTR);
diff --git a/include/win.h b/include/win.h
index 81c3df7..6c8d577 100644
--- a/include/win.h
+++ b/include/win.h
@@ -89,6 +89,8 @@
 extern void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter );
 extern void WIN_UnlinkWindow( HWND hwnd );
 extern void WIN_SetOwner( HWND hwnd, HWND owner );
+extern 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 HWND WIN_FindWinToRepaint( HWND hwnd );
 extern LRESULT WIN_DestroyWindow( HWND hwnd );
@@ -97,7 +99,6 @@
 extern BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL );
 extern HWND *WIN_ListParents( HWND hwnd );
 extern HWND *WIN_ListChildren( HWND hwnd );
-extern HWND WIN_SetParent( HWND hwnd, HWND parent );
 extern BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly );
 
 inline static HWND WIN_GetFullHandle( HWND hwnd )
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 25ba881..375667c 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -1601,6 +1601,7 @@
     user_handle_t  handle;
     user_handle_t  parent;
     user_handle_t  previous;
+    user_handle_t  full_parent;
 };
 
 
@@ -1613,6 +1614,16 @@
 
 
 
+struct set_window_owner_request
+{
+    struct request_header __header;
+    user_handle_t  handle;
+    user_handle_t  owner;
+    user_handle_t  full_owner;
+};
+
+
+
 struct get_window_info_request
 {
     struct request_header __header;
@@ -1620,10 +1631,35 @@
     user_handle_t  full_handle;
     void*          pid;
     void*          tid;
+    atom_t         atom;
 };
 
 
 
+struct set_window_info_request
+{
+    struct request_header __header;
+    user_handle_t  handle;
+    unsigned int   flags;
+    unsigned int   style;
+    unsigned int   ex_style;
+    unsigned int   id;
+    void*          instance;
+    void*          user_data;
+    unsigned int   old_style;
+    unsigned int   old_ex_style;
+    unsigned int   old_id;
+    void*          old_instance;
+    void*          old_user_data;
+};
+#define SET_WIN_STYLE     0x01
+#define SET_WIN_EXSTYLE   0x02
+#define SET_WIN_ID        0x04
+#define SET_WIN_INSTANCE  0x08
+#define SET_WIN_USERDATA  0x10
+
+
+
 struct get_window_parents_request
 {
     struct request_header __header;
@@ -1858,7 +1894,9 @@
     REQ_create_window,
     REQ_link_window,
     REQ_destroy_window,
+    REQ_set_window_owner,
     REQ_get_window_info,
+    REQ_set_window_info,
     REQ_get_window_parents,
     REQ_get_window_children,
     REQ_get_window_tree,
@@ -2001,7 +2039,9 @@
     struct create_window_request create_window;
     struct link_window_request link_window;
     struct destroy_window_request destroy_window;
+    struct set_window_owner_request set_window_owner;
     struct get_window_info_request get_window_info;
+    struct set_window_info_request set_window_info;
     struct get_window_parents_request get_window_parents;
     struct get_window_children_request get_window_children;
     struct get_window_tree_request get_window_tree;
@@ -2014,6 +2054,6 @@
     struct get_window_properties_request get_window_properties;
 };
 
-#define SERVER_PROTOCOL_VERSION 60
+#define SERVER_PROTOCOL_VERSION 61
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/protocol.def b/server/protocol.def
index 78955d9..be779ea 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1434,6 +1434,7 @@
     user_handle_t  parent;      /* handle to the parent */
     user_handle_t  previous;    /* previous child in Z-order */
 @REPLY
+    user_handle_t  full_parent; /* full handle of new parent */
 @END
 
 
@@ -1443,6 +1444,15 @@
 @END
 
 
+/* Set a window owner */
+@REQ(set_window_owner)
+    user_handle_t  handle;      /* handle to the window */
+    user_handle_t  owner;       /* new owner */
+@REPLY
+    user_handle_t  full_owner;  /* full handle of new owner */
+@END
+
+
 /* Get information from a window handle */
 @REQ(get_window_info)
     user_handle_t  handle;      /* handle to the window */
@@ -1450,9 +1460,33 @@
     user_handle_t  full_handle; /* full 32-bit handle */
     void*          pid;         /* process owning the window */
     void*          tid;         /* thread owning the window */
+    atom_t         atom;        /* class atom */
 @END
 
 
+/* Set some information in a window */
+@REQ(set_window_info)
+    user_handle_t  handle;        /* handle to the window */
+    unsigned int   flags;         /* flags for fields to set (see below) */
+    unsigned int   style;         /* window style */
+    unsigned int   ex_style;      /* window extended style */
+    unsigned int   id;            /* window id */
+    void*          instance;      /* creator instance */
+    void*          user_data;     /* user-specific data */
+@REPLY
+    unsigned int   old_style;     /* old window style */
+    unsigned int   old_ex_style;  /* old window extended style */
+    unsigned int   old_id;        /* old window id */
+    void*          old_instance;  /* old creator instance */
+    void*          old_user_data; /* old user-specific data */
+@END
+#define SET_WIN_STYLE     0x01
+#define SET_WIN_EXSTYLE   0x02
+#define SET_WIN_ID        0x04
+#define SET_WIN_INSTANCE  0x08
+#define SET_WIN_USERDATA  0x10
+
+
 /* Get a list of the window parents, up to the root of the tree */
 @REQ(get_window_parents)
     user_handle_t  handle;        /* handle to the window */
diff --git a/server/request.h b/server/request.h
index aae7aea..2d1204f 100644
--- a/server/request.h
+++ b/server/request.h
@@ -191,7 +191,9 @@
 DECL_HANDLER(create_window);
 DECL_HANDLER(link_window);
 DECL_HANDLER(destroy_window);
+DECL_HANDLER(set_window_owner);
 DECL_HANDLER(get_window_info);
+DECL_HANDLER(set_window_info);
 DECL_HANDLER(get_window_parents);
 DECL_HANDLER(get_window_children);
 DECL_HANDLER(get_window_tree);
@@ -333,7 +335,9 @@
     (req_handler)req_create_window,
     (req_handler)req_link_window,
     (req_handler)req_destroy_window,
+    (req_handler)req_set_window_owner,
     (req_handler)req_get_window_info,
+    (req_handler)req_set_window_info,
     (req_handler)req_get_window_parents,
     (req_handler)req_get_window_children,
     (req_handler)req_get_window_tree,
diff --git a/server/trace.c b/server/trace.c
index 1d3330e..7c68db2 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -1707,11 +1707,27 @@
     fprintf( stderr, " previous=%08x", req->previous );
 }
 
+static void dump_link_window_reply( const struct link_window_request *req )
+{
+    fprintf( stderr, " full_parent=%08x", req->full_parent );
+}
+
 static void dump_destroy_window_request( const struct destroy_window_request *req )
 {
     fprintf( stderr, " handle=%08x", req->handle );
 }
 
+static void dump_set_window_owner_request( const struct set_window_owner_request *req )
+{
+    fprintf( stderr, " handle=%08x,", req->handle );
+    fprintf( stderr, " owner=%08x", req->owner );
+}
+
+static void dump_set_window_owner_reply( const struct set_window_owner_request *req )
+{
+    fprintf( stderr, " full_owner=%08x", req->full_owner );
+}
+
 static void dump_get_window_info_request( const struct get_window_info_request *req )
 {
     fprintf( stderr, " handle=%08x", req->handle );
@@ -1721,7 +1737,28 @@
 {
     fprintf( stderr, " full_handle=%08x,", req->full_handle );
     fprintf( stderr, " pid=%p,", req->pid );
-    fprintf( stderr, " tid=%p", req->tid );
+    fprintf( stderr, " tid=%p,", req->tid );
+    fprintf( stderr, " atom=%04x", req->atom );
+}
+
+static void dump_set_window_info_request( const struct set_window_info_request *req )
+{
+    fprintf( stderr, " handle=%08x,", req->handle );
+    fprintf( stderr, " flags=%08x,", req->flags );
+    fprintf( stderr, " style=%08x,", req->style );
+    fprintf( stderr, " ex_style=%08x,", req->ex_style );
+    fprintf( stderr, " id=%08x,", req->id );
+    fprintf( stderr, " instance=%p,", req->instance );
+    fprintf( stderr, " user_data=%p", req->user_data );
+}
+
+static void dump_set_window_info_reply( const struct set_window_info_request *req )
+{
+    fprintf( stderr, " old_style=%08x,", req->old_style );
+    fprintf( stderr, " old_ex_style=%08x,", req->old_ex_style );
+    fprintf( stderr, " old_id=%08x,", req->old_id );
+    fprintf( stderr, " old_instance=%p,", req->old_instance );
+    fprintf( stderr, " old_user_data=%p", req->old_user_data );
 }
 
 static void dump_get_window_parents_request( const struct get_window_parents_request *req )
@@ -1970,7 +2007,9 @@
     (dump_func)dump_create_window_request,
     (dump_func)dump_link_window_request,
     (dump_func)dump_destroy_window_request,
+    (dump_func)dump_set_window_owner_request,
     (dump_func)dump_get_window_info_request,
+    (dump_func)dump_set_window_info_request,
     (dump_func)dump_get_window_parents_request,
     (dump_func)dump_get_window_children_request,
     (dump_func)dump_get_window_tree_request,
@@ -2107,9 +2146,11 @@
     (dump_func)0,
     (dump_func)dump_get_named_pipe_info_reply,
     (dump_func)dump_create_window_reply,
+    (dump_func)dump_link_window_reply,
     (dump_func)0,
-    (dump_func)0,
+    (dump_func)dump_set_window_owner_reply,
     (dump_func)dump_get_window_info_reply,
+    (dump_func)dump_set_window_info_reply,
     (dump_func)dump_get_window_parents_reply,
     (dump_func)dump_get_window_children_reply,
     (dump_func)dump_get_window_tree_reply,
@@ -2248,7 +2289,9 @@
     "create_window",
     "link_window",
     "destroy_window",
+    "set_window_owner",
     "get_window_info",
+    "set_window_info",
     "get_window_parents",
     "get_window_children",
     "get_window_tree",
diff --git a/server/window.c b/server/window.c
index 1559d44..c5333aa 100644
--- a/server/window.c
+++ b/server/window.c
@@ -42,6 +42,11 @@
     atom_t           atom;            /* class atom */
     rectangle_t      window_rect;     /* window rectangle */
     rectangle_t      client_rect;     /* client rectangle */
+    unsigned int     style;           /* window style */
+    unsigned int     ex_style;        /* window extended style */
+    unsigned int     id;              /* window id */
+    void*            instance;        /* creator instance */
+    void*            user_data;       /* user-specific data */
     int              prop_inuse;      /* number of in-use window properties */
     int              prop_alloc;      /* number of allocated window properties */
     struct property *properties;      /* window properties array */
@@ -81,7 +86,11 @@
 
     if (parent)
     {
-        win->parent = parent;
+        if (win->parent != parent)
+        {
+            win->owner = NULL;  /* reset owner if changing parent */
+            win->parent = parent;
+        }
         if ((win->prev = previous))
         {
             if ((win->next = previous->next)) win->next->prev = win;
@@ -261,6 +270,11 @@
     win->first_unlinked = NULL;
     win->thread         = current;
     win->atom           = atom;
+    win->style          = 0;
+    win->ex_style       = 0;
+    win->id             = 0;
+    win->instance       = NULL;
+    win->user_data      = NULL;
     win->prop_inuse     = 0;
     win->prop_alloc     = 0;
     win->properties     = NULL;
@@ -323,6 +337,12 @@
 
         if (!(parent = get_window( req->parent ))) return;
         if (req->owner && !(owner = get_window( req->owner ))) return;
+        if (owner && owner->parent != parent)
+        {
+            /* owner must be a sibling of the new window */
+            set_error( STATUS_ACCESS_DENIED );
+            return;
+        }
         if (!(win = create_window( parent, owner, req->atom ))) return;
         req->handle = win->handle;
     }
@@ -342,6 +362,7 @@
         set_error( STATUS_INVALID_PARAMETER );
         return;
     }
+    req->full_parent = parent ? parent->handle : 0;
     if (parent && req->previous)
     {
         if (req->previous == (user_handle_t)1)  /* special case: HWND_BOTTOM */
@@ -376,6 +397,24 @@
 }
 
 
+/* set a window owner */
+DECL_HANDLER(set_window_owner)
+{
+    struct window *win = get_window( req->handle );
+    struct window *owner = get_window( req->owner );
+
+    if (!win || !owner) return;
+    if (owner->parent != win->parent)
+    {
+        /* owner has to be a sibling of window */
+        set_error( STATUS_ACCESS_DENIED );
+        return;
+    }
+    win->owner = owner;
+    req->full_owner = owner->handle;
+}
+
+
 /* get information from a window handle */
 DECL_HANDLER(get_window_info)
 {
@@ -388,13 +427,32 @@
         req->full_handle = win->handle;
         if (win->thread)
         {
-            req->tid = get_thread_id( win->thread );
-            req->pid = get_process_id( win->thread->process );
+            req->tid  = get_thread_id( win->thread );
+            req->pid  = get_process_id( win->thread->process );
+            req->atom = win->atom;
         }
     }
 }
 
 
+/* set some information in a window */
+DECL_HANDLER(set_window_info)
+{
+    struct window *win = get_window( req->handle );
+    if (!win) return;
+    req->old_style     = win->style;
+    req->old_ex_style  = win->ex_style;
+    req->old_id        = win->id;
+    req->old_instance  = win->instance;
+    req->old_user_data = win->user_data;
+    if (req->flags & SET_WIN_STYLE) win->style = req->style;
+    if (req->flags & SET_WIN_EXSTYLE) win->ex_style = req->ex_style;
+    if (req->flags & SET_WIN_ID) win->id = req->id;
+    if (req->flags & SET_WIN_INSTANCE) win->instance = req->instance;
+    if (req->flags & SET_WIN_USERDATA) win->user_data = req->user_data;
+}
+
+
 /* get a list of the window parents, up to the root of the tree */
 DECL_HANDLER(get_window_parents)
 {
diff --git a/windows/defwnd.c b/windows/defwnd.c
index 69649cc..af998c9 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -168,9 +168,7 @@
     {
 	if( !bVisible )
 	{
-	    wndPtr->dwStyle |= WS_VISIBLE;
-            if (USER_Driver.pSetWindowStyle)
-                USER_Driver.pSetWindowStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
+            WIN_SetStyle( hwnd, wndPtr->dwStyle | WS_VISIBLE );
             DCE_InvalidateDCE( hwnd, &wndPtr->rectWindow );
 	}
     }
@@ -181,9 +179,7 @@
 
         RedrawWindow( hwnd, NULL, 0, wParam );
         DCE_InvalidateDCE( hwnd, &wndPtr->rectWindow );
-	wndPtr->dwStyle &= ~WS_VISIBLE;
-        if (USER_Driver.pSetWindowStyle)
-            USER_Driver.pSetWindowStyle( hwnd, wndPtr->dwStyle | WS_VISIBLE );
+        WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
     }
     WIN_ReleaseWndPtr( wndPtr );
 }
diff --git a/windows/win.c b/windows/win.c
index dc85efc..0c8deea 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -362,7 +362,6 @@
  */
 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
 {
-    BOOL ret;
     WND *wndPtr = WIN_GetPtr( hwnd );
 
     if (!wndPtr) return;
@@ -377,10 +376,17 @@
         req->handle   = hwnd;
         req->parent   = parent;
         req->previous = hwndInsertAfter;
-        ret = !SERVER_CALL_ERR();
+        if (!SERVER_CALL())
+        {
+            if (req->full_parent && req->full_parent != wndPtr->parent)
+            {
+                wndPtr->owner = 0;  /* reset owner when changing parent */
+                wndPtr->parent = req->full_parent;
+            }
+        }
+
     }
     SERVER_END_REQ;
-    if (ret && parent) wndPtr->parent = WIN_GetFullHandle(parent);
     WIN_ReleasePtr( wndPtr );
 }
 
@@ -392,12 +398,102 @@
  */
 void WIN_SetOwner( HWND hwnd, HWND owner )
 {
-    WND *win = WIN_FindWndPtr( hwnd );
-    if (win)
+    WND *win = WIN_GetPtr( hwnd );
+
+    if (!win) return;
+    if (win == WND_OTHER_PROCESS)
     {
-        win->owner = owner;
-        WIN_ReleaseWndPtr( win );
+        if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd );
+        return;
     }
+    SERVER_START_REQ( set_window_owner )
+    {
+        req->handle = hwnd;
+        req->owner  = owner;
+        if (!SERVER_CALL()) win->owner = req->full_owner;
+    }
+    SERVER_END_REQ;
+    WIN_ReleasePtr( win );
+}
+
+
+/***********************************************************************
+ *           WIN_SetStyle
+ *
+ * Change the style of a window.
+ */
+LONG WIN_SetStyle( HWND hwnd, LONG style )
+{
+    BOOL ok;
+    LONG ret = 0;
+    WND *win = WIN_GetPtr( hwnd );
+
+    if (!win) return 0;
+    if (win == WND_OTHER_PROCESS)
+    {
+        if (IsWindow(hwnd))
+            ERR( "cannot set style %lx on other process window %x\n", style, hwnd );
+        return 0;
+    }
+    if (style == win->dwStyle)
+    {
+        WIN_ReleasePtr( win );
+        return style;
+    }
+    SERVER_START_REQ( set_window_info )
+    {
+        req->handle = hwnd;
+        req->flags  = SET_WIN_STYLE;
+        req->style  = style;
+        if ((ok = !SERVER_CALL()))
+        {
+            ret = req->old_style;
+            win->dwStyle = style;
+        }
+    }
+    SERVER_END_REQ;
+    WIN_ReleasePtr( win );
+    if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
+    return ret;
+}
+
+
+/***********************************************************************
+ *           WIN_SetExStyle
+ *
+ * Change the extended style of a window.
+ */
+LONG WIN_SetExStyle( HWND hwnd, LONG style )
+{
+    LONG ret = 0;
+    WND *win = WIN_GetPtr( hwnd );
+
+    if (!win) return 0;
+    if (win == WND_OTHER_PROCESS)
+    {
+        if (IsWindow(hwnd))
+            ERR( "cannot set exstyle %lx on other process window %x\n", style, hwnd );
+        return 0;
+    }
+    if (style == win->dwExStyle)
+    {
+        WIN_ReleasePtr( win );
+        return style;
+    }
+    SERVER_START_REQ( set_window_info )
+    {
+        req->handle   = hwnd;
+        req->flags    = SET_WIN_EXSTYLE;
+        req->ex_style = style;
+        if (!SERVER_CALL())
+        {
+            ret = req->old_ex_style;
+            win->dwExStyle = style;
+        }
+    }
+    SERVER_END_REQ;
+    WIN_ReleasePtr( win );
+    return ret;
 }
 
 
@@ -603,11 +699,10 @@
     wndPtr->hmemTaskQ = 0;
 
     if (!(wndPtr->dwStyle & WS_CHILD))
-       if (wndPtr->wIDmenu)
-       {
-	   DestroyMenu( wndPtr->wIDmenu );
-	   wndPtr->wIDmenu = 0;
-       }
+    {
+        HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
+        if (menu) DestroyMenu( menu );
+    }
     if (wndPtr->hSysMenu)
     {
 	DestroyMenu( wndPtr->hSysMenu );
@@ -682,8 +777,7 @@
     pWndDesktop->hmemTaskQ         = 0;
     pWndDesktop->hrgnUpdate        = 0;
     pWndDesktop->hwndLastActive    = hwndDesktop;
-    pWndDesktop->dwStyle           = WS_VISIBLE | WS_CLIPCHILDREN |
-                                     WS_CLIPSIBLINGS;
+    pWndDesktop->dwStyle           = 0;
     pWndDesktop->dwExStyle         = 0;
     pWndDesktop->clsStyle          = clsStyle;
     pWndDesktop->dce               = NULL;
@@ -712,6 +806,7 @@
 
     SetRect( &rect, 0, 0, cs.cx, cs.cy );
     WIN_SetRectangles( hwndDesktop, &rect, &rect );
+    WIN_SetStyle( hwndDesktop, WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS );
 
     if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
 
@@ -798,11 +893,9 @@
     struct tagCLASS *classPtr;
     WND *wndPtr;
     HWND hwnd, hwndLinkAfter, parent, owner;
-    POINT maxSize, maxPos, minTrack, maxTrack;
     INT wndExtra;
     DWORD clsStyle;
     WNDPROC winproc;
-    RECT rect;
     DCE *dce;
     BOOL unicode = (type == WIN_PROC_32W);
 
@@ -924,8 +1017,8 @@
 	    TRACE("CBT-hook returned 0\n");
             free_window_handle( hwnd );
             CLASS_RemoveWindow( classPtr );
-            hwnd =  0;
-            goto end;
+            WIN_ReleaseWndPtr(wndPtr);
+            return 0;
 	}
     }
 
@@ -940,6 +1033,16 @@
             wndPtr->flags |= WIN_NEED_SIZE;
 	}
     }
+    SERVER_START_REQ( set_window_info )
+    {
+        req->handle    = hwnd;
+        req->flags     = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
+        req->style     = wndPtr->dwStyle;
+        req->ex_style  = wndPtr->dwExStyle;
+        req->instance  = (void *)wndPtr->hInstance;
+        SERVER_CALL();
+    }
+    SERVER_END_REQ;
 
     /* Get class or window DC if needed */
 
@@ -947,28 +1050,6 @@
     else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
     else wndPtr->dce = NULL;
 
-    /* Initialize the dimensions before sending WM_GETMINMAXINFO */
-
-    SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy );
-    WIN_SetRectangles( hwnd, &rect, &rect );
-
-    /* Send the WM_GETMINMAXINFO message and fix the size if needed */
-
-    if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
-    {
-        WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
-        if (maxSize.x < cs->cx) cs->cx = maxSize.x;
-        if (maxSize.y < cs->cy) cs->cy = maxSize.y;
-        if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
-        if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
-    }
-
-    if (cs->cx < 0) cs->cx = 0;
-    if (cs->cy < 0) cs->cy = 0;
-
-    SetRect( &rect, cs->x, cs->y, cs->x + cs->cx, cs->y + cs->cy );
-    WIN_SetRectangles( hwnd, &rect, &rect );
-
     /* Set the window menu */
 
     if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
@@ -988,41 +1069,35 @@
             }
         }
     }
-    else wndPtr->wIDmenu = (UINT)cs->hMenu;
+    else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
+    WIN_ReleaseWndPtr( wndPtr );
 
     if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
     {
-        WARN("aborted by WM_xxCREATE!\n");
-        WIN_ReleaseWndPtr( wndPtr );
         WIN_DestroyWindow( hwnd );
-        CLASS_RemoveWindow( classPtr );
         return 0;
     }
 
     /* Notify the parent window only */
 
     send_parent_notify( hwnd, WM_CREATE );
-    if( !IsWindow(hwnd) )
-    {
-        hwnd = 0;
-        goto end;
-    }
+    if (!IsWindow( hwnd )) return 0;
 
     if (cs->style & WS_VISIBLE)
     {
         /* in case WS_VISIBLE got set in the meantime */
-        wndPtr->dwStyle &= ~WS_VISIBLE;
+        if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
+        WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
+        WIN_ReleasePtr( wndPtr );
         ShowWindow( hwnd, sw );
     }
 
     /* Call WH_SHELL hook */
 
-    if (!(wndPtr->dwStyle & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
+    if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
         HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
 
     TRACE("created window %04x\n", hwnd);
- end:
-    WIN_ReleaseWndPtr(wndPtr);
     return hwnd;
 }
 
@@ -1524,27 +1599,31 @@
 {
     WND *wndPtr;
     BOOL retvalue;
+    LONG style;
+    HWND full_handle;
+
+    if (!(full_handle = WIN_IsCurrentThread( hwnd )))
+        return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
+
+    hwnd = full_handle;
 
     TRACE("( %x, %d )\n", hwnd, enable);
 
-    if (USER_Driver.pEnableWindow)
-        return USER_Driver.pEnableWindow( hwnd, enable );
+    if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
+    style = wndPtr->dwStyle;
+    retvalue = ((style & WS_DISABLED) != 0);
+    WIN_ReleasePtr( wndPtr );
 
-    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
-    hwnd = wndPtr->hwndSelf;  /* make it a full handle */
-
-    retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
-
-    if (enable && (wndPtr->dwStyle & WS_DISABLED))
+    if (enable && retvalue)
     {
-        wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
+        WIN_SetStyle( hwnd, style & ~WS_DISABLED );
         SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
     }
-    else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
+    else if (!enable && !retvalue)
     {
         SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
 
-        wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
+        WIN_SetStyle( hwnd, style | WS_DISABLED );
 
         if (hwnd == GetFocus())
             SetFocus( 0 );  /* A disabled window can't have the focus */
@@ -1554,7 +1633,6 @@
 
         SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
     }
-    WIN_ReleaseWndPtr(wndPtr);
     return retvalue;
 }
 
@@ -1588,22 +1666,32 @@
  */
 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
 {
-    WORD retvalue;
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
-    if (!wndPtr) return 0;
     if (offset >= 0)
     {
-        if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
+        WORD retvalue = 0;
+        WND *wndPtr = WIN_GetPtr( hwnd );
+        if (!wndPtr)
+        {
+            SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+            return 0;
+        }
+        if (wndPtr == WND_OTHER_PROCESS)
+        {
+            if (IsWindow( hwnd ))
+                FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
+            SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+            return 0;
+        }
+        if (offset > wndPtr->cbWndExtra - sizeof(WORD))
         {
             WARN("Invalid offset %d\n", offset );
-            retvalue = 0;
+            SetLastError( ERROR_INVALID_INDEX );
         }
         else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
-        WIN_ReleaseWndPtr(wndPtr);
+        WIN_ReleasePtr( wndPtr );
         return retvalue;
     }
 
-    WIN_ReleaseWndPtr(wndPtr);
     switch(offset)
     {
     case GWL_HWNDPARENT:
@@ -1629,24 +1717,8 @@
 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
 {
     WORD *ptr, retval;
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
-    if (!wndPtr) return 0;
-    if (offset >= 0)
-    {
-        if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
-        {
-            WARN("Invalid offset %d\n", offset );
-            WIN_ReleaseWndPtr(wndPtr);
-            return 0;
-        }
-        ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
-        retval = *ptr;
-        *ptr = newval;
-        WIN_ReleaseWndPtr(wndPtr);
-        return retval;
-    }
+    WND * wndPtr;
 
-    WIN_ReleaseWndPtr(wndPtr);
     switch(offset)
     {
     case GWL_ID:
@@ -1654,9 +1726,40 @@
     case GWL_HWNDPARENT:
         return SetWindowLongW( hwnd, offset, (UINT)newval );
     default:
+        if (offset < 0)
+        {
+            WARN("Invalid offset %d\n", offset );
+            SetLastError( ERROR_INVALID_INDEX );
+            return 0;
+        }
+    }
+
+    wndPtr = WIN_GetPtr( hwnd );
+    if (wndPtr == WND_OTHER_PROCESS)
+    {
+        if (IsWindow(hwnd))
+            FIXME( "set %d <- %x not supported yet on other process window %x\n",
+                   offset, newval, hwnd );
+        wndPtr = NULL;
+    }
+    if (!wndPtr)
+    {
+       SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+       return 0;
+    }
+
+    if (offset > wndPtr->cbWndExtra - sizeof(WORD))
+    {
         WARN("Invalid offset %d\n", offset );
+        WIN_ReleasePtr(wndPtr);
+        SetLastError( ERROR_INVALID_INDEX );
         return 0;
     }
+    ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
+    retval = *ptr;
+    *ptr = newval;
+    WIN_ReleasePtr(wndPtr);
+    return retval;
 }
 
 
@@ -1667,49 +1770,87 @@
  */
 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
 {
-    LONG retvalue;
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
-    if (!wndPtr) return 0;
+    LONG retvalue = 0;
+    WND *wndPtr;
+
+    if (offset == GWL_HWNDPARENT) return (LONG)GetParent( hwnd );
+
+    if (!(wndPtr = WIN_GetPtr( hwnd )))
+    {
+        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+        return 0;
+    }
+
+    if (wndPtr == WND_OTHER_PROCESS)
+    {
+        if (offset >= 0)
+        {
+            FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
+            SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+            return 0;
+        }
+        if (offset == GWL_WNDPROC)
+        {
+            SetLastError( ERROR_ACCESS_DENIED );
+            return 0;
+        }
+        SERVER_START_REQ( set_window_info )
+        {
+            req->handle = hwnd;
+            req->flags  = 0;  /* don't set anything, just retrieve */
+            if (!SERVER_CALL_ERR())
+            {
+                switch(offset)
+                {
+                case GWL_STYLE:     retvalue = req->style; break;
+                case GWL_EXSTYLE:   retvalue = req->ex_style; break;
+                case GWL_ID:        retvalue = req->id; break;
+                case GWL_HINSTANCE: retvalue = (ULONG_PTR)req->instance; break;
+                case GWL_USERDATA:  retvalue = (ULONG_PTR)req->user_data; break;
+                default:
+                    SetLastError( ERROR_INVALID_INDEX );
+                    break;
+                }
+            }
+        }
+        SERVER_END_REQ;
+        return retvalue;
+    }
+
+    /* now we have a valid wndPtr */
+
     if (offset >= 0)
     {
-        if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
+        if (offset > wndPtr->cbWndExtra - sizeof(LONG))
         {
             WARN("Invalid offset %d\n", offset );
-            retvalue = 0;
-            goto end;
+            WIN_ReleasePtr( wndPtr );
+            SetLastError( ERROR_INVALID_INDEX );
+            return 0;
         }
-        retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
         /* Special case for dialog window procedure */
         if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
-        {
             retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
-            goto end;
+        else
+            retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
+        WIN_ReleasePtr( wndPtr );
+        return retvalue;
     }
-        goto end;
-    }
+
     switch(offset)
     {
-        case GWL_USERDATA:   retvalue = wndPtr->userdata;
-                             goto end;
-        case GWL_STYLE:      retvalue = wndPtr->dwStyle;
-                             goto end;
-        case GWL_EXSTYLE:    retvalue = wndPtr->dwExStyle;
-                             goto end;
-        case GWL_ID:         retvalue = (LONG)wndPtr->wIDmenu;
-                             goto end;
-        case GWL_WNDPROC:    retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
-                                                           type );
-                             goto end;
-        case GWL_HWNDPARENT: retvalue = (LONG)GetParent(hwnd);
-                             goto end;
-        case GWL_HINSTANCE:  retvalue = wndPtr->hInstance;
-                             goto end;
-        default:
-            WARN("Unknown offset %d\n", offset );
+    case GWL_USERDATA:   retvalue = wndPtr->userdata; break;
+    case GWL_STYLE:      retvalue = wndPtr->dwStyle; break;
+    case GWL_EXSTYLE:    retvalue = wndPtr->dwExStyle; break;
+    case GWL_ID:         retvalue = (LONG)wndPtr->wIDmenu; break;
+    case GWL_WNDPROC:    retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
+    case GWL_HINSTANCE:  retvalue = wndPtr->hInstance; break;
+    default:
+        WARN("Unknown offset %d\n", offset );
+        SetLastError( ERROR_INVALID_INDEX );
+        break;
     }
-    retvalue = 0;
-end:
-    WIN_ReleaseWndPtr(wndPtr);
+    WIN_ReleasePtr(wndPtr);
     return retvalue;
 }
 
@@ -1721,99 +1862,148 @@
  *
  * 0 is the failure code. However, in the case of failure SetLastError
  * must be set to distinguish between a 0 return value and a failure.
- *
- * FIXME: The error values for SetLastError may not be right. Can
- *        someone check with the real thing?
  */
 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
                                WINDOWPROCTYPE type )
 {
-    LONG *ptr, retval;
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
-    STYLESTRUCT style;
+    LONG retval = 0;
+    WND *wndPtr;
 
-    TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
+    TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
 
-    if (!wndPtr)
+    if (!WIN_IsCurrentThread( hwnd ))
     {
-       /* Is this the right error? */
-       SetLastError( ERROR_INVALID_WINDOW_HANDLE );
-       return 0;
+        ERR("set %x %d %x\n", hwnd, offset, newval );
+        return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
     }
 
+    wndPtr = WIN_GetPtr( hwnd );
+
     if (offset >= 0)
     {
-        if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
+        LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
+        if (offset > wndPtr->cbWndExtra - sizeof(LONG))
         {
             WARN("Invalid offset %d\n", offset );
-
-            /* Is this the right error? */
-            SetLastError( ERROR_OUTOFMEMORY );
-
-            retval = 0;
-            goto end;
+            WIN_ReleasePtr( wndPtr );
+            SetLastError( ERROR_INVALID_INDEX );
+            return 0;
         }
-        ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
         /* Special case for dialog window procedure */
         if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
         {
             retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
             WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
                              type, WIN_PROC_WINDOW );
-            goto end;
+            WIN_ReleasePtr( wndPtr );
+            return retval;
         }
+        retval = *ptr;
+        *ptr = newval;
+        WIN_ReleasePtr( wndPtr );
     }
-    else switch(offset)
+    else
     {
-	case GWL_ID:
-		ptr = (DWORD*)&wndPtr->wIDmenu;
-		break;
-	case GWL_HINSTANCE:
-                ptr = (DWORD*)&wndPtr->hInstance;
-                break;
-        case GWL_USERDATA:
-                ptr = &wndPtr->userdata;
-                break;
-        case GWL_HWNDPARENT:
-                retval = SetParent( hwnd, (HWND)newval );
-                goto end;
-	case GWL_WNDPROC:
-		retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
-		WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
-						type, WIN_PROC_WINDOW );
-		goto end;
-	case GWL_STYLE:
-                retval = wndPtr->dwStyle;
-	       	style.styleOld = wndPtr->dwStyle;
-		style.styleNew = newval;
-                SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
-		wndPtr->dwStyle = style.styleNew;
-                if (USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, retval );
-                SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
-                retval = style.styleOld;
-                goto end;
+        STYLESTRUCT style;
+        BOOL ok;
+
+        /* first some special cases */
+        switch( offset )
+        {
+        case GWL_STYLE:
         case GWL_EXSTYLE:
-	        style.styleOld = wndPtr->dwExStyle;
-		style.styleNew = newval;
-                SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
-		wndPtr->dwExStyle = style.styleNew;
-                SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
-                retval = style.styleOld;
-                goto end;
-
-	default:
+            style.styleOld = wndPtr->dwStyle;
+            style.styleNew = newval;
+            WIN_ReleasePtr( wndPtr );
+            SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
+            if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
+            newval = style.styleNew;
+            break;
+        case GWL_HWNDPARENT:
+            WIN_ReleasePtr( wndPtr );
+            return (LONG)SetParent( hwnd, (HWND)newval );
+        case GWL_WNDPROC:
+            retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
+            WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
+                             type, WIN_PROC_WINDOW );
+            WIN_ReleasePtr( wndPtr );
+            return retval;
+        case GWL_ID:
+        case GWL_HINSTANCE:
+        case GWL_USERDATA:
+            break;
+        default:
+            WIN_ReleasePtr( wndPtr );
             WARN("Invalid offset %d\n", offset );
+            SetLastError( ERROR_INVALID_INDEX );
+            return 0;
+        }
 
-            /* Don't think this is right error but it should do */
-            SetLastError( ERROR_OUTOFMEMORY );
+        SERVER_START_REQ( set_window_info )
+        {
+            req->handle = hwnd;
+            switch(offset)
+            {
+            case GWL_STYLE:
+                req->flags = SET_WIN_STYLE;
+                req->style = newval;
+                break;
+            case GWL_EXSTYLE:
+                req->flags = SET_WIN_EXSTYLE;
+                req->ex_style = newval;
+                break;
+            case GWL_ID:
+                req->flags = SET_WIN_ID;
+                req->id = newval;
+                break;
+            case GWL_HINSTANCE:
+                req->flags = SET_WIN_INSTANCE;
+                req->instance = (void *)newval;
+                break;
+            case GWL_USERDATA:
+                req->flags = SET_WIN_USERDATA;
+                req->user_data = (void *)newval;
+                break;
+            }
+            if ((ok = !SERVER_CALL_ERR()))
+            {
+                switch(offset)
+                {
+                case GWL_STYLE:
+                    wndPtr->dwStyle = newval;
+                    retval = req->old_style;
+                    break;
+                case GWL_EXSTYLE:
+                    wndPtr->dwExStyle = newval;
+                    retval = req->old_ex_style;
+                    break;
+                case GWL_ID:
+                    wndPtr->wIDmenu = newval;
+                    retval = req->old_id;
+                    break;
+                case GWL_HINSTANCE:
+                    wndPtr->hInstance = newval;
+                    retval = (HINSTANCE)req->old_instance;
+                    break;
+                case GWL_USERDATA:
+                    wndPtr->userdata = newval;
+                    retval = (ULONG_PTR)req->old_user_data;
+                    break;
+                }
+            }
+        }
+        SERVER_END_REQ;
+        WIN_ReleasePtr( wndPtr );
 
-            retval = 0;
-            goto end;
+        if (!ok) return 0;
+
+        if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
+            USER_Driver.pSetWindowStyle( hwnd, retval );
+
+        if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
+            SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
+
     }
-    retval = *ptr;
-    *ptr = newval;
-end:
-    WIN_ReleaseWndPtr(wndPtr);
     return retval;
 }
 
@@ -1928,15 +2118,6 @@
  * it sends WM_STYLECHANGING before changing the settings
  * and WM_STYLECHANGED afterwards.
  * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
- *
- * BUGS
- *
- * GWL_STYLE does not dispatch WM_STYLE... messages.
- *
- * CONFORMANCE
- *
- * ECMA-234, Win32
- *
  */
 LONG WINAPI SetWindowLongW(
     HWND hwnd,  /* [in] window to alter */
@@ -2089,13 +2270,33 @@
     WND *wndPtr;
     HWND retvalue = 0;
 
-    if ((wndPtr = WIN_FindWndPtr(hwnd)))
+    if (!(wndPtr = WIN_GetPtr( hwnd )))
     {
-        if (wndPtr->dwStyle & WS_CHILD)
-            retvalue = wndPtr->parent;
-        else if (wndPtr->dwStyle & WS_POPUP)
-            retvalue = wndPtr->owner;
-        WIN_ReleaseWndPtr(wndPtr);
+        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+        return 0;
+    }
+    if (wndPtr == WND_OTHER_PROCESS)
+    {
+        LONG style = GetWindowLongW( hwnd, GWL_STYLE );
+        if (style & (WS_POPUP | WS_CHILD))
+        {
+            SERVER_START_REQ( get_window_tree )
+            {
+                req->handle = hwnd;
+                if (!SERVER_CALL_ERR())
+                {
+                    if (style & WS_CHILD) retvalue = req->parent;
+                    else retvalue = req->owner;
+                }
+            }
+            SERVER_END_REQ;
+        }
+    }
+    else
+    {
+        if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
+        else if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
+        WIN_ReleasePtr( wndPtr );
     }
     return retvalue;
 }
@@ -2106,8 +2307,30 @@
  */
 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
 {
+    WND *win;
     HWND ret = 0;
-    size_t size = (type == GA_PARENT) ? sizeof(user_handle_t) : REQUEST_MAX_VAR_SIZE;
+    size_t size;
+
+    for (;;)
+    {
+        if (!(win = WIN_GetPtr( hwnd )))
+        {
+            SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+            return 0;
+        }
+        if (win == WND_OTHER_PROCESS) break;  /* need to do it the hard way */
+        ret = win->parent;
+        WIN_ReleasePtr( win );
+        if (type == GA_PARENT) return ret;
+        if (!ret || ret == GetDesktopWindow())
+        {
+            ret = hwnd;  /* if ret is the desktop, hwnd is the root ancestor */
+            goto done;
+        }
+        hwnd = ret;  /* restart with parent as hwnd */
+    }
+
+    size = (type == GA_PARENT) ? sizeof(user_handle_t) : REQUEST_MAX_VAR_SIZE;
 
     SERVER_START_VAR_REQ( get_window_parents, size )
     {
@@ -2134,6 +2357,7 @@
     }
     SERVER_END_VAR_REQ;
 
+ done:
     if (ret && type == GA_ROOTOWNER)
     {
         for (;;)
@@ -2148,16 +2372,28 @@
 
 
 /*****************************************************************
- *		WIN_SetParent
- *
- * Implementation of SetParent, runs in the thread owning the window.
+ *		SetParent (USER32.@)
  */
-HWND WIN_SetParent( HWND hwnd, HWND parent )
+HWND WINAPI SetParent( HWND hwnd, HWND parent )
 {
     WND *wndPtr;
-    HWND retvalue;
+    HWND retvalue, full_handle;
     BOOL was_visible;
 
+    if (!parent) parent = GetDesktopWindow();
+    else parent = WIN_GetFullHandle( parent );
+
+    if (!IsWindow( parent ))
+    {
+        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+        return 0;
+    }
+
+    if (!(full_handle = WIN_IsCurrentThread( hwnd )))
+        return SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
+
+    hwnd = full_handle;
+
     if (USER_Driver.pSetParent)
         return USER_Driver.pSetParent( hwnd, parent );
 
@@ -2196,34 +2432,6 @@
 }
 
 
-/*****************************************************************
- *		SetParent (USER32.@)
- */
-HWND WINAPI SetParent( HWND hwnd, HWND parent )
-{
-    HWND full_handle;
-
-    if (!parent) parent = GetDesktopWindow();
-    else parent = WIN_GetFullHandle( parent );
-
-    if (!IsWindow( parent ))
-    {
-        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
-        return 0;
-    }
-
-    if ((full_handle = WIN_IsCurrentThread( hwnd )))
-        return WIN_SetParent( full_handle, parent );
-
-    if ((full_handle = WIN_GetFullHandle(hwnd)) == GetDesktopWindow())
-    {
-        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
-        return 0;
-    }
-    return SendMessageW( full_handle, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
-}
-
-
 /*******************************************************************
  *		IsChild (USER32.@)
  */
@@ -2305,13 +2513,21 @@
 {
     HWND retval = 0;
 
-    if (rel == GW_OWNER)  /* special case: not fully supported in the server yet */
+    if (rel == GW_OWNER)  /* this one may be available locally */
     {
-        WND *wndPtr = WIN_FindWndPtr( hwnd );
-        if (!wndPtr) return 0;
-        retval = wndPtr->owner;
-        WIN_ReleaseWndPtr( wndPtr );
-        return retval;
+        WND *wndPtr = WIN_GetPtr( hwnd );
+        if (!wndPtr)
+        {
+            SetLastError( ERROR_INVALID_HANDLE );
+            return 0;
+        }
+        if (wndPtr != WND_OTHER_PROCESS)
+        {
+            retval = wndPtr->owner;
+            WIN_ReleasePtr( wndPtr );
+            return retval;
+        }
+        /* else fall through to server call */
     }
 
     SERVER_START_REQ( get_window_tree )
@@ -2333,6 +2549,9 @@
             case GW_HWNDPREV:
                 retval = req->prev_sibling;
                 break;
+            case GW_OWNER:
+                retval = req->owner;
+                break;
             case GW_CHILD:
                 retval = req->first_child;
                 break;
diff --git a/windows/winpos.c b/windows/winpos.c
index 448e448..f288fcb 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -215,15 +215,25 @@
 int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
 {
     int nRet = ERROR;
-    WND *wndPtr = WIN_FindWndPtr( hwnd );
-    if (wndPtr)
+    WND *wndPtr = WIN_GetPtr( hwnd );
+
+    if (wndPtr == WND_OTHER_PROCESS)
     {
-        if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY );
-        WIN_ReleaseWndPtr(wndPtr);
+        if (IsWindow( hwnd ))
+            FIXME( "not supported on other process window %x\n", hwnd );
+        wndPtr = NULL;
     }
+    if (!wndPtr)
+    {
+        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+        return ERROR;
+    }
+    if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY );
+    WIN_ReleasePtr( wndPtr );
     return nRet;
 }
 
+
 /***********************************************************************
  *		SetWindowRgn (USER32.@)
  */
@@ -231,22 +241,31 @@
 {
     RECT rect;
     WND *wndPtr;
-    int ret = FALSE;
+
+    if (hrgn) /* verify that region really exists */
+    {
+        if (GetRgnBox( hrgn, &rect ) == ERROR) return FALSE;
+    }
 
     if (USER_Driver.pSetWindowRgn)
         return USER_Driver.pSetWindowRgn( hwnd, hrgn, bRedraw );
 
-    if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
+    if ((wndPtr = WIN_GetPtr( hwnd )) == WND_OTHER_PROCESS)
+    {
+        if (IsWindow( hwnd ))
+            FIXME( "not supported on other process window %x\n", hwnd );
+        wndPtr = NULL;
+    }
+    if (!wndPtr)
+    {
+        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+        return FALSE;
+    }
 
     if (wndPtr->hrgnWnd == hrgn)
     {
-        ret = TRUE;
-        goto done;
-    }
-
-    if (hrgn) /* verify that region really exists */
-    {
-        if (GetRgnBox( hrgn, &rect ) == ERROR) goto done;
+        WIN_ReleasePtr( wndPtr );
+        return TRUE;
     }
 
     if (wndPtr->hrgnWnd)
@@ -256,17 +275,14 @@
         wndPtr->hrgnWnd = 0;
     }
     wndPtr->hrgnWnd = hrgn;
+    WIN_ReleasePtr( wndPtr );
 
     /* Size the window to the rectangle of the new region (if it isn't NULL) */
     if (hrgn) SetWindowPos( hwnd, 0, rect.left, rect.top,
                             rect.right  - rect.left, rect.bottom - rect.top,
                             SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOACTIVATE |
                             SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) );
-    ret = TRUE;
-
- done:
-    WIN_ReleaseWndPtr(wndPtr);
-    return ret;
+    return TRUE;
 }