Renamed WIN_GetWndPtr into WIN_GetPtr and added corresponding
WIN_ReleasePtr. Started using it instead of WIN_FindWndPtr where we
don't need to access windows of other processes.

diff --git a/controls/icontitle.c b/controls/icontitle.c
index 85bcd42..c048092 100644
--- a/controls/icontitle.c
+++ b/controls/icontitle.c
@@ -46,25 +46,22 @@
     WND* wndPtr;
     HWND hWnd;
     HINSTANCE instance = GetWindowLongA( owner, GWL_HINSTANCE );
+    LONG style = WS_CLIPSIBLINGS;
 
+    if (!IsWindowEnabled(owner)) style |= WS_DISABLED;
     if( GetWindowLongA( owner, GWL_STYLE ) & WS_CHILD )
 	hWnd = CreateWindowExA( 0, ICONTITLE_CLASS_ATOM, NULL,
-				  WS_CHILD | WS_CLIPSIBLINGS, 0, 0, 1, 1,
-				  GetParent(owner), 0, instance, NULL );
+                                style | WS_CHILD, 0, 0, 1, 1,
+                                GetParent(owner), 0, instance, NULL );
     else
 	hWnd = CreateWindowExA( 0, ICONTITLE_CLASS_ATOM, NULL,
-				  WS_CLIPSIBLINGS, 0, 0, 1, 1,
-				  owner, 0, instance, NULL );
-    wndPtr = WIN_FindWndPtr( hWnd );
-    if( wndPtr )
-    {
-        wndPtr->owner = owner; /* MDI depends on this */
-	wndPtr->dwStyle &= ~(WS_CAPTION | WS_BORDER);
-        if (!IsWindowEnabled(owner)) wndPtr->dwStyle |= WS_DISABLED;
-        WIN_ReleaseWndPtr(wndPtr);
-	return hWnd;
-    }
-    return 0;
+                                style, 0, 0, 1, 1,
+                                owner, 0, instance, NULL );
+    if (!(wndPtr = WIN_GetPtr( hWnd ))) return 0;
+    wndPtr->owner = owner; /* MDI depends on this */
+    wndPtr->dwStyle &= ~(WS_CAPTION | WS_BORDER);
+    WIN_ReleasePtr(wndPtr);
+    return hWnd;
 }
 
 /***********************************************************************
diff --git a/controls/scroll.c b/controls/scroll.c
index 02720b5..60d8ce6 100644
--- a/controls/scroll.c
+++ b/controls/scroll.c
@@ -791,7 +791,7 @@
     if (!wndPtr || !infoPtr ||
         ((nBar == SB_VERT) && !(wndPtr->dwStyle & WS_VSCROLL)) ||
         ((nBar == SB_HORZ) && !(wndPtr->dwStyle & WS_HSCROLL))) goto END;
-    if (!WIN_IsWindowDrawable( wndPtr, FALSE )) goto END;
+    if (!WIN_IsWindowDrawable( hwnd, FALSE )) goto END;
     hwnd = wndPtr->hwndSelf;  /* make it a full handle */
 
     vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
diff --git a/dlls/user/msg16.c b/dlls/user/msg16.c
index 2ed9979..29c1941 100644
--- a/dlls/user/msg16.c
+++ b/dlls/user/msg16.c
@@ -5,6 +5,7 @@
  */
 
 #include "wine/winuser16.h"
+#include "winerror.h"
 #include "heap.h"
 #include "hook.h"
 #include "message.h"
@@ -263,35 +264,44 @@
         }
     }
 
-    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
-    if (!wndPtr->winproc)
+    if (!(wndPtr = WIN_GetPtr( msg->hwnd )))
     {
-        WIN_ReleaseWndPtr( wndPtr );
+        if (msg->hwnd) SetLastError( ERROR_INVALID_WINDOW_HANDLE );
         return 0;
     }
-    winproc = (WNDPROC16)wndPtr->winproc;
+    if (wndPtr == WND_OTHER_PROCESS)
+    {
+        if (IsWindow( msg->hwnd ))
+            ERR( "cannot dispatch msg to other process window %x\n", msg->hwnd );
+        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+        return 0;
+    }
+
+    if (!(winproc = (WNDPROC16)wndPtr->winproc))
+    {
+        WIN_ReleasePtr( wndPtr );
+        return 0;
+    }
     painting = (msg->message == WM_PAINT);
     if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT;
-    WIN_ReleaseWndPtr( wndPtr );
+    WIN_ReleasePtr( wndPtr );
 
     SPY_EnterMessage( SPY_DISPATCHMESSAGE16, hwnd, msg->message, msg->wParam, msg->lParam );
     retval = CallWindowProc16( winproc, msg->hwnd, msg->message, msg->wParam, msg->lParam );
     SPY_ExitMessage( SPY_RESULT_OK16, hwnd, msg->message, retval, msg->wParam, msg->lParam );
 
-    if (!painting) return retval;
-
-    if ((wndPtr = WIN_FindWndPtr( hwnd )))
+    if (painting && (wndPtr = WIN_GetPtr( hwnd )) && (wndPtr != WND_OTHER_PROCESS))
     {
-        if ((wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate)
+        BOOL validate = ((wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate);
+        wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
+        WIN_ReleasePtr( wndPtr );
+        if (validate)
         {
             ERR( "BeginPaint not called on WM_PAINT for hwnd %04x!\n", msg->hwnd );
-            wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
-            WIN_ReleaseWndPtr( wndPtr );
             /* Validate the update region to avoid infinite WM_PAINT loop */
             RedrawWindow( hwnd, NULL, 0,
                           RDW_NOFRAME | RDW_VALIDATE | RDW_NOCHILDREN | RDW_NOINTERNALPAINT );
         }
-        else WIN_ReleaseWndPtr( wndPtr );
     }
     return retval;
 }
diff --git a/dlls/x11drv/desktop.c b/dlls/x11drv/desktop.c
index b78da81..5576f14 100644
--- a/dlls/x11drv/desktop.c
+++ b/dlls/x11drv/desktop.c
@@ -54,11 +54,11 @@
     hwnd = GetDesktopWindow();
 
     /* patch the desktop window queue to point to our queue */
-    win = WIN_FindWndPtr( hwnd );
+    win = WIN_GetPtr( hwnd );
     win->tid = GetCurrentThreadId();
     win->hmemTaskQ = InitThreadInput16( 0, 0 );
     X11DRV_register_window( display, hwnd, win->pDriverData );
-    WIN_ReleaseWndPtr( win );
+    WIN_ReleasePtr( win );
 
     SetWindowLongW( hwnd, GWL_WNDPROC, (LONG)desktop_winproc );
     wine_tsx11_lock();
diff --git a/dlls/x11drv/scroll.c b/dlls/x11drv/scroll.c
index ab506c4..443c6d2 100644
--- a/dlls/x11drv/scroll.c
+++ b/dlls/x11drv/scroll.c
@@ -142,16 +142,9 @@
     INT  retVal = NULLREGION;
     BOOL bCaret = FALSE, bOwnRgn = TRUE;
     RECT rc, cliprc;
-    WND*   wnd = WIN_FindWndPtr( hwnd );
 
-    if (!wnd) return ERROR;
-    if (!WIN_IsWindowDrawable( wnd, TRUE ))
-    {
-        WIN_ReleaseWndPtr( wnd );
-        return ERROR;
-    }
-    hwnd = wnd->hwndSelf;  /* make it a full handle */
-    WIN_ReleaseWndPtr( wnd );
+    if (!WIN_IsWindowDrawable( hwnd, TRUE )) return ERROR;
+    hwnd = WIN_GetFullHandle( hwnd );
 
     GetClientRect(hwnd, &rc);
     if (rect) IntersectRect(&rc, &rc, rect);
diff --git a/dlls/x11drv/window.c b/dlls/x11drv/window.c
index b1a5905..b9023c7 100644
--- a/dlls/x11drv/window.c
+++ b/dlls/x11drv/window.c
@@ -45,6 +45,9 @@
 Atom kwmDockWindow = None;
 Atom _kde_net_wm_system_tray_window_for = None; /* KDE 2 Final */
 
+static LPCSTR whole_window_atom;
+static LPCSTR client_window_atom;
+static LPCSTR icon_window_atom;
 
 /***********************************************************************
  *		is_window_managed
@@ -197,7 +200,7 @@
     wine_tsx11_unlock();
 
     TRACE( "created %lx\n", data->icon_window );
-    SetPropA( win->hwndSelf, "__wine_x11_icon_window", (HANDLE)data->icon_window );
+    SetPropA( win->hwndSelf, icon_window_atom, (HANDLE)data->icon_window );
     return data->icon_window;
 }
 
@@ -216,7 +219,7 @@
     XDestroyWindow( display, data->icon_window );
     data->icon_window = 0;
     wine_tsx11_unlock();
-    RemovePropA( win->hwndSelf, "__wine_x11_icon_window" );
+    RemovePropA( win->hwndSelf, icon_window_atom );
 }
 
 
@@ -600,11 +603,15 @@
     _kde_net_wm_system_tray_window_for = XInternAtom( display, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False );
     wine_tsx11_unlock();
 
+    whole_window_atom  = MAKEINTATOMA( GlobalAddAtomA( "__wine_x11_whole_window" ));
+    client_window_atom = MAKEINTATOMA( GlobalAddAtomA( "__wine_x11_client_window" ));
+    icon_window_atom   = MAKEINTATOMA( GlobalAddAtomA( "__wine_x11_icon_window" ));
+
     data->whole_window = data->client_window = root_window;
     data->whole_rect = data->client_rect = wndPtr->rectWindow;
 
-    SetPropA( wndPtr->hwndSelf, "__wine_x11_whole_window", (HANDLE)root_window );
-    SetPropA( wndPtr->hwndSelf, "__wine_x11_client_window", (HANDLE)root_window );
+    SetPropA( wndPtr->hwndSelf, whole_window_atom, (HANDLE)root_window );
+    SetPropA( wndPtr->hwndSelf, client_window_atom, (HANDLE)root_window );
     SetPropA( wndPtr->hwndSelf, "__wine_x11_visual_id", (HANDLE)XVisualIDFromVisual(visual) );
 
     SendMessageW( wndPtr->hwndSelf, WM_NCCREATE, 0, (LPARAM)cs );
@@ -717,10 +724,8 @@
     char *utf8_buffer;
     static UINT text_cp = (UINT)-1;
     Window win;
-    WND *wndPtr = WIN_FindWndPtr( hwnd );
 
-    if (!wndPtr) return FALSE;
-    if ((win = get_whole_window(wndPtr)))
+    if ((win = X11DRV_get_whole_window( hwnd )))
     {
         if (text_cp == (UINT)-1)
         {
@@ -743,7 +748,6 @@
         if (!(buffer = HeapAlloc( GetProcessHeap(), 0, count )))
         {
             ERR("Not enough memory for window text\n");
-            WIN_ReleaseWndPtr( wndPtr );
             return FALSE;
         }
         WideCharToMultiByte(text_cp, 0, text, -1, buffer, count, NULL, NULL);
@@ -752,7 +756,6 @@
         if (!(utf8_buffer = HeapAlloc( GetProcessHeap(), 0, count )))
         {
             ERR("Not enough memory for window text in UTF-8\n");
-            WIN_ReleaseWndPtr( wndPtr );
             return FALSE;
         }
         WideCharToMultiByte(CP_UTF8, 0, text, strlenW(text), utf8_buffer, count, NULL, NULL);
@@ -775,7 +778,6 @@
         HeapFree( GetProcessHeap(), 0, utf8_buffer );
         HeapFree( GetProcessHeap(), 0, buffer );
     }
-    WIN_ReleaseWndPtr( wndPtr );
     return TRUE;
 }
 
@@ -786,7 +788,7 @@
 BOOL X11DRV_DestroyWindow( HWND hwnd )
 {
     Display *display = thread_display();
-    WND *wndPtr = WIN_FindWndPtr( hwnd );
+    WND *wndPtr = WIN_GetPtr( hwnd );
     X11DRV_WND_DATA *data = wndPtr->pDriverData;
 
     if (!data) goto done;
@@ -808,7 +810,7 @@
     HeapFree( GetProcessHeap(), 0, data );
     wndPtr->pDriverData = NULL;
  done:
-    WIN_ReleaseWndPtr( wndPtr );
+    WIN_ReleasePtr( wndPtr );
     return TRUE;
 }
 
@@ -847,8 +849,8 @@
 
     WIN_ReleaseWndPtr( wndPtr );
 
-    SetPropA( hwnd, "__wine_x11_whole_window", (HANDLE)data->whole_window );
-    SetPropA( hwnd, "__wine_x11_client_window", (HANDLE)data->client_window );
+    SetPropA( hwnd, whole_window_atom, (HANDLE)data->whole_window );
+    SetPropA( hwnd, client_window_atom, (HANDLE)data->client_window );
 
     /* send WM_NCCREATE */
     TRACE( "hwnd %x cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cs->cx, cs->cy );
@@ -958,12 +960,16 @@
 Window X11DRV_get_client_window( HWND hwnd )
 {
     Window ret = 0;
-    WND *win = WIN_FindWndPtr( hwnd );
+    WND *win = WIN_GetPtr( hwnd );
+
+    if (win == WND_OTHER_PROCESS)
+        return GetPropA( hwnd, client_window_atom );
+
     if (win)
     {
         struct x11drv_win_data *data = win->pDriverData;
         ret = data->client_window;
-        WIN_ReleaseWndPtr( win );
+        WIN_ReleasePtr( win );
     }
     return ret;
 }
@@ -977,12 +983,16 @@
 Window X11DRV_get_whole_window( HWND hwnd )
 {
     Window ret = 0;
-    WND *win = WIN_FindWndPtr( hwnd );
+    WND *win = WIN_GetPtr( hwnd );
+
+    if (win == WND_OTHER_PROCESS)
+        return GetPropA( hwnd, whole_window_atom );
+
     if (win)
     {
         struct x11drv_win_data *data = win->pDriverData;
         ret = data->whole_window;
-        WIN_ReleaseWndPtr( win );
+        WIN_ReleasePtr( win );
     }
     return ret;
 }
@@ -1176,19 +1186,15 @@
  */
 HICON X11DRV_SetWindowIcon( HWND hwnd, HICON icon, BOOL small )
 {
+    WND *wndPtr;
     Display *display = thread_display();
-    WND *wndPtr = WIN_FindWndPtr( hwnd );
-    int index = small ? GCL_HICONSM : GCL_HICON;
-    HICON old;
-
-    if (!wndPtr) return 0;
-
-    old = GetClassLongW( hwnd, index );
-    SetClassLongW( hwnd, index, icon );
+    HICON old = SetClassLongW( hwnd, small ? GCL_HICONSM : GCL_HICON, icon );
 
     SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE |
                   SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
 
+    if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return old;
+
     if (wndPtr->dwExStyle & WS_EX_MANAGED)
     {
         Window win = get_whole_window(wndPtr);
@@ -1202,7 +1208,6 @@
             TSXFree( wm_hints );
         }
     }
-
-    WIN_ReleaseWndPtr( wndPtr );
+    WIN_ReleasePtr( wndPtr );
     return old;
 }
diff --git a/dlls/x11drv/winpos.c b/dlls/x11drv/winpos.c
index 1852df1..ba7e4fa 100644
--- a/dlls/x11drv/winpos.c
+++ b/dlls/x11drv/winpos.c
@@ -148,7 +148,7 @@
 
     if (top && top != win->hwndSelf)  /* need to clip siblings of ancestors */
     {
-        WND *parent, *ptr = WIN_LockWndPtr( win );
+        WND *parent, *ptr = WIN_FindWndPtr( win->hwndSelf );
         HRGN tmp = 0;
 
         OffsetRgn( rgn, xoffset, yoffset );
@@ -194,7 +194,7 @@
 {
     HRGN tmp;
     int ret;
-    WND *parent, *ptr = WIN_LockWndPtr( win );
+    WND *parent, *ptr = WIN_FindWndPtr( win->hwndSelf );
     int xoffset = 0, yoffset = 0;
 
     tmp = CreateRectRgn( 0, 0, 0, 0 );
@@ -384,7 +384,7 @@
     rect.right  = rect.left + event->width;
     rect.bottom = rect.top + event->height;
 
-    if (!(win = WIN_FindWndPtr(hwnd))) return;
+    if (!(win = WIN_GetPtr( hwnd ))) return;
     data = win->pDriverData;
 
     if (event->window != data->client_window)  /* whole window or icon window */
@@ -393,7 +393,7 @@
         /* make position relative to client area instead of window */
         OffsetRect( &rect, -data->client_rect.left, -data->client_rect.top );
     }
-    WIN_ReleaseWndPtr( win );
+    WIN_ReleasePtr( win );
 
     expose_window( hwnd, &rect, 0, flags );
 }
@@ -1434,7 +1434,7 @@
     WINDOWPOS winpos;
     int x = event->x, y = event->y;
 
-    if (!(win = WIN_FindWndPtr( hwnd ))) return;
+    if (!(win = WIN_GetPtr( hwnd ))) return;
     data = win->pDriverData;
 
     /* Get geometry */
@@ -1455,7 +1455,7 @@
            hwnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top,
            event->x, event->y, event->width, event->height );
     X11DRV_X_to_window_rect( win, &rect );
-    WIN_ReleaseWndPtr( win );
+    WIN_ReleasePtr( win );
 
     winpos.hwnd  = hwnd;
     winpos.x     = rect.left;
diff --git a/include/win.h b/include/win.h
index f454d11..dcd7ed0 100644
--- a/include/win.h
+++ b/include/win.h
@@ -14,6 +14,8 @@
 #include "winuser.h"
 #include "wine/windef16.h"
 
+#include "user.h"
+
 #define WND_MAGIC     0x444e4957  /* 'WIND' */
 
 struct tagCLASS;
@@ -76,22 +78,20 @@
 #define WIN_NEEDS_INTERNALSOP  0x1000 /* Window was hidden by WIN_InternalShowOwnedPopups */
 
   /* Window functions */
-extern WND *WIN_GetWndPtr( HWND hwnd );
+extern WND *WIN_GetPtr( HWND hwnd );
 extern int    WIN_SuspendWndsLock( void );
 extern void   WIN_RestoreWndsLock(int ipreviousLock);
 extern WND*   WIN_FindWndPtr( HWND hwnd );
-extern WND*   WIN_LockWndPtr(WND *wndPtr);
 extern void   WIN_ReleaseWndPtr(WND *wndPtr);
-extern void   WIN_UpdateWndPtr(WND **oldPtr,WND *newPtr);
 extern HWND WIN_Handle32( HWND16 hwnd16 );
-extern BOOL WIN_IsCurrentProcess( HWND hwnd );
-extern BOOL WIN_IsCurrentThread( HWND hwnd );
+extern HWND WIN_IsCurrentProcess( HWND hwnd );
+extern HWND WIN_IsCurrentThread( HWND hwnd );
 extern void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter );
 extern void WIN_UnlinkWindow( HWND hwnd );
 extern HWND WIN_FindWinToRepaint( HWND hwnd );
 extern void WIN_DestroyThreadWindows( HWND hwnd );
 extern BOOL WIN_CreateDesktopWindow(void);
-extern BOOL WIN_IsWindowDrawable(WND*, BOOL );
+extern BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL );
 extern HWND *WIN_ListParents( HWND hwnd );
 extern HWND *WIN_ListChildren( HWND hwnd );
 extern BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly );
@@ -113,7 +113,13 @@
     return WIN_FindWndPtr( (HWND)(ULONG_PTR)hwnd );
 }
 
-#define BAD_WND_PTR ((WND *)1)  /* returned by WIN_GetWndPtr on bad window handles */
+/* to release pointers retrieved by WIN_GetPtr; do not confuse with WIN_ReleaseWndPtr!! */
+inline static void WIN_ReleasePtr( WND *ptr )
+{
+    USER_Unlock();
+}
+
+#define WND_OTHER_PROCESS ((WND *)1)  /* returned by WIN_GetPtr on unknown window handles */
 
 extern HWND CARET_GetHwnd(void);
 extern void CARET_GetRect(LPRECT lprc);  /* windows/caret.c */
diff --git a/windows/class.c b/windows/class.c
index 1ec7797..9c5724a 100644
--- a/windows/class.c
+++ b/windows/class.c
@@ -58,25 +58,27 @@
 /***********************************************************************
  *           get_class_ptr
  */
-static CLASS *get_class_ptr( HWND hwnd )
+static CLASS *get_class_ptr( HWND hwnd, BOOL write_access )
 {
-    CLASS *ret = NULL;
-    WND *ptr = WIN_GetWndPtr( hwnd );
+    WND *ptr = WIN_GetPtr( hwnd );
 
-    if (!ptr)
+    if (ptr)
     {
+        if (ptr != WND_OTHER_PROCESS) return ptr->class;
         if (IsWindow( hwnd )) /* check other processes */
         {
-            ERR( "class of window %04x belongs to other process\n", hwnd );
+            if (write_access)
+            {
+                /* modifying classes in other processes is not allowed */
+                SetLastError( ERROR_ACCESS_DENIED );
+                return NULL;
+            }
+            FIXME( "reading from class of other process window %04x\n", hwnd );
             /* DbgBreakPoint(); */
         }
     }
-    else
-    {
-        if (ptr != BAD_WND_PTR) ret = ptr->class;
-        else SetLastError( ERROR_INVALID_WINDOW_HANDLE );
-    }
-    return ret;
+    SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+    return NULL;
 }
 
 
@@ -741,7 +743,7 @@
 
     TRACE("%x %x\n",hwnd, offset);
 
-    if (!(class = get_class_ptr( hwnd ))) return 0;
+    if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
 
     if (offset <= class->cbClsExtra - sizeof(WORD))
         retvalue = GET_WORD((char *)(class + 1) + offset);
@@ -766,7 +768,7 @@
     switch( offset )
     {
     case GCL_WNDPROC:
-        if (!(class = get_class_ptr( hwnd ))) return 0;
+        if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
         ret = (LONG)CLASS_GetProc( class, WIN_PROC_16 );
         release_class_ptr( class );
         return ret;
@@ -789,7 +791,7 @@
 
     TRACE("%x %d\n", hwnd, offset);
 
-    if (!(class = get_class_ptr( hwnd ))) return 0;
+    if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
 
     if (offset >= 0)
     {
@@ -858,7 +860,7 @@
 
     TRACE("%x %d\n", hwnd, offset);
 
-    if (!(class = get_class_ptr( hwnd ))) return 0;
+    if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
 
     if (offset == GCL_WNDPROC)
         retvalue = (LONG)CLASS_GetProc( class, WIN_PROC_32W );
@@ -882,7 +884,7 @@
 
     TRACE("%x %d %x\n", hwnd, offset, newval);
 
-    if (!(class = get_class_ptr( hwnd ))) return 0;
+    if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
 
     if (offset <= class->cbClsExtra - sizeof(WORD))
     {
@@ -911,7 +913,7 @@
     switch(offset)
     {
     case GCL_WNDPROC:
-        if (!(class = get_class_ptr( hwnd ))) return 0;
+        if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
         retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_16 );
         release_class_ptr( class );
         return retval;
@@ -934,7 +936,7 @@
 
     TRACE("%x %d %lx\n", hwnd, offset, newval);
 
-    if (!(class = get_class_ptr( hwnd ))) return 0;
+    if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
 
     if (offset >= 0)
     {
@@ -979,10 +981,6 @@
         retval = (LONG)class->cbWndExtra;
         class->cbWndExtra = newval;
         break;
-    case GCL_CBCLSEXTRA:
-        retval = (LONG)class->cbClsExtra;
-        class->cbClsExtra = newval;
-        break;
     case GCL_HMODULE:
         retval = (LONG)class->hInstance;
         class->hInstance = newval;
@@ -991,6 +989,9 @@
         retval = (DWORD)class->atomName;
         class->atomName = newval;
         break;
+    case GCL_CBCLSEXTRA:  /* cannot change this one */
+        SetLastError( ERROR_INVALID_PARAMETER );
+        break;
     default:
         SetLastError( ERROR_INVALID_INDEX );
         break;
@@ -1013,7 +1014,7 @@
 
     TRACE("%x %d %lx\n", hwnd, offset, newval);
 
-    if (!(class = get_class_ptr( hwnd ))) return 0;
+    if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
 
     if (offset == GCL_WNDPROC)
         retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_32W );
@@ -1032,12 +1033,7 @@
  */
 INT WINAPI GetClassNameA( HWND hwnd, LPSTR buffer, INT count )
 {
-    INT ret;
-    CLASS *class;
-
-    if (!(class = get_class_ptr( hwnd ))) return 0;
-    ret = GlobalGetAtomNameA( class->atomName, buffer, count );
-    release_class_ptr( class );
+    INT ret = GlobalGetAtomNameA( GetClassLongA( hwnd, GCW_ATOM ), buffer, count );
 
     TRACE("%x %s %x\n",hwnd, debugstr_a(buffer), count);
     return ret;
@@ -1049,12 +1045,7 @@
  */
 INT WINAPI GetClassNameW( HWND hwnd, LPWSTR buffer, INT count )
 {
-    INT ret;
-    CLASS *class;
-
-    if (!(class = get_class_ptr( hwnd ))) return 0;
-    ret = GlobalGetAtomNameW( class->atomName, buffer, count );
-    release_class_ptr( class );
+    INT ret = GlobalGetAtomNameW( GetClassLongW( hwnd, GCW_ATOM ), buffer, count );
 
     TRACE("%x %s %x\n",hwnd, debugstr_w(buffer), count);
     return ret;
diff --git a/windows/dce.c b/windows/dce.c
index d9cf0d7..c8e1688 100644
--- a/windows/dce.c
+++ b/windows/dce.c
@@ -274,65 +274,42 @@
 
 	for (dce = firstDCE; (dce); dce = dce->next)
 	{
-            WND* wndCurrent;
-            HWND tmp;
-            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;
 
             /* check if DCE window is within the z-order scope */
 
-            for (tmp = dce->hwndCurrent; tmp; tmp = GetAncestor( tmp, GA_PARENT ))
+            if (hwndScope == dce->hwndCurrent || IsChild( hwndScope, dce->hwndCurrent ))
             {
-                if (tmp == hwndScope )
+                if (hwnd != dce->hwndCurrent)
                 {
-                    RECT wndRect;
+                    /* check if the window rectangle intersects this DCE window */
+                    RECT rect;
+                    GetWindowRect( dce->hwndCurrent, &rect );
+                    MapWindowPoints( 0, hwndScope, (POINT *)&rect, 2 );
+                    if (!IntersectRect( &rect, &rect, pRectUpdate )) continue;
 
-                    wndRect = wndCurrent->rectWindow;
+                }
+                if( !(dce->DCXflags & DCX_DCEBUSY) )
+                {
+                    /* Don't bother with visible regions of unused DCEs */
 
-                    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;
-                        }
-                    }
-                    break;
+                    TRACE("\tpurged %p dce [%04x]\n", dce, dce->hwndCurrent);
+                    dce->hwndCurrent = 0;
+                    dce->DCXflags &= DCX_CACHE;
+                    dce->DCXflags |= DCX_DCEEMPTY;
                 }
                 else
                 {
-                    WND* wnd = WIN_FindWndPtr( tmp );
-                    xoffset += wnd->rectClient.left;
-                    yoffset += wnd->rectClient.top;
-                    WIN_ReleaseWndPtr( wnd );
+                    /* Set dirty bits in the hDC and DCE structs */
+
+                    TRACE("\tfixed up %p dce [%04x]\n", dce, dce->hwndCurrent);
+                    dce->DCXflags |= DCX_DCEDIRTY;
+                    SetHookFlags16(dce->hDC, DCHF_INVALIDATEVISRGN);
+                    bRet = TRUE;
                 }
             }
-            WIN_ReleaseWndPtr(wndCurrent);
 	} /* dce list */
     }
     return bRet;
diff --git a/windows/defdlg.c b/windows/defdlg.c
index 3cc9b71..d63c9e3 100644
--- a/windows/defdlg.c
+++ b/windows/defdlg.c
@@ -12,6 +12,9 @@
 #include "controls.h"
 #include "win.h"
 #include "winproc.h"
+#include "debugtools.h"
+
+DEFAULT_DEBUG_CHANNEL(dialog);
 
 
 /***********************************************************************
@@ -19,13 +22,17 @@
  */
 static WNDPROC DEFDLG_GetDlgProc( HWND hwnd )
 {
-    WNDPROC ret = 0;
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
-    if (wndPtr)
+    WNDPROC ret;
+    WND *wndPtr = WIN_GetPtr( hwnd );
+
+    if (!wndPtr) return 0;
+    if (wndPtr == WND_OTHER_PROCESS)
     {
-        ret = *(WNDPROC *)((char *)wndPtr->wExtra + DWL_DLGPROC);
-        WIN_ReleaseWndPtr(wndPtr);
+        ERR( "cannot get dlg proc %x from other process\n", hwnd );
+        return 0;
     }
+    ret = *(WNDPROC *)((char *)wndPtr->wExtra + DWL_DLGPROC);
+    WIN_ReleasePtr( wndPtr );
     return ret;
 }
 
diff --git a/windows/defwnd.c b/windows/defwnd.c
index 8567523..f7573d6 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -38,10 +38,10 @@
 static void DEFWND_HandleWindowPosChanged( HWND hwnd, UINT flags )
 {
     RECT rect;
-    WND *wndPtr = WIN_FindWndPtr( hwnd );
+    WND *wndPtr = WIN_GetPtr( hwnd );
 
     rect = wndPtr->rectClient;
-    WIN_ReleaseWndPtr( wndPtr );
+    WIN_ReleasePtr( wndPtr );
 
     if (!(flags & SWP_NOCLIENTMOVE))
         SendMessageW( hwnd, WM_MOVE, 0, MAKELONG(rect.left, rect.top));
@@ -96,14 +96,14 @@
     if (!text) text = empty_string;
     count = strlenW(text) + 1;
 
-    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
+    if (!(wndPtr = WIN_GetPtr( hwnd ))) return;
     if (wndPtr->text) HeapFree(GetProcessHeap(), 0, wndPtr->text);
     if ((wndPtr->text = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR))))
 	strcpyW( wndPtr->text, text );
     else
         ERR("Not enough memory for window text\n");
     text = wndPtr->text;
-    WIN_ReleaseWndPtr( wndPtr );
+    WIN_ReleasePtr( wndPtr );
 
     if (USER_Driver.pSetWindowText) USER_Driver.pSetWindowText( hwnd, text );
 }
@@ -357,9 +357,9 @@
         {
             LONG hitcode;
             POINT pt;
-            WND *wndPtr = WIN_FindWndPtr( hwnd );
+            WND *wndPtr = WIN_GetPtr( hwnd );
             HMENU hMenu = wndPtr->hSysMenu;
-            WIN_ReleaseWndPtr( wndPtr );
+            WIN_ReleasePtr( wndPtr );
             if (!hMenu) return 0;
             pt.x = SLOWORD(lParam);
             pt.y = SHIWORD(lParam);
@@ -378,14 +378,14 @@
 
     case WM_NCDESTROY:
         {
-            WND *wndPtr = WIN_FindWndPtr( hwnd );
+            WND *wndPtr = WIN_GetPtr( hwnd );
             if (!wndPtr) return 0;
             if (wndPtr->text) HeapFree( GetProcessHeap(), 0, wndPtr->text );
             wndPtr->text = NULL;
             if (wndPtr->pVScroll) HeapFree( GetProcessHeap(), 0, wndPtr->pVScroll );
             if (wndPtr->pHScroll) HeapFree( GetProcessHeap(), 0, wndPtr->pHScroll );
             wndPtr->pVScroll = wndPtr->pHScroll = NULL;
-            WIN_ReleaseWndPtr( wndPtr );
+            WIN_ReleasePtr( wndPtr );
             return 0;
         }
 
@@ -607,9 +607,9 @@
 
     case WM_ISACTIVEICON:
         {
-            WND *wndPtr = WIN_FindWndPtr( hwnd );
+            WND *wndPtr = WIN_GetPtr( hwnd );
             BOOL ret = (wndPtr->flags & WIN_NCACTIVATED) != 0;
-            WIN_ReleaseWndPtr( wndPtr );
+            WIN_ReleasePtr( wndPtr );
             return ret;
         }
 
@@ -626,21 +626,15 @@
             return USER_Driver.pSetWindowIcon( hwnd, lParam, (wParam != ICON_SMALL) );
         else
 	{
-		int index = (wParam != ICON_SMALL) ? GCL_HICON : GCL_HICONSM;
-		HICON hOldIcon = GetClassLongW(hwnd, index); 
-		SetClassLongW(hwnd, index, lParam);
-
-		SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED
-			 | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE
-			 | SWP_NOZORDER);
-		return hOldIcon;
+            HICON hOldIcon = SetClassLongW( hwnd, (wParam != ICON_SMALL) ? GCL_HICON : GCL_HICONSM,
+                                            lParam);
+            SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE |
+                         SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
+            return hOldIcon;
 	}
 
     case WM_GETICON:
-	{
-		int index = (wParam != ICON_SMALL) ? GCL_HICON : GCL_HICONSM;
-		return GetClassLongW(hwnd, index); 
-	}
+        return GetClassLongW( hwnd, (wParam != ICON_SMALL) ? GCL_HICON : GCL_HICONSM );
 
     case WM_HELP:
         SendMessageW( GetParent(hwnd), msg, wParam, lParam );
@@ -661,7 +655,12 @@
     LRESULT result = 0;
     HWND hwnd = WIN_Handle32( hwnd16 );
 
-    if (!IsWindow( hwnd )) return 0;
+    if (!WIN_IsCurrentProcess( hwnd ))
+    {
+        if (!IsWindow( hwnd )) return 0;
+        ERR( "called for other process window %x\n", hwnd );
+        return 0;
+    }
     SPY_EnterMessage( SPY_DEFWNDPROC16, hwnd, msg, wParam, lParam );
 
     switch(msg)
@@ -719,9 +718,16 @@
 LRESULT WINAPI DefWindowProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
 {
     LRESULT result = 0;
+    HWND full_handle;
 
-    if (!IsWindow( hwnd )) return 0;
-    hwnd = WIN_GetFullHandle( hwnd );
+    if (!(full_handle = WIN_IsCurrentProcess( hwnd )))
+    {
+        if (!IsWindow( hwnd )) return 0;
+        ERR( "called for other process window %x\n", hwnd );
+        return 0;
+    }
+    hwnd = full_handle;
+
     SPY_EnterMessage( SPY_DEFWNDPROC, hwnd, msg, wParam, lParam );
 
     switch(msg)
@@ -754,17 +760,17 @@
 
     case WM_GETTEXTLENGTH:
         {
-            WND *wndPtr = WIN_FindWndPtr( hwnd );
+            WND *wndPtr = WIN_GetPtr( hwnd );
             if (wndPtr && wndPtr->text)
                 result = WideCharToMultiByte( CP_ACP, 0, wndPtr->text, strlenW(wndPtr->text),
                                               NULL, 0, NULL, NULL );
-            WIN_ReleaseWndPtr( wndPtr );
+            WIN_ReleasePtr( wndPtr );
         }
         break;
 
     case WM_GETTEXT:
         {
-            WND *wndPtr = WIN_FindWndPtr( hwnd );
+            WND *wndPtr = WIN_GetPtr( hwnd );
             if (wParam && wndPtr && wndPtr->text)
             {
                 LPSTR dest = (LPSTR)lParam;
@@ -772,7 +778,7 @@
                                           dest, wParam, NULL, NULL )) dest[wParam-1] = 0;
                 result = strlen( dest );
             }
-            WIN_ReleaseWndPtr( wndPtr );
+            WIN_ReleasePtr( wndPtr );
         }
         break;
 
@@ -849,9 +855,15 @@
     LPARAM lParam )   /* [in] second message parameter */
 {
     LRESULT result = 0;
+    HWND full_handle;
 
-    if (!IsWindow( hwnd )) return 0;
-    hwnd = WIN_GetFullHandle( hwnd );
+    if (!(full_handle = WIN_IsCurrentProcess( hwnd )))
+    {
+        if (!IsWindow( hwnd )) return 0;
+        ERR( "called for other process window %x\n", hwnd );
+        return 0;
+    }
+    hwnd = full_handle;
     SPY_EnterMessage( SPY_DEFWNDPROC, hwnd, msg, wParam, lParam );
 
     switch(msg)
@@ -884,22 +896,22 @@
 
     case WM_GETTEXTLENGTH:
         {
-            WND *wndPtr = WIN_FindWndPtr( hwnd );
+            WND *wndPtr = WIN_GetPtr( hwnd );
             if (wndPtr && wndPtr->text) result = (LRESULT)strlenW(wndPtr->text);
-            WIN_ReleaseWndPtr( wndPtr );
+            WIN_ReleasePtr( wndPtr );
         }
         break;
 
     case WM_GETTEXT:
         {
-            WND *wndPtr = WIN_FindWndPtr( hwnd );
+            WND *wndPtr = WIN_GetPtr( hwnd );
             if (wParam && wndPtr && wndPtr->text)
             {
                 LPWSTR dest = (LPWSTR)lParam;
                 lstrcpynW( dest, wndPtr->text, wParam );
                 result = strlenW( dest );
             }
-            WIN_ReleaseWndPtr( wndPtr );
+            WIN_ReleasePtr( wndPtr );
         }
         break;
 
diff --git a/windows/dialog.c b/windows/dialog.c
index 76551ee..576a75e 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -851,9 +851,9 @@
         HeapFree( GetProcessHeap(), 0, dlgInfo );
 	return 0;
     }
-    wndPtr = WIN_FindWndPtr( hwnd );
+    wndPtr = WIN_GetPtr( hwnd );
     wndPtr->flags |= WIN_ISDIALOG;
-    WIN_ReleaseWndPtr(wndPtr);
+    WIN_ReleasePtr( wndPtr );
 
     if (template.helpId) SetWindowContextHelpId( hwnd, template.helpId );
     SetWindowLongW( hwnd, DWL_WINE_DIALOGINFO, (LONG)dlgInfo );
diff --git a/windows/mdi.c b/windows/mdi.c
index 92a4449..c1ba909 100644
--- a/windows/mdi.c
+++ b/windows/mdi.c
@@ -180,9 +180,14 @@
 static MDICLIENTINFO *get_client_info( HWND client )
 {
     MDICLIENTINFO *ret = NULL;
-    WND *win = WIN_FindWndPtr( client );
+    WND *win = WIN_GetPtr( client );
     if (win)
     {
+        if (win == WND_OTHER_PROCESS)
+        {
+            ERR( "client %x belongs to other process\n", client );
+            return NULL;
+        }
         if (win->cbWndExtra < sizeof(MDICLIENTINFO)) WARN( "%x is not an MDI client\n", client );
         else ret = (MDICLIENTINFO *)win->wExtra;
         WIN_ReleaseWndPtr( win );
@@ -1215,7 +1220,7 @@
           /* Since we are using only cs->lpCreateParams, we can safely
            * cast to LPCREATESTRUCTA here */
           LPCREATESTRUCTA cs = (LPCREATESTRUCTA)lParam;
-          WND *wndPtr = WIN_FindWndPtr( hwnd );
+          WND *wndPtr = WIN_GetPtr( hwnd );
 
 	/* Translation layer doesn't know what's in the cs->lpCreateParams
 	 * so we have to keep track of what environment we're in. */
@@ -1233,7 +1238,7 @@
 	    ci->hWindowMenu	= ccs->hWindowMenu;
 	    ci->idFirstChild	= ccs->idFirstChild;
 	}
-        WIN_ReleaseWndPtr( wndPtr );
+        WIN_ReleasePtr( wndPtr );
 
 	ci->hwndChildMaximized  = 0;
 	ci->nActiveChildren	= 0;
@@ -1549,17 +1554,17 @@
                 {
                     /* control menu is between the frame system menu and 
                      * the first entry of menu bar */
-                    WND *wndPtr = WIN_FindWndPtr(hwnd);
+                    WND *wndPtr = WIN_GetPtr(hwnd);
 
                     if( (wParam == VK_LEFT && GetMenu(hwnd) == next_menu->hmenuIn) ||
                         (wParam == VK_RIGHT && GetSubMenu(wndPtr->hSysMenu, 0) == next_menu->hmenuIn) )
                     {
-                        WIN_ReleaseWndPtr(wndPtr);
-                        wndPtr = WIN_FindWndPtr(ci->hwndActiveChild);
+                        WIN_ReleasePtr(wndPtr);
+                        wndPtr = WIN_GetPtr(ci->hwndActiveChild);
                         next_menu->hmenuNext = GetSubMenu(wndPtr->hSysMenu, 0);
                         next_menu->hwndNext = ci->hwndActiveChild;
-                        WIN_ReleaseWndPtr(wndPtr);
                     }
+                    WIN_ReleasePtr(wndPtr);
                 }
                 return 0;
             }
@@ -1765,9 +1770,9 @@
 
             if( wParam == VK_LEFT )  /* switch to frame system menu */
             {
-                WND *wndPtr = WIN_FindWndPtr( parent );
+                WND *wndPtr = WIN_GetPtr( parent );
                 next_menu->hmenuNext = GetSubMenu( wndPtr->hSysMenu, 0 );
-                WIN_ReleaseWndPtr( wndPtr );
+                WIN_ReleasePtr( wndPtr );
             }
             if( wParam == VK_RIGHT )  /* to frame menu bar */
             {
diff --git a/windows/message.c b/windows/message.c
index 8fd2f38..077af86 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -1006,7 +1006,8 @@
     WND * wndPtr;
     LONG retval;
     int painting;
-    
+    WNDPROC winproc;
+
       /* Process timer messages */
     if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
     {
@@ -1025,40 +1026,48 @@
         }
     }
 
-    if (!msg->hwnd) return 0;
-    if (!(wndPtr = WIN_FindWndPtr( msg->hwnd ))) return 0;
-    if (!wndPtr->winproc)
+    if (!(wndPtr = WIN_GetPtr( msg->hwnd )))
     {
-        retval = 0;
-        goto END;
+        if (msg->hwnd) SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+        return 0;
+    }
+    if (wndPtr == WND_OTHER_PROCESS)
+    {
+        if (IsWindow( msg->hwnd ))
+            ERR( "cannot dispatch msg to other process window %x\n", msg->hwnd );
+        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+        return 0;
+    }
+    if (!(winproc = wndPtr->winproc))
+    {
+        WIN_ReleasePtr( wndPtr );
+        return 0;
     }
     painting = (msg->message == WM_PAINT);
     if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT;
-/*    HOOK_CallHooks32A( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
+    WIN_ReleasePtr( wndPtr );
+/*    hook_CallHooks32A( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
 
     SPY_EnterMessage( SPY_DISPATCHMESSAGE, msg->hwnd, msg->message,
                       msg->wParam, msg->lParam );
-    retval = CallWindowProcA( (WNDPROC)wndPtr->winproc,
-                                msg->hwnd, msg->message,
-                                msg->wParam, msg->lParam );
+    retval = CallWindowProcA( winproc, msg->hwnd, msg->message,
+                              msg->wParam, msg->lParam );
     SPY_ExitMessage( SPY_RESULT_OK, msg->hwnd, msg->message, retval,
-		     msg->wParam, msg->lParam );
+                     msg->wParam, msg->lParam );
 
-    WIN_ReleaseWndPtr(wndPtr);
-    wndPtr = WIN_FindWndPtr(msg->hwnd);
-
-    if (painting && wndPtr &&
-        (wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate)
+    if (painting && (wndPtr = WIN_GetPtr( msg->hwnd )) && (wndPtr != WND_OTHER_PROCESS))
     {
-	ERR("BeginPaint not called on WM_PAINT for hwnd %04x!\n", 
-	    msg->hwnd);
-	wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
-        /* Validate the update region to avoid infinite WM_PAINT loop */
-        RedrawWindow( wndPtr->hwndSelf, NULL, 0,
-                      RDW_NOFRAME | RDW_VALIDATE | RDW_NOCHILDREN | RDW_NOINTERNALPAINT );
+        BOOL validate = ((wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate);
+        wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
+        WIN_ReleasePtr( wndPtr );
+        if (validate)
+        {
+            ERR( "BeginPaint not called on WM_PAINT for hwnd %04x!\n", msg->hwnd );
+            /* Validate the update region to avoid infinite WM_PAINT loop */
+            RedrawWindow( msg->hwnd, NULL, 0,
+                          RDW_NOFRAME | RDW_VALIDATE | RDW_NOCHILDREN | RDW_NOINTERNALPAINT );
+        }
     }
-END:
-    WIN_ReleaseWndPtr(wndPtr);
     return retval;
 }
 
@@ -1089,7 +1098,8 @@
     WND * wndPtr;
     LONG retval;
     int painting;
-    
+    WNDPROC winproc;
+
       /* Process timer messages */
     if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
     {
@@ -1108,40 +1118,48 @@
         }
     }
 
-    if (!msg->hwnd) return 0;
-    if (!(wndPtr = WIN_FindWndPtr( msg->hwnd ))) return 0;
-    if (!wndPtr->winproc)
+    if (!(wndPtr = WIN_GetPtr( msg->hwnd )))
     {
-        retval = 0;
-        goto END;
+        if (msg->hwnd) SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+        return 0;
+    }
+    if (wndPtr == WND_OTHER_PROCESS)
+    {
+        if (IsWindow( msg->hwnd ))
+            ERR( "cannot dispatch msg to other process window %x\n", msg->hwnd );
+        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+        return 0;
+    }
+    if (!(winproc = wndPtr->winproc))
+    {
+        WIN_ReleasePtr( wndPtr );
+        return 0;
     }
     painting = (msg->message == WM_PAINT);
     if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT;
+    WIN_ReleasePtr( wndPtr );
 /*    HOOK_CallHooks32W( WH_CALLWNDPROC, HC_ACTION, 0, FIXME ); */
 
     SPY_EnterMessage( SPY_DISPATCHMESSAGE, msg->hwnd, msg->message,
                       msg->wParam, msg->lParam );
-    retval = CallWindowProcW( (WNDPROC)wndPtr->winproc,
-                                msg->hwnd, msg->message,
-                                msg->wParam, msg->lParam );
+    retval = CallWindowProcW( winproc, msg->hwnd, msg->message,
+                              msg->wParam, msg->lParam );
     SPY_ExitMessage( SPY_RESULT_OK, msg->hwnd, msg->message, retval,
-		     msg->wParam, msg->lParam );
+                     msg->wParam, msg->lParam );
 
-    WIN_ReleaseWndPtr(wndPtr);
-    wndPtr = WIN_FindWndPtr(msg->hwnd);
-
-    if (painting && wndPtr &&
-        (wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate)
+    if (painting && (wndPtr = WIN_GetPtr( msg->hwnd )) && (wndPtr != WND_OTHER_PROCESS))
     {
-	ERR("BeginPaint not called on WM_PAINT for hwnd %04x!\n", 
-	    msg->hwnd);
-	wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
-        /* Validate the update region to avoid infinite WM_PAINT loop */
-        RedrawWindow( wndPtr->hwndSelf, NULL, 0,
-                      RDW_NOFRAME | RDW_VALIDATE | RDW_NOCHILDREN | RDW_NOINTERNALPAINT );
+        BOOL validate = ((wndPtr->flags & WIN_NEEDS_BEGINPAINT) && wndPtr->hrgnUpdate);
+        wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
+        WIN_ReleasePtr( wndPtr );
+        if (validate)
+        {
+            ERR( "BeginPaint not called on WM_PAINT for hwnd %04x!\n", msg->hwnd );
+            /* Validate the update region to avoid infinite WM_PAINT loop */
+            RedrawWindow( msg->hwnd, NULL, 0,
+                          RDW_NOFRAME | RDW_VALIDATE | RDW_NOCHILDREN | RDW_NOINTERNALPAINT );
+        }
     }
-END:
-    WIN_ReleaseWndPtr(wndPtr);
     return retval;
 }
 
diff --git a/windows/nonclient.c b/windows/nonclient.c
index 1ed679f..111568d 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -1401,7 +1401,7 @@
     HWND hwnd = wndPtr->hwndSelf;
 
     if ( wndPtr->dwStyle & WS_MINIMIZE ||
-	!WIN_IsWindowDrawable( wndPtr, 0 )) return; /* Nothing to do */
+         !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
 
     active  = wndPtr->flags & WIN_NCACTIVATED;
 
@@ -1513,7 +1513,7 @@
     HWND hwnd = wndPtr->hwndSelf;
 
     if ( wndPtr->dwStyle & WS_MINIMIZE ||
-	!WIN_IsWindowDrawable( wndPtr, 0 )) return; /* Nothing to do */
+         !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
 
     active  = wndPtr->flags & WIN_NCACTIVATED;
 
diff --git a/windows/painting.c b/windows/painting.c
index 3b81485..6c854fe 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -787,16 +787,12 @@
     WND* wndPtr;
 
     if (!hwnd) hwnd = GetDesktopWindow();
-    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
 
     /* check if the window or its parents are visible/not minimized */
 
-    if (!WIN_IsWindowDrawable( wndPtr, !(flags & RDW_FRAME) ) )
-    {
-        WIN_ReleaseWndPtr(wndPtr);
-        return TRUE; 
-    }
+    if (!WIN_IsWindowDrawable( hwnd, !(flags & RDW_FRAME) )) return TRUE;
 
+    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
     if (TRACE_ON(win))
     {
 	if( hrgnUpdate )
diff --git a/windows/spy.c b/windows/spy.c
index c3a0ede..3270b21 100644
--- a/windows/spy.c
+++ b/windows/spy.c
@@ -1710,19 +1710,17 @@
  */
 void SPY_GetWndName( SPY_INSTANCE *sp_e )
 {
-    WND* pWnd = WIN_FindWndPtr( sp_e->msg_hwnd );
-    if( pWnd )
+    WND* pWnd = WIN_GetPtr( sp_e->msg_hwnd );
+    if (pWnd && pWnd != WND_OTHER_PROCESS)
     {
-	LPSTR p = (LPSTR)&sp_e->wnd_name;
-	LPSTR s = (LPSTR)&sp_e->wnd_name;
+	LPSTR p = sp_e->wnd_name;
+	LPSTR s = sp_e->wnd_name;
         char  postfix;
 	DWORD save_error;
 
 	/* save and restore error code over the next call */	
 	save_error = GetLastError();
-	GlobalGetAtomNameA((ATOM) GetClassWord(pWnd->hwndSelf, GCW_ATOM), 
-			       (LPSTR)&sp_e->wnd_class, 
-			       sizeof(sp_e->wnd_class)-1);
+	GetClassNameA( sp_e->msg_hwnd, sp_e->wnd_class, sizeof(sp_e->wnd_class)-1);
 	SetLastError(save_error);
 
 	if( pWnd->text && pWnd->text[0] != '\0' )
@@ -1734,7 +1732,7 @@
 	}
 	else /* get class name */
 	{
-	    LPSTR src = (LPSTR)&sp_e->wnd_class;
+	    LPSTR src = sp_e->wnd_class;
 	    int n=sizeof(sp_e->wnd_name)-2;
 	    *(p++) = '{';
 	    while ((n-- > 0) && *src) *p++ = *src++;
@@ -1749,10 +1747,14 @@
 	}
 	*(p++) = postfix;
 	*(p++) = '\0';
-        WIN_ReleaseWndPtr(pWnd);
+        WIN_ReleasePtr(pWnd);
 
     }
-    else {strcpy( sp_e->wnd_name, "\"NULL\"" ); sp_e->wnd_class[0] = 0;}
+    else
+    {
+        strcpy( sp_e->wnd_name, "\"NULL\"" );
+        sp_e->wnd_class[0] = 0;
+    }
     return;
 }
 
diff --git a/windows/timer.c b/windows/timer.c
index 0f760db..2168d61 100644
--- a/windows/timer.c
+++ b/windows/timer.c
@@ -104,7 +104,7 @@
     TIMER * pTimer;
     HWINDOWPROC winproc = 0;
 
-    if (hwnd && !WIN_IsCurrentThread( hwnd ))
+    if (hwnd && !(hwnd = WIN_IsCurrentThread( hwnd )))
     {
         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
         return 0;
@@ -243,8 +243,7 @@
 {
     TRACE("%04x %d %d %08lx\n",
                    hwnd, id, timeout, (LONG)proc );
-    return TIMER_SetTimer( WIN_GetFullHandle(hwnd), id, timeout, (WNDPROC16)proc,
-                           WIN_PROC_32A, FALSE );
+    return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc, WIN_PROC_32A, FALSE );
 }
 
 
@@ -294,8 +293,7 @@
 {
     TRACE("%04x %d %d %08lx\n", 
                    hwnd, id, timeout, (LONG)proc );
-    return TIMER_SetTimer( WIN_GetFullHandle(hwnd), id, timeout, (WNDPROC16)proc,
-                           WIN_PROC_32A, TRUE );
+    return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc, WIN_PROC_32A, TRUE );
 }
 
 
diff --git a/windows/win.c b/windows/win.c
index c35e7c0..106a60c 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -176,26 +176,27 @@
 
 
 /***********************************************************************
- *           WIN_GetWndPtr
+ *           WIN_GetPtr
  *
  * Return a pointer to the WND structure if local to the process,
- * or BAD_WND_PTR is handle is local but not valid.
- * If ret value is a valid pointer, the user lock is held.
+ * or WND_OTHER_PROCESS is handle may be valid in other process.
+ * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
  */
-WND *WIN_GetWndPtr( HWND hwnd )
+WND *WIN_GetPtr( HWND hwnd )
 {
     WND * ptr;
     WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
 
-    if (index >= NB_USER_HANDLES) return BAD_WND_PTR;
+    if (index >= NB_USER_HANDLES) return NULL;
 
     USER_Lock();
     if ((ptr = user_handles[index]))
     {
         if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
             return ptr;
-        ptr = BAD_WND_PTR;
+        ptr = NULL;
     }
+    else ptr = WND_OTHER_PROCESS;
     USER_Unlock();
     return ptr;
 }
@@ -204,32 +205,34 @@
 /***********************************************************************
  *           WIN_IsCurrentProcess
  *
- * Check whether a given window belongs to the current process.
+ * Check whether a given window belongs to the current process (and return the full handle).
  */
-BOOL WIN_IsCurrentProcess( HWND hwnd )
+HWND WIN_IsCurrentProcess( HWND hwnd )
 {
     WND *ptr;
+    HWND ret;
 
-    if (!(ptr = WIN_GetWndPtr( hwnd )) || ptr == BAD_WND_PTR) return FALSE;
-    USER_Unlock();
-    return TRUE;
+    if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
+    ret = ptr->hwndSelf;
+    WIN_ReleasePtr( ptr );
+    return ret;
 }
 
 
 /***********************************************************************
  *           WIN_IsCurrentThread
  *
- * Check whether a given window belongs to the current thread.
+ * Check whether a given window belongs to the current thread (and return the full handle).
  */
-BOOL WIN_IsCurrentThread( HWND hwnd )
+HWND WIN_IsCurrentThread( HWND hwnd )
 {
     WND *ptr;
-    BOOL ret = FALSE;
+    HWND ret = 0;
 
-    if ((ptr = WIN_GetWndPtr( hwnd )) && ptr != BAD_WND_PTR)
+    if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
     {
-        ret = (ptr->tid == GetCurrentThreadId());
-        USER_Unlock();
+        if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
+        WIN_ReleasePtr( ptr );
     }
     return ret;
 }
@@ -249,13 +252,12 @@
     /* do sign extension for -2 and -3 */
     if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
 
-    if ((ptr = WIN_GetWndPtr( hwnd )))
+    if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
+
+    if (ptr != WND_OTHER_PROCESS)
     {
-        if (ptr != BAD_WND_PTR)
-        {
-            hwnd = ptr->hwndSelf;
-            USER_Unlock();
-        }
+        hwnd = ptr->hwndSelf;
+        WIN_ReleasePtr( ptr );
     }
     else  /* may belong to another process */
     {
@@ -281,19 +283,19 @@
 
     if (!hwnd) return NULL;
 
-    if ((ptr = WIN_GetWndPtr( hwnd )))
+    if ((ptr = WIN_GetPtr( hwnd )))
     {
-        if (ptr != BAD_WND_PTR)
+        if (ptr != WND_OTHER_PROCESS)
         {
             /* increment destruction monitoring */
             ptr->irefCount++;
             return ptr;
         }
-    }
-    else if (IsWindow( hwnd )) /* check other processes */
-    {
-        ERR( "window %04x belongs to other process\n", hwnd );
-        /* DbgBreakPoint(); */
+        if (IsWindow( hwnd )) /* check other processes */
+        {
+            ERR( "window %04x belongs to other process\n", hwnd );
+            /* DbgBreakPoint(); */
+        }
     }
     SetLastError( ERROR_INVALID_WINDOW_HANDLE );
     return NULL;
@@ -301,26 +303,6 @@
 
 
 /***********************************************************************
- *           WIN_LockWndPtr
- *
- * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
- * but by initWndPtr;
- * Returns the locked initialisation pointer
- */
-WND *WIN_LockWndPtr(WND *initWndPtr)
-{
-    if(!initWndPtr) return 0;
-
-    /* Lock all WND structures for thread safeness*/
-    USER_Lock();
-    /*and increment destruction monitoring*/
-    initWndPtr->irefCount++;
-
-    return initWndPtr;
-
-}
-
-/***********************************************************************
  *           WIN_ReleaseWndPtr
  *
  * Release the pointer to the WND structure.
@@ -346,21 +328,6 @@
      USER_Unlock();
 }
 
-/***********************************************************************
- *           WIN_UpdateWndPtr
- *
- * Updates the value of oldPtr to newPtr.
- */
-void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
-{
-    WND *tmpWnd = NULL;
-
-    tmpWnd = WIN_LockWndPtr(newPtr);
-    WIN_ReleaseWndPtr(*oldPtr);
-    *oldPtr = tmpWnd;
-
-}
-
 
 /***********************************************************************
  *           WIN_UnlinkWindow
@@ -421,9 +388,9 @@
 
     for (i = 0; list[i] && !ret; i++)
     {
-        WND *win = WIN_GetWndPtr( list[i] );
-        if (win == BAD_WND_PTR) continue;  /* ignore it */
-        if (!win)
+        WND *win = WIN_GetPtr( list[i] );
+        if (!win) continue;  /* ignore it */
+        if (win == WND_OTHER_PROCESS)
         {
             /* doesn't belong to this process, but check children */
             ret = find_child_to_repaint( list[i] );
@@ -431,14 +398,14 @@
         }
         if (!(win->dwStyle & WS_VISIBLE))
         {
-            USER_Unlock();
+            WIN_ReleasePtr( win );
             continue;
         }
         if ((win->tid != GetCurrentThreadId()) ||
             (!win->hrgnUpdate && !(win->flags & WIN_INTERNAL_PAINT)))
         {
             /* does not need repaint, check children */
-            USER_Unlock();
+            WIN_ReleasePtr( win );
             ret = find_child_to_repaint( list[i] );
             continue;
         }
@@ -448,29 +415,29 @@
         if (!(win->dwExStyle & WS_EX_TRANSPARENT))
         {
             /* not transparent, we can repaint it */
-            USER_Unlock();
+            WIN_ReleasePtr( win );
             break;
         }
-        USER_Unlock();
+        WIN_ReleasePtr( win );
 
         /* transparent window, look for non-transparent sibling to paint first */
         for (i++; list[i]; i++)
         {
-            if (!(win = WIN_GetWndPtr( list[i] ))) continue;
-            if (win == BAD_WND_PTR) continue;
+            if (!(win = WIN_GetPtr( list[i] ))) continue;
+            if (win == WND_OTHER_PROCESS) continue;
             if (!(win->dwStyle & WS_VISIBLE))
             {
-                USER_Unlock();
+                WIN_ReleasePtr( win );
                 continue;
             }
             if (!(win->dwExStyle & WS_EX_TRANSPARENT) &&
                 (win->hrgnUpdate || (win->flags & WIN_INTERNAL_PAINT)))
             {
                 ret = list[i];
-                USER_Unlock();
+                WIN_ReleasePtr( win );
                 break;
             }
-            USER_Unlock();
+            WIN_ReleasePtr( win );
         }
     }
     HeapFree( GetProcessHeap(), 0, list );
@@ -587,7 +554,6 @@
     if (!(list = WIN_ListChildren( hwnd ))) return;
     for (i = 0; list[i]; i++)
     {
-        if (!IsWindow( list[i] )) continue;
         if (WIN_IsCurrentThread( list[i] ))
             DestroyWindow( list[i] );
         else
@@ -779,16 +745,7 @@
             WARN("Bad parent %04x\n", cs->hwndParent );
 	    return 0;
 	}
-        if (cs->style & WS_CHILD)
-        {
-            parent = WIN_GetFullHandle(cs->hwndParent);
-            if (!WIN_IsCurrentProcess(parent))
-            {
-                FIXME( "creating child window of %x in other process not supported yet\n",
-                       parent );
-                return 0;
-            }
-        }
+        if (cs->style & WS_CHILD) parent = WIN_GetFullHandle(cs->hwndParent);
         else owner = GetAncestor( cs->hwndParent, GA_ROOT );
     }
     else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP))
@@ -2033,10 +1990,11 @@
     WND *ptr;
     BOOL ret;
 
-    if ((ptr = WIN_GetWndPtr( hwnd )))
+    if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
+
+    if (ptr != WND_OTHER_PROCESS)
     {
-        if (ptr == BAD_WND_PTR) return FALSE;
-        USER_Unlock();
+        WIN_ReleasePtr( ptr );
         return TRUE;
     }
 
@@ -2059,16 +2017,18 @@
     WND *ptr;
     DWORD tid = 0;
 
-    if ((ptr = WIN_GetWndPtr( hwnd )))
+    if (!(ptr = WIN_GetPtr( hwnd )))
     {
-        if (ptr != BAD_WND_PTR)
-        {
-            /* got a valid window */
-            tid = ptr->tid;
-            if (process) *process = GetCurrentProcessId();
-            USER_Unlock();
-        }
-        else SetLastError( ERROR_INVALID_WINDOW_HANDLE);
+        SetLastError( ERROR_INVALID_WINDOW_HANDLE);
+        return 0;
+    }
+
+    if (ptr != WND_OTHER_PROCESS)
+    {
+        /* got a valid window */
+        tid = ptr->tid;
+        if (process) *process = GetCurrentProcessId();
+        WIN_ReleasePtr( ptr );
         return tid;
     }
 
@@ -2256,17 +2216,17 @@
  * minimized, and it is itself not minimized unless we are
  * trying to draw its default class icon.
  */
-BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
+BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
 {
     HWND *list;
     BOOL retval;
     int i;
+    LONG style = GetWindowLongW( hwnd, GWL_STYLE );
 
-    if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
-    if ((wnd->dwStyle & WS_MINIMIZE) &&
-        icon && GetClassLongA( wnd->hwndSelf, GCL_HICON ))  return FALSE;
+    if (!(style & WS_VISIBLE)) return FALSE;
+    if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON ))  return FALSE;
 
-    if (!(list = WIN_ListParents( wnd->hwndSelf ))) return TRUE;
+    if (!(list = WIN_ListParents( hwnd ))) return TRUE;
     for (i = 0; list[i]; i++)
         if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
             break;