Authors: Alexandre Julliard <julliard@codeweavers.com> (for Corel), Albert den Haan <albertd@corel.com>
Added syslevel locking for GDI operations.
Propagate the changes through the graphics code.

diff --git a/dlls/ddraw/dsurface/dga.c b/dlls/ddraw/dsurface/dga.c
index df8a377..c405eca 100644
--- a/dlls/ddraw/dsurface/dga.c
+++ b/dlls/ddraw/dsurface/dga.c
@@ -107,7 +107,7 @@
 	    BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(This->s.DIBsection, BITMAP_MAGIC);
 	    X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *)bmp->dib;
 	    dib->colorMap = This->s.palette ? This->s.palette->screen_palents : NULL;
-	    GDI_HEAP_UNLOCK(This->s.DIBsection);
+	    GDI_ReleaseObj(This->s.DIBsection);
 	}
 	TSXFlush(display);
     }
@@ -137,7 +137,7 @@
 	BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(This->s.DIBsection, BITMAP_MAGIC);
 	X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *)bmp->dib;
 	dib->colorMap = dspriv->oldDIBmap;
-	GDI_HEAP_UNLOCK(This->s.DIBsection);
+	GDI_ReleaseObj(This->s.DIBsection);
 
 	SelectObject(This->s.hdc, This->s.holdbitmap);
 	DeleteDC(This->s.hdc);
@@ -173,7 +173,7 @@
 	X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *)bmp->dib;
 	dspriv->oldDIBmap = dib->colorMap;
 	dib->colorMap = This->s.palette ? This->s.palette->screen_palents : NULL;
-	GDI_HEAP_UNLOCK(This->s.DIBsection);
+	GDI_ReleaseObj(This->s.DIBsection);
     }
     return result;
 }
diff --git a/dlls/ddraw/dsurface/x11.c b/dlls/ddraw/dsurface/x11.c
index 14722e3..ef22624 100644
--- a/dlls/ddraw/dsurface/x11.c
+++ b/dlls/ddraw/dsurface/x11.c
@@ -401,7 +401,7 @@
 	    BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(This->s.DIBsection, BITMAP_MAGIC);
 	    X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *)bmp->dib;
 	    dib->colorMap = This->s.palette ? This->s.palette->screen_palents : NULL;
-	    GDI_HEAP_UNLOCK(This->s.DIBsection);
+	    GDI_ReleaseObj(This->s.DIBsection);
 	}
     }
     return DD_OK;
@@ -453,7 +453,7 @@
 	BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr(This->s.DIBsection, BITMAP_MAGIC);
 	X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *)bmp->dib;
 	dib->colorMap = dspriv->oldDIBmap;
-	GDI_HEAP_UNLOCK(This->s.DIBsection);
+	GDI_ReleaseObj(This->s.DIBsection);
 
 	SelectObject(This->s.hdc, This->s.holdbitmap);
 	DeleteDC(This->s.hdc);
@@ -479,7 +479,7 @@
 	X11DRV_DIBSECTION *dib = (X11DRV_DIBSECTION *)bmp->dib;
 	dspriv->oldDIBmap = dib->colorMap;
 	dib->colorMap = This->s.palette ? This->s.palette->screen_palents : NULL;
-	GDI_HEAP_UNLOCK(This->s.DIBsection);
+	GDI_ReleaseObj(This->s.DIBsection);
     }
     return result;
 }
diff --git a/dlls/gdi/gdi_main.c b/dlls/gdi/gdi_main.c
index 84b46f9..f71d6e1 100644
--- a/dlls/gdi/gdi_main.c
+++ b/dlls/gdi/gdi_main.c
@@ -15,15 +15,9 @@
 /***********************************************************************
  *           GDI initialisation routine
  */
-BOOL WINAPI MAIN_GdiInit(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+BOOL WINAPI MAIN_GdiInit(HINSTANCE hinstDLL, DWORD reason, LPVOID lpvReserved)
 {
-    HINSTANCE16 instance;
-
-    if ( GDI_HeapSel ) return TRUE;
-
-    /* Create GDI heap */
-    if ((instance = LoadLibrary16( "GDI.EXE" )) < 32) return FALSE;
-    GDI_HeapSel = GlobalHandleToSel16( instance );
+    if (reason != DLL_PROCESS_ATTACH) return TRUE;
 
     if (!TWEAK_Init()) return FALSE;
 
diff --git a/dlls/gdi/printdrv.c b/dlls/gdi/printdrv.c
index 8090861..8d0e331 100644
--- a/dlls/gdi/printdrv.c
+++ b/dlls/gdi/printdrv.c
@@ -69,6 +69,7 @@
  */
 INT WINAPI StartDocA(HDC hdc, const DOCINFOA* doc)
 {
+    INT ret;
     DC *dc = DC_GetDCPtr( hdc );
 
     TRACE("DocName = '%s' Output = '%s' Datatype = '%s'\n",
@@ -77,10 +78,12 @@
     if(!dc) return SP_ERROR;
 
     if(dc->funcs->pStartDoc)
-        return dc->funcs->pStartDoc( dc, doc );
+        ret = dc->funcs->pStartDoc( dc, doc );
     else
-        return Escape(hdc, STARTDOC, strlen(doc->lpszDocName),
+        ret = Escape(hdc, STARTDOC, strlen(doc->lpszDocName),
 		      doc->lpszDocName, (LPVOID)doc);
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 /*************************************************************************
@@ -128,13 +131,16 @@
  */
 INT WINAPI EndDoc(HDC hdc)
 {
+    INT ret;
     DC *dc = DC_GetDCPtr( hdc );
     if(!dc) return SP_ERROR;
 
     if(dc->funcs->pEndDoc)
-        return dc->funcs->pEndDoc( dc );
+        ret = dc->funcs->pEndDoc( dc );
     else
-        return Escape(hdc, ENDDOC, 0, 0, 0);
+        ret = Escape(hdc, ENDDOC, 0, 0, 0);
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 /******************************************************************
@@ -152,14 +158,16 @@
  */
 INT WINAPI StartPage(HDC hdc)
 {
+    INT ret = 1;
     DC *dc = DC_GetDCPtr( hdc );
     if(!dc) return SP_ERROR;
 
     if(dc->funcs->pStartPage)
-        return dc->funcs->pStartPage( dc );
-
-    FIXME("stub\n");
-    return 1;
+        ret = dc->funcs->pStartPage( dc );
+    else
+        FIXME("stub\n");
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 /******************************************************************
@@ -177,13 +185,16 @@
  */
 INT WINAPI EndPage(HDC hdc)
 {
+    INT ret;
     DC *dc = DC_GetDCPtr( hdc );
     if(!dc) return SP_ERROR;
 
     if(dc->funcs->pEndPage)
-        return dc->funcs->pEndPage( dc );
+        ret = dc->funcs->pEndPage( dc );
     else
-        return Escape(hdc, NEWFRAME, 0, 0, 0);
+        ret = Escape(hdc, NEWFRAME, 0, 0, 0);
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 /******************************************************************************
@@ -199,13 +210,16 @@
  */
 INT WINAPI AbortDoc(HDC hdc)
 {
+    INT ret;
     DC *dc = DC_GetDCPtr( hdc );
     if(!dc) return SP_ERROR;
 
     if(dc->funcs->pAbortDoc)
-        return dc->funcs->pAbortDoc( dc );
+        ret = dc->funcs->pAbortDoc( dc );
     else
-        return Escape(hdc, ABORTDOC, 0, 0, 0);
+        ret = Escape(hdc, ABORTDOC, 0, 0, 0);
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 /**********************************************************************
@@ -219,6 +233,7 @@
  */
 BOOL16 WINAPI QueryAbort16(HDC16 hdc, INT16 reserved)
 {
+    BOOL ret = TRUE;
     DC *dc = DC_GetDCPtr( hdc );
 
     if(!dc) {
@@ -226,9 +241,9 @@
 	return FALSE;
     }
 
-    if(!dc->w.pAbortProc)
-        return TRUE;
-    return dc->w.pAbortProc(hdc, 0);
+    if (dc->w.pAbortProc) ret = dc->w.pAbortProc(hdc, 0);
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 /* ### start build ### */
@@ -256,6 +271,7 @@
 
     if(dc->w.pAbortProc) THUNK_Free((FARPROC)dc->w.pAbortProc);
     dc->w.pAbortProc = abrtprc;
+    GDI_ReleaseObj( hdc );
     return TRUE;
 }
 
diff --git a/dlls/gdi/wing.c b/dlls/gdi/wing.c
index 490c517..8527772 100644
--- a/dlls/gdi/wing.c
+++ b/dlls/gdi/wing.c
@@ -91,6 +91,7 @@
 SEGPTR WINAPI WinGGetDIBPointer16(HBITMAP16 hWinGBitmap, BITMAPINFO* bmpi)
 {
   BITMAPOBJ*	bmp = (BITMAPOBJ *) GDI_GetObjPtr( hWinGBitmap, BITMAP_MAGIC );
+    SEGPTR res = 0;
 
     TRACE("(%d,%p)\n", hWinGBitmap, bmpi);
     if (!bmp) return (SEGPTR)NULL;
@@ -99,10 +100,11 @@
 	FIXME(": Todo - implement setting BITMAPINFO\n");
 
 #ifndef X_DISPLAY_MISSING
-    return PTR_SEG_OFF_TO_SEGPTR(((X11DRV_DIBSECTION *) bmp->dib)->selector, 0);
-#else /* !defined(X_DISPLAY_MISSING) */
-    return NULL;
+    res = PTR_SEG_OFF_TO_SEGPTR(((X11DRV_DIBSECTION *) bmp->dib)->selector, 0);
 #endif /* !defined(X_DISPLAY_MISSING) */
+    
+    GDI_ReleaseObj( hWinGBitmap );
+    return res;
 }
 
 /***********************************************************************
diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c
index 9aa66e9..803ba97 100644
--- a/dlls/opengl32/wgl.c
+++ b/dlls/opengl32/wgl.c
@@ -94,6 +94,7 @@
   if (vis == NULL) {
     ERR("NULL visual !!!\n");
     /* Need to set errors here */
+    GDI_ReleaseObj( hdc );
     return NULL;
   }
 
@@ -106,6 +107,7 @@
 
   TRACE(" creating context %p (GL context creation delayed)\n", ret);
   
+  GDI_ReleaseObj( hdc );
   return (HGLRC) ret;
 }
 
@@ -342,6 +344,7 @@
 			   physDev->drawable,
 			   ctx->ctx);
       LEAVE_GL();
+      GDI_ReleaseObj( hdc );
     }
   }
   TRACE(" returning %s\n", (ret ? "True" : "False"));
@@ -431,7 +434,7 @@
   /* I assume that the glyphs are at the same position for X and for Windows */
   glXUseXFont(fid, first, count, listBase);
   LEAVE_GL();
-  
+  GDI_ReleaseObj( hdc );
   return TRUE;
 }
  
diff --git a/dlls/ttydrv/bitmap.c b/dlls/ttydrv/bitmap.c
index ddcc670..de648f1 100644
--- a/dlls/ttydrv/bitmap.c
+++ b/dlls/ttydrv/bitmap.c
@@ -55,7 +55,7 @@
     result = 0;
   }
   
-  GDI_HEAP_UNLOCK(hbitmap);
+  GDI_ReleaseObj(hbitmap);
   return result;
 }
 
@@ -73,7 +73,7 @@
     return FALSE;
   
   if(!(physBitmap = TTYDRV_DC_AllocBitmap(bitmap))) {
-    GDI_HEAP_UNLOCK(hbitmap);
+    GDI_ReleaseObj(hbitmap);
     return FALSE;
   }
  
@@ -84,7 +84,7 @@
 			 DDB_SET );
   }
 
-  GDI_HEAP_UNLOCK(hbitmap);
+  GDI_ReleaseObj(hbitmap);
   
   return TRUE;
 }
diff --git a/dlls/ttydrv/dc.c b/dlls/ttydrv/dc.c
index 0467fbb..d01888c 100644
--- a/dlls/ttydrv/dc.c
+++ b/dlls/ttydrv/dc.c
@@ -232,7 +232,7 @@
     dc->w.totalExtent.bottom = bmp->bitmap.bmHeight;
     dc->w.hVisRgn            = CreateRectRgnIndirect( &dc->w.totalExtent );
     
-    GDI_HEAP_UNLOCK( dc->w.hBitmap );
+    GDI_ReleaseObj( dc->w.hBitmap );
   } else {
     physDev->window = TTYDRV_GetRootWindow();
     physDev->cellWidth = cell_width;
diff --git a/dlls/ttydrv/objects.c b/dlls/ttydrv/objects.c
index f85dcc3..0719ed7 100644
--- a/dlls/ttydrv/objects.c
+++ b/dlls/ttydrv/objects.c
@@ -98,7 +98,7 @@
       ERR("handle (0x%04x) has unknown magic (0x%04x)\n", handle, ptr->wMagic);
   }
 
-  GDI_HEAP_UNLOCK(handle);
+  GDI_ReleaseObj(handle);
     
   return result;
 }
@@ -129,7 +129,7 @@
       result = FALSE;
   }
 
-  GDI_HEAP_UNLOCK(handle);
+  GDI_ReleaseObj(handle);
 
   return result;
 }
diff --git a/dlls/ttydrv/wnd.c b/dlls/ttydrv/wnd.c
index a3acb7e..acc1ea7 100644
--- a/dlls/ttydrv/wnd.c
+++ b/dlls/ttydrv/wnd.c
@@ -230,20 +230,20 @@
     if (!dc) return;
     TRACE("(%p, %p, %d, %d)\n", wndPtr, dc, flags, bSetClipOrigin);
 
-  /* FIXME: Should be done in the common code instead */
-  if(!wndPtr)  {
-    dc->w.DCOrgX = 0;
-    dc->w.DCOrgY = 0;
-  } else {
-    if(flags & DCX_WINDOW) {
-      dc->w.DCOrgX = wndPtr->rectWindow.left;
-      dc->w.DCOrgY = wndPtr->rectWindow.top;
+    /* FIXME: Should be done in the common code instead */
+    if(!wndPtr)  {
+        dc->w.DCOrgX = 0;
+        dc->w.DCOrgY = 0;
     } else {
-      dc->w.DCOrgX = wndPtr->rectClient.left;
-      dc->w.DCOrgY = wndPtr->rectClient.top;
+        if(flags & DCX_WINDOW) {
+            dc->w.DCOrgX = wndPtr->rectWindow.left;
+            dc->w.DCOrgY = wndPtr->rectWindow.top;
+        } else {
+            dc->w.DCOrgX = wndPtr->rectClient.left;
+            dc->w.DCOrgY = wndPtr->rectClient.top;
+        }
     }
-  }
-  GDI_HEAP_UNLOCK( hdc );
+    GDI_ReleaseObj( hdc );
 }
 
 /***********************************************************************
diff --git a/dlls/wineps/brush.c b/dlls/wineps/brush.c
index 0064b8d..d1a5dda 100644
--- a/dlls/wineps/brush.c
+++ b/dlls/wineps/brush.c
@@ -60,6 +60,7 @@
  */
 static BOOL PSDRV_SetBrush(DC *dc)
 {
+    BOOL ret = TRUE;
     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
     BRUSHOBJ *brush = (BRUSHOBJ *)GDI_GetObjPtr( dc->w.hBrush, BRUSH_MAGIC );
 
@@ -78,11 +79,12 @@
         break;
 
     default:
-        return FALSE;
+        ret = FALSE;
         break;
 
     }
     physDev->brush.set = TRUE;
+    GDI_ReleaseObj( dc->w.hBrush );
     return TRUE;
 }
 
@@ -121,6 +123,7 @@
  */
 BOOL PSDRV_Brush(DC *dc, BOOL EO)
 {
+    BOOL ret = TRUE;
     BRUSHOBJ *brush = (BRUSHOBJ *)GDI_GetObjPtr( dc->w.hBrush, BRUSH_MAGIC );
     PSDRV_PDEVICE *physDev = dc->physDev;
 
@@ -135,7 +138,6 @@
 	PSDRV_WriteGSave(dc);
         PSDRV_Fill(dc, EO);
 	PSDRV_WriteGRestore(dc);
-	return TRUE;
 	break;
 
     case BS_HATCHED:
@@ -185,13 +187,12 @@
 
 	default:
 	    ERR("Unknown hatch style\n");
-	    return FALSE;
+	    ret = FALSE;
+            break;
 	}
-	return TRUE;
 	break;
 
     case BS_NULL:
-        return TRUE;
 	break;
 
     case BS_PATTERN:
@@ -212,18 +213,19 @@
 		PSDRV_WriteGRestore(dc);
 	    } else {
 	        FIXME("Trying to set a pattern brush on a level 1 printer\n");
+		ret = FALSE;
 	    }
 	    HeapFree(PSDRV_Heap, 0, bits);	
-	    return TRUE;
 	}
 	break;
 
-
-
     default:
-        return FALSE;
+        ret = FALSE;
 	break;
     }
+
+    GDI_ReleaseObj( dc->w.hBrush );
+    return ret;
 }
 
 
diff --git a/dlls/wineps/font.c b/dlls/wineps/font.c
index 4e407f2..8bccf80 100644
--- a/dlls/wineps/font.c
+++ b/dlls/wineps/font.c
@@ -8,6 +8,8 @@
 #include "winspool.h"
 #include "psdrv.h"
 #include "debugtools.h"
+#include "dc.h"
+#include "winerror.h"
 
 DEFAULT_DEBUG_CHANNEL(psdrv)
 
@@ -265,11 +267,15 @@
 /***********************************************************************
  *           PSDRV_GetFontMetric
  */
-static UINT PSDRV_GetFontMetric(DC *dc, AFM *pafm, NEWTEXTMETRIC16 *pTM, 
+static UINT PSDRV_GetFontMetric(HDC hdc, AFM *pafm, NEWTEXTMETRIC16 *pTM, 
               ENUMLOGFONTEX16 *pLF, INT16 size)
 
 {
+    DC *dc = DC_GetDCPtr( hdc );
     float scale = size / (pafm->FullAscender - pafm->Descender);
+
+    if (!dc) return FALSE;
+
     memset( pLF, 0, sizeof(*pLF) );
     memset( pTM, 0, sizeof(*pTM) );
 
@@ -300,8 +306,8 @@
 
     *(INT*)&pTM->tmFirstChar = 32;
 
+    GDI_ReleaseObj( hdc );
     /* return font type */
-
     return DEVICE_FONTTYPE;
 
 }
@@ -309,7 +315,7 @@
 /***********************************************************************
  *           PSDRV_EnumDeviceFonts
  */
-BOOL PSDRV_EnumDeviceFonts( DC* dc, LPLOGFONT16 plf, 
+BOOL PSDRV_EnumDeviceFonts( HDC hdc, LPLOGFONT16 plf, 
 				        DEVICEFONTENUMPROC proc, LPARAM lp )
 {
     ENUMLOGFONTEX16	lf;
@@ -317,7 +323,14 @@
     BOOL	  	b, bRet = 0;
     AFMLISTENTRY	*afmle;
     FONTFAMILY		*family;
-    PSDRV_PDEVICE	*physDev = (PSDRV_PDEVICE *)dc->physDev;
+    PSDRV_PDEVICE	*physDev;
+
+    DC *dc = DC_GetDCPtr( hdc );
+    if (!dc) return FALSE;
+
+    physDev = (PSDRV_PDEVICE *)dc->physDev;
+    /* FIXME!! should reevaluate dc->physDev after every callback */
+    GDI_ReleaseObj( hdc );
 
     if( plf->lfFaceName[0] ) {
         TRACE("lfFaceName = '%s'\n", plf->lfFaceName);
@@ -330,7 +343,7 @@
 	    for(afmle = family->afmlist; afmle; afmle = afmle->next) {
 	        TRACE("Got '%s'\n", afmle->afm->FontName);
 		if( (b = (*proc)( &lf, &tm, 
-			PSDRV_GetFontMetric( dc, afmle->afm, &tm, &lf, 200 ),
+			PSDRV_GetFontMetric( hdc, afmle->afm, &tm, &lf, 200 ),
 				  lp )) )
 		     bRet = b;
 		else break;
@@ -343,7 +356,7 @@
 	    afmle = family->afmlist;
 	    TRACE("Got '%s'\n", afmle->afm->FontName);
 	    if( (b = (*proc)( &lf, &tm, 
-		   PSDRV_GetFontMetric( dc, afmle->afm, &tm, &lf, 200 ), 
+		   PSDRV_GetFontMetric( hdc, afmle->afm, &tm, &lf, 200 ), 
 			      lp )) )
 	        bRet = b;
 	    else break;
diff --git a/dlls/wineps/objects.c b/dlls/wineps/objects.c
index d51f0dc..e55f2dc 100644
--- a/dlls/wineps/objects.c
+++ b/dlls/wineps/objects.c
@@ -57,6 +57,6 @@
 	  ERR("Unknown object magic %04x\n", ptr->wMagic);
 	  break;
     }
-    GDI_HEAP_UNLOCK( handle );
+    GDI_ReleaseObj( handle );
     return ret;
 }
diff --git a/dlls/wineps/psdrv.h b/dlls/wineps/psdrv.h
index 367dfa8..55e1a7e 100644
--- a/dlls/wineps/psdrv.h
+++ b/dlls/wineps/psdrv.h
@@ -324,7 +324,7 @@
 			     INT bottom );
 extern INT PSDRV_EndDoc( DC *dc );
 extern INT PSDRV_EndPage( DC *dc );
-extern BOOL PSDRV_EnumDeviceFonts( DC* dc, LPLOGFONT16 plf, 
+extern BOOL PSDRV_EnumDeviceFonts( HDC hdc, LPLOGFONT16 plf, 
 				     DEVICEFONTENUMPROC proc, LPARAM lp );
 extern INT PSDRV_Escape( DC *dc, INT nEscape, INT cbInput, 
 			   SEGPTR lpInData, SEGPTR lpOutData );
diff --git a/graphics/bitblt.c b/graphics/bitblt.c
index b739aec..c7c0f87 100644
--- a/graphics/bitblt.c
+++ b/graphics/bitblt.c
@@ -7,9 +7,7 @@
 #include "dc.h"
 #include "debugtools.h"
 
-DEFAULT_DEBUG_CHANNEL(bitblt)
-DECLARE_DEBUG_CHANNEL(bitmap)
-DECLARE_DEBUG_CHANNEL(gdi)
+DEFAULT_DEBUG_CHANNEL(bitblt);
 
 
 /***********************************************************************
@@ -18,11 +16,7 @@
 BOOL16 WINAPI PatBlt16( HDC16 hdc, INT16 left, INT16 top,
                         INT16 width, INT16 height, DWORD rop)
 {
-    DC * dc = DC_GetDCPtr( hdc );
-    if (!dc || !dc->funcs->pPatBlt) return FALSE;
-
-    TRACE("%04x %d,%d %dx%d %06lx\n", hdc, left, top, width, height, rop );
-    return dc->funcs->pPatBlt( dc, left, top, width, height, rop );
+    return PatBlt( hdc, left, top, width, height, rop );
 }
 
 
@@ -33,10 +27,17 @@
                         INT width, INT height, DWORD rop)
 {
     DC * dc = DC_GetDCPtr( hdc );
-    if (!dc || !dc->funcs->pPatBlt) return FALSE;
+    BOOL bRet = FALSE;
 
-    TRACE("%04x %d,%d %dx%d %06lx\n", hdc, left, top, width, height, rop );
-    return dc->funcs->pPatBlt( dc, left, top, width, height, rop );
+    if (!dc) return FALSE;
+
+    if (dc->funcs->pPatBlt)
+    {
+        TRACE("%04x %d,%d %dx%d %06lx\n", hdc, left, top, width, height, rop );
+        bRet = dc->funcs->pPatBlt( dc, left, top, width, height, rop );
+    }
+    GDI_ReleaseObj( hdc );
+    return bRet;
 }
 
 
@@ -47,17 +48,7 @@
                         INT16 height, HDC16 hdcSrc, INT16 xSrc, INT16 ySrc,
                         DWORD rop )
 {
-    DC *dcDst, *dcSrc;
-
-    if (!(dcDst = DC_GetDCPtr( hdcDst ))) return FALSE;
-    if (!dcDst->funcs->pBitBlt) return FALSE;
-    dcSrc = DC_GetDCPtr( hdcSrc );
-
-    TRACE("hdcSrc=%04x %d,%d %d bpp->hdcDest=%04x %d,%d %dx%dx%d rop=%06lx\n",
-          hdcSrc, xSrc, ySrc, dcSrc ? dcSrc->w.bitsPerPixel : 0,
-          hdcDst, xDst, yDst, width, height, dcDst->w.bitsPerPixel, rop);
-    return dcDst->funcs->pBitBlt( dcDst, xDst, yDst, width, height,
-                                  dcSrc, xSrc, ySrc, rop );
+    return BitBlt( hdcDst, xDst, yDst, width, height, hdcSrc, xSrc, ySrc, rop );
 }
 
 
@@ -65,20 +56,26 @@
  *           BitBlt    (GDI32.10)
  */
 BOOL WINAPI BitBlt( HDC hdcDst, INT xDst, INT yDst, INT width,
-                        INT height, HDC hdcSrc, INT xSrc, INT ySrc,
-                        DWORD rop )
+                    INT height, HDC hdcSrc, INT xSrc, INT ySrc, DWORD rop )
 {
+    BOOL ret = FALSE;
     DC *dcDst, *dcSrc;
 
-    if (!(dcDst = DC_GetDCPtr( hdcDst ))) return FALSE;
-    if (!dcDst->funcs->pBitBlt) return FALSE;
-    dcSrc = DC_GetDCPtr( hdcSrc );
-
-    TRACE("hdcSrc=%04x %d,%d %d bpp->hdcDest=%04x %d,%d %dx%dx%d rop=%06lx\n",
-          hdcSrc, xSrc, ySrc, dcSrc ? dcSrc->w.bitsPerPixel : 0,
-          hdcDst, xDst, yDst, width, height, dcDst->w.bitsPerPixel, rop);
-    return dcDst->funcs->pBitBlt( dcDst, xDst, yDst, width, height,
-                                  dcSrc, xSrc, ySrc, rop );
+    if ((dcSrc = DC_GetDCUpdate( hdcSrc ))) GDI_ReleaseObj( hdcSrc );
+    /* FIXME: there is a race condition here */
+    if ((dcDst = DC_GetDCUpdate( hdcDst )))
+    {
+        dcSrc = DC_GetDCPtr( hdcSrc );
+        TRACE("hdcSrc=%04x %d,%d %d bpp->hdcDest=%04x %d,%d %dx%dx%d rop=%06lx\n",
+              hdcSrc, xSrc, ySrc, dcSrc ? dcSrc->w.bitsPerPixel : 0,
+              hdcDst, xDst, yDst, width, height, dcDst->w.bitsPerPixel, rop);
+        if (dcDst->funcs->pBitBlt)
+            ret = dcDst->funcs->pBitBlt( dcDst, xDst, yDst, width, height,
+                                         dcSrc, xSrc, ySrc, rop );
+        if (dcSrc) GDI_ReleaseObj( hdcSrc );
+        GDI_ReleaseObj( hdcDst );
+    }
+    return ret;
 }
 
 
@@ -90,19 +87,8 @@
                             HDC16 hdcSrc, INT16 xSrc, INT16 ySrc,
                             INT16 widthSrc, INT16 heightSrc, DWORD rop )
 {
-    DC *dcDst, *dcSrc;
-
-    if (!(dcDst = DC_GetDCPtr( hdcDst ))) return FALSE;
-    if (!dcDst->funcs->pStretchBlt) return FALSE;
-    dcSrc = DC_GetDCPtr( hdcSrc );
-
-    TRACE("%04x %d,%d %dx%dx%d -> %04x %d,%d %dx%dx%d rop=%06lx\n",
-          hdcSrc, xSrc, ySrc, widthSrc, heightSrc,
-          dcSrc ? dcSrc->w.bitsPerPixel : 0, hdcDst, xDst, yDst,
-          widthDst, heightDst, dcDst->w.bitsPerPixel, rop );
-    return dcDst->funcs->pStretchBlt( dcDst, xDst, yDst, widthDst, heightDst,
-                                      dcSrc, xSrc, ySrc, widthSrc, heightSrc,
-                                      rop );
+    return StretchBlt( hdcDst, xDst, yDst, widthDst, heightDst,
+                       hdcSrc, xSrc, ySrc, widthSrc, heightSrc, rop );
 }
 
 
@@ -112,21 +98,32 @@
 BOOL WINAPI StretchBlt( HDC hdcDst, INT xDst, INT yDst,
                             INT widthDst, INT heightDst,
                             HDC hdcSrc, INT xSrc, INT ySrc,
-                            INT widthSrc, INT heightSrc, DWORD rop )
+                            INT widthSrc, INT heightSrc, 
+			DWORD rop )
 {
+    BOOL ret = FALSE;
     DC *dcDst, *dcSrc;
 
-    if (!(dcDst = DC_GetDCPtr( hdcDst ))) return FALSE;
-    if (!dcDst->funcs->pStretchBlt) return FALSE;
-    dcSrc = DC_GetDCPtr( hdcSrc );
+    if ((dcSrc = DC_GetDCUpdate( hdcSrc ))) GDI_ReleaseObj( hdcSrc );
+    /* FIXME: there is a race condition here */
+    if ((dcDst = DC_GetDCUpdate( hdcDst )))
+    {
+        dcSrc = DC_GetDCPtr( hdcSrc );
 
-    TRACE("%04x %d,%d %dx%dx%d -> %04x %d,%d %dx%dx%d rop=%06lx\n",
-          hdcSrc, xSrc, ySrc, widthSrc, heightSrc,
-          dcSrc ? dcSrc->w.bitsPerPixel : 0, hdcDst, xDst, yDst,
-          widthDst, heightDst, dcDst->w.bitsPerPixel, rop );
-    return dcDst->funcs->pStretchBlt( dcDst, xDst, yDst, widthDst, heightDst,
-                                      dcSrc, xSrc, ySrc, widthSrc, heightSrc,
-                                      rop );
+        TRACE("%04x %d,%d %dx%dx%d -> %04x %d,%d %dx%dx%d rop=%06lx\n",
+              hdcSrc, xSrc, ySrc, widthSrc, heightSrc,
+              dcSrc ? dcSrc->w.bitsPerPixel : 0, hdcDst, xDst, yDst,
+              widthDst, heightDst, dcDst->w.bitsPerPixel, rop );
+
+	if (dcSrc) {
+	    if (dcDst->funcs->pStretchBlt)
+		ret = dcDst->funcs->pStretchBlt( dcDst, xDst, yDst, widthDst, heightDst,
+						 dcSrc, xSrc, ySrc, widthSrc, heightSrc, rop );
+	    GDI_ReleaseObj( hdcSrc );
+	}
+        GDI_ReleaseObj( hdcDst );
+    }
+    return ret;
 }
 
 
@@ -147,7 +144,10 @@
               rect->bottom - rect->top - height, rop );
     SelectObject( hdc, hbrush );
     return TRUE;
+
 }
+
+
 /***********************************************************************
  *           MaskBlt [GDI32.252]
  */
@@ -156,7 +156,7 @@
 			INT nXSrc, INT nYSrc, HBITMAP hbmMask,
 			INT xMask, INT yMask, DWORD dwRop)
 {
-    FIXME_(bitmap)("(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%ld): stub\n",
+    FIXME("(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%ld): stub\n",
              hdcDest,nXDest,nYDest,nWidth,nHeight,hdcSource,nXSrc,nYSrc,
              hbmMask,xMask,yMask,dwRop);
     return 1;
@@ -170,7 +170,7 @@
                         HDC hdcSrc, INT nXDest, INT nYDest, INT nWidth,
                         INT nHeight, HBITMAP hbmMask, INT xMask, INT yMask)
 {
-        FIXME_(gdi)("PlgBlt, stub\n");
+    FIXME("PlgBlt, stub\n");
         return 1;
 }
  
diff --git a/graphics/enhmetafiledrv/init.c b/graphics/enhmetafiledrv/init.c
index 07f38bc..82c6e1b 100644
--- a/graphics/enhmetafiledrv/init.c
+++ b/graphics/enhmetafiledrv/init.c
@@ -129,7 +129,7 @@
     if (physDev->emh) HeapFree( GetProcessHeap(), 0, physDev->emh );
     HeapFree( GetProcessHeap(), 0, physDev );
     dc->physDev = NULL;
-    GDI_FreeObject(dc->hSelf);
+    GDI_FreeObject( dc->hSelf, dc );
     return TRUE;
 }
 
@@ -245,6 +245,7 @@
     LPCWSTR       description /* optional description */ 
     )
 {
+    HDC ret;
     DC *dc;
     HDC hRefDC = hdc ? hdc : CreateDCA("DISPLAY",NULL,NULL,NULL); /* If no ref, use current display */
     EMFDRV_PDEVICE *physDev;
@@ -258,7 +259,7 @@
 
     physDev = (EMFDRV_PDEVICE *)HeapAlloc(GetProcessHeap(),0,sizeof(*physDev));
     if (!physDev) {
-        GDI_HEAP_FREE( dc->hSelf );
+        GDI_FreeObject( dc->hSelf, dc );
         return 0;
     }
     dc->physDev = physDev;
@@ -273,7 +274,7 @@
 
     if (!(physDev->emh = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size))) {
         HeapFree( GetProcessHeap(), 0, physDev );
-        GDI_HEAP_FREE( dc->hSelf );
+        GDI_FreeObject( dc->hSelf, dc );
         return 0;
     }
 
@@ -337,8 +338,9 @@
       DeleteDC( hRefDC );
 	
     TRACE("returning %04x\n", dc->hSelf);
-    return dc->hSelf;
-
+    ret = dc->hSelf;
+    GDI_ReleaseObj( dc->hSelf );
+    return ret;
 }
 
 /******************************************************************
diff --git a/graphics/enhmetafiledrv/objects.c b/graphics/enhmetafiledrv/objects.c
index 0e0ccd9..2d615c2 100644
--- a/graphics/enhmetafiledrv/objects.c
+++ b/graphics/enhmetafiledrv/objects.c
@@ -89,9 +89,9 @@
         break;
     default:
         FIXME("Unknown style %x\n", brushObj->logbrush.lbStyle);
-	return FALSE;
+	break;
     }
-    GDI_HEAP_UNLOCK( hBrush );
+    GDI_ReleaseObj( hBrush );
     return index;
 }
 
@@ -170,7 +170,7 @@
 
     if(!EMFDRV_WriteRecord( dc, &emr.emr ))
         index = 0;
-    GDI_HEAP_UNLOCK( hFont );
+    GDI_ReleaseObj( hFont );
     return index;
 }
 
@@ -233,7 +233,7 @@
 
     if(!EMFDRV_WriteRecord( dc, &emr.emr ))
         index = 0;
-    GDI_HEAP_UNLOCK( hPen );
+    GDI_ReleaseObj( hPen );
     return index;
 }
 
@@ -303,7 +303,7 @@
 	  ret = EMFDRV_BITMAP_SelectObject( dc, handle );
 	  break;
     }
-    GDI_HEAP_UNLOCK( handle );
+    GDI_ReleaseObj( handle );
     return ret;
 }
 
diff --git a/graphics/escape.c b/graphics/escape.c
index 5e9e2bc..d4dd462 100644
--- a/graphics/escape.c
+++ b/graphics/escape.c
@@ -21,10 +21,18 @@
 INT16 WINAPI Escape16( HDC16 hdc, INT16 nEscape, INT16 cbInput,
                        SEGPTR lpszInData, SEGPTR lpvOutData )
 {
+    INT16 ret = 0;
     DC * dc = DC_GetDCPtr( hdc );
-    if (!dc || !dc->funcs->pEscape) return 0;
-    if(nEscape == SETABORTPROC) SetAbortProc16(hdc, lpszInData);
-    return dc->funcs->pEscape( dc, nEscape, cbInput, lpszInData, lpvOutData );
+    if (dc)
+    {
+        if (dc->funcs->pEscape)
+        {
+            if(nEscape == SETABORTPROC) SetAbortProc16(hdc, lpszInData);
+            ret = dc->funcs->pEscape( dc, nEscape, cbInput, lpszInData, lpvOutData );
+        }
+        GDI_ReleaseObj( hdc );
+    }
+    return ret;
 }
 
 /************************************************************************
@@ -34,9 +42,10 @@
 		   LPCSTR lpszInData, LPVOID lpvOutData )
 {
     SEGPTR	segin,segout;
-    INT	ret;
+    INT	ret = 0;
     DC * dc = DC_GetDCPtr( hdc );
-    if (!dc || !dc->funcs->pEscape) return 0;
+    if (!dc) return 0;
+    if (!dc->funcs->pEscape) goto done;
 
     segin	= (SEGPTR)lpszInData;
     segout	= (SEGPTR)lpvOutData;
@@ -227,6 +236,8 @@
     default:
     	break;
     }
+ done:
+    GDI_ReleaseObj( hdc );
     return ret;
 }
 
diff --git a/graphics/mapping.c b/graphics/mapping.c
index 4cab204..a23ca2f 100644
--- a/graphics/mapping.c
+++ b/graphics/mapping.c
@@ -48,6 +48,7 @@
 	points->y = YDPTOLP( dc, points->y );
         points++;
     }
+    GDI_ReleaseObj( hdc );
     return TRUE;
 }
 
@@ -63,10 +64,11 @@
     while (count--)
     {
         if (!INTERNAL_DPTOLP( dc, points ))
-	    return FALSE;
+	    break;
         points++;
     }
-    return TRUE;
+    GDI_ReleaseObj( hdc );
+    return (count < 0);
 }
 
 
@@ -84,6 +86,7 @@
 	points->y = YLPTODP( dc, points->y );
         points++;
     }
+    GDI_ReleaseObj( hdc );
     return TRUE;
 }
 
@@ -101,6 +104,7 @@
 	INTERNAL_LPTODP( dc, points );
         points++;
     }
+    GDI_ReleaseObj( hdc );
     return TRUE;
 }
 
@@ -122,7 +126,11 @@
     INT prevMode;
     DC * dc = DC_GetDCPtr( hdc );
     if (!dc) return 0;
-    if (dc->funcs->pSetMapMode) return dc->funcs->pSetMapMode( dc, mode );
+    if (dc->funcs->pSetMapMode)
+    {
+        prevMode = dc->funcs->pSetMapMode( dc, mode );
+        goto done;
+    }
 
     TRACE("%04x %d\n", hdc, mode );
     
@@ -176,10 +184,12 @@
 	  break;
 
       default:
-	  return prevMode;
+	  goto done;
     }
     dc->w.MapMode = mode;
     DC_UpdateXforms( dc );
+ done:
+    GDI_ReleaseObj( hdc );
     return prevMode;
 }
 
@@ -212,23 +222,33 @@
  */
 BOOL WINAPI SetViewportExtEx( HDC hdc, INT x, INT y, LPSIZE size )
 {
+    BOOL ret = TRUE;
     DC * dc = DC_GetDCPtr( hdc );
     if (!dc) return FALSE;
     if (dc->funcs->pSetViewportExt)
-        return dc->funcs->pSetViewportExt( dc, x, y );
+    {
+        ret = dc->funcs->pSetViewportExt( dc, x, y );
+        goto done;
+    }
     if (size)
     {
 	size->cx = dc->vportExtX;
 	size->cy = dc->vportExtY;
     }
     if ((dc->w.MapMode != MM_ISOTROPIC) && (dc->w.MapMode != MM_ANISOTROPIC))
-	return TRUE;
-    if (!x || !y) return FALSE;
+	goto done;
+    if (!x || !y)
+    {
+        ret = FALSE;
+        goto done;
+    }
     dc->vportExtX = x;
     dc->vportExtY = y;
     if (dc->w.MapMode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc );
     DC_UpdateXforms( dc );
-    return TRUE;
+ done:
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
@@ -260,19 +280,24 @@
  */
 BOOL WINAPI SetViewportOrgEx( HDC hdc, INT x, INT y, LPPOINT pt )
 {
+    BOOL ret = TRUE;
     DC * dc = DC_GetDCPtr( hdc );
     if (!dc) return FALSE;
     if (dc->funcs->pSetViewportOrg)
-        return dc->funcs->pSetViewportOrg( dc, x, y );
-    if (pt)
+        ret = dc->funcs->pSetViewportOrg( dc, x, y );
+    else
     {
-	pt->x = dc->vportOrgX;
-	pt->y = dc->vportOrgY;
+        if (pt)
+        {
+            pt->x = dc->vportOrgX;
+            pt->y = dc->vportOrgY;
+        }
+        dc->vportOrgX = x;
+        dc->vportOrgY = y;
+        DC_UpdateXforms( dc );
     }
-    dc->vportOrgX = x;
-    dc->vportOrgY = y;
-    DC_UpdateXforms( dc );
-    return TRUE;
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
@@ -304,22 +329,33 @@
  */
 BOOL WINAPI SetWindowExtEx( HDC hdc, INT x, INT y, LPSIZE size )
 {
+    BOOL ret = TRUE;
     DC * dc = DC_GetDCPtr( hdc );
     if (!dc) return FALSE;
-    if (dc->funcs->pSetWindowExt) return dc->funcs->pSetWindowExt( dc, x, y );
+    if (dc->funcs->pSetWindowExt)
+    {
+        ret = dc->funcs->pSetWindowExt( dc, x, y );
+        goto done;
+    }
     if (size)
     {
 	size->cx = dc->wndExtX;
 	size->cy = dc->wndExtY;
     }
     if ((dc->w.MapMode != MM_ISOTROPIC) && (dc->w.MapMode != MM_ANISOTROPIC))
-	return TRUE;
-    if (!x || !y) return FALSE;
+	goto done;
+    if (!x || !y)
+    {
+        ret = FALSE;
+        goto done;
+    }
     dc->wndExtX = x;
     dc->wndExtY = y;
     if (dc->w.MapMode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc );
     DC_UpdateXforms( dc );
-    return TRUE;
+ done:
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
@@ -351,18 +387,23 @@
  */
 BOOL WINAPI SetWindowOrgEx( HDC hdc, INT x, INT y, LPPOINT pt )
 {
+    BOOL ret = TRUE;
     DC * dc = DC_GetDCPtr( hdc );
     if (!dc) return FALSE;
-    if (dc->funcs->pSetWindowOrg) return dc->funcs->pSetWindowOrg( dc, x, y );
-    if (pt)
+    if (dc->funcs->pSetWindowOrg) ret = dc->funcs->pSetWindowOrg( dc, x, y );
+    else
     {
-	pt->x = dc->wndOrgX;
-	pt->y = dc->wndOrgY;
+        if (pt)
+        {
+            pt->x = dc->wndOrgX;
+            pt->y = dc->wndOrgY;
+        }
+        dc->wndOrgX = x;
+        dc->wndOrgY = y;
+        DC_UpdateXforms( dc );
     }
-    dc->wndOrgX = x;
-    dc->wndOrgY = y;
-    DC_UpdateXforms( dc );
-    return TRUE;
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
@@ -394,19 +435,24 @@
  */
 BOOL WINAPI OffsetViewportOrgEx( HDC hdc, INT x, INT y, LPPOINT pt)
 {
+    BOOL ret = TRUE;
     DC * dc = DC_GetDCPtr( hdc );
     if (!dc) return FALSE;
     if (dc->funcs->pOffsetViewportOrg)
-        return dc->funcs->pOffsetViewportOrg( dc, x, y );
-    if (pt)
+        ret = dc->funcs->pOffsetViewportOrg( dc, x, y );
+    else
     {
-	pt->x = dc->vportOrgX;
-	pt->y = dc->vportOrgY;
+        if (pt)
+        {
+            pt->x = dc->vportOrgX;
+            pt->y = dc->vportOrgY;
+        }
+        dc->vportOrgX += x;
+        dc->vportOrgY += y;
+        DC_UpdateXforms( dc );
     }
-    dc->vportOrgX += x;
-    dc->vportOrgY += y;
-    DC_UpdateXforms( dc );
-    return TRUE;
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
@@ -438,19 +484,24 @@
  */
 BOOL WINAPI OffsetWindowOrgEx( HDC hdc, INT x, INT y, LPPOINT pt )
 {
+    BOOL ret = TRUE;
     DC * dc = DC_GetDCPtr( hdc );
     if (!dc) return FALSE;
     if (dc->funcs->pOffsetWindowOrg)
-        return dc->funcs->pOffsetWindowOrg( dc, x, y );
-    if (pt)
+        ret = dc->funcs->pOffsetWindowOrg( dc, x, y );
+    else
     {
-	pt->x = dc->wndOrgX;
-	pt->y = dc->wndOrgY;
+        if (pt)
+        {
+            pt->x = dc->wndOrgX;
+            pt->y = dc->wndOrgY;
+        }
+        dc->wndOrgX += x;
+        dc->wndOrgY += y;
+        DC_UpdateXforms( dc );
     }
-    dc->wndOrgX += x;
-    dc->wndOrgY += y;
-    DC_UpdateXforms( dc );
-    return TRUE;
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
@@ -487,25 +538,35 @@
 BOOL WINAPI ScaleViewportExtEx( HDC hdc, INT xNum, INT xDenom,
                                     INT yNum, INT yDenom, LPSIZE size )
 {
+    BOOL ret = TRUE;
     DC * dc = DC_GetDCPtr( hdc );
     if (!dc) return FALSE;
     if (dc->funcs->pScaleViewportExt)
-        return dc->funcs->pScaleViewportExt( dc, xNum, xDenom, yNum, yDenom );
+    {
+        ret = dc->funcs->pScaleViewportExt( dc, xNum, xDenom, yNum, yDenom );
+        goto done;
+    }
     if (size)
     {
 	size->cx = dc->vportExtX;
 	size->cy = dc->vportExtY;
     }
     if ((dc->w.MapMode != MM_ISOTROPIC) && (dc->w.MapMode != MM_ANISOTROPIC))
-	return TRUE;
-    if (!xNum || !xDenom || !xNum || !yDenom) return FALSE;
+	goto done;
+    if (!xNum || !xDenom || !xNum || !yDenom)
+    {
+        ret = FALSE;
+        goto done;
+    }
     dc->vportExtX = (dc->vportExtX * xNum) / xDenom;
     dc->vportExtY = (dc->vportExtY * yNum) / yDenom;
     if (dc->vportExtX == 0) dc->vportExtX = 1;
     if (dc->vportExtY == 0) dc->vportExtY = 1;
     if (dc->w.MapMode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc );
     DC_UpdateXforms( dc );
-    return TRUE;
+ done:
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
@@ -542,23 +603,33 @@
 BOOL WINAPI ScaleWindowExtEx( HDC hdc, INT xNum, INT xDenom,
                                   INT yNum, INT yDenom, LPSIZE size )
 {
+    BOOL ret = TRUE;
     DC * dc = DC_GetDCPtr( hdc );
     if (!dc) return FALSE;
     if (dc->funcs->pScaleWindowExt)
-        return dc->funcs->pScaleWindowExt( dc, xNum, xDenom, yNum, yDenom );
+    {
+        ret = dc->funcs->pScaleWindowExt( dc, xNum, xDenom, yNum, yDenom );
+        goto done;
+    }
     if (size)
     {
 	size->cx = dc->wndExtX;
 	size->cy = dc->wndExtY;
     }
     if ((dc->w.MapMode != MM_ISOTROPIC) && (dc->w.MapMode != MM_ANISOTROPIC))
-	return TRUE;
-    if (!xNum || !xDenom || !xNum || !yDenom) return FALSE;
+	goto done;
+    if (!xNum || !xDenom || !xNum || !yDenom)
+    {
+        ret = FALSE;
+        goto done;
+    }
     dc->wndExtX = (dc->wndExtX * xNum) / xDenom;
     dc->wndExtY = (dc->wndExtY * yNum) / yDenom;
     if (dc->wndExtX == 0) dc->wndExtX = 1;
     if (dc->wndExtY == 0) dc->wndExtY = 1;
     if (dc->w.MapMode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc );
     DC_UpdateXforms( dc );
-    return TRUE;
+ done:
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
diff --git a/graphics/metafiledrv/init.c b/graphics/metafiledrv/init.c
index b9c64ff..d155304 100644
--- a/graphics/metafiledrv/init.c
+++ b/graphics/metafiledrv/init.c
@@ -133,7 +133,7 @@
     physDev = (METAFILEDRV_PDEVICE *)HeapAlloc(GetProcessHeap(),0,sizeof(*physDev));
     if (!physDev)
     {
-        GDI_HEAP_FREE( dc->hSelf );
+        GDI_FreeObject( dc->hSelf, dc );
         return NULL;
     }
     dc->physDev = physDev;
@@ -141,7 +141,7 @@
     if (!(physDev->mh = HeapAlloc( GetProcessHeap(), 0, sizeof(*physDev->mh) )))
     {
         HeapFree( GetProcessHeap(), 0, physDev );
-        GDI_HEAP_FREE( dc->hSelf );
+        GDI_FreeObject( dc->hSelf, dc );
         return NULL;
     }
 
@@ -169,7 +169,7 @@
     if (physDev->mh) HeapFree( GetProcessHeap(), 0, physDev->mh );
     HeapFree( GetProcessHeap(), 0, physDev );
     dc->physDev = NULL;
-    GDI_FreeObject(dc->hSelf);
+    GDI_FreeObject( dc->hSelf, dc );
     return TRUE;
 }
 
@@ -186,6 +186,7 @@
 			      LPCSTR filename /* Filename of disk metafile */
 )
 {
+    HDC ret;
     DC *dc;
     METAFILEDRV_PDEVICE *physDev;
     HFILE hFile;
@@ -217,7 +218,9 @@
 	physDev->mh->mtType = METAFILE_MEMORY;
 	
     TRACE("returning %04x\n", dc->hSelf);
-    return dc->hSelf;
+    ret = dc->hSelf;
+    GDI_ReleaseObj( dc->hSelf );
+    return ret;
 }
 
 /**********************************************************************
diff --git a/graphics/metafiledrv/objects.c b/graphics/metafiledrv/objects.c
index 88db9b2..e796be0 100644
--- a/graphics/metafiledrv/objects.c
+++ b/graphics/metafiledrv/objects.c
@@ -35,7 +35,7 @@
 
 INT16 MFDRV_CreateBrushIndirect(DC *dc, HBRUSH hBrush )
 {
-    INT16 index;
+    INT16 index = -1;
     DWORD size;
     METARECORD *mr;
     BRUSHOBJ *brushObj = (BRUSHOBJ *)GDI_GetObjPtr( hBrush, BRUSH_MAGIC );
@@ -68,7 +68,7 @@
 	    GetObjectA(brushObj->logbrush.lbHatch, sizeof(bm), &bm);
 	    if(bm.bmBitsPixel != 1 || bm.bmPlanes != 1) {
 	        FIXME("Trying to store a colour pattern brush\n");
-		return FALSE;
+		goto done;
 	    }
 
 	    bmSize = DIB_GetDIBImageBytes(bm.bmWidth, bm.bmHeight, 1);
@@ -77,7 +77,7 @@
 	      sizeof(RGBQUAD) + bmSize;
 
 	    mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
-	    if(!mr) return FALSE;
+	    if(!mr) goto done;
 	    mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
 	    mr->rdSize = size / 2;
 	    mr->rdParm[0] = BS_PATTERN;
@@ -114,7 +114,7 @@
 					  LOWORD(brushObj->logbrush.lbColor)); 
 	      size = sizeof(METARECORD) + biSize + bmSize + 2;
 	      mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
-	      if(!mr) return FALSE;
+	      if(!mr) goto done;
 	      mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
 	      mr->rdSize = size / 2;
 	      *(mr->rdParm) = brushObj->logbrush.lbStyle;
@@ -130,7 +130,8 @@
     if(!MFDRV_WriteRecord( dc, mr, mr->rdSize * 2))
         index = -1;
     HeapFree(GetProcessHeap(), 0, mr);
-    GDI_HEAP_UNLOCK( hBrush );
+done:
+    GDI_ReleaseObj( hBrush );
     return index;
 }
 
@@ -260,7 +261,7 @@
 	  ret = (HGDIOBJ16)SelectClipRgn16( dc->hSelf, handle );
 	  break;
     }
-    GDI_HEAP_UNLOCK( handle );
+    GDI_ReleaseObj( handle );
     return ret;
 }
 
diff --git a/graphics/painting.c b/graphics/painting.c
index aacb7fc..050048c 100644
--- a/graphics/painting.c
+++ b/graphics/painting.c
@@ -34,19 +34,20 @@
  */
 BOOL WINAPI LineTo( HDC hdc, INT x, INT y )
 {
-    DC * dc = DC_GetDCPtr( hdc );
+    DC * dc = DC_GetDCUpdate( hdc );
     BOOL ret;
 
     if(!dc) return FALSE;
 
     if(PATH_IsPathOpen(dc->w.path))
-        ret = PATH_LineTo(hdc, x, y);
+        ret = PATH_LineTo(dc, x, y);
     else
         ret = dc->funcs->pLineTo && dc->funcs->pLineTo(dc,x,y);
     if(ret) {
         dc->w.CursPosX = x;
         dc->w.CursPosY = y;
     }
+    GDI_ReleaseObj( hdc );
     return ret;
 }
 
@@ -83,7 +84,8 @@
  */
 BOOL WINAPI MoveToEx( HDC hdc, INT x, INT y, LPPOINT pt )
 {
-    DC * dc = DC_GetDCPtr( hdc );
+    BOOL ret = TRUE;
+    DC * dc = DC_GetDCUpdate( hdc );
 
     if(!dc) return FALSE;
 
@@ -94,12 +96,10 @@
     dc->w.CursPosX = x;
     dc->w.CursPosY = y;
 
-    if(PATH_IsPathOpen(dc->w.path))
-        return PATH_MoveTo(hdc);
-
-    if(dc->funcs->pMoveToEx)
-        return dc->funcs->pMoveToEx(dc,x,y,pt);
-    return TRUE;
+    if(PATH_IsPathOpen(dc->w.path)) ret = PATH_MoveTo(dc);
+    else if (dc->funcs->pMoveToEx) ret = dc->funcs->pMoveToEx(dc,x,y,pt);
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
@@ -123,15 +123,17 @@
                      INT bottom, INT xstart, INT ystart,
                      INT xend, INT yend )
 {
-    DC * dc = DC_GetDCPtr( hdc );
-    if(!dc) return FALSE;
-
+    BOOL ret = FALSE;
+    DC * dc = DC_GetDCUpdate( hdc );
+    if (dc)
+    {
     if(PATH_IsPathOpen(dc->w.path))
-        return PATH_Arc(hdc, left, top, right, bottom, xstart, ystart, xend,
-	   yend);
-    
-    return dc->funcs->pArc &&
-    	   dc->funcs->pArc(dc,left,top,right,bottom,xstart,ystart,xend,yend);
+            ret = PATH_Arc(dc, left, top, right, bottom, xstart, ystart, xend, yend);
+        else if (dc->funcs->pArc)
+            ret = dc->funcs->pArc(dc,left,top,right,bottom,xstart,ystart,xend,yend);
+        GDI_ReleaseObj( hdc );
+}
+    return ret;
 }
 
 /***********************************************************************
@@ -144,37 +146,32 @@
                      INT xend,   INT yend )
 {
     BOOL result;
-    DC * dc = DC_GetDCPtr( hdc );
+    DC * dc = DC_GetDCUpdate( hdc );
     if(!dc) return FALSE;
 
     if(dc->funcs->pArcTo)
-        return dc->funcs->pArcTo( dc, left, top, right, bottom,
+    {
+        result = dc->funcs->pArcTo( dc, left, top, right, bottom,
 				  xstart, ystart, xend, yend );
+        GDI_ReleaseObj( hdc );
+        return result;
+    }
+    GDI_ReleaseObj( hdc );
     /* 
      * Else emulate it.
      * According to the documentation, a line is drawn from the current
      * position to the starting point of the arc.
      */
     LineTo(hdc, xstart, ystart);
-
     /*
      * Then the arc is drawn.
      */
-    result = Arc(hdc, 
-                  left, top,
-                  right, bottom,
-                  xstart, ystart,
-                  xend, yend);
-
+    result = Arc(hdc, left, top, right, bottom, xstart, ystart, xend, yend);
     /*
      * If no error occured, the current position is moved to the ending
      * point of the arc.
      */
-    if (result)
-    {
-        MoveToEx(hdc, xend, yend, NULL);
-    }
-
+    if (result) MoveToEx(hdc, xend, yend, NULL);
     return result;
 }
 
@@ -198,16 +195,17 @@
                      INT right, INT bottom, INT xstart, INT ystart,
                      INT xend, INT yend )
 {
-    DC * dc = DC_GetDCPtr( hdc );
-    if(!dc) return FALSE;
-
-    if(PATH_IsPathOpen(dc->w.path)) {
+    BOOL ret = FALSE;
+    DC * dc = DC_GetDCUpdate( hdc );
+    if (dc)
+    {
+        if (PATH_IsPathOpen(dc->w.path))
         FIXME("-> Path: stub\n");
-	return FALSE;
+        else if (dc->funcs->pPie)
+            ret = dc->funcs->pPie(dc,left,top,right,bottom,xstart,ystart,xend,yend);
+        GDI_ReleaseObj( hdc );
     }
-
-    return dc->funcs->pPie &&
-    	   dc->funcs->pPie(dc,left,top,right,bottom,xstart,ystart,xend,yend);
+    return ret;
 }
 
 
@@ -229,16 +227,17 @@
                        INT right, INT bottom, INT xstart, INT ystart,
                        INT xend, INT yend )
 {
-    DC * dc = DC_GetDCPtr( hdc );
-    if(!dc) return FALSE;
-
-    if(PATH_IsPathOpen(dc->w.path)) {
+    BOOL ret = FALSE;
+    DC * dc = DC_GetDCUpdate( hdc );
+    if (dc)
+    {
+        if(PATH_IsPathOpen(dc->w.path))
         FIXME("-> Path: stub\n");
-	return FALSE;
+        else if (dc->funcs->pChord)
+            ret = dc->funcs->pChord(dc,left,top,right,bottom,xstart,ystart,xend,yend);
+        GDI_ReleaseObj( hdc );
     }
-  
-    return dc->funcs->pChord &&
-    	   dc->funcs->pChord(dc,left,top,right,bottom,xstart,ystart,xend,yend);
+    return ret;
 }
 
 
@@ -258,16 +257,17 @@
 BOOL WINAPI Ellipse( HDC hdc, INT left, INT top,
                          INT right, INT bottom )
 {
-    DC * dc = DC_GetDCPtr( hdc );
-    if(!dc) return FALSE;
-
-    if(PATH_IsPathOpen(dc->w.path)) {
+    BOOL ret = FALSE;
+    DC * dc = DC_GetDCUpdate( hdc );
+    if (dc)
+    {
+        if(PATH_IsPathOpen(dc->w.path))
         FIXME("-> Path: stub\n");
-	return FALSE;
+        else if (dc->funcs->pEllipse)
+            ret = dc->funcs->pEllipse(dc,left,top,right,bottom);
+        GDI_ReleaseObj( hdc );
     }
-  
-    return dc->funcs->pEllipse &&
-    	   dc->funcs->pEllipse(dc,left,top,right,bottom);
+    return ret;
 }
 
 
@@ -287,14 +287,17 @@
 BOOL WINAPI Rectangle( HDC hdc, INT left, INT top,
                            INT right, INT bottom )
 {
-    DC * dc = DC_GetDCPtr( hdc );
-    if(!dc) return FALSE;
-
+    BOOL ret = FALSE;
+    DC * dc = DC_GetDCUpdate( hdc );
+    if (dc)
+    {  
     if(PATH_IsPathOpen(dc->w.path))
-        return PATH_Rectangle(hdc, left, top, right, bottom);
-
-    return dc->funcs->pRectangle &&
-    	   dc->funcs->pRectangle(dc,left,top,right,bottom);
+            ret = PATH_Rectangle(dc, left, top, right, bottom);
+        else if (dc->funcs->pRectangle)
+            ret = dc->funcs->pRectangle(dc,left,top,right,bottom);
+        GDI_ReleaseObj( hdc );
+}
+    return ret;
 }
 
 
@@ -314,16 +317,18 @@
 BOOL WINAPI RoundRect( HDC hdc, INT left, INT top, INT right,
                            INT bottom, INT ell_width, INT ell_height )
 {
-    DC * dc = DC_GetDCPtr( hdc );
-    if(!dc) return FALSE;
+    BOOL ret = FALSE;
+    DC *dc = DC_GetDCUpdate( hdc );
 
-    if(PATH_IsPathOpen(dc->w.path)) {
+    if (dc)
+    {
+        if(PATH_IsPathOpen(dc->w.path))
         FIXME("-> Path: stub\n");
-	return FALSE;
+        else if (dc->funcs->pRoundRect)
+            ret = dc->funcs->pRoundRect(dc,left,top,right,bottom,ell_width,ell_height);
+        GDI_ReleaseObj( hdc );
     }
-
-    return dc->funcs->pRoundRect &&
-      dc->funcs->pRoundRect(dc,left,top,right,bottom,ell_width,ell_height);
+    return ret;
 }
 
 /***********************************************************************
@@ -340,10 +345,14 @@
  */
 COLORREF WINAPI SetPixel( HDC hdc, INT x, INT y, COLORREF color )
 {
-    DC * dc = DC_GetDCPtr( hdc );
-  
-    if (!dc || !dc->funcs->pSetPixel) return 0;
-    return dc->funcs->pSetPixel(dc,x,y,color);
+    COLORREF ret = 0;
+    DC * dc = DC_GetDCUpdate( hdc );
+    if (dc)
+    {
+        if (dc->funcs->pSetPixel) ret = dc->funcs->pSetPixel(dc,x,y,color);
+        GDI_ReleaseObj( hdc );
+    }
+    return ret;
 }
 
 /***********************************************************************
@@ -351,11 +360,18 @@
  */
 BOOL WINAPI SetPixelV( HDC hdc, INT x, INT y, COLORREF color )
 {
-    DC * dc = DC_GetDCPtr( hdc );
-  
-    if (!dc || !dc->funcs->pSetPixel) return FALSE;
+    BOOL ret = FALSE;
+    DC * dc = DC_GetDCUpdate( hdc );
+    if (dc)
+    {
+        if (dc->funcs->pSetPixel)
+        {
     dc->funcs->pSetPixel(dc,x,y,color);
-    return TRUE;
+            ret = TRUE;
+}
+        GDI_ReleaseObj( hdc );
+    }
+    return ret;
 }
 
 /***********************************************************************
@@ -372,17 +388,19 @@
  */
 COLORREF WINAPI GetPixel( HDC hdc, INT x, INT y )
 {
-    DC * dc = DC_GetDCPtr( hdc );
+    COLORREF ret = 0;
+    DC * dc = DC_GetDCUpdate( hdc );
 
-    if (!dc) return 0;
-#ifdef SOLITAIRE_SPEED_HACK
-    return 0;
-#endif
-
+    if (dc)
+    {
     /* FIXME: should this be in the graphics driver? */
-    if (!PtVisible( hdc, x, y )) return 0;
-    if (!dc || !dc->funcs->pGetPixel) return 0;
-    return dc->funcs->pGetPixel(dc,x,y);
+        if (PtVisible( hdc, x, y ))
+        {
+            if (dc->funcs->pGetPixel) ret = dc->funcs->pGetPixel(dc,x,y);
+        }
+        GDI_ReleaseObj( hdc );
+    }
+    return ret;
 }
 
 
@@ -400,17 +418,18 @@
  */
 INT WINAPI ChoosePixelFormat( HDC hdc, const LPPIXELFORMATDESCRIPTOR ppfd )
 {
-  DC * dc = DC_GetDCPtr( hdc );
+    INT ret = 0;
+    DC * dc = DC_GetDCPtr( hdc );
 
-  TRACE("(%08x,%p)\n",hdc,ppfd);
+    TRACE("(%08x,%p)\n",hdc,ppfd);
   
-  if (dc == NULL) return 0;
-  if (dc->funcs->pChoosePixelFormat == NULL) {
-    FIXME(" :stub\n");
-    return 0;
-  }
-  
-  return dc->funcs->pChoosePixelFormat(dc,ppfd);
+    if (!dc) return 0;
+
+    if (!dc->funcs->pChoosePixelFormat) FIXME(" :stub\n");
+    else ret = dc->funcs->pChoosePixelFormat(dc,ppfd);
+
+    GDI_ReleaseObj( hdc );  
+    return ret;
 }
 
 
@@ -428,16 +447,18 @@
 BOOL WINAPI SetPixelFormat( HDC hdc, INT iPixelFormat,
                             const PIXELFORMATDESCRIPTOR *ppfd)
 {
-  DC * dc = DC_GetDCPtr( hdc );
+    INT bRet = FALSE;
+    DC * dc = DC_GetDCPtr( hdc );
 
-  TRACE("(%d,%d,%p)\n",hdc,iPixelFormat,ppfd);
+    TRACE("(%d,%d,%p)\n",hdc,iPixelFormat,ppfd);
 
-  if (dc == NULL) return 0;
-  if (dc->funcs->pSetPixelFormat == NULL) {
-    FIXME(" :stub\n");
-    return 0;
-  }
-  return dc->funcs->pSetPixelFormat(dc,iPixelFormat,ppfd);
+    if (!dc) return 0;
+
+    if (!dc->funcs->pSetPixelFormat) FIXME(" :stub\n");
+    else bRet = dc->funcs->pSetPixelFormat(dc,iPixelFormat,ppfd);
+
+    GDI_ReleaseObj( hdc );  
+    return bRet;
 }
 
 
@@ -454,16 +475,18 @@
  */
 INT WINAPI GetPixelFormat( HDC hdc )
 {
-  DC * dc = DC_GetDCPtr( hdc );
+    INT ret = 0;
+    DC * dc = DC_GetDCPtr( hdc );
 
-  TRACE("(%08x)\n",hdc);
+    TRACE("(%08x)\n",hdc);
 
-  if (dc == NULL) return 0;
-  if (dc->funcs->pGetPixelFormat == NULL) {
-    FIXME(" :stub\n");
-    return 0;
-  }
-  return dc->funcs->pGetPixelFormat(dc);
+    if (!dc) return 0;
+
+    if (!dc->funcs->pGetPixelFormat) FIXME(" :stub\n");
+    else ret = dc->funcs->pGetPixelFormat(dc);
+
+    GDI_ReleaseObj( hdc );  
+    return ret;
 }
 
 
@@ -484,18 +507,24 @@
 INT WINAPI DescribePixelFormat( HDC hdc, INT iPixelFormat, UINT nBytes,
                                 LPPIXELFORMATDESCRIPTOR ppfd )
 {
-  DC * dc = DC_GetDCPtr( hdc );
+    INT ret = 0;
+    DC * dc = DC_GetDCPtr( hdc );
 
-  TRACE("(%08x,%d,%d,%p): stub\n",hdc,iPixelFormat,nBytes,ppfd);
+    TRACE("(%08x,%d,%d,%p): stub\n",hdc,iPixelFormat,nBytes,ppfd);
 
-  if (dc == NULL) return 0;
-  if (dc->funcs->pDescribePixelFormat == NULL) {
-    FIXME(" :stub\n");
-    ppfd->nSize = nBytes;
-    ppfd->nVersion = 1;
-    return 3;
-  }
-  return dc->funcs->pDescribePixelFormat(dc,iPixelFormat,nBytes,ppfd);
+    if (!dc) return 0;
+
+    if (!dc->funcs->pDescribePixelFormat)
+    {
+        FIXME(" :stub\n");
+        ppfd->nSize = nBytes;
+        ppfd->nVersion = 1;
+	ret = 3;
+    }
+    else ret = dc->funcs->pDescribePixelFormat(dc,iPixelFormat,nBytes,ppfd);
+
+    GDI_ReleaseObj( hdc );  
+    return ret;
 }
 
 
@@ -510,16 +539,22 @@
  */
 BOOL WINAPI SwapBuffers( HDC hdc )
 {
-  DC * dc = DC_GetDCPtr( hdc );
+    INT bRet = FALSE;
+    DC * dc = DC_GetDCPtr( hdc );
 
-  TRACE("(%08x)\n",hdc);
+    TRACE("(%08x)\n",hdc);
 
-  if (dc == NULL) return 0;
-  if (dc->funcs->pSwapBuffers == NULL) {
-    FIXME(" :stub\n");
-    return TRUE;
-  }
-  return dc->funcs->pSwapBuffers(dc);
+    if (!dc) return TRUE;
+
+    if (!dc->funcs->pSwapBuffers)
+    {
+        FIXME(" :stub\n");
+	bRet = TRUE;
+    }
+    else bRet = dc->funcs->pSwapBuffers(dc);
+
+    GDI_ReleaseObj( hdc );  
+    return bRet;
 }
 
 
@@ -537,10 +572,14 @@
  */
 BOOL WINAPI PaintRgn( HDC hdc, HRGN hrgn )
 {
-    DC * dc = DC_GetDCPtr( hdc );
-
-    return dc && dc->funcs->pPaintRgn &&
-	   dc->funcs->pPaintRgn(dc,hrgn);
+    BOOL ret = FALSE;
+    DC * dc = DC_GetDCUpdate( hdc );
+    if (dc)
+    {
+        if (dc->funcs->pPaintRgn) ret = dc->funcs->pPaintRgn(dc,hrgn);
+        GDI_ReleaseObj( hdc );
+    }
+    return ret;
 }
 
 
@@ -558,18 +597,19 @@
  */
 BOOL WINAPI FillRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush )
 {
-    BOOL retval;
+    BOOL retval = FALSE;
     HBRUSH prevBrush;
-    DC * dc = DC_GetDCPtr( hdc );
+    DC * dc = DC_GetDCUpdate( hdc );
 
     if (!dc) return FALSE;
     if(dc->funcs->pFillRgn)
-        return dc->funcs->pFillRgn(dc, hrgn, hbrush);
-
-    prevBrush = SelectObject( hdc, hbrush );
-    if (!prevBrush) return FALSE;
+        retval = dc->funcs->pFillRgn(dc, hrgn, hbrush);
+    else if ((prevBrush = SelectObject( hdc, hbrush )))
+    {
     retval = PaintRgn( hdc, hrgn );
     SelectObject( hdc, prevBrush );
+    }
+    GDI_ReleaseObj( hdc );
     return retval;
 }
 
@@ -590,17 +630,27 @@
 BOOL WINAPI FrameRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush,
                           INT nWidth, INT nHeight )
 {
-    HRGN tmp;
-    DC *dc = DC_GetDCPtr( hdc );
+    BOOL ret = FALSE;
+    DC *dc = DC_GetDCUpdate( hdc );
 
+    if (!dc) return FALSE;
     if(dc->funcs->pFrameRgn)
-        return dc->funcs->pFrameRgn( dc, hrgn, hbrush, nWidth, nHeight );
-
-    tmp = CreateRectRgn( 0, 0, 0, 0 );
-    if(!REGION_FrameRgn( tmp, hrgn, nWidth, nHeight )) return FALSE;
+        ret = dc->funcs->pFrameRgn( dc, hrgn, hbrush, nWidth, nHeight );
+    else
+    {
+        HRGN tmp = CreateRectRgn( 0, 0, 0, 0 );
+        if (tmp)
+        {
+            if (REGION_FrameRgn( tmp, hrgn, nWidth, nHeight ))
+            {
     FillRgn( hdc, tmp, hbrush );
+                ret = TRUE;
+            }
     DeleteObject( tmp );
-    return TRUE;
+}
+    }
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
@@ -621,16 +671,20 @@
     HBRUSH prevBrush;
     INT prevROP;
     BOOL retval;
-    DC *dc = DC_GetDCPtr( hdc );
+    DC *dc = DC_GetDCUpdate( hdc );
+    if (!dc) return FALSE;
 
     if(dc->funcs->pInvertRgn)
-        return dc->funcs->pInvertRgn( dc, hrgn );
-
+        retval = dc->funcs->pInvertRgn( dc, hrgn );
+    else
+    {
     prevBrush = SelectObject( hdc, GetStockObject(BLACK_BRUSH) );
     prevROP = SetROP2( hdc, R2_NOT );
     retval = PaintRgn( hdc, hrgn );
     SelectObject( hdc, prevBrush );
     SetROP2( hdc, prevROP );
+    }
+    GDI_ReleaseObj( hdc );
     return retval;
 }
 
@@ -657,14 +711,15 @@
  */
 BOOL WINAPI Polyline( HDC hdc, const POINT* pt, INT count )
 {
-    DC * dc = DC_GetDCPtr( hdc );
-    if(!dc) return FALSE;
-
-    if(PATH_IsPathOpen(dc->w.path))
-        return PATH_Polyline(hdc, pt, count);
-
-    return dc->funcs->pPolyline &&
-    	   dc->funcs->pPolyline(dc,pt,count);
+    BOOL ret = FALSE;
+    DC * dc = DC_GetDCUpdate( hdc );
+    if (dc)
+    {
+        if (PATH_IsPathOpen(dc->w.path)) ret = PATH_Polyline(dc, pt, count);
+        else if (dc->funcs->pPolyline) ret = dc->funcs->pPolyline(dc,pt,count);
+        GDI_ReleaseObj( hdc );
+    }
+    return ret;
 }
 
 /**********************************************************************
@@ -672,13 +727,13 @@
  */
 BOOL WINAPI PolylineTo( HDC hdc, const POINT* pt, DWORD cCount )
 {
-    DC * dc = DC_GetDCPtr( hdc );
-    BOOL ret;
+    DC * dc = DC_GetDCUpdate( hdc );
+    BOOL ret = FALSE;
 
     if(!dc) return FALSE;
 
     if(PATH_IsPathOpen(dc->w.path))
-        ret = PATH_PolylineTo(hdc, pt, cCount);
+        ret = PATH_PolylineTo(dc, pt, cCount);
 
     else if(dc->funcs->pPolylineTo)
         ret = dc->funcs->pPolylineTo(dc, pt, cCount);
@@ -686,18 +741,20 @@
     else { /* do it using Polyline */
         POINT *pts = HeapAlloc( GetProcessHeap(), 0,
 				sizeof(POINT) * (cCount + 1) );
-	if(!pts) return FALSE;
-
+	if (pts)
+        {
 	pts[0].x = dc->w.CursPosX;
 	pts[0].y = dc->w.CursPosY;
 	memcpy( pts + 1, pt, sizeof(POINT) * cCount );
 	ret = Polyline( hdc, pts, cCount + 1 );
 	HeapFree( GetProcessHeap(), 0, pts );
     }
+    }
     if(ret) {
         dc->w.CursPosX = pt[cCount-1].x;
 	dc->w.CursPosY = pt[cCount-1].y;
     }
+    GDI_ReleaseObj( hdc );
     return ret;
 }
 
@@ -724,14 +781,15 @@
  */
 BOOL WINAPI Polygon( HDC hdc, const POINT* pt, INT count )
 {
-    DC * dc = DC_GetDCPtr( hdc );
-    if(!dc) return FALSE;
-
-    if(PATH_IsPathOpen(dc->w.path))
-	return PATH_Polygon(hdc, pt, count);
-
-    return dc->funcs->pPolygon &&
-    	   dc->funcs->pPolygon(dc,pt,count);
+    BOOL ret = FALSE;
+    DC * dc = DC_GetDCUpdate( hdc );
+    if (dc)
+    {
+        if (PATH_IsPathOpen(dc->w.path)) ret = PATH_Polygon(dc, pt, count);
+        else if (dc->funcs->pPolygon) ret = dc->funcs->pPolygon(dc,pt,count);
+        GDI_ReleaseObj( hdc );
+}
+    return ret;
 }
 
 
@@ -772,14 +830,15 @@
 BOOL WINAPI PolyPolygon( HDC hdc, const POINT* pt, const INT* counts,
                              UINT polygons )
 {
-    DC * dc = DC_GetDCPtr( hdc );
-    if(!dc) return FALSE;
-
-    if(PATH_IsPathOpen(dc->w.path))
-        return PATH_PolyPolygon(hdc, pt, counts, polygons);
-
-    return dc->funcs->pPolyPolygon &&
-    	   dc->funcs->pPolyPolygon(dc,pt,counts,polygons);
+    BOOL ret = FALSE;
+    DC * dc = DC_GetDCUpdate( hdc );
+    if (dc)
+    {
+        if (PATH_IsPathOpen(dc->w.path)) ret = PATH_PolyPolygon(dc, pt, counts, polygons);
+        else if (dc->funcs->pPolyPolygon) ret = dc->funcs->pPolyPolygon(dc,pt,counts,polygons);
+        GDI_ReleaseObj( hdc );
+    }
+    return ret;
 }
 
 /**********************************************************************
@@ -788,14 +847,15 @@
 BOOL WINAPI PolyPolyline( HDC hdc, const POINT* pt, const DWORD* counts,
                             DWORD polylines )
 {
-    DC * dc = DC_GetDCPtr( hdc );
-    if(!dc) return FALSE;
-
-    if(PATH_IsPathOpen(dc->w.path))
-        return PATH_PolyPolyline(hdc, pt, counts, polylines);
-
-    return dc->funcs->pPolyPolyline &&
-    	   dc->funcs->pPolyPolyline(dc,pt,counts,polylines);
+    BOOL ret = FALSE;
+    DC * dc = DC_GetDCUpdate( hdc );
+    if (dc)
+    {
+        if (PATH_IsPathOpen(dc->w.path)) ret = PATH_PolyPolyline(dc, pt, counts, polylines);
+        else if (dc->funcs->pPolyPolyline) ret = dc->funcs->pPolyPolyline(dc,pt,counts,polylines);
+        GDI_ReleaseObj( hdc );
+}
+    return ret;
 }
 
 /**********************************************************************
@@ -814,10 +874,14 @@
 BOOL WINAPI ExtFloodFill( HDC hdc, INT x, INT y, COLORREF color,
                               UINT fillType )
 {
-    DC *dc = DC_GetDCPtr( hdc );
-
-    return dc && dc->funcs->pExtFloodFill &&
-	   dc->funcs->pExtFloodFill(dc,x,y,color,fillType);
+    BOOL ret = FALSE;
+    DC * dc = DC_GetDCUpdate( hdc );
+    if (dc)
+    {
+        if (dc->funcs->pExtFloodFill) ret = dc->funcs->pExtFloodFill(dc,x,y,color,fillType);
+        GDI_ReleaseObj( hdc );
+}
+    return ret;
 }
 
 
@@ -884,30 +948,32 @@
  */
 BOOL WINAPI PolyBezier( HDC hdc, const POINT* lppt, DWORD cPoints )
 {
-    DC * dc = DC_GetDCPtr( hdc );
+    BOOL ret = FALSE;
+    DC * dc = DC_GetDCUpdate( hdc );
+
     if(!dc) return FALSE;
 
     if(PATH_IsPathOpen(dc->w.path))
-	return PATH_PolyBezier(hdc, lppt, cPoints);
-
-    if(dc->funcs->pPolyBezier)
-        return dc->funcs->pPolyBezier(dc, lppt, cPoints);
-
-    /* We'll convert it into line segments and draw them using Polyline */
+	ret = PATH_PolyBezier(dc, lppt, cPoints);
+    else if (dc->funcs->pPolyBezier)
+        ret = dc->funcs->pPolyBezier(dc, lppt, cPoints);
+    else  /* We'll convert it into line segments and draw them using Polyline */
     {
         POINT *Pts;
 	INT nOut;
-	BOOL ret;
 
-	Pts = GDI_Bezier( lppt, cPoints, &nOut );
-	if(!Pts) return FALSE;
+	if ((Pts = GDI_Bezier( lppt, cPoints, &nOut )))
+        {
 	TRACE("Pts = %p, no = %d\n", Pts, nOut);
 	ret = Polyline( dc->hSelf, Pts, nOut );
 	HeapFree( GetProcessHeap(), 0, Pts );
-	return ret;
     }
 }
 
+    GDI_ReleaseObj( hdc );
+    return ret;
+}
+
 /******************************************************************************
  * PolyBezierTo [GDI32.269]
  * Draws one or more Bezier curves
@@ -921,13 +987,13 @@
  */
 BOOL WINAPI PolyBezierTo( HDC hdc, const POINT* lppt, DWORD cPoints )
 {
-    DC * dc = DC_GetDCPtr( hdc );
+    DC * dc = DC_GetDCUpdate( hdc );
     BOOL ret;
 
     if(!dc) return FALSE;
 
     if(PATH_IsPathOpen(dc->w.path))
-        ret = PATH_PolyBezierTo(hdc, lppt, cPoints);
+        ret = PATH_PolyBezierTo(dc, lppt, cPoints);
     else if(dc->funcs->pPolyBezierTo)
         ret = dc->funcs->pPolyBezierTo(dc, lppt, cPoints);
     else { /* We'll do it using PolyBezier */
@@ -944,6 +1010,7 @@
         dc->w.CursPosX = lppt[cPoints-1].x;
         dc->w.CursPosY = lppt[cPoints-1].y;
     }
+    GDI_ReleaseObj( hdc );
     return ret;
 }
 
diff --git a/graphics/path.c b/graphics/path.c
index 5ae3779..e82925d 100644
--- a/graphics/path.c
+++ b/graphics/path.c
@@ -73,7 +73,6 @@
 static BOOL PATH_AddEntry(GdiPath *pPath, const POINT *pPoint,
    BYTE flags);
 static BOOL PATH_ReserveEntries(GdiPath *pPath, INT numEntries);
-static BOOL PATH_GetPathFromHDC(HDC hdc, GdiPath **ppPath);
 static BOOL PATH_DoArcPart(GdiPath *pPath, FLOAT_POINT corners[],
    double angleStart, double angleEnd, BOOL addMoveTo);
 static void PATH_ScaleNormalizedPoint(FLOAT_POINT corners[], double x,
@@ -96,31 +95,28 @@
  */
 BOOL WINAPI BeginPath(HDC hdc)
 {
-   DC *dc = DC_GetDCPtr( hdc );
-   GdiPath *pPath;
+    BOOL ret = TRUE;
+    DC *dc = DC_GetDCPtr( hdc );
    
-   if(!dc) {
-     SetLastError(ERROR_INVALID_HANDLE);
-     return FALSE;
-   }
+    if(!dc) return FALSE;
 
-   if(dc->funcs->pBeginPath)
-     return dc->funcs->pBeginPath(dc);
+    if(dc->funcs->pBeginPath)
+        ret = dc->funcs->pBeginPath(dc);
+    else
+    {
+        /* If path is already open, do nothing */
+        if(dc->w.path.state != PATH_Open)
+        {
+            /* Make sure that path is empty */
+            PATH_EmptyPath(&dc->w.path);
 
-   pPath = &dc->w.path;
-
-   /* If path is already open, do nothing */
-   if(pPath->state==PATH_Open)
-      return TRUE;
-
-   /* Make sure that path is empty */
-   PATH_EmptyPath(pPath);
-
-   /* Initialize variables for new path */
-   pPath->newStroke=TRUE;
-   pPath->state=PATH_Open;
-   
-   return TRUE;
+            /* Initialize variables for new path */
+            dc->w.path.newStroke=TRUE;
+            dc->w.path.state=PATH_Open;
+        }
+    }
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
@@ -138,30 +134,26 @@
  */
 BOOL WINAPI EndPath(HDC hdc)
 {
-   DC *dc = DC_GetDCPtr( hdc );
-   GdiPath *pPath;
+    BOOL ret = TRUE;
+    DC *dc = DC_GetDCPtr( hdc );
    
-   if(!dc) {
-     SetLastError(ERROR_INVALID_HANDLE);
-     return FALSE;
-   }
+    if(!dc) return FALSE;
 
-   if(dc->funcs->pEndPath)
-     return dc->funcs->pEndPath(dc);
-
-   pPath = &dc->w.path;
-
-   /* Check that path is currently being constructed */
-   if(pPath->state!=PATH_Open)
-   {
-      SetLastError(ERROR_CAN_NOT_COMPLETE);
-      return FALSE;
-   }
-   
-   /* Set flag to indicate that path is finished */
-   pPath->state=PATH_Closed;
-   
-   return TRUE;
+    if(dc->funcs->pEndPath)
+        ret = dc->funcs->pEndPath(dc);
+    else
+    {
+        /* Check that path is currently being constructed */
+        if(dc->w.path.state!=PATH_Open)
+        {
+            SetLastError(ERROR_CAN_NOT_COMPLETE);
+            ret = FALSE;
+        }
+        /* Set flag to indicate that path is finished */
+        else dc->w.path.state=PATH_Closed;
+    }
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
@@ -188,23 +180,17 @@
  */
 BOOL WINAPI AbortPath( HDC hdc )
 {
-   DC *dc = DC_GetDCPtr( hdc );
-   GdiPath *pPath;
+    BOOL ret = TRUE;
+    DC *dc = DC_GetDCPtr( hdc );
    
-   if(!dc) {
-     SetLastError(ERROR_INVALID_HANDLE);
-     return FALSE;
-   }
+    if(!dc) return FALSE;
 
-   if(dc->funcs->pAbortPath)
-     return dc->funcs->pAbortPath(dc);
-
-   pPath = &dc->w.path;
-   
-   /* Remove all entries from the path */
-   PATH_EmptyPath(pPath);
-
-   return TRUE;
+    if(dc->funcs->pAbortPath)
+        ret = dc->funcs->pAbortPath(dc);
+    else /* Remove all entries from the path */
+        PATH_EmptyPath( &dc->w.path );
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
@@ -224,34 +210,35 @@
  */
 BOOL WINAPI CloseFigure(HDC hdc)
 {
-   DC *dc = DC_GetDCPtr( hdc );
-   GdiPath *pPath;
+    BOOL ret = TRUE;
+    DC *dc = DC_GetDCPtr( hdc );
    
-   if(!dc) {
-     SetLastError(ERROR_INVALID_HANDLE);
-     return FALSE;
-   }
+    if(!dc) return FALSE;
 
-   if(dc->funcs->pCloseFigure)
-     return dc->funcs->pCloseFigure(dc);
-
-   pPath = &dc->w.path;
-
-   /* Check that path is open */
-   if(pPath->state!=PATH_Open)
-   {
-      SetLastError(ERROR_CAN_NOT_COMPLETE);
-      return FALSE;
-   }
-   
-   /* Set PT_CLOSEFIGURE on the last entry and start a new stroke */
-   if(pPath->numEntriesUsed)
-   {
-      pPath->pFlags[pPath->numEntriesUsed-1]|=PT_CLOSEFIGURE;
-      pPath->newStroke=TRUE;
-   }
-
-   return TRUE;
+    if(dc->funcs->pCloseFigure)
+        ret = dc->funcs->pCloseFigure(dc);
+    else
+    {
+        /* Check that path is open */
+        if(dc->w.path.state!=PATH_Open)
+        {
+            SetLastError(ERROR_CAN_NOT_COMPLETE);
+            ret = FALSE;
+        }
+        else
+        {
+            /* FIXME: Shouldn't we draw a line to the beginning of the
+               figure? */
+            /* Set PT_CLOSEFIGURE on the last entry and start a new stroke */
+            if(dc->w.path.numEntriesUsed)
+            {
+                dc->w.path.pFlags[dc->w.path.numEntriesUsed-1]|=PT_CLOSEFIGURE;
+                dc->w.path.newStroke=TRUE;
+            }
+        }
+    }
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
@@ -273,28 +260,27 @@
 INT WINAPI GetPath(HDC hdc, LPPOINT pPoints, LPBYTE pTypes,
    INT nSize)
 {
+   INT ret = -1;
    GdiPath *pPath;
+   DC *dc = DC_GetDCPtr( hdc );
    
-   /* Get pointer to path */
-   if(!PATH_GetPathFromHDC(hdc, &pPath))
-   {
-      SetLastError(ERROR_INVALID_PARAMETER);
-      return -1;
-   }
+   if(!dc) return -1;
+   
+   pPath = &dc->w.path;
    
    /* Check that path is closed */
    if(pPath->state!=PATH_Closed)
    {
       SetLastError(ERROR_CAN_NOT_COMPLETE);
-      return -1;
+      goto done;
    }
    
    if(nSize==0)
-      return pPath->numEntriesUsed;
+      ret = pPath->numEntriesUsed;
    else if(nSize<pPath->numEntriesUsed)
    {
       SetLastError(ERROR_INVALID_PARAMETER);
-      return -1;
+      goto done;
    }
    else
    {
@@ -306,11 +292,13 @@
       {
 	 /* FIXME: Is this the correct value? */
          SetLastError(ERROR_CAN_NOT_COMPLETE);
-         return -1;
+	goto done;
       }
-      
-      return pPath->numEntriesUsed;
+     else ret = pPath->numEntriesUsed;
    }
+ done:
+   GDI_ReleaseObj( hdc );
+   return ret;
 }
 
 /***********************************************************************
@@ -333,32 +321,29 @@
 HRGN WINAPI PathToRegion(HDC hdc)
 {
    GdiPath *pPath;
-   HRGN  hrgnRval;
+   HRGN  hrgnRval = 0;
+   DC *dc = DC_GetDCPtr( hdc );
 
    /* Get pointer to path */
-   if(!PATH_GetPathFromHDC(hdc, &pPath))
-   {
-      SetLastError(ERROR_INVALID_PARAMETER);
-      return 0;
-   }
+   if(!dc) return -1;
+   
+    pPath = &dc->w.path;
    
    /* Check that path is closed */
-   if(pPath->state!=PATH_Closed)
-   {
-      SetLastError(ERROR_CAN_NOT_COMPLETE);
-      return 0;
-   }
-   
-   /* FIXME: Should we empty the path even if conversion failed? */
-   if(PATH_PathToRegion(pPath, GetPolyFillMode(hdc), &hrgnRval))
-      PATH_EmptyPath(pPath);
+   if(pPath->state!=PATH_Closed) SetLastError(ERROR_CAN_NOT_COMPLETE);
    else
-      hrgnRval=0;
-
+   {
+       /* FIXME: Should we empty the path even if conversion failed? */
+       if(PATH_PathToRegion(pPath, GetPolyFillMode(hdc), &hrgnRval))
+           PATH_EmptyPath(pPath);
+       else
+           hrgnRval=0;
+   }
+   GDI_ReleaseObj( hdc );
    return hrgnRval;
 }
 
-static BOOL PATH_FillPath(HDC hdc, GdiPath *pPath)
+static BOOL PATH_FillPath(DC *dc, GdiPath *pPath)
 {
    INT   mapMode, graphicsMode;
    SIZE  ptViewportExt, ptWindowExt;
@@ -366,6 +351,9 @@
    XFORM xform;
    HRGN  hrgn;
 
+   if(dc->funcs->pFillPath)
+       return dc->funcs->pFillPath(dc);
+
    /* Check that path is closed */
    if(pPath->state!=PATH_Closed)
    {
@@ -374,7 +362,7 @@
    }
    
    /* Construct a region from the path and fill it */
-   if(PATH_PathToRegion(pPath, GetPolyFillMode(hdc), &hrgn))
+   if(PATH_PathToRegion(pPath, dc->w.polyFillMode, &hrgn))
    {
       /* Since PaintRgn interprets the region as being in logical coordinates
        * but the points we store for the path are already in device
@@ -385,11 +373,11 @@
        */
        
       /* Save the information about the old mapping mode */
-      mapMode=GetMapMode(hdc);
-      GetViewportExtEx(hdc, &ptViewportExt);
-      GetViewportOrgEx(hdc, &ptViewportOrg);
-      GetWindowExtEx(hdc, &ptWindowExt);
-      GetWindowOrgEx(hdc, &ptWindowOrg);
+      mapMode=GetMapMode(dc->hSelf);
+      GetViewportExtEx(dc->hSelf, &ptViewportExt);
+      GetViewportOrgEx(dc->hSelf, &ptViewportOrg);
+      GetWindowExtEx(dc->hSelf, &ptWindowExt);
+      GetWindowOrgEx(dc->hSelf, &ptWindowOrg);
       
       /* Save world transform
        * NB: The Windows documentation on world transforms would lead one to
@@ -397,28 +385,28 @@
        * tests show that resetting the graphics mode to GM_COMPATIBLE does
        * not reset the world transform.
        */
-      GetWorldTransform(hdc, &xform);
+      GetWorldTransform(dc->hSelf, &xform);
       
       /* Set MM_TEXT */
-      SetMapMode(hdc, MM_TEXT);
-      SetViewportOrgEx(hdc, 0, 0, NULL);
-      SetWindowOrgEx(hdc, 0, 0, NULL);
+      SetMapMode(dc->hSelf, MM_TEXT);
+      SetViewportOrgEx(dc->hSelf, 0, 0, NULL);
+      SetWindowOrgEx(dc->hSelf, 0, 0, NULL);
 
       /* Paint the region */
-      PaintRgn(hdc, hrgn);
+      PaintRgn(dc->hSelf, hrgn);
       DeleteObject(hrgn);
       /* Restore the old mapping mode */
-      SetMapMode(hdc, mapMode);
-      SetViewportExtEx(hdc, ptViewportExt.cx, ptViewportExt.cy, NULL);
-      SetViewportOrgEx(hdc, ptViewportOrg.x, ptViewportOrg.y, NULL);
-      SetWindowExtEx(hdc, ptWindowExt.cx, ptWindowExt.cy, NULL);
-      SetWindowOrgEx(hdc, ptWindowOrg.x, ptWindowOrg.y, NULL);
+      SetMapMode(dc->hSelf, mapMode);
+      SetViewportExtEx(dc->hSelf, ptViewportExt.cx, ptViewportExt.cy, NULL);
+      SetViewportOrgEx(dc->hSelf, ptViewportOrg.x, ptViewportOrg.y, NULL);
+      SetWindowExtEx(dc->hSelf, ptWindowExt.cx, ptWindowExt.cy, NULL);
+      SetWindowOrgEx(dc->hSelf, ptWindowOrg.x, ptWindowOrg.y, NULL);
 
       /* Go to GM_ADVANCED temporarily to restore the world transform */
-      graphicsMode=GetGraphicsMode(hdc);
-      SetGraphicsMode(hdc, GM_ADVANCED);
-      SetWorldTransform(hdc, &xform);
-      SetGraphicsMode(hdc, graphicsMode);
+      graphicsMode=GetGraphicsMode(dc->hSelf);
+      SetGraphicsMode(dc->hSelf, GM_ADVANCED);
+      SetWorldTransform(dc->hSelf, &xform);
+      SetGraphicsMode(dc->hSelf, graphicsMode);
       return TRUE;
    }
    return FALSE;
@@ -440,22 +428,25 @@
  */
 BOOL WINAPI FillPath(HDC hdc)
 {
-   DC *dc = DC_GetDCPtr( hdc );
+    DC *dc = DC_GetDCPtr( hdc );
+    BOOL bRet = FALSE;
    
-   if(!dc) {
-     SetLastError(ERROR_INVALID_HANDLE);
-     return FALSE;
-   }
+    if(!dc) return FALSE;
 
-   if(dc->funcs->pFillPath)
-     return dc->funcs->pFillPath(dc);
-
-   if(!PATH_FillPath(hdc, &dc->w.path))
-      return FALSE;
-
-   /* FIXME: Should the path be emptied even if conversion failed? */
-   PATH_EmptyPath(&dc->w.path);
-   return TRUE;
+    if(dc->funcs->pFillPath)
+        bRet = dc->funcs->pFillPath(dc);
+    else
+    {
+        bRet = PATH_FillPath(dc, &dc->w.path);
+        if(bRet)
+        {
+            /* FIXME: Should the path be emptied even if conversion
+               failed? */
+            PATH_EmptyPath(&dc->w.path);
+        }
+    }
+    GDI_ReleaseObj( hdc );
+    return bRet;
 }
 
 /***********************************************************************
@@ -475,41 +466,34 @@
 {
    GdiPath *pPath;
    HRGN  hrgnPath;
-   BOOL  success;
+   BOOL  success = FALSE;
    DC *dc = DC_GetDCPtr( hdc );
    
-   if(!dc) {
-     SetLastError(ERROR_INVALID_HANDLE);
-     return FALSE;
-   }
+   if(!dc) return FALSE;
 
    if(dc->funcs->pSelectClipPath)
-     return dc->funcs->pSelectClipPath(dc, iMode);
-
-   pPath = &dc->w.path;
-   
-   /* Check that path is closed */
-   if(pPath->state!=PATH_Closed)
-   {
-      SetLastError(ERROR_CAN_NOT_COMPLETE);
-      return FALSE;
-   }
-   
-   /* Construct a region from the path */
-   if(PATH_PathToRegion(pPath, GetPolyFillMode(hdc), &hrgnPath))
-   {
-      success = ExtSelectClipRgn( hdc, hrgnPath, iMode ) != ERROR;
-      DeleteObject(hrgnPath);
-
-      /* Empty the path */
-      if(success)
-         PATH_EmptyPath(pPath);
-      /* FIXME: Should this function delete the path even if it failed? */
-
-      return success;
-   }
+     success = dc->funcs->pSelectClipPath(dc, iMode);
    else
-      return FALSE;
+   {
+       pPath = &dc->w.path;
+   
+       /* Check that path is closed */
+       if(pPath->state!=PATH_Closed)
+           SetLastError(ERROR_CAN_NOT_COMPLETE);
+       /* Construct a region from the path */
+       else if(PATH_PathToRegion(pPath, GetPolyFillMode(hdc), &hrgnPath))
+       {
+           success = ExtSelectClipRgn( hdc, hrgnPath, iMode ) != ERROR;
+           DeleteObject(hrgnPath);
+
+           /* Empty the path */
+           if(success)
+               PATH_EmptyPath(pPath);
+           /* FIXME: Should this function delete the path even if it failed? */
+       }
+   }
+   GDI_ReleaseObj( hdc );
+   return success;
 }
 
 
@@ -581,13 +565,9 @@
  * open path. This starts a new stroke. Returns TRUE if successful, else
  * FALSE.
  */
-BOOL PATH_MoveTo(HDC hdc)
+BOOL PATH_MoveTo(DC *dc)
 {
-   GdiPath *pPath;
-   
-   /* Get pointer to path */
-   if(!PATH_GetPathFromHDC(hdc, &pPath))
-      return FALSE;
+   GdiPath *pPath = &dc->w.path;
    
    /* Check that path is open */
    if(pPath->state!=PATH_Open)
@@ -607,15 +587,11 @@
  * a PT_MOVETO entry, if this is the first LineTo in a stroke).
  * Returns TRUE if successful, else FALSE.
  */
-BOOL PATH_LineTo(HDC hdc, INT x, INT y)
+BOOL PATH_LineTo(DC *dc, INT x, INT y)
 {
-   GdiPath *pPath;
+   GdiPath *pPath = &dc->w.path;
    POINT point, pointCurPos;
    
-   /* Get pointer to path */
-   if(!PATH_GetPathFromHDC(hdc, &pPath))
-      return FALSE;
-   
    /* Check that path is open */
    if(pPath->state!=PATH_Open)
       return FALSE;
@@ -623,15 +599,16 @@
    /* Convert point to device coordinates */
    point.x=x;
    point.y=y;
-   if(!LPtoDP(hdc, &point, 1))
+   if(!LPtoDP(dc->hSelf, &point, 1))
       return FALSE;
    
    /* Add a PT_MOVETO if necessary */
    if(pPath->newStroke)
    {
       pPath->newStroke=FALSE;
-      if(!GetCurrentPositionEx(hdc, &pointCurPos) ||
-         !LPtoDP(hdc, &pointCurPos, 1))
+      pointCurPos.x = dc->w.CursPosX;
+      pointCurPos.y = dc->w.CursPosY;
+      if(!LPtoDP(dc->hSelf, &pointCurPos, 1))
          return FALSE;
       if(!PATH_AddEntry(pPath, &pointCurPos, PT_MOVETO))
          return FALSE;
@@ -646,16 +623,12 @@
  * Should be called when a call to Rectangle is performed on a DC that has
  * an open path. Returns TRUE if successful, else FALSE.
  */
-BOOL PATH_Rectangle(HDC hdc, INT x1, INT y1, INT x2, INT y2)
+BOOL PATH_Rectangle(DC *dc, INT x1, INT y1, INT x2, INT y2)
 {
-   GdiPath *pPath;
+   GdiPath *pPath = &dc->w.path;
    POINT corners[2], pointTemp;
    INT   temp;
 
-   /* Get pointer to path */
-   if(!PATH_GetPathFromHDC(hdc, &pPath))
-      return FALSE;
-   
    /* Check that path is open */
    if(pPath->state!=PATH_Open)
       return FALSE;
@@ -665,7 +638,7 @@
    corners[0].y=y1;
    corners[1].x=x2;
    corners[1].y=y2;
-   if(!LPtoDP(hdc, corners, 2))
+   if(!LPtoDP(dc->hSelf, corners, 2))
       return FALSE;
    
    /* Make sure first corner is top left and second corner is bottom right */
@@ -683,14 +656,14 @@
    }
    
    /* In GM_COMPATIBLE, don't include bottom and right edges */
-   if(GetGraphicsMode(hdc)==GM_COMPATIBLE)
+   if(dc->w.GraphicsMode==GM_COMPATIBLE)
    {
       corners[1].x--;
       corners[1].y--;
    }
 
    /* Close any previous figure */
-   if(!CloseFigure(hdc))
+   if(!CloseFigure(dc->hSelf))
    {
       /* The CloseFigure call shouldn't have failed */
       assert(FALSE);
@@ -712,7 +685,7 @@
       return FALSE;
 
    /* Close the rectangle figure */
-   if(!CloseFigure(hdc))
+   if(!CloseFigure(dc->hSelf))
    {
       /* The CloseFigure call shouldn't have failed */
       assert(FALSE);
@@ -728,11 +701,11 @@
  * an open path. This adds four Bezier splines representing the ellipse
  * to the path. Returns TRUE if successful, else FALSE.
  */
-BOOL PATH_Ellipse(HDC hdc, INT x1, INT y1, INT x2, INT y2)
+BOOL PATH_Ellipse(DC *dc, INT x1, INT y1, INT x2, INT y2)
 {
    /* TODO: This should probably be revised to call PATH_AngleArc */
    /* (once it exists) */
-   return PATH_Arc(hdc, x1, y1, x2, y2, x1, (y1+y2)/2, x1, (y1+y2)/2);
+   return PATH_Arc(dc, x1, y1, x2, y2, x1, (y1+y2)/2, x1, (y1+y2)/2);
 }
 
 /* PATH_Arc
@@ -741,11 +714,10 @@
  * an open path. This adds up to five Bezier splines representing the arc
  * to the path. Returns TRUE if successful, else FALSE.
  */
-BOOL PATH_Arc(HDC hdc, INT x1, INT y1, INT x2, INT y2,
+BOOL PATH_Arc(DC *dc, INT x1, INT y1, INT x2, INT y2,
    INT xStart, INT yStart, INT xEnd, INT yEnd)
 {
-   GdiPath     *pPath;
-   DC          *pDC;
+   GdiPath     *pPath = &dc->w.path;
    double      angleStart, angleEnd, angleStartQuadrant, angleEndQuadrant=0.0;
                /* Initialize angleEndQuadrant to silence gcc's warning */
    double      x, y;
@@ -756,15 +728,6 @@
    /* FIXME: This function should check for all possible error returns */
    /* FIXME: Do we have to respect newStroke? */
    
-   /* Get pointer to DC */
-   pDC=DC_GetDCPtr(hdc);
-   if(pDC==NULL)
-      return FALSE;
-
-   /* Get pointer to path */
-   if(!PATH_GetPathFromHDC(hdc, &pPath))
-      return FALSE;
-   
    /* Check that path is open */
    if(pPath->state!=PATH_Open)
       return FALSE;
@@ -785,10 +748,10 @@
    pointStart.y=(FLOAT)yStart;
    pointEnd.x=(FLOAT)xEnd;
    pointEnd.y=(FLOAT)yEnd;
-   INTERNAL_LPTODP_FLOAT(pDC, corners);
-   INTERNAL_LPTODP_FLOAT(pDC, corners+1);
-   INTERNAL_LPTODP_FLOAT(pDC, &pointStart);
-   INTERNAL_LPTODP_FLOAT(pDC, &pointEnd);
+   INTERNAL_LPTODP_FLOAT(dc, corners);
+   INTERNAL_LPTODP_FLOAT(dc, corners+1);
+   INTERNAL_LPTODP_FLOAT(dc, &pointStart);
+   INTERNAL_LPTODP_FLOAT(dc, &pointEnd);
 
    /* Make sure first corner is top left and second corner is bottom right */
    if(corners[0].x>corners[1].x)
@@ -811,7 +774,7 @@
    angleEnd=atan2(y, x);
 
    /* Make sure the end angle is "on the right side" of the start angle */
-   if(GetArcDirection(hdc)==AD_CLOCKWISE)
+   if(dc->w.ArcDirection==AD_CLOCKWISE)
    {
       if(angleEnd<=angleStart)
       {
@@ -829,7 +792,7 @@
    }
 
    /* In GM_COMPATIBLE, don't include bottom and right edges */
-   if(GetGraphicsMode(hdc)==GM_COMPATIBLE)
+   if(dc->w.GraphicsMode==GM_COMPATIBLE)
    {
       corners[1].x--;
       corners[1].y--;
@@ -845,7 +808,7 @@
       if(start)
       {
          angleStartQuadrant=angleStart;
-	 if(GetArcDirection(hdc)==AD_CLOCKWISE)
+	 if(dc->w.ArcDirection==AD_CLOCKWISE)
 	    angleEndQuadrant=(floor(angleStart/M_PI_2)+1.0)*M_PI_2;
 	 else
 	    angleEndQuadrant=(ceil(angleStart/M_PI_2)-1.0)*M_PI_2;
@@ -853,16 +816,16 @@
       else
       {
 	 angleStartQuadrant=angleEndQuadrant;
-	 if(GetArcDirection(hdc)==AD_CLOCKWISE)
+	 if(dc->w.ArcDirection==AD_CLOCKWISE)
 	    angleEndQuadrant+=M_PI_2;
 	 else
 	    angleEndQuadrant-=M_PI_2;
       }
 
       /* Have we reached the last part of the arc? */
-      if((GetArcDirection(hdc)==AD_CLOCKWISE &&
+      if((dc->w.ArcDirection==AD_CLOCKWISE &&
          angleEnd<angleEndQuadrant) ||
-	 (GetArcDirection(hdc)==AD_COUNTERCLOCKWISE &&
+	 (dc->w.ArcDirection==AD_COUNTERCLOCKWISE &&
 	 angleEnd>angleEndQuadrant))
       {
 	 /* Adjust the end angle for this quadrant */
@@ -879,15 +842,12 @@
    return TRUE;
 }
 
-BOOL PATH_PolyBezierTo(HDC hdc, const POINT *pts, DWORD cbPoints)
+BOOL PATH_PolyBezierTo(DC *dc, const POINT *pts, DWORD cbPoints)
 {
-   GdiPath     *pPath;
+   GdiPath     *pPath = &dc->w.path;
    POINT       pt;
    INT         i;
 
-   if(!PATH_GetPathFromHDC(hdc, &pPath))
-      return FALSE;
-   
    /* Check that path is open */
    if(pPath->state!=PATH_Open)
       return FALSE;
@@ -896,8 +856,9 @@
    if(pPath->newStroke)
    {
       pPath->newStroke=FALSE;
-      if(!GetCurrentPositionEx(hdc, &pt) ||
-         !LPtoDP(hdc, &pt, 1))
+      pt.x = dc->w.CursPosX;
+      pt.y = dc->w.CursPosY;
+      if(!LPtoDP(dc->hSelf, &pt, 1))
          return FALSE;
       if(!PATH_AddEntry(pPath, &pt, PT_MOVETO))
          return FALSE;
@@ -905,66 +866,57 @@
 
    for(i = 0; i < cbPoints; i++) {
        pt = pts[i];
-       if(!LPtoDP(hdc, &pt, 1))
+       if(!LPtoDP(dc->hSelf, &pt, 1))
 	   return FALSE;
        PATH_AddEntry(pPath, &pt, PT_BEZIERTO);
    }
    return TRUE;
 }
    
-BOOL PATH_PolyBezier(HDC hdc, const POINT *pts, DWORD cbPoints)
+BOOL PATH_PolyBezier(DC *dc, const POINT *pts, DWORD cbPoints)
 {
-   GdiPath     *pPath;
+   GdiPath     *pPath = &dc->w.path;
    POINT       pt;
    INT         i;
 
-   if(!PATH_GetPathFromHDC(hdc, &pPath))
-      return FALSE;
-   
    /* Check that path is open */
    if(pPath->state!=PATH_Open)
       return FALSE;
 
    for(i = 0; i < cbPoints; i++) {
        pt = pts[i];
-       if(!LPtoDP(hdc, &pt, 1))
+       if(!LPtoDP(dc->hSelf, &pt, 1))
 	   return FALSE;
        PATH_AddEntry(pPath, &pt, (i == 0) ? PT_MOVETO : PT_BEZIERTO);
    }
    return TRUE;
 }
 
-BOOL PATH_Polyline(HDC hdc, const POINT *pts, DWORD cbPoints)
+BOOL PATH_Polyline(DC *dc, const POINT *pts, DWORD cbPoints)
 {
-   GdiPath     *pPath;
+   GdiPath     *pPath = &dc->w.path;
    POINT       pt;
    INT         i;
 
-   if(!PATH_GetPathFromHDC(hdc, &pPath))
-      return FALSE;
-   
    /* Check that path is open */
    if(pPath->state!=PATH_Open)
       return FALSE;
 
    for(i = 0; i < cbPoints; i++) {
        pt = pts[i];
-       if(!LPtoDP(hdc, &pt, 1))
+       if(!LPtoDP(dc->hSelf, &pt, 1))
 	   return FALSE;
        PATH_AddEntry(pPath, &pt, (i == 0) ? PT_MOVETO : PT_LINETO);
    }
    return TRUE;
 }
    
-BOOL PATH_PolylineTo(HDC hdc, const POINT *pts, DWORD cbPoints)
+BOOL PATH_PolylineTo(DC *dc, const POINT *pts, DWORD cbPoints)
 {
-   GdiPath     *pPath;
+   GdiPath     *pPath = &dc->w.path;
    POINT       pt;
    INT         i;
 
-   if(!PATH_GetPathFromHDC(hdc, &pPath))
-      return FALSE;
-   
    /* Check that path is open */
    if(pPath->state!=PATH_Open)
       return FALSE;
@@ -973,8 +925,9 @@
    if(pPath->newStroke)
    {
       pPath->newStroke=FALSE;
-      if(!GetCurrentPositionEx(hdc, &pt) ||
-         !LPtoDP(hdc, &pt, 1))
+      pt.x = dc->w.CursPosX;
+      pt.y = dc->w.CursPosY;
+      if(!LPtoDP(dc->hSelf, &pt, 1))
          return FALSE;
       if(!PATH_AddEntry(pPath, &pt, PT_MOVETO))
          return FALSE;
@@ -982,7 +935,7 @@
 
    for(i = 0; i < cbPoints; i++) {
        pt = pts[i];
-       if(!LPtoDP(hdc, &pt, 1))
+       if(!LPtoDP(dc->hSelf, &pt, 1))
 	   return FALSE;
        PATH_AddEntry(pPath, &pt, PT_LINETO);
    }
@@ -991,22 +944,19 @@
 }
 
 
-BOOL PATH_Polygon(HDC hdc, const POINT *pts, DWORD cbPoints)
+BOOL PATH_Polygon(DC *dc, const POINT *pts, DWORD cbPoints)
 {
-   GdiPath     *pPath;
+   GdiPath     *pPath = &dc->w.path;
    POINT       pt;
    INT         i;
 
-   if(!PATH_GetPathFromHDC(hdc, &pPath))
-      return FALSE;
-   
    /* Check that path is open */
    if(pPath->state!=PATH_Open)
       return FALSE;
 
    for(i = 0; i < cbPoints; i++) {
        pt = pts[i];
-       if(!LPtoDP(hdc, &pt, 1))
+       if(!LPtoDP(dc->hSelf, &pt, 1))
 	   return FALSE;
        PATH_AddEntry(pPath, &pt, (i == 0) ? PT_MOVETO :
 		     ((i == cbPoints-1) ? PT_LINETO | PT_CLOSEFIGURE :
@@ -1015,16 +965,13 @@
    return TRUE;
 }
 
-BOOL PATH_PolyPolygon( HDC hdc, const POINT* pts, const INT* counts,
+BOOL PATH_PolyPolygon( DC *dc, const POINT* pts, const INT* counts,
 		       UINT polygons )
 {
-   GdiPath     *pPath;
+   GdiPath     *pPath = &dc->w.path;
    POINT       pt, startpt;
    INT         poly, point, i;
 
-   if(!PATH_GetPathFromHDC(hdc, &pPath))
-      return FALSE;
-   
    /* Check that path is open */
    if(pPath->state!=PATH_Open)
       return FALSE;
@@ -1032,7 +979,7 @@
    for(i = 0, poly = 0; poly < polygons; poly++) {
        for(point = 0; point < counts[poly]; point++, i++) {
 	   pt = pts[i];
-	   if(!LPtoDP(hdc, &pt, 1))
+	   if(!LPtoDP(dc->hSelf, &pt, 1))
 	       return FALSE;
 	   if(point == 0) startpt = pt;
 	   PATH_AddEntry(pPath, &pt, (point == 0) ? PT_MOVETO : PT_LINETO);
@@ -1043,16 +990,13 @@
    return TRUE;
 }
 
-BOOL PATH_PolyPolyline( HDC hdc, const POINT* pts, const DWORD* counts,
+BOOL PATH_PolyPolyline( DC *dc, const POINT* pts, const DWORD* counts,
 			DWORD polylines )
 {
-   GdiPath     *pPath;
+   GdiPath     *pPath = &dc->w.path;
    POINT       pt;
    INT         poly, point, i;
 
-   if(!PATH_GetPathFromHDC(hdc, &pPath))
-      return FALSE;
-   
    /* Check that path is open */
    if(pPath->state!=PATH_Open)
       return FALSE;
@@ -1060,7 +1004,7 @@
    for(i = 0, poly = 0; poly < polylines; poly++) {
        for(point = 0; point < counts[poly]; point++, i++) {
 	   pt = pts[i];
-	   if(!LPtoDP(hdc, &pt, 1))
+	   if(!LPtoDP(dc->hSelf, &pt, 1))
 	       return FALSE;
 	   PATH_AddEntry(pPath, &pt, (point == 0) ? PT_MOVETO : PT_LINETO);
        }
@@ -1306,25 +1250,6 @@
    return TRUE;
 }
 
-/* PATH_GetPathFromHDC
- *
- * Retrieves a pointer to the GdiPath structure contained in an HDC and
- * places it in *ppPath. TRUE is returned if successful, FALSE otherwise.
- */
-static BOOL PATH_GetPathFromHDC(HDC hdc, GdiPath **ppPath)
-{
-   DC *pDC;
-
-   pDC=DC_GetDCPtr(hdc);
-   if(pDC)
-   {
-      *ppPath=&pDC->w.path;
-      return TRUE;
-   }
-   else
-      return FALSE;
-}
-
 /* PATH_DoArcPart
  *
  * Creates a Bezier spline that corresponds to part of an arc and appends the
@@ -1434,50 +1359,51 @@
  */
 BOOL WINAPI FlattenPath(HDC hdc)
 {
-   DC *dc = DC_GetDCPtr( hdc );
-   GdiPath *pPath;
-   TRACE("%08x\n", hdc);
+    BOOL ret = FALSE;
+    DC *dc = DC_GetDCPtr( hdc );
 
-   if(!dc) {
-     SetLastError(ERROR_INVALID_HANDLE);
-     return FALSE;
-   }
+    if(!dc) return FALSE;
 
-   if(dc->funcs->pFlattenPath)
-     return dc->funcs->pFlattenPath(dc);
-
-    pPath = &dc->w.path;
-    if(pPath->state != PATH_Closed)
-        return FALSE;
-   return PATH_FlattenPath(pPath);
+    if(dc->funcs->pFlattenPath) ret = dc->funcs->pFlattenPath(dc);
+    else 
+    {
+	GdiPath *pPath = &dc->w.path;
+        if(pPath->state != PATH_Closed)
+	    ret = PATH_FlattenPath(pPath);
+    }
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
-static BOOL PATH_StrokePath(HDC hdc, GdiPath *pPath)
+static BOOL PATH_StrokePath(DC *dc, GdiPath *pPath)
 {
     INT i;
     POINT ptLastMove = {0,0};
 
+    if(dc->funcs->pStrokePath)
+        return dc->funcs->pStrokePath(dc);
+
     if(pPath->state != PATH_Closed)
         return FALSE;
 
-    SaveDC(hdc);
-    SetMapMode(hdc, MM_TEXT);
-    SetViewportOrgEx(hdc, 0, 0, NULL);
-    SetWindowOrgEx(hdc, 0, 0, NULL);
+    SaveDC(dc->hSelf);
+    SetMapMode(dc->hSelf, MM_TEXT);
+    SetViewportOrgEx(dc->hSelf, 0, 0, NULL);
+    SetWindowOrgEx(dc->hSelf, 0, 0, NULL);
     for(i = 0; i < pPath->numEntriesUsed; i++) {
         switch(pPath->pFlags[i]) {
 	case PT_MOVETO:
 	    TRACE("Got PT_MOVETO (%ld, %ld)\n",
 		  pPath->pPoints[i].x, pPath->pPoints[i].y);
-	    MoveToEx(hdc, pPath->pPoints[i].x, pPath->pPoints[i].y, NULL);
+	    MoveToEx(dc->hSelf, pPath->pPoints[i].x, pPath->pPoints[i].y, NULL);
 	    ptLastMove = pPath->pPoints[i];
 	    break;
 	case PT_LINETO:
 	case (PT_LINETO | PT_CLOSEFIGURE):
 	    TRACE("Got PT_LINETO (%ld, %ld)\n",
 		  pPath->pPoints[i].x, pPath->pPoints[i].y);
-	    LineTo(hdc, pPath->pPoints[i].x, pPath->pPoints[i].y);
+	    LineTo(dc->hSelf, pPath->pPoints[i].x, pPath->pPoints[i].y);
 	    break;
 	case PT_BEZIERTO:
 	    TRACE("Got PT_BEZIERTO\n");
@@ -1486,7 +1412,7 @@
 	        ERR("Path didn't contain 3 successive PT_BEZIERTOs\n");
 		return FALSE;
 	    }
-	    PolyBezierTo(hdc, &pPath->pPoints[i], 3);
+	    PolyBezierTo(dc->hSelf, &pPath->pPoints[i], 3);
 	    i += 2;
 	    break;
 	default:
@@ -1494,9 +1420,9 @@
 	    return FALSE;
 	}
 	if(pPath->pFlags[i] & PT_CLOSEFIGURE)
-	    LineTo(hdc, ptLastMove.x, ptLastMove.y);
+	    LineTo(dc->hSelf, ptLastMove.x, ptLastMove.y);
     }
-    RestoreDC(hdc, -1);
+    RestoreDC(dc->hSelf , -1);
     return TRUE;
 }
 
@@ -1519,19 +1445,19 @@
 BOOL WINAPI StrokeAndFillPath(HDC hdc)
 {
    DC *dc = DC_GetDCPtr( hdc );
-   BOOL bRet;
+   BOOL bRet = FALSE;
 
-   if(!dc) {
-     SetLastError(ERROR_INVALID_HANDLE);
-     return FALSE;
-   }
+   if(!dc) return FALSE;
 
    if(dc->funcs->pStrokeAndFillPath)
-     return dc->funcs->pStrokeAndFillPath(dc);
-
-   bRet = PATH_FillPath(hdc, &dc->w.path);
-   if(bRet) bRet = PATH_StrokePath(hdc, &dc->w.path);
-   if(bRet) PATH_EmptyPath(&dc->w.path);
+       bRet = dc->funcs->pStrokeAndFillPath(dc);
+   else
+   {
+       bRet = PATH_FillPath(dc, &dc->w.path);
+       if(bRet) bRet = PATH_StrokePath(dc, &dc->w.path);
+       if(bRet) PATH_EmptyPath(&dc->w.path);
+   }
+   GDI_ReleaseObj( hdc );
    return bRet;
 }
 
@@ -1554,20 +1480,21 @@
 {
     DC *dc = DC_GetDCPtr( hdc );
     GdiPath *pPath;
+    BOOL bRet = FALSE;
 
     TRACE("(%08x)\n", hdc);
-    if(!dc) {
-        SetLastError(ERROR_INVALID_HANDLE);
-	return FALSE;
-    }
+    if(!dc) return FALSE;
 
     if(dc->funcs->pStrokePath)
-        return dc->funcs->pStrokePath(dc);
-
-    pPath = &dc->w.path;
-    PATH_StrokePath(hdc, pPath);
-    PATH_EmptyPath(pPath);
-    return TRUE;
+        bRet = dc->funcs->pStrokePath(dc);
+    else
+    {
+        pPath = &dc->w.path;
+        bRet = PATH_StrokePath(dc, pPath);
+        PATH_EmptyPath(pPath);
+    }
+    GDI_ReleaseObj( hdc );
+    return bRet;
 }
 
 /*******************************************************************
@@ -1588,15 +1515,14 @@
 BOOL WINAPI WidenPath(HDC hdc)
 {
    DC *dc = DC_GetDCPtr( hdc );
+   BOOL ret = FALSE;
    
-   if(!dc) {
-     SetLastError(ERROR_INVALID_HANDLE);
-     return FALSE;
-   }
+   if(!dc) return FALSE;
 
    if(dc->funcs->pWidenPath)
-     return dc->funcs->pWidenPath(dc);
+     ret = dc->funcs->pWidenPath(dc);
 
    FIXME("stub\n");
-   return 0;
+   GDI_ReleaseObj( hdc );
+   return ret;
 }
diff --git a/graphics/win16drv/font.c b/graphics/win16drv/font.c
index c525e8f..4c9c0bc 100644
--- a/graphics/win16drv/font.c
+++ b/graphics/win16drv/font.c
@@ -11,6 +11,7 @@
 #include "module.h"
 #include "font.h"
 #include "heap.h"
+#include "dc.h"
 #include "debugtools.h"
 
 DEFAULT_DEBUG_CHANNEL(win16drv)
@@ -179,15 +180,21 @@
  *           WIN16DRV_EnumDeviceFonts
  */
 
-BOOL	WIN16DRV_EnumDeviceFonts( DC* dc, LPLOGFONT16 plf, 
+BOOL	WIN16DRV_EnumDeviceFonts( HDC hdc, LPLOGFONT16 plf, 
 				        DEVICEFONTENUMPROC proc, LPARAM lp )
 {
-    WIN16DRV_PDEVICE *physDev = (WIN16DRV_PDEVICE *)dc->physDev;
+    WIN16DRV_PDEVICE *physDev;
     WORD wRet;
     WEPFC wepfc;
+    DC *dc;
     /* EnumDFontCallback is GDI.158 */
     FARPROC16 pfnCallback = NE_GetEntryPoint( GetModuleHandle16("GDI"), 158 );
 
+    if (!(dc = DC_GetDCPtr( hdc ))) return 0;
+    physDev = (WIN16DRV_PDEVICE *)dc->physDev;
+    /* FIXME!! */
+    GDI_ReleaseObj( hdc );
+
     wepfc.proc = (int (*)(LPENUMLOGFONT16,LPNEWTEXTMETRIC16,UINT16,LPARAM))proc;
     wepfc.lp = lp;
 
diff --git a/graphics/win16drv/objects.c b/graphics/win16drv/objects.c
index e21fb31..21d77f7 100644
--- a/graphics/win16drv/objects.c
+++ b/graphics/win16drv/objects.c
@@ -54,6 +54,6 @@
 	ret = (HGDIOBJ16)SelectClipRgn16( dc->hSelf, handle );
 	break;
     }
-    GDI_HEAP_UNLOCK( handle );
+    GDI_ReleaseObj( handle );
     return ret;
 }
diff --git a/graphics/x11drv/bitmap.c b/graphics/x11drv/bitmap.c
index 484a7b6..47c9fc6 100644
--- a/graphics/x11drv/bitmap.c
+++ b/graphics/x11drv/bitmap.c
@@ -84,24 +84,20 @@
 	return 0;
     }
 
+    hrgn = CreateRectRgn(0, 0, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight);
+    if (!hrgn) return 0;
+
     dc->w.totalExtent.left   = 0;
     dc->w.totalExtent.top    = 0;
     dc->w.totalExtent.right  = bmp->bitmap.bmWidth;
     dc->w.totalExtent.bottom = bmp->bitmap.bmHeight;
 
-    if (dc->w.hVisRgn)
-       SetRectRgn( dc->w.hVisRgn, 0, 0,
-                     bmp->bitmap.bmWidth, bmp->bitmap.bmHeight );
-    else
-    { 
-       hrgn = CreateRectRgn(0, 0, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight);
-       if (!hrgn) return 0;
-       dc->w.hVisRgn    = hrgn;
-    }
-
     physDev->drawable = (Pixmap)bmp->physBitmap;
     dc->w.hBitmap     = hbitmap;
 
+    SelectVisRgn16( dc->hSelf, hrgn );
+    DeleteObject( hrgn );
+
       /* Change GC depth if needed */
 
     if (dc->w.bitsPerPixel != bmp->bitmap.bmBitsPixel)
@@ -112,7 +108,6 @@
 	dc->w.bitsPerPixel = bmp->bitmap.bmBitsPixel;
         DC_InitDC( dc );
     }
-    else CLIPPING_UpdateGCRegion( dc );  /* Just update GC clip region */
     return prevHandle;
 }
 
@@ -158,13 +153,17 @@
     }
 
       /* Check parameters */
-    if (bmp->bitmap.bmPlanes != 1) return 0;
+    if (bmp->bitmap.bmPlanes != 1)
+    {
+        GDI_ReleaseObj( hbitmap );
+        return 0;
+    }
     if ((bmp->bitmap.bmBitsPixel != 1) && 
 	(bmp->bitmap.bmBitsPixel != X11DRV_GetDepth()))
     {
         ERR("Trying to make bitmap with planes=%d, bpp=%d\n",
 	    bmp->bitmap.bmPlanes, bmp->bitmap.bmBitsPixel);
-        GDI_HEAP_UNLOCK( hbitmap );
+        GDI_ReleaseObj( hbitmap );
 	return FALSE;
     }
 
@@ -177,7 +176,7 @@
                                                     bmp->bitmap.bmBitsPixel)))
     {
         WARN("Can't create Pixmap\n");
-	GDI_HEAP_UNLOCK( hbitmap );
+	GDI_ReleaseObj( hbitmap );
 	return FALSE;
     }
     bmp->funcs = &X11DRV_DC_Funcs;
@@ -187,7 +186,7 @@
 			   bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes,
 			   DDB_SET );
 
-    GDI_HEAP_UNLOCK( hbitmap );
+    GDI_ReleaseObj( hbitmap );
     return TRUE;
 }
 
@@ -476,8 +475,7 @@
         ERR("Unknown flags value %d\n", flags);
 	ret = 0;
     }
-    
-    GDI_HEAP_UNLOCK( hbitmap );
+    GDI_ReleaseObj( hbitmap );
     return ret;
 }
 
@@ -526,6 +524,7 @@
     
     pBmp->funcs = &X11DRV_DC_Funcs;
     pBmp->physBitmap = (void *)pixmap;
+    GDI_ReleaseObj( hBmp );
 
 END:
     TRACE("\tReturning HBITMAP %x\n", hBmp);
@@ -612,7 +611,10 @@
  */
 Pixmap X11DRV_BITMAP_Pixmap(HBITMAP hbitmap)
 {
+    Pixmap pixmap;
     BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
-    return (Pixmap)bmp->physBitmap;
+    pixmap = (Pixmap)bmp->physBitmap;
+    GDI_ReleaseObj( hbitmap );
+    return pixmap;
 }
 
diff --git a/graphics/x11drv/brush.c b/graphics/x11drv/brush.c
index d5a090a..81e2c95 100644
--- a/graphics/x11drv/brush.c
+++ b/graphics/x11drv/brush.c
@@ -172,17 +172,18 @@
  */
 static BOOL BRUSH_SelectPatternBrush( DC * dc, HBITMAP hbitmap )
 {
+    BOOL ret = FALSE;
     X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
     BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
     if (!bmp) return FALSE;
 
    if(!bmp->physBitmap)
         if(!X11DRV_CreateBitmap(hbitmap))
-	    return 0;
+	    goto done;
 
     if(bmp->funcs != dc->funcs) {
         WARN("Trying to select non-X11 DDB into an X11 dc\n");
-	return 0;
+	goto done;
     }
 
     if ((dc->w.bitsPerPixel == 1) && (bmp->bitmap.bmBitsPixel != 1))
@@ -211,8 +212,10 @@
 	physDev->brush.fillStyle = FillOpaqueStippled;
 	physDev->brush.pixel = -1;  /* Special case (see DC_SetupGCForBrush) */
     }
-    GDI_HEAP_UNLOCK( hbitmap );
-    return TRUE;
+    ret = TRUE;
+ done:
+    GDI_ReleaseObj( hbitmap );
+    return ret;
 }
 
 
diff --git a/graphics/x11drv/clipping.c b/graphics/x11drv/clipping.c
index 5905217..1d8dd28 100644
--- a/graphics/x11drv/clipping.c
+++ b/graphics/x11drv/clipping.c
@@ -49,7 +49,7 @@
 	if(!pXrect)
 	{
 	    WARN("Can't alloc buffer\n");
-	    GDI_HEAP_UNLOCK( dc->w.hGCClipRgn );
+	    GDI_ReleaseObj( dc->w.hGCClipRgn );
 	    return;
 	}
 
@@ -70,6 +70,6 @@
     if(pXrect)
         HeapFree( GetProcessHeap(), 0, pXrect );
 
-    GDI_HEAP_UNLOCK( dc->w.hGCClipRgn );
+    GDI_ReleaseObj( dc->w.hGCClipRgn );
 }
 
diff --git a/graphics/x11drv/dib.c b/graphics/x11drv/dib.c
index 22c0dac..3bc0071 100644
--- a/graphics/x11drv/dib.c
+++ b/graphics/x11drv/dib.c
@@ -2595,9 +2595,6 @@
     int lines = descr->lines >= 0 ? descr->lines : -descr->lines;
     XImage *bmpImage;
 
-    if ( descr->dc && descr->dc->w.flags & DC_DIRTY ) 
-        CLIPPING_UpdateGCRegion( descr->dc );
-
     if (descr->image)
         bmpImage = descr->image;
     else {
@@ -2984,11 +2981,18 @@
    */
   if( info->bmiHeader.biHeight < 0 && lines > 0) lines = -lines;
 
-  if( startscan >= bmp->bitmap.bmHeight ) return FALSE;
+  if( startscan >= bmp->bitmap.bmHeight )
+  {
+      lines = 0;
+      goto done;
+  }
   
   if (DIB_GetBitmapInfo( &info->bmiHeader, &descr.infoWidth, &descr.lines,
                         &descr.infoBpp, &descr.compression ) == -1)
-      return FALSE;
+  {
+      lines = 0;
+      goto done;
+  }
 
   switch (descr.infoBpp)
   {
@@ -3060,7 +3064,8 @@
 
   info->bmiHeader.biCompression = 0;
 
-  GDI_HEAP_UNLOCK( dc->w.hPalette );
+done:
+  GDI_ReleaseObj( dc->w.hPalette );
  
   return lines;
 }
@@ -3193,7 +3198,7 @@
 	break;
       }
   
-  GDI_HEAP_UNLOCK( (HBITMAP)res );
+  GDI_ReleaseObj( (HBITMAP)res );
   return handled;
 }
 
@@ -3276,7 +3281,7 @@
 
   X11DRV_DIB_CmnUpdateDIBSection(bmp, toDIB);
 
-  GDI_HEAP_UNLOCK(hbmp);
+  GDI_ReleaseObj(hbmp);
 }
 
 /***********************************************************************
@@ -3325,12 +3330,11 @@
 	  TRACE("ptr = %p, size =%d, selector = %04x, segptr = %ld\n",
 			 dib->dsBm.bmBits, size, ((X11DRV_DIBSECTION *) bmp->dib)->selector,
 			 PTR_SEG_OFF_TO_SEGPTR(((X11DRV_DIBSECTION *) bmp->dib)->selector, 0));
-	}
-      GDI_HEAP_UNLOCK( res );
-      
       if ( bits ) 
 	*bits = PTR_SEG_OFF_TO_SEGPTR( ((X11DRV_DIBSECTION *) bmp->dib)->selector, 0 );
     }
+      if (bmp) GDI_ReleaseObj( res );
+    }
 
     return res;
 }
@@ -3545,6 +3549,7 @@
       if (dib && dib->image) { XDestroyImage(dib->image); dib->image = NULL; }
       if (colorMap) { HeapFree(GetProcessHeap(), 0, colorMap); colorMap = NULL; }
       if (dib) { HeapFree(GetProcessHeap(), 0, dib); dib = NULL; }
+      if (bmp) { GDI_ReleaseObj(res); bmp = NULL; }
       if (res) { DeleteObject(res); res = 0; }
     }
   
@@ -3567,7 +3572,7 @@
     }
 
   /* Return BITMAP handle and storage location */
-  if (res) GDI_HEAP_UNLOCK(res);
+  if (bmp) GDI_ReleaseObj(res);
   if (bm.bmBits && bits) *bits = bm.bmBits;
   return res;
 }
@@ -3642,6 +3647,7 @@
         pBmp->physBitmap = NULL;
         pBmp->funcs = NULL;
     }
+    GDI_ReleaseObj( hBmp );
     DeleteObject(hBmp);  
     
 END:
@@ -3695,6 +3701,7 @@
     pBmp->funcs = NULL;
 
     /* Delete the DDB we created earlier now that we have stolen its pixmap */
+    GDI_ReleaseObj( hBmp );
     DeleteObject(hBmp);
     
     TRACE("\tReturning Pixmap %ld\n", pixmap);
diff --git a/graphics/x11drv/graphics.c b/graphics/x11drv/graphics.c
index dcd95e5..3376546 100644
--- a/graphics/x11drv/graphics.c
+++ b/graphics/x11drv/graphics.c
@@ -99,8 +99,6 @@
         val.background = X11DRV_PALETTE_XPixelToPalette[val.background];
     }
 
-    if (dc->w.flags & DC_DIRTY) CLIPPING_UpdateGCRegion(dc);
-
     val.function = X11DRV_XROPfunction[dc->w.ROPmode-1];
     /*
     ** Let's replace GXinvert by GXxor with (black xor white)
@@ -187,8 +185,6 @@
 
     if (physDev->pen.style == PS_NULL) return FALSE;
 
-    if (dc->w.flags & DC_DIRTY) CLIPPING_UpdateGCRegion(dc); 
-
     switch (dc->w.ROPmode)
     {
     case R2_BLACK :
@@ -275,8 +271,6 @@
     {
 	XGCValues val;
 
-	if (dc->w.flags & DC_DIRTY) CLIPPING_UpdateGCRegion(dc);
-
 	val.function   = GXcopy;  /* Text is always GXcopy */
 	val.foreground = physDev->textPixel;
 	val.background = physDev->backgroundPixel;
diff --git a/graphics/x11drv/init.c b/graphics/x11drv/init.c
index 0fe27ca..399bc8d 100644
--- a/graphics/x11drv/init.c
+++ b/graphics/x11drv/init.c
@@ -240,9 +240,13 @@
     dc->w.devCaps      = &X11DRV_DevCaps;
     if (dc->w.flags & DC_MEMORY)
     {
-        BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr( dc->w.hBitmap,
-                                                      BITMAP_MAGIC );
-	if (!bmp->physBitmap) X11DRV_CreateBitmap( dc->w.hBitmap );
+        BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr( dc->w.hBitmap, BITMAP_MAGIC );
+	if (!bmp) 
+	{
+	    HeapFree( GetProcessHeap(), 0, physDev );
+	    return FALSE;
+        }
+        if (!bmp->physBitmap) X11DRV_CreateBitmap( dc->w.hBitmap );
         physDev->drawable  = (Pixmap)bmp->physBitmap;
         physDev->gc        = TSXCreateGC(display, physDev->drawable, 0, NULL);
         dc->w.bitsPerPixel = bmp->bitmap.bmBitsPixel;
@@ -253,7 +257,7 @@
         dc->w.totalExtent.bottom = bmp->bitmap.bmHeight;
         dc->w.hVisRgn            = CreateRectRgnIndirect( &dc->w.totalExtent );
 
-	GDI_HEAP_UNLOCK( dc->w.hBitmap );
+        GDI_ReleaseObj( dc->w.hBitmap );
     }
     else
     {
@@ -274,6 +278,7 @@
     if (!dc->w.hVisRgn)
     {
         TSXFreeGC( display, physDev->gc );
+	HeapFree( GetProcessHeap(), 0, physDev );
         return FALSE;
     }
 
diff --git a/graphics/x11drv/objects.c b/graphics/x11drv/objects.c
index ec3576f..9645221 100644
--- a/graphics/x11drv/objects.c
+++ b/graphics/x11drv/objects.c
@@ -58,7 +58,7 @@
 	  ret = (HGDIOBJ16)SelectClipRgn16( dc->hSelf, handle );
 	  break;
     }
-    GDI_HEAP_UNLOCK( handle );
+    GDI_ReleaseObj( handle );
     return ret;
 }
 
@@ -83,7 +83,7 @@
 	ret = FALSE;
 	break;
     }
-    GDI_HEAP_UNLOCK( handle );
+    GDI_ReleaseObj( handle );
     return ret;
 }
 
diff --git a/graphics/x11drv/oembitmap.c b/graphics/x11drv/oembitmap.c
index 1908721..2a4add8 100644
--- a/graphics/x11drv/oembitmap.c
+++ b/graphics/x11drv/oembitmap.c
@@ -341,15 +341,12 @@
 static HBITMAP16 OBM_MakeBitmap( WORD width, WORD height,
                                  WORD bpp, Pixmap pixmap )
 {
-    HBITMAP16 hbitmap;
+    HBITMAP hbitmap;
     BITMAPOBJ * bmpObjPtr;
 
     if (!pixmap) return 0;
 
-    hbitmap = GDI_AllocObject( sizeof(BITMAPOBJ), BITMAP_MAGIC );
-    if (!hbitmap) return 0;
-
-    bmpObjPtr = (BITMAPOBJ *) GDI_HEAP_LOCK( hbitmap );
+    if (!(bmpObjPtr = GDI_AllocObject( sizeof(BITMAPOBJ), BITMAP_MAGIC, &hbitmap ))) return 0;
     bmpObjPtr->size.cx = width;
     bmpObjPtr->size.cy = height;
     bmpObjPtr->bitmap.bmType       = 0;
@@ -364,7 +361,7 @@
     bmpObjPtr->funcs = &X11DRV_DC_Funcs;
     bmpObjPtr->physBitmap = (void *)pixmap;
 
-    GDI_HEAP_UNLOCK( hbitmap );
+    GDI_ReleaseObj( hbitmap );
     return hbitmap;
 }
 #endif /* defined(HAVE_LIBXXPM) */
@@ -412,8 +409,8 @@
     {
         if (pixmap) XFreePixmap( display, pixmap );
         if (pixmask) XFreePixmap( display, pixmask );
-        if (descr->bitmap) GDI_FreeObject( descr->bitmap );
-        if (descr->need_mask && descr->mask) GDI_FreeObject( descr->mask );
+        if (descr->bitmap) DeleteObject( descr->bitmap );
+        if (descr->need_mask && descr->mask) DeleteObject( descr->mask );
         return FALSE;
     }
     else return TRUE;
@@ -512,11 +509,7 @@
 
     if (!(handle = GlobalAlloc16( GMEM_MOVEABLE,
                                   sizeof(CURSORICONINFO) + sizeXor + sizeAnd)))
-    {
-        DeleteObject( descr.bitmap );
-        DeleteObject( descr.mask );
-        return 0;
-    }
+        goto done;
 
     pInfo = (CURSORICONINFO *)GlobalLock16( handle );
     pInfo->ptHotSpot.x   = descr.hotspot.x;
@@ -554,11 +547,12 @@
     if (descr.mask) GetBitmapBits( descr.mask, sizeAnd, (char *)(pInfo + 1));
     else memset( (char *)(pInfo + 1), 0xff, sizeAnd );
     GetBitmapBits( descr.bitmap, sizeXor, (char *)(pInfo + 1) + sizeAnd );
-
+    if (fCursor) OBM_Cursors[id] = handle;
+ done:
+    GDI_ReleaseObj( descr.mask );
+    GDI_ReleaseObj( descr.bitmap );
     DeleteObject( descr.bitmap );
     DeleteObject( descr.mask );
-
-    if (fCursor) OBM_Cursors[id] = handle;
     return handle;
 }
 
diff --git a/graphics/x11drv/palette.c b/graphics/x11drv/palette.c
index 0878334..bf363d2 100644
--- a/graphics/x11drv/palette.c
+++ b/graphics/x11drv/palette.c
@@ -692,14 +692,15 @@
             if( (idx = color & 0xffff) >= palPtr->logpalette.palNumEntries)
             {
                 WARN("RGB(%lx) : idx %d is out of bounds, assuming black\n", color, idx);
-		GDI_HEAP_UNLOCK( hPal );
+		GDI_ReleaseObj( hPal );
                 return 0;
             }
 
             if( palPtr->mapping ) 
 	    {
-		GDI_HEAP_UNLOCK( hPal );
-		return palPtr->mapping[idx];
+                int ret = palPtr->mapping[idx];
+		GDI_ReleaseObj( hPal );
+		return ret;
 	    }
 	    color = *(COLORREF*)(palPtr->logpalette.palPalEntry + idx);
 	    break;
@@ -711,7 +712,7 @@
 	  case 0: /* RGB */
 	    if( dc && (dc->w.bitsPerPixel == 1) )
 	    {
-		GDI_HEAP_UNLOCK( hPal );
+		GDI_ReleaseObj( hPal );
 		return (((color >> 16) & 0xff) +
 			((color >> 8) & 0xff) + (color & 0xff) > 255*3/2) ? 1 : 0;
 	    }
@@ -723,7 +724,7 @@
 	if (X11DRV_PALETTE_Graymax)
         {
 	    /* grayscale only; return scaled value */
-	    GDI_HEAP_UNLOCK( hPal );
+	    GDI_ReleaseObj( hPal );
             return ( (red * 30 + green * 69 + blue * 11) * X11DRV_PALETTE_Graymax) / 25500;
 	}
 	else
@@ -736,7 +737,7 @@
 	    if (X11DRV_PALETTE_Bluemax != 255)
 		blue = MulDiv(blue, X11DRV_PALETTE_Bluemax, 255);
 
-	    GDI_HEAP_UNLOCK( hPal );
+	    GDI_ReleaseObj( hPal );
 	    return (red << X11DRV_PALETTE_Redshift) | (green << X11DRV_PALETTE_Greenshift) | (blue << X11DRV_PALETTE_Blueshift);
         }
     }
@@ -755,7 +756,7 @@
        	    case 0:  /* RGB */
 		if( dc && (dc->w.bitsPerPixel == 1) )
 		{
-		    GDI_HEAP_UNLOCK( hPal );
+		    GDI_ReleaseObj( hPal );
 		    return (((color >> 16) & 0xff) +
 			    ((color >> 8) & 0xff) + (color & 0xff) > 255*3/2) ? 1 : 0;
 		}
@@ -786,7 +787,7 @@
 	}
     }
 
-    GDI_HEAP_UNLOCK( hPal );
+    GDI_ReleaseObj( hPal );
     return index;
 }
 
diff --git a/graphics/x11drv/xfont.c b/graphics/x11drv/xfont.c
index 8c4050e..19a52fe 100644
--- a/graphics/x11drv/xfont.c
+++ b/graphics/x11drv/xfont.c
@@ -2991,7 +2991,7 @@
  *
  *           X11DRV_EnumDeviceFonts
  */
-BOOL	X11DRV_EnumDeviceFonts( DC* dc, LPLOGFONT16 plf, 
+BOOL X11DRV_EnumDeviceFonts( HDC hdc, LPLOGFONT16 plf, 
 				        DEVICEFONTENUMPROC proc, LPARAM lp )
 {
     ENUMLOGFONTEX16	lf;
diff --git a/include/dc.h b/include/dc.h
index 95903e0..313de44 100644
--- a/include/dc.h
+++ b/include/dc.h
@@ -16,6 +16,7 @@
 
 extern DC * DC_AllocDC( const DC_FUNCTIONS *funcs );
 extern DC * DC_GetDCPtr( HDC hdc );
+extern DC * DC_GetDCUpdate( HDC hdc );
 extern void DC_InitDC( DC * dc );
 extern void DC_UpdateXforms( DC * dc );
 
diff --git a/include/gdi.h b/include/gdi.h
index 6cd7a95..91b5fd1 100644
--- a/include/gdi.h
+++ b/include/gdi.h
@@ -193,7 +193,7 @@
     INT      (*pEndDoc)(DC*);
     INT      (*pEndPage)(DC*);
     BOOL     (*pEndPath)(DC*);
-    BOOL     (*pEnumDeviceFonts)(DC*,LPLOGFONT16,DEVICEFONTENUMPROC,LPARAM);
+    BOOL     (*pEnumDeviceFonts)(HDC,LPLOGFONT16,DEVICEFONTENUMPROC,LPARAM);
     INT      (*pEscape)(DC*,INT,INT,SEGPTR,SEGPTR);
     INT      (*pExcludeClipRect)(DC*,INT,INT,INT,INT);
     INT      (*pExtDeviceMode)(LPSTR,HWND,LPDEVMODEA,LPSTR,LPSTR,LPDEVMODEA,
@@ -444,30 +444,12 @@
 
   /* GDI local heap */
 
-extern WORD GDI_HeapSel;
-
-#define GDI_HEAP_ALLOC(size) \
-            LOCAL_Alloc( GDI_HeapSel, LMEM_FIXED, (size) )
-#define GDI_HEAP_ALLOC_MOVEABLE(size) \
-            LOCAL_Alloc( GDI_HeapSel, LMEM_MOVEABLE, (size) )
-#define GDI_HEAP_REALLOC(handle,size) \
-            LOCAL_ReAlloc( GDI_HeapSel, (handle), (size), LMEM_FIXED )
-#define GDI_HEAP_FREE(handle) \
-            LOCAL_Free( GDI_HeapSel, (handle) )
-
-#define GDI_HEAP_LOCK(handle) \
-            LOCAL_Lock( GDI_HeapSel, (handle) )
-#define GDI_HEAP_LOCK_SEGPTR(handle) \
-            LOCAL_LockSegptr( GDI_HeapSel, (handle) )
-#define GDI_HEAP_UNLOCK(handle) \
-    ((((HGDIOBJ16)(handle) >= FIRST_STOCK_HANDLE) && \
-      ((HGDIOBJ16)(handle)<=LAST_STOCK_HANDLE)) ? \
-      0 : LOCAL_Unlock( GDI_HeapSel, (handle) ))
-
 extern BOOL GDI_Init(void);
-extern HGDIOBJ GDI_AllocObject( WORD, WORD );
-extern BOOL GDI_FreeObject( HGDIOBJ );
-extern GDIOBJHDR * GDI_GetObjPtr( HGDIOBJ, WORD );
+extern void *GDI_AllocObject( WORD, WORD, HGDIOBJ * );
+extern void *GDI_ReallocObject( WORD, HGDIOBJ, void *obj );
+extern BOOL GDI_FreeObject( HGDIOBJ, void *obj );
+extern void *GDI_GetObjPtr( HGDIOBJ, WORD );
+extern void GDI_ReleaseObj( HGDIOBJ );
 
 extern BOOL DRIVER_RegisterDriver( LPCSTR name, const DC_FUNCTIONS *funcs );
 extern const DC_FUNCTIONS *DRIVER_FindDriver( LPCSTR name );
diff --git a/include/global.h b/include/global.h
index 45557b8..b1e530f 100644
--- a/include/global.h
+++ b/include/global.h
@@ -19,8 +19,6 @@
                                BOOL16 isCode, BOOL16 is32Bit,
                                BOOL16 isReadOnly );
 
-extern WORD WINAPI GlobalHandleToSel16( HGLOBAL16 handle );
-
 /* memory/virtual.c */
 extern DWORD VIRTUAL_GetPageSize(void);
 extern DWORD VIRTUAL_GetGranularity(void);
diff --git a/include/path.h b/include/path.h
index c75d356..db3f197 100644
--- a/include/path.h
+++ b/include/path.h
@@ -42,22 +42,24 @@
 extern BOOL PATH_AssignGdiPath(GdiPath *pPathDest,
    const GdiPath *pPathSrc);
 
-extern BOOL PATH_MoveTo(HDC hdc);
-extern BOOL PATH_LineTo(HDC hdc, INT x, INT y);
-extern BOOL PATH_Rectangle(HDC hdc, INT x1, INT y1,
+struct tagDC;
+
+extern BOOL PATH_MoveTo(struct tagDC *dc);
+extern BOOL PATH_LineTo(struct tagDC *dc, INT x, INT y);
+extern BOOL PATH_Rectangle(struct tagDC *dc, INT x1, INT y1,
    INT x2, INT y2);
-extern BOOL PATH_Ellipse(HDC hdc, INT x1, INT y1,
+extern BOOL PATH_Ellipse(struct tagDC *dc, INT x1, INT y1,
    INT x2, INT y2);
-extern BOOL PATH_Arc(HDC hdc, INT x1, INT y1, INT x2, INT y2,
+extern BOOL PATH_Arc(struct tagDC *dc, INT x1, INT y1, INT x2, INT y2,
    INT xStart, INT yStart, INT xEnd, INT yEnd);
-extern BOOL PATH_PolyBezierTo(HDC hdc, const POINT *pt, DWORD cbCount);
-extern BOOL PATH_PolyBezier(HDC hdc, const POINT *pt, DWORD cbCount);
-extern BOOL PATH_PolylineTo(HDC hdc, const POINT *pt, DWORD cbCount);
-extern BOOL PATH_Polyline(HDC hdc, const POINT *pt, DWORD cbCount);
-extern BOOL PATH_Polygon(HDC hdc, const POINT *pt, DWORD cbCount);
-extern BOOL PATH_PolyPolyline(HDC hdc, const POINT *pt, const DWORD *counts,
+extern BOOL PATH_PolyBezierTo(struct tagDC *dc, const POINT *pt, DWORD cbCount);
+extern BOOL PATH_PolyBezier(struct tagDC *dc, const POINT *pt, DWORD cbCount);
+extern BOOL PATH_PolylineTo(struct tagDC *dc, const POINT *pt, DWORD cbCount);
+extern BOOL PATH_Polyline(struct tagDC *dc, const POINT *pt, DWORD cbCount);
+extern BOOL PATH_Polygon(struct tagDC *dc, const POINT *pt, DWORD cbCount);
+extern BOOL PATH_PolyPolyline(struct tagDC *dc, const POINT *pt, const DWORD *counts,
 			      DWORD polylines);
-extern BOOL PATH_PolyPolygon(HDC hdc, const POINT *pt, const INT *counts,
+extern BOOL PATH_PolyPolygon(struct tagDC *dc, const POINT *pt, const INT *counts,
 			     UINT polygons);
 #endif /* __WINE_PATH_H */
 
diff --git a/include/win.h b/include/win.h
index 2de2471..5e8e31f 100644
--- a/include/win.h
+++ b/include/win.h
@@ -54,7 +54,6 @@
 
 struct tagCLASS;
 struct tagDCE;
-struct tagDC;
 struct tagMESSAGEQUEUE;
 struct tagWND_DRIVER;
 
diff --git a/include/win16drv.h b/include/win16drv.h
index f5e7fb2..102042d 100644
--- a/include/win16drv.h
+++ b/include/win16drv.h
@@ -225,7 +225,7 @@
 extern BOOL WIN16DRV_PatBlt( struct tagDC *dc, INT left, INT top,
                                INT width, INT height, DWORD rop );
 extern BOOL WIN16DRV_Ellipse(DC *dc, INT left, INT top, INT right, INT bottom);
-extern BOOL WIN16DRV_EnumDeviceFonts( DC* dc, LPLOGFONT16 plf, 
+extern BOOL WIN16DRV_EnumDeviceFonts( HDC hdc, LPLOGFONT16 plf, 
 				        DEVICEFONTENUMPROC proc, LPARAM lp );
 
 extern INT WIN16DRV_ExtDeviceMode(LPSTR lpszDriver, HWND hwnd,
diff --git a/include/wine/winbase16.h b/include/wine/winbase16.h
index a0ce055..5b9d72c 100644
--- a/include/wine/winbase16.h
+++ b/include/wine/winbase16.h
@@ -71,6 +71,7 @@
 WORD        WINAPI GlobalDOSFree16(WORD);
 void        WINAPI GlobalFreeAll16(HGLOBAL16);
 DWORD       WINAPI GlobalHandleNoRIP16(WORD);
+WORD        WINAPI GlobalHandleToSel16(HGLOBAL16);
 HGLOBAL16   WINAPI GlobalLRUNewest16(HGLOBAL16);
 HGLOBAL16   WINAPI GlobalLRUOldest16(HGLOBAL16);
 VOID        WINAPI GlobalNotify16(FARPROC16);
diff --git a/include/x11drv.h b/include/x11drv.h
index adbaa88..ac9680f 100644
--- a/include/x11drv.h
+++ b/include/x11drv.h
@@ -90,7 +90,7 @@
 extern BOOL X11DRV_BitBlt( struct tagDC *dcDst, INT xDst, INT yDst,
                              INT width, INT height, struct tagDC *dcSrc,
                              INT xSrc, INT ySrc, DWORD rop );
-extern BOOL X11DRV_EnumDeviceFonts( struct tagDC *dc, LPLOGFONT16 plf,
+extern BOOL X11DRV_EnumDeviceFonts( HDC hdc, LPLOGFONT16 plf,
 				      DEVICEFONTENUMPROC dfeproc, LPARAM lp );
 extern BOOL X11DRV_GetCharWidth( struct tagDC *dc, UINT firstChar,
                                    UINT lastChar, LPINT buffer );
diff --git a/memory/local.c b/memory/local.c
index ed815ac..a7f92e7 100644
--- a/memory/local.c
+++ b/memory/local.c
@@ -110,7 +110,6 @@
 #define LOCAL_HEAP_MAGIC  0x484c  /* 'LH' */
 
 WORD USER_HeapSel = 0;  /* USER heap selector */
-WORD GDI_HeapSel = 0;   /* GDI heap selector */
 
   /* All local heap allocations are aligned on 4-byte boundaries */
 #define LALIGN(word)          (((word) + 3) & ~3)
@@ -842,6 +841,29 @@
     return 0;
 }
 
+
+/***********************************************************************
+ *           get_heap_name
+ */
+static const char *get_heap_name( WORD ds )
+{
+    HINSTANCE16 inst = LoadLibrary16( "GDI" );
+    if (ds == GlobalHandleToSel16( inst ))
+    {
+        FreeLibrary16( inst );
+        return "GDI";
+    }
+    FreeLibrary16( inst );
+    inst = LoadLibrary16( "USER" );
+    if (ds == GlobalHandleToSel16( inst ))
+    {
+        FreeLibrary16( inst );
+        return "USER";
+    }
+    FreeLibrary16( inst );
+    return "local";
+}
+
 /***********************************************************************
  *           LOCAL_GetBlock
  * The segment may get moved around in this function, so all callers
@@ -890,16 +912,8 @@
 	arena = LOCAL_FindFreeBlock( ds, size );
     }
     if (arena == 0) {
-        if (ds == GDI_HeapSel) { 
-	    ERR("not enough space in GDI local heap "
-			 "(%04x) for %d bytes\n", ds, size );
-	} else if (ds == USER_HeapSel) {
-	    ERR("not enough space in USER local heap "
-			 "(%04x) for %d bytes\n", ds, size );
-	} else {
-	    ERR("not enough space in local heap "
-			 "%04x for %d bytes\n", ds, size );
-	}
+        ERR( "not enough space in %s heap %04x for %d bytes\n",
+             get_heap_name(ds), ds, size );
 #if 0
         if ((pInfo->notify) &&
         /* FIXME: "size" correct ? (should indicate bytes needed) */
diff --git a/objects/bitmap.c b/objects/bitmap.c
index cc1aa5c..aea222e 100644
--- a/objects/bitmap.c
+++ b/objects/bitmap.c
@@ -122,14 +122,11 @@
     if (width < 0) width = -width;
 
       /* Create the BITMAPOBJ */
-    hbitmap = GDI_AllocObject( sizeof(BITMAPOBJ), BITMAP_MAGIC );
-    if (!hbitmap) return 0;
+    if (!(bmp = GDI_AllocObject( sizeof(BITMAPOBJ), BITMAP_MAGIC, &hbitmap ))) return 0;
 
     TRACE("%dx%d, %d colors returning %08x\n", width, height,
 	  1 << (planes*bpp), hbitmap);
 
-    bmp = (BITMAPOBJ *) GDI_HEAP_LOCK( hbitmap );
-
     bmp->size.cx = 0;
     bmp->size.cy = 0;
     bmp->bitmap.bmType = 0;
@@ -147,7 +144,7 @@
     if (bits) /* Set bitmap bits */
 	SetBitmapBits( hbitmap, height * bmp->bitmap.bmWidthBytes,
                          bits );
-    GDI_HEAP_UNLOCK( hbitmap );
+    GDI_ReleaseObj( hbitmap );
     return hbitmap;
 }
 
@@ -193,7 +190,7 @@
 	    dc->funcs->pCreateBitmap( hbmpRet );
     }
     TRACE("\t\t%04x\n", hbmpRet);
-    GDI_HEAP_UNLOCK(hdc);
+    GDI_ReleaseObj(hdc);
     return hbmpRet;
 }
 
@@ -251,7 +248,10 @@
     
     /* If the bits vector is null, the function should return the read size */
     if(bits == NULL)
-	return bmp->bitmap.bmWidthBytes * bmp->bitmap.bmHeight;
+    {
+        ret = bmp->bitmap.bmWidthBytes * bmp->bitmap.bmHeight;
+        goto done;
+    }
 
     if (count < 0) {
 	WARN("(%ld): Negative number of bytes passed???\n", count );
@@ -265,8 +265,8 @@
     if (count == 0)
       {
 	WARN("Less then one entire line requested\n");
-	GDI_HEAP_UNLOCK( hbitmap );
-	return 0;
+        ret = 0;
+        goto done;
       }
 
 
@@ -295,8 +295,8 @@
 	}
 
     }
-
-    GDI_HEAP_UNLOCK( hbitmap );
+ done:
+    GDI_ReleaseObj( hbitmap );
     return ret;
 }
 
@@ -365,7 +365,7 @@
 	}
     }
 
-    GDI_HEAP_UNLOCK( hbitmap );
+    GDI_ReleaseObj( hbitmap );
     return ret;
 }
 
@@ -393,7 +393,7 @@
 	HeapFree( GetProcessHeap(), 0, buf );
     }
 
-    GDI_HEAP_UNLOCK( hbitmap );
+    GDI_ReleaseObj( hbitmap );
     return res;
 }
 
@@ -410,7 +410,7 @@
 
     DIB_DeleteDIBSection( bmp );
 
-    return GDI_FreeObject( hbitmap );
+    return GDI_FreeObject( hbitmap, bmp );
 }
 
 	
@@ -523,7 +523,7 @@
     BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
     if (!bmp) return FALSE;
     CONV_SIZE32TO16( &bmp->size, size );
-    GDI_HEAP_UNLOCK( hbitmap );
+    GDI_ReleaseObj( hbitmap );
     return TRUE;
 }
 
@@ -542,7 +542,7 @@
     BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
     if (!bmp) return FALSE;
     *size = bmp->size;
-    GDI_HEAP_UNLOCK( hbitmap );
+    GDI_ReleaseObj( hbitmap );
     return TRUE;
 }
 
@@ -569,7 +569,7 @@
     if (prevSize) CONV_SIZE32TO16( &bmp->size, prevSize );
     bmp->size.cx = x;
     bmp->size.cy = y;
-    GDI_HEAP_UNLOCK( hbitmap );
+    GDI_ReleaseObj( hbitmap );
     return TRUE;
 }
 
@@ -592,7 +592,7 @@
     if (prevSize) *prevSize = bmp->size;
     bmp->size.cx = x;
     bmp->size.cy = y;
-    GDI_HEAP_UNLOCK( hbitmap );
+    GDI_ReleaseObj( hbitmap );
     return TRUE;
 }
 
diff --git a/objects/brush.c b/objects/brush.c
index 068f4e5..080da3c 100644
--- a/objects/brush.c
+++ b/objects/brush.c
@@ -105,19 +105,19 @@
 {
     BOOL success;
     BRUSHOBJ * brushPtr;
-    HBRUSH16 hbrush = GDI_AllocObject( sizeof(BRUSHOBJ), BRUSH_MAGIC );
-    if (!hbrush) return 0;
-    brushPtr = (BRUSHOBJ *) GDI_HEAP_LOCK( hbrush );
+    HBRUSH hbrush;
+
+    if (!(brushPtr = GDI_AllocObject( sizeof(BRUSHOBJ), BRUSH_MAGIC, &hbrush ))) return 0;
     brushPtr->logbrush.lbStyle = brush->lbStyle;
     brushPtr->logbrush.lbColor = brush->lbColor;
     brushPtr->logbrush.lbHatch = brush->lbHatch;
     success = create_brush_indirect(brushPtr, TRUE);
-    GDI_HEAP_UNLOCK( hbrush );
     if(!success)
     {
-       GDI_FreeObject(hbrush);
+       GDI_FreeObject( hbrush, brushPtr );
        hbrush = 0;
     }
+    else GDI_ReleaseObj( hbrush );
     TRACE("%04x\n", hbrush);
     return hbrush;
 }
@@ -136,19 +136,18 @@
 {
     BOOL success;
     BRUSHOBJ * brushPtr;
-    HBRUSH hbrush = GDI_AllocObject( sizeof(BRUSHOBJ), BRUSH_MAGIC );
-    if (!hbrush) return 0;
-    brushPtr = (BRUSHOBJ *) GDI_HEAP_LOCK( hbrush );
+    HBRUSH hbrush;
+    if (!(brushPtr = GDI_AllocObject( sizeof(BRUSHOBJ), BRUSH_MAGIC, &hbrush ))) return 0;
     brushPtr->logbrush.lbStyle = brush->lbStyle;
     brushPtr->logbrush.lbColor = brush->lbColor;
     brushPtr->logbrush.lbHatch = brush->lbHatch;
     success = create_brush_indirect(brushPtr, FALSE);
-    GDI_HEAP_UNLOCK( hbrush );
     if(!success)
     {
-       GDI_FreeObject(hbrush);
+       GDI_FreeObject( hbrush, brushPtr );
        hbrush = 0;
     }
+    else GDI_ReleaseObj( hbrush );
     TRACE("%08x\n", hbrush);
     return hbrush;
 }
@@ -319,6 +318,7 @@
     retval = dc->w.brushOrgX | (dc->w.brushOrgY << 16);
     dc->w.brushOrgX = x;
     dc->w.brushOrgY = y;
+    GDI_ReleaseObj( hdc );
     return retval;
 }
 
@@ -338,6 +338,7 @@
     }
     dc->w.brushOrgX = x;
     dc->w.brushOrgY = y;
+    GDI_ReleaseObj( hdc );
     return TRUE;
 }
 
@@ -365,7 +366,7 @@
 	  GlobalFree16( (HGLOBAL16)brush->logbrush.lbHatch );
 	  break;
     }
-    return GDI_FreeObject( hbrush );
+    return GDI_FreeObject( hbrush, brush );
 }
 
 
diff --git a/objects/clipping.c b/objects/clipping.c
index 3f83d32..e7ac965 100644
--- a/objects/clipping.c
+++ b/objects/clipping.c
@@ -12,15 +12,7 @@
 #include "wingdi.h"
 #include "wine/winuser16.h"
 
-DEFAULT_DEBUG_CHANNEL(clipping)
-DECLARE_DEBUG_CHANNEL(region)
-
-#define UPDATE_DIRTY_DC(dc) \
- do { \
-   if ((dc)->hookThunk && !((dc)->w.flags & (DC_SAVED | DC_MEMORY))) \
-     (dc)->hookThunk( (dc)->hSelf, DCHC_INVALIDVISRGN, (dc)->dwHookData, 0 ); \
- } while(0)
-
+DEFAULT_DEBUG_CHANNEL(clipping);
 
 
 /***********************************************************************
@@ -34,15 +26,11 @@
 
     if (!dc->w.hVisRgn)
     {
-        ERR_(region)("hVisRgn is zero. Please report this.\n" );
+        ERR("hVisRgn is zero. Please report this.\n" );
         exit(1);
     }
 
-    if (dc->w.flags & DC_DIRTY)
-    {
-        UPDATE_DIRTY_DC(dc);
-        dc->w.flags &= ~DC_DIRTY;
-    }
+    if (dc->w.flags & DC_DIRTY) ERR( "DC is dirty. Please report this.\n" );
 
     if (!dc->w.hClipRgn)
         CombineRgn( dc->w.hGCClipRgn, dc->w.hVisRgn, 0, RGN_COPY );
@@ -83,7 +71,7 @@
 INT WINAPI ExtSelectClipRgn( HDC hdc, HRGN hrgn, INT fnMode )
 {
     INT retval;
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    DC * dc = DC_GetDCUpdate( hdc );
     if (!dc) return ERROR;
 
     TRACE("%04x %04x %d\n", hdc, hrgn, fnMode );
@@ -99,6 +87,7 @@
         else
         {
             FIXME("Unimplemented: hrgn NULL in mode: %d\n", fnMode); 
+            GDI_ReleaseObj( hdc );
             return ERROR;
         }
     }
@@ -119,9 +108,8 @@
         OffsetRgn( dc->w.hClipRgn, dc->w.DCOrgX, dc->w.DCOrgY );
     }
 
-
     CLIPPING_UpdateGCRegion( dc );
-    GDI_HEAP_UNLOCK( hdc );
+    GDI_ReleaseObj( hdc );
     return retval;
 }
 
@@ -131,8 +119,10 @@
 INT16 WINAPI SelectVisRgn16( HDC16 hdc, HRGN16 hrgn )
 {
     int retval;
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc || !hrgn) return ERROR;
+    DC * dc;
+
+    if (!hrgn) return ERROR;
+    if (!(dc = DC_GetDCPtr( hdc ))) return ERROR;
 
     TRACE("%04x %04x\n", hdc, hrgn );
 
@@ -140,7 +130,7 @@
 
     retval = CombineRgn16( dc->w.hVisRgn, hrgn, 0, RGN_COPY );
     CLIPPING_UpdateGCRegion( dc );
-    GDI_HEAP_UNLOCK( hdc );
+    GDI_ReleaseObj( hdc );
     return retval;
 }
 
@@ -160,7 +150,7 @@
 INT WINAPI OffsetClipRgn( HDC hdc, INT x, INT y )
 {
     INT ret = SIMPLEREGION;
-    DC *dc = DC_GetDCPtr( hdc );
+    DC *dc = DC_GetDCUpdate( hdc );
     if (!dc) return ERROR;
 
     TRACE("%04x %d,%d\n", hdc, x, y );
@@ -171,7 +161,7 @@
         ret = OffsetRgn( dc->w.hClipRgn, XLSTODS(dc,x), YLSTODS(dc,y));
 	CLIPPING_UpdateGCRegion( dc );
     }
-    GDI_HEAP_UNLOCK( hdc );
+    GDI_ReleaseObj( hdc );
     return ret;
 }
 
@@ -182,12 +172,12 @@
 INT16 WINAPI OffsetVisRgn16( HDC16 hdc, INT16 x, INT16 y )
 {
     INT16 retval;
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    DC * dc = DC_GetDCUpdate( hdc );
     if (!dc) return ERROR;    
     TRACE("%04x %d,%d\n", hdc, x, y );
     retval = OffsetRgn( dc->w.hVisRgn, x, y );
     CLIPPING_UpdateGCRegion( dc );
-    GDI_HEAP_UNLOCK( hdc );
+    GDI_ReleaseObj( hdc );
     return retval;
 }
 
@@ -257,7 +247,7 @@
                                 INT right, INT bottom )
 {
     INT ret;
-    DC *dc = DC_GetDCPtr( hdc );
+    DC *dc = DC_GetDCUpdate( hdc );
     if (!dc) return ERROR;
 
     TRACE("%04x %dx%d,%dx%d\n", hdc, left, top, right, bottom );
@@ -272,7 +262,7 @@
 
 	ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_EXCLUDE );
     }
-    GDI_HEAP_UNLOCK( hdc );
+    GDI_ReleaseObj( hdc );
     return ret;
 }
 
@@ -294,7 +284,7 @@
                                   INT right, INT bottom )
 {
     INT ret;
-    DC *dc = DC_GetDCPtr( hdc );
+    DC *dc = DC_GetDCUpdate( hdc );
     if (!dc) return ERROR;
 
     TRACE("%04x %dx%d,%dx%d\n", hdc, left, top, right, bottom );
@@ -309,7 +299,7 @@
 
 	ret = CLIPPING_IntersectClipRect( dc, left, top, right, bottom, CLIP_INTERSECT );
     }
-    GDI_HEAP_UNLOCK( hdc );
+    GDI_ReleaseObj( hdc );
     return ret;
 }
 
@@ -346,12 +336,19 @@
     if (ret != ERROR)
     {
         RGNOBJ *newObj  = (RGNOBJ*)GDI_GetObjPtr( newRgn, REGION_MAGIC);
-        RGNOBJ *prevObj = (RGNOBJ*)GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC);
-        if (newObj && prevObj) newObj->header.hNext = prevObj->header.hNext;
+        if (newObj)
+        {
+            RGNOBJ *prevObj = (RGNOBJ*)GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC);
+            if (prevObj)
+            {
+                newObj->header.hNext = prevObj->header.hNext;
+                GDI_ReleaseObj( dc->w.hVisRgn );
+            }
+            GDI_ReleaseObj( newRgn );
+        }
         DeleteObject( dc->w.hVisRgn );
         dc->w.hVisRgn = newRgn;    
         CLIPPING_UpdateGCRegion( dc );
-	GDI_HEAP_UNLOCK( newRgn );
     }
     else DeleteObject( newRgn );
     return ret;
@@ -364,7 +361,8 @@
 INT16 WINAPI ExcludeVisRect16( HDC16 hdc, INT16 left, INT16 top,
                              INT16 right, INT16 bottom )
 {
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    INT16 ret;
+    DC * dc = DC_GetDCUpdate( hdc );
     if (!dc) return ERROR;    
 
     left   = XLPTODP( dc, left );
@@ -374,7 +372,9 @@
 
     TRACE("%04x %dx%d,%dx%d\n", hdc, left, top, right, bottom );
 
-    return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, TRUE );
+    ret = CLIPPING_IntersectVisRect( dc, left, top, right, bottom, TRUE );
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
@@ -384,6 +384,7 @@
 INT16 WINAPI IntersectVisRect16( HDC16 hdc, INT16 left, INT16 top,
                                INT16 right, INT16 bottom )
 {
+    INT16 ret;
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) return ERROR;    
 
@@ -394,7 +395,9 @@
 
     TRACE("%04x %dx%d,%dx%d\n", hdc, left, top, right, bottom );
 
-    return CLIPPING_IntersectVisRect( dc, left, top, right, bottom, FALSE );
+    ret = CLIPPING_IntersectVisRect( dc, left, top, right, bottom, FALSE );
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
@@ -412,18 +415,19 @@
  */
 BOOL WINAPI PtVisible( HDC hdc, INT x, INT y )
 {
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) return ERROR;    
+    BOOL ret = FALSE;
+    DC *dc = DC_GetDCUpdate( hdc );
 
     TRACE("%04x %d,%d\n", hdc, x, y );
-    if (!dc->w.hGCClipRgn) return FALSE;
-
-    if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
-    dc->w.flags &= ~DC_DIRTY;
-
-    return PtInRegion( dc->w.hGCClipRgn, XLPTODP(dc,x) + dc->w.DCOrgX, 
+    if (!dc) return FALSE;
+    if (dc->w.hGCClipRgn)
+    {
+        ret = PtInRegion( dc->w.hGCClipRgn, XLPTODP(dc,x) + dc->w.DCOrgX, 
                                            YLPTODP(dc,y) + dc->w.DCOrgY );
 }
+    GDI_ReleaseObj( hdc );
+    return ret;
+}
 
 
 /***********************************************************************
@@ -431,20 +435,25 @@
  */
 BOOL16 WINAPI RectVisible16( HDC16 hdc, const RECT16* rect )
 {
+    BOOL ret = FALSE;
     RECT16 tmpRect;
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) return FALSE;
     TRACE("%04x %d,%dx%d,%d\n",
           hdc, rect->left, rect->top, rect->right, rect->bottom );
-    if (!dc->w.hGCClipRgn) return FALSE;
-    /* copy rectangle to avoid overwriting by LPtoDP */
-    tmpRect = *rect;
-    LPtoDP16( hdc, (LPPOINT16)&tmpRect, 2 );
-    tmpRect.left   += dc->w.DCOrgX;
-    tmpRect.right  += dc->w.DCOrgX;
-    tmpRect.top    += dc->w.DCOrgY;
-    tmpRect.bottom += dc->w.DCOrgY;
-    return RectInRegion16( dc->w.hGCClipRgn, &tmpRect );
+    if (dc->w.hGCClipRgn)
+    {
+        /* copy rectangle to avoid overwriting by LPtoDP */
+        tmpRect = *rect;
+        LPtoDP16( hdc, (LPPOINT16)&tmpRect, 2 );
+        tmpRect.left   += dc->w.DCOrgX;
+        tmpRect.right  += dc->w.DCOrgX;
+        tmpRect.top    += dc->w.DCOrgY;
+        tmpRect.bottom += dc->w.DCOrgY;
+        ret = RectInRegion16( dc->w.hGCClipRgn, &tmpRect );
+    }
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
@@ -474,6 +483,7 @@
     rect->bottom -= dc->w.DCOrgY;
     DPtoLP16( hdc, (LPPOINT16)rect, 2 );
     TRACE("%d,%d-%d,%d\n", rect->left,rect->top,rect->right,rect->bottom );
+    GDI_ReleaseObj( hdc );
     return ret;
 }
 
@@ -492,6 +502,7 @@
     rect->top    -= dc->w.DCOrgY;
     rect->bottom -= dc->w.DCOrgY;
     DPtoLP( hdc, (LPPOINT)rect, 2 );
+    GDI_ReleaseObj( hdc );
     return ret;
 }
 
@@ -501,8 +512,9 @@
  */
 INT WINAPI GetClipRgn( HDC hdc, HRGN hRgn )
 {
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if( dc && hRgn )
+    INT ret = -1;
+    DC * dc;
+    if (hRgn && (dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC )))
     {
       if( dc->w.hClipRgn )
       { 
@@ -512,12 +524,13 @@
 	if( CombineRgn(hRgn, dc->w.hClipRgn, 0, RGN_COPY) != ERROR )
         {
             OffsetRgn( hRgn, -dc->w.DCOrgX, -dc->w.DCOrgY );
-	    return 1;
+            ret = 1;
         }
       }
-      else return 0;
+      else ret = 0;
+      GDI_ReleaseObj( hdc );
     }
-    return -1;
+    return ret;
 }
 
 /***********************************************************************
@@ -527,40 +540,35 @@
 {
     HRGN copy;
     RGNOBJ *obj, *copyObj;
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    DC *dc = DC_GetDCUpdate( hdc );
+
     if (!dc) return 0;
     TRACE("%04x\n", hdc );
-    if (!dc->w.hVisRgn)
-    {
-        ERR_(region)("hVisRgn is zero. Please report this.\n" );
-        exit(1);
-    }
-    if( dc->w.flags & DC_DIRTY ) UPDATE_DIRTY_DC(dc);
-    dc->w.flags &= ~DC_DIRTY;
 
     if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
     {
-        GDI_HEAP_UNLOCK( hdc );
+        GDI_ReleaseObj( hdc );
 	return 0;
     }
     if (!(copy = CreateRectRgn( 0, 0, 0, 0 )))
     {
-        GDI_HEAP_UNLOCK( dc->w.hVisRgn );
-        GDI_HEAP_UNLOCK( hdc );
+        GDI_ReleaseObj( dc->w.hVisRgn );
+        GDI_ReleaseObj( hdc );
         return 0;
     }  
     CombineRgn( copy, dc->w.hVisRgn, 0, RGN_COPY );
     if (!(copyObj = (RGNOBJ *) GDI_GetObjPtr( copy, REGION_MAGIC )))
     {
-        GDI_HEAP_UNLOCK( dc->w.hVisRgn );
-        GDI_HEAP_UNLOCK( hdc );
+        DeleteObject( copy );
+        GDI_ReleaseObj( dc->w.hVisRgn );
+        GDI_ReleaseObj( hdc );
 	return 0;
     }
     copyObj->header.hNext = obj->header.hNext;
     obj->header.hNext = copy;
-    GDI_HEAP_UNLOCK( dc->w.hVisRgn );
-    GDI_HEAP_UNLOCK( hdc );
-    GDI_HEAP_UNLOCK( copy );
+    GDI_ReleaseObj( copy );
+    GDI_ReleaseObj( dc->w.hVisRgn );
+    GDI_ReleaseObj( hdc );
     return copy;
 }
 
@@ -573,37 +581,24 @@
     HRGN saved;
     RGNOBJ *obj, *savedObj;
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    INT16 ret;
+    INT16 ret = ERROR;
 
     if (!dc) return ERROR;    
-    if (!dc->w.hVisRgn)
-    {
-        GDI_HEAP_UNLOCK( hdc );
-        return ERROR;    
-    }
+    if (!dc->w.hVisRgn) goto done;
     TRACE("%04x\n", hdc );
-    if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
-    {
-        GDI_HEAP_UNLOCK( hdc );
-	return ERROR;
-    }
-    if (!(saved = obj->header.hNext)) 
-    {
-        GDI_HEAP_UNLOCK( dc->w.hVisRgn );
-        GDI_HEAP_UNLOCK( hdc );
-        return ERROR;
-    }
-    if (!(savedObj = (RGNOBJ *) GDI_GetObjPtr( saved, REGION_MAGIC )))
-    {
-        GDI_HEAP_UNLOCK( dc->w.hVisRgn );
-        GDI_HEAP_UNLOCK( hdc );
-        return ERROR;
-    }
+    if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC ))) goto done;
+
+    saved = obj->header.hNext;
+    GDI_ReleaseObj( dc->w.hVisRgn );
+    if (!saved || !(savedObj = (RGNOBJ *) GDI_GetObjPtr( saved, REGION_MAGIC ))) goto done;
+
     DeleteObject( dc->w.hVisRgn );
     dc->w.hVisRgn = saved;
+    dc->w.flags &= ~DC_DIRTY;
     CLIPPING_UpdateGCRegion( dc );
-    GDI_HEAP_UNLOCK( hdc );
     ret = savedObj->rgn->type; /* FIXME */
-    GDI_HEAP_UNLOCK( saved );
+    GDI_ReleaseObj( saved );
+ done:
+    GDI_ReleaseObj( hdc );
     return ret;
 }
diff --git a/objects/dc.c b/objects/dc.c
index 4307e1a..5a9e3d2 100644
--- a/objects/dc.c
+++ b/objects/dc.c
@@ -83,12 +83,10 @@
  */
 DC *DC_AllocDC( const DC_FUNCTIONS *funcs )
 {
-    HDC16 hdc;
+    HDC hdc;
     DC *dc;
 
-    if (!(hdc = GDI_AllocObject( sizeof(DC), DC_MAGIC ))) return NULL;
-    dc = (DC *) GDI_HEAP_LOCK( hdc );
-
+    if (!(dc = GDI_AllocObject( sizeof(DC), DC_MAGIC, &hdc ))) return NULL;
     dc->hSelf      = hdc;
     dc->funcs      = funcs;
     dc->physDev    = NULL;
@@ -117,16 +115,45 @@
  */
 DC *DC_GetDCPtr( HDC hdc )
 {
-    GDIOBJHDR *ptr = (GDIOBJHDR *)GDI_HEAP_LOCK( hdc );
+    GDIOBJHDR *ptr = GDI_GetObjPtr( hdc, MAGIC_DONTCARE );
     if (!ptr) return NULL;
     if ((ptr->wMagic == DC_MAGIC) || (ptr->wMagic == METAFILE_DC_MAGIC) ||
 	(ptr->wMagic == ENHMETAFILE_DC_MAGIC))
         return (DC *)ptr;
-    GDI_HEAP_UNLOCK( hdc );
+    GDI_ReleaseObj( hdc );
     SetLastError( ERROR_INVALID_HANDLE );
     return NULL;
 }
 
+/***********************************************************************
+ *           DC_GetDCUpdate
+ *
+ * Retrieve a DC ptr while making sure the visRgn is updated.
+ * This function may call up to USER so the GDI lock should _not_
+ * be held when calling it.
+ */
+DC *DC_GetDCUpdate( HDC hdc )
+{
+    DC *dc = DC_GetDCPtr( hdc );
+    if (!dc) return NULL;
+    while (dc->w.flags & DC_DIRTY)
+    {
+        dc->w.flags &= ~DC_DIRTY;
+        if (!(dc->w.flags & (DC_SAVED | DC_MEMORY)))
+        {
+            DCHOOKPROC proc = dc->hookThunk;
+            if (proc)
+            {
+                DWORD data = dc->dwHookData;
+                GDI_ReleaseObj( hdc );
+                proc( hdc, DCHC_INVALIDVISRGN, data, 0 );
+                if (!(dc = DC_GetDCPtr( hdc ))) break;
+                /* otherwise restart the loop in case it became dirty again in the meantime */
+            }
+        }
+    }
+    return dc;
+}
 
 /***********************************************************************
  *           DC_InitDC
@@ -217,16 +244,14 @@
 HDC16 WINAPI GetDCState16( HDC16 hdc )
 {
     DC * newdc, * dc;
-    HGDIOBJ16 handle;
+    HGDIOBJ handle;
     
-    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
-    if (!(handle = GDI_AllocObject( sizeof(DC), DC_MAGIC )))
+    if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
+    if (!(newdc = GDI_AllocObject( sizeof(DC), DC_MAGIC, &handle )))
     {
-      GDI_HEAP_UNLOCK( hdc );
+      GDI_ReleaseObj( hdc );
       return 0;
     }
-    newdc = (DC *) GDI_HEAP_LOCK( handle );
-
     TRACE("(%04x): returning %04x\n", hdc, handle );
 
     newdc->w.flags            = dc->w.flags | DC_SAVED;
@@ -295,8 +320,8 @@
     }
     else
 	newdc->w.hClipRgn = 0;
-    GDI_HEAP_UNLOCK( handle );
-    GDI_HEAP_UNLOCK( hdc );
+    GDI_ReleaseObj( handle );
+    GDI_ReleaseObj( hdc );
     return handle;
 }
 
@@ -311,13 +336,13 @@
     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return;
     if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC )))
     {
-      GDI_HEAP_UNLOCK( hdc );
+      GDI_ReleaseObj( hdc );
       return;
     }
     if (!dcs->w.flags & DC_SAVED)
     {
-      GDI_HEAP_UNLOCK( hdc );
-      GDI_HEAP_UNLOCK( hdcs );
+      GDI_ReleaseObj( hdc );
+      GDI_ReleaseObj( hdcs );
       return;
     }
     TRACE("%04x %04x\n", hdc, hdcs );
@@ -386,8 +411,8 @@
     SetBkColor( hdc, dcs->w.backgroundColor);
     SetTextColor( hdc, dcs->w.textColor);
     GDISelectPalette16( hdc, dcs->w.hPalette, FALSE );
-    GDI_HEAP_UNLOCK( hdc );
-    GDI_HEAP_UNLOCK( hdcs );
+    GDI_ReleaseObj( hdcs );
+    GDI_ReleaseObj( hdc );
 }
 
 
@@ -409,18 +434,22 @@
     DC * dc, * dcs;
     INT ret;
 
-    dc = DC_GetDCPtr( hdc );
+    dc = DC_GetDCUpdate( hdc );
     if (!dc) return 0;
 
     if(dc->funcs->pSaveDC)
-        return dc->funcs->pSaveDC( dc );
+    {
+        ret = dc->funcs->pSaveDC( dc );
+        GDI_ReleaseObj( hdc );
+        return ret;
+    }
 
     if (!(hdcs = GetDCState16( hdc )))
     {
-      GDI_HEAP_UNLOCK( hdc );
+      GDI_ReleaseObj( hdc );
       return 0;
     }
-    dcs = (DC *) GDI_HEAP_LOCK( hdcs );
+    dcs = GDI_GetObjPtr( hdcs, DC_MAGIC );
 
     /* Copy path. The reason why path saving / restoring is in SaveDC/
      * RestoreDC and not in GetDCState/SetDCState is that the ...DCState
@@ -430,8 +459,8 @@
      */
     if (!PATH_AssignGdiPath( &dcs->w.path, &dc->w.path ))
     {
-        GDI_HEAP_UNLOCK( hdc );
-	GDI_HEAP_UNLOCK( hdcs );
+        GDI_ReleaseObj( hdc );
+	GDI_ReleaseObj( hdcs );
 	DeleteDC( hdcs );
 	return 0;
     }
@@ -440,8 +469,8 @@
     dc->header.hNext = hdcs;
     TRACE("(%04x): returning %d\n", hdc, dc->saveLevel+1 );
     ret = ++dc->saveLevel;
-    GDI_HEAP_UNLOCK( hdcs );
-    GDI_HEAP_UNLOCK( hdc );
+    GDI_ReleaseObj( hdcs );
+    GDI_ReleaseObj( hdc );
     return ret;
 }
 
@@ -467,13 +496,23 @@
     dc = DC_GetDCPtr( hdc );
     if(!dc) return FALSE;
     if(dc->funcs->pRestoreDC)
-        return dc->funcs->pRestoreDC( dc, level );
+    {
+        success = dc->funcs->pRestoreDC( dc, level );
+        GDI_ReleaseObj( hdc );
+        return success;
+    }
 
     if (level == -1) level = dc->saveLevel;
-    if ((level < 1) || (level > dc->saveLevel))
+    if ((level < 1) 
+            /* This pair of checks disagrees with MSDN "Platform SDK:
+               Windows GDI" July 2000 which says all negative values
+               for level will be interpreted as an instance relative
+               to the current state.  Restricting it to just -1 does
+               not satisfy this */
+	|| (level > dc->saveLevel))
     {
-      GDI_HEAP_UNLOCK( hdc );
-      return FALSE;
+        GDI_ReleaseObj( hdc );
+        return FALSE;
     }
     
     success=TRUE;
@@ -482,7 +521,7 @@
 	HDC16 hdcs = dc->header.hNext;
 	if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC )))
 	{
-	  GDI_HEAP_UNLOCK( hdc );
+	  GDI_ReleaseObj( hdc );
 	  return FALSE;
 	}	
 	dc->header.hNext = dcs->header.hNext;
@@ -494,9 +533,10 @@
 		 * returning FALSE but still destroying the saved DC state */
 	        success=FALSE;
 	}
+        GDI_ReleaseObj( hdcs );
 	DeleteDC( hdcs );
     }
-    GDI_HEAP_UNLOCK( hdc );
+    GDI_ReleaseObj( hdc );
     return success;
 }
 
@@ -507,6 +547,7 @@
 HDC16 WINAPI CreateDC16( LPCSTR driver, LPCSTR device, LPCSTR output,
                          const DEVMODEA *initData )
 {
+    HDC hdc;
     DC * dc;
     const DC_FUNCTIONS *funcs;
     char buf[300];
@@ -525,13 +566,14 @@
         !dc->funcs->pCreateDC( dc, buf, device, output, initData ))
     {
         WARN("creation aborted by device\n" );
-        GDI_HEAP_FREE( dc->hSelf );
+        GDI_FreeObject( dc->hSelf, dc );
         return 0;
     }
 
     DC_InitDC( dc );
-    GDI_HEAP_UNLOCK( dc->hSelf );
-    return dc->hSelf;
+    hdc = dc->hSelf;
+    GDI_ReleaseObj( hdc );
+    return hdc;
 }
 
 
@@ -615,9 +657,12 @@
 
     if ((origDC = (DC *)GDI_GetObjPtr( hdc, DC_MAGIC ))) funcs = origDC->funcs;
     else funcs = DRIVER_FindDriver( "DISPLAY" );
-    if (!funcs) return 0;
 
-    if (!(dc = DC_AllocDC( funcs ))) return 0;
+    if (!funcs || !(dc = DC_AllocDC( funcs )))
+    {
+        if (origDC) GDI_ReleaseObj( hdc );
+        return 0;
+    }
 
     TRACE("(%04x): returning %04x\n",
                hdc, dc->hSelf );
@@ -636,12 +681,14 @@
         !dc->funcs->pCreateDC( dc, NULL, NULL, NULL, NULL ))
     {
         WARN("creation aborted by device\n");
-        GDI_HEAP_FREE( dc->hSelf );
+        GDI_FreeObject( dc->hSelf, dc );
+	if (origDC) GDI_ReleaseObj( hdc );
         return 0;
     }
 
     DC_InitDC( dc );
-    GDI_HEAP_UNLOCK( dc->hSelf );
+    GDI_ReleaseObj( dc->hSelf );
+    if (origDC) GDI_ReleaseObj( hdc );
     return dc->hSelf;
 }
 
@@ -666,11 +713,16 @@
     TRACE("%04x\n", hdc );
 
     /* Call hook procedure to check whether is it OK to delete this DC */
-    if (    dc->hookThunk && !(dc->w.flags & (DC_SAVED | DC_MEMORY))
-         && dc->hookThunk( hdc, DCHC_DELETEDC, dc->dwHookData, 0 ) == FALSE )
+    if (dc->hookThunk && !(dc->w.flags & (DC_SAVED | DC_MEMORY)))
     {
-        GDI_HEAP_UNLOCK( hdc );
-        return FALSE;
+        DCHOOKPROC proc = dc->hookThunk;
+        if (proc)
+        {
+            DWORD data = dc->dwHookData;
+            GDI_ReleaseObj( hdc );
+            if (!proc( hdc, DCHC_DELETEDC, data, 0 )) return FALSE;
+            if (!(dc = DC_GetDCPtr( hdc ))) return FALSE;
+        }
     }
 
     while (dc->saveLevel)
@@ -680,6 +732,7 @@
 	if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC ))) break;
 	dc->header.hNext = dcs->header.hNext;
 	dc->saveLevel--;
+        GDI_ReleaseObj( hdcs );
 	DeleteDC( hdcs );
     }
     
@@ -698,7 +751,7 @@
     if (dc->hookThunk) THUNK_Free( (FARPROC)dc->hookThunk );
     PATH_DestroyGdiPath(&dc->w.path);
     
-    return GDI_FreeObject( hdc );
+    return GDI_FreeObject( hdc, dc );
 }
 
 
@@ -747,7 +800,7 @@
 INT WINAPI GetDeviceCaps( HDC hdc, INT cap )
 {
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    INT ret;
+    INT ret = 0;
     POINT pt;
 
     if (!dc) return 0;
@@ -777,7 +830,7 @@
 
     if ((cap < 0) || (cap > sizeof(DeviceCaps)-sizeof(WORD)))
     {
-      GDI_HEAP_UNLOCK( hdc );
+      GDI_ReleaseObj( hdc );
       return 0;
     }
 
@@ -788,7 +841,7 @@
     TRACE("(%04x,%d): returning %d\n",
 	    hdc, cap, *(WORD *)(((char *)dc->w.devCaps) + cap) );
     ret = *(WORD *)(((char *)dc->w.devCaps) + cap);
-    GDI_HEAP_UNLOCK( hdc );
+    GDI_ReleaseObj( hdc );
     return ret;
 }
 
@@ -817,7 +870,7 @@
 	oldColor = dc->w.backgroundColor;
 	dc->w.backgroundColor = color;
     }
-    GDI_HEAP_UNLOCK( hdc );
+    GDI_ReleaseObj( hdc );
     return oldColor;
 }
 
@@ -846,7 +899,7 @@
 	oldColor = dc->w.textColor;
 	dc->w.textColor = color;
     }
-    GDI_HEAP_UNLOCK( hdc );
+    GDI_ReleaseObj( hdc );
     return oldColor;
 }
 
@@ -873,7 +926,7 @@
 	prevAlign = dc->w.textAlign;
 	dc->w.textAlign = align;
     }
-    GDI_HEAP_UNLOCK( hdc );
+    GDI_ReleaseObj( hdc );
     return prevAlign;
 }
 
@@ -891,7 +944,7 @@
     if (dc->funcs->pGetDCOrgEx) dc->funcs->pGetDCOrgEx( dc, lpp );
     lpp->x += dc->w.DCOrgX;
     lpp->y += dc->w.DCOrgY;
-    GDI_HEAP_UNLOCK( hDC );
+    GDI_ReleaseObj( hDC );
     return TRUE;
 }
 
@@ -919,28 +972,17 @@
     prevOrg = dc->w.DCOrgX | (dc->w.DCOrgY << 16);
     dc->w.DCOrgX = x;
     dc->w.DCOrgY = y;
-    GDI_HEAP_UNLOCK( hdc );
+    GDI_ReleaseObj( hdc );
     return prevOrg;
 }
 
 
 /***********************************************************************
- *           GetGraphicsMode    (GDI32.188)
- */
-INT WINAPI GetGraphicsMode( HDC hdc )
-{
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) return 0;
-    return dc->w.GraphicsMode;
-}
-
-
-/***********************************************************************
  *           SetGraphicsMode    (GDI32.317)
  */
 INT WINAPI SetGraphicsMode( HDC hdc, INT mode )
 {
-    INT ret;
+    INT ret = 0;
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
 
     /* One would think that setting the graphics mode to GM_COMPATIBLE
@@ -950,37 +992,17 @@
      */
     
     if (!dc) return 0;
-    if ((mode <= 0) || (mode > GM_LAST)) return 0;
+    if ((mode > 0) || (mode <= GM_LAST)) 
+    {
     ret = dc->w.GraphicsMode;
     dc->w.GraphicsMode = mode;
+}
+    GDI_ReleaseObj( hdc );
     return ret;
 }
 
 
 /***********************************************************************
- *           GetArcDirection16    (GDI.524)
- */
-INT16 WINAPI GetArcDirection16( HDC16 hdc )
-{
-    return GetArcDirection( (HDC)hdc );
-}
-
-
-/***********************************************************************
- *           GetArcDirection    (GDI32.141)
- */
-INT WINAPI GetArcDirection( HDC hdc )
-{
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    
-    if (!dc)
-        return 0;
-
-    return dc->w.ArcDirection;
-}
-
-
-/***********************************************************************
  *           SetArcDirection16    (GDI.525)
  */
 INT16 WINAPI SetArcDirection16( HDC16 hdc, INT16 nDirection )
@@ -994,11 +1016,8 @@
  */
 INT WINAPI SetArcDirection( HDC hdc, INT nDirection )
 {
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    INT nOldDirection;
-    
-    if (!dc)
-        return 0;
+    DC * dc;
+    INT nOldDirection = 0;
 
     if (nDirection!=AD_COUNTERCLOCKWISE && nDirection!=AD_CLOCKWISE)
     {
@@ -1006,9 +1025,12 @@
 	return 0;
     }
 
+    if ((dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC )))
+    {
     nOldDirection = dc->w.ArcDirection;
     dc->w.ArcDirection = nDirection;
-
+        GDI_ReleaseObj( hdc );
+    }
     return nOldDirection;
 }
 
@@ -1018,15 +1040,11 @@
  */
 BOOL WINAPI GetWorldTransform( HDC hdc, LPXFORM xform )
 {
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    
-    if (!dc)
-        return FALSE;
-    if (!xform)
-	return FALSE;
-
+    DC * dc;
+    if (!xform) return FALSE;
+    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return FALSE;
     *xform = dc->w.xformWorld2Wnd;
-    
+    GDI_ReleaseObj( hdc );
     return TRUE;
 }
 
@@ -1036,6 +1054,7 @@
  */
 BOOL WINAPI SetWorldTransform( HDC hdc, const XFORM *xform )
 {
+    BOOL ret = FALSE;
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     
     if (!dc)
@@ -1044,18 +1063,17 @@
         return FALSE;
     }
 
-    if (!xform)
-	return FALSE;
+    if (!xform) goto done;
     
     /* Check that graphics mode is GM_ADVANCED */
-    if (dc->w.GraphicsMode!=GM_ADVANCED)
-       return FALSE;
+    if (dc->w.GraphicsMode!=GM_ADVANCED) goto done;
 
     dc->w.xformWorld2Wnd = *xform;
-    
     DC_UpdateXforms( dc );
-
-    return TRUE;
+    ret = TRUE;
+ done:
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
@@ -1084,6 +1102,7 @@
 BOOL WINAPI ModifyWorldTransform( HDC hdc, const XFORM *xform,
     DWORD iMode )
 {
+    BOOL ret = FALSE;
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     
     /* Check for illegal parameters */
@@ -1092,12 +1111,10 @@
         SetLastError( ERROR_INVALID_HANDLE );
         return FALSE;
     }
-    if (!xform)
-	return FALSE;
+    if (!xform) goto done;
     
     /* Check that graphics mode is GM_ADVANCED */
-    if (dc->w.GraphicsMode!=GM_ADVANCED)
-       return FALSE;
+    if (dc->w.GraphicsMode!=GM_ADVANCED) goto done;
        
     switch (iMode)
     {
@@ -1118,12 +1135,14 @@
 	        xform );
 	    break;
         default:
-	    return FALSE;
+            goto done;
     }
 
     DC_UpdateXforms( dc );
-
-    return TRUE;
+    ret = TRUE;
+ done:
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
@@ -1206,7 +1225,7 @@
     dc->hookThunk = (DCHOOKPROC)
                     THUNK_Alloc( hookProc, (RELAY)GDI_CallTo16_word_wwll );
 
-    GDI_HEAP_UNLOCK( hdc );
+    GDI_ReleaseObj( hdc );
     return TRUE;
 }
 
@@ -1219,7 +1238,7 @@
     DC *dc = (DC *)GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) return 0;
     *phookProc = dc->hookProc;
-    GDI_HEAP_UNLOCK( hdc );
+    GDI_ReleaseObj( hdc );
     return dc->dwHookData;
 }
 
@@ -1244,7 +1263,7 @@
             dc->w.flags |= DC_DIRTY;
         else if( flags & DCHF_VALIDATEVISRGN || !flags )
             dc->w.flags &= ~DC_DIRTY;
-	GDI_HEAP_UNLOCK( hDC );
+	GDI_ReleaseObj( hDC );
         return wRet;
     }
     return 0;
diff --git a/objects/dcvalues.c b/objects/dcvalues.c
index 9afd47a..0b23150 100644
--- a/objects/dcvalues.c
+++ b/objects/dcvalues.c
@@ -5,31 +5,55 @@
  *
  */
 
+#include "winbase.h"
+#include "winerror.h"
 #include "gdi.h"
 #include "dc.h"
 
+#define COLORREF16 COLORREF  /*hack*/
+
 #define DC_GET_VAL_16( func_type, func_name, dc_field ) \
 func_type WINAPI func_name( HDC16 hdc ) \
 { \
+    func_type ret = 0; \
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ); \
-    if (!dc) return 0; \
-    return dc->dc_field; \
+    if (dc) \
+    { \
+        ret = dc->dc_field; \
+        GDI_ReleaseObj( hdc ); \
+    } \
+    return ret; \
 }
 
-#define DC_GET_VAL_32( func_type, func_name, dc_field ) \
+#define DC_GET_VAL( func_type, func_name, dc_field ) \
+func_type##16 WINAPI func_name##16( HDC16 hdc ) \
+{ \
+    return func_name( hdc ); \
+} \
+ \
 func_type WINAPI func_name( HDC hdc ) \
 { \
+    func_type ret = 0; \
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ); \
-    if (!dc) return 0; \
-    return dc->dc_field; \
+    if (dc) \
+    { \
+        ret = dc->dc_field; \
+        GDI_ReleaseObj( hdc ); \
+    } \
+    return ret; \
 }
 
 #define DC_GET_X_Y( func_type, func_name, ret_x, ret_y ) \
 func_type WINAPI func_name( HDC16 hdc ) \
 { \
+    func_type ret = 0; \
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ); \
-    if (!dc) return 0; \
-    return MAKELONG( dc->ret_x, dc->ret_y ); \
+    if (dc) \
+    { \
+        ret = MAKELONG( dc->ret_x, dc->ret_y ); \
+        GDI_ReleaseObj( hdc ); \
+    } \
+    return ret; \
 }
 
 /* DC_GET_VAL_EX is used to define functions returning a POINT or a SIZE. It is 
@@ -43,15 +67,17 @@
     if (!dc) return FALSE; \
     ((LPPOINT16)pt)->x = dc->ret_x; \
     ((LPPOINT16)pt)->y = dc->ret_y; \
+    GDI_ReleaseObj( hdc ); \
     return TRUE; \
 } \
  \
 BOOL WINAPI func_name( HDC hdc, LP##type pt ) \
 { \
-    DC * dc = (DC *) GDI_GetObjPtr( (HDC16)hdc, DC_MAGIC ); \
+    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ); \
     if (!dc) return FALSE; \
     ((LPPOINT)pt)->x = dc->ret_x; \
     ((LPPOINT)pt)->y = dc->ret_y; \
+    GDI_ReleaseObj( hdc ); \
     return TRUE; \
 }
 
@@ -64,16 +90,19 @@
 INT WINAPI func_name( HDC hdc, INT mode ) \
 { \
     INT prevMode; \
-    DC *dc = DC_GetDCPtr( hdc ); \
-    if(!dc) return 0; \
-    if ((mode < min_val) || (mode > max_val)) return 0; \
+    DC *dc; \
+    if ((mode < min_val) || (mode > max_val)) { \
+        SetLastError(ERROR_INVALID_PARAMETER); \
+        return 0; \
+    } \
+    if (!(dc = DC_GetDCPtr( hdc ))) return 0; \
     if (dc->funcs->p##func_name) { \
 	prevMode = dc->funcs->p##func_name( dc, mode ); \
     } else { \
         prevMode = dc->dc_field; \
         dc->dc_field = mode; \
     } \
-    GDI_HEAP_UNLOCK( hdc ); \
+    GDI_ReleaseObj( hdc ); \
     return prevMode; \
 }
 
@@ -104,24 +133,14 @@
 DC_SET_MODE( SetStretchBltMode, w.stretchBltMode, BLACKONWHITE, HALFTONE )
 
 /***********************************************************************
- *		GetBkColor16		(GDI.75)
+ *		GetBkColor		(GDI.75) (GDI32.145)
  */
-DC_GET_VAL_16( COLORREF, GetBkColor16, w.backgroundColor )
+DC_GET_VAL( COLORREF, GetBkColor, w.backgroundColor )
 
 /***********************************************************************
- *		GetBkColor		(GDI32.145)
+ *		GetBkMode		(GDI.76) (GDI32.146)
  */
-DC_GET_VAL_32( COLORREF, GetBkColor, w.backgroundColor )
-
-/***********************************************************************
- *		GetBkMode16		(GDI.76)
- */
-DC_GET_VAL_16( INT16, GetBkMode16, w.backgroundMode )
-
-/***********************************************************************
- *		GetBkMode		(GDI32.146)
- */
-DC_GET_VAL_32( INT, GetBkMode, w.backgroundMode )
+DC_GET_VAL( INT, GetBkMode, w.backgroundMode )
 
 /***********************************************************************
  *		GetCurrentPosition16	(GDI.78)
@@ -129,34 +148,19 @@
 DC_GET_X_Y( DWORD, GetCurrentPosition16, w.CursPosX, w.CursPosY )
 
 /***********************************************************************
- *		GetMapMode16		(GDI.81)
+ *		GetMapMode		(GDI.81) (GDI32.196)
  */
-DC_GET_VAL_16( INT16, GetMapMode16, w.MapMode )
+DC_GET_VAL( INT, GetMapMode, w.MapMode )
 
 /***********************************************************************
- *		GetMapMode		(GDI32.196)
+ *		GetPolyFillMode		(GDI.84) (GDI32.213)
  */
-DC_GET_VAL_32( INT, GetMapMode, w.MapMode )
+DC_GET_VAL( INT, GetPolyFillMode, w.polyFillMode )
 
 /***********************************************************************
- *		GetPolyFillMode16	(GDI.84)
+ *		GetROP2			(GDI.85) (GDI32.214)
  */
-DC_GET_VAL_16( INT16, GetPolyFillMode16, w.polyFillMode )
-
-/***********************************************************************
- *		GetPolyFillMode		(GDI32.213)
- */
-DC_GET_VAL_32( INT, GetPolyFillMode, w.polyFillMode )
-
-/***********************************************************************
- *		GetROP216		(GDI.85)
- */
-DC_GET_VAL_16( INT16, GetROP216, w.ROPmode )
-
-/***********************************************************************
- *		GetROP2			(GDI32.214)
- */
-DC_GET_VAL_32( INT, GetROP2, w.ROPmode )
+DC_GET_VAL( INT, GetROP2, w.ROPmode )
 
 /***********************************************************************
  *		GetRelAbs16		(GDI.86)
@@ -164,24 +168,14 @@
 DC_GET_VAL_16( INT16, GetRelAbs16, w.relAbsMode )
 
 /***********************************************************************
- *		GetStretchBltMode16	(GDI.88)
+ *		GetStretchBltMode	(GDI.88) (GDI32.221)
  */
-DC_GET_VAL_16( INT16, GetStretchBltMode16, w.stretchBltMode )
+DC_GET_VAL( INT, GetStretchBltMode, w.stretchBltMode )
 
 /***********************************************************************
- *		GetStretchBltMode	(GDI32.221)
+ *		GetTextColor		(GDI.90) (GDI32.227)
  */
-DC_GET_VAL_32( INT, GetStretchBltMode, w.stretchBltMode )
-
-/***********************************************************************
- *		GetTextColor16		(GDI.90)
- */
-DC_GET_VAL_16( COLORREF, GetTextColor16, w.textColor )
-
-/***********************************************************************
- *		GetTextColor		(GDI32.227)
- */
-DC_GET_VAL_32( COLORREF, GetTextColor, w.textColor )
+DC_GET_VAL( COLORREF, GetTextColor, w.textColor )
 
 /***********************************************************************
  *		GetViewportExt16	(GDI.94)
@@ -219,14 +213,9 @@
 DC_GET_X_Y( DWORD, GetBrushOrg16, w.brushOrgX, w.brushOrgY )
 
 /***********************************************************************
- *		GetTextAlign16	(GDI.345)
+ *		GetTextAlign	(GDI.345) (GDI32,224)
  */
-DC_GET_VAL_16( UINT16, GetTextAlign16, w.textAlign )
-
-/***********************************************************************
- *		GetTextAlign	(GDI32.224)
- */
-DC_GET_VAL_32( UINT, GetTextAlign, w.textAlign )
+DC_GET_VAL( UINT, GetTextAlign, w.textAlign )
 
 /***********************************************************************
  *		GetCurLogFont16	(GDI.411)
@@ -234,6 +223,16 @@
 DC_GET_VAL_16( HFONT16, GetCurLogFont16, w.hFont )
 
 /***********************************************************************
+ *		GetArcDirection	(GDI.524) (GDI32.141)
+ */
+DC_GET_VAL( INT, GetArcDirection, w.ArcDirection )
+
+/***********************************************************************
+ *		GetGraphicsMode (GDI32.188)
+ */
+DC_GET_VAL( INT, GetGraphicsMode, w.GraphicsMode)
+
+/***********************************************************************
  *		GetBrushOrgEx	(GDI.469) (GDI32.148)
  */
 DC_GET_VAL_EX( GetBrushOrgEx, w.brushOrgX, w.brushOrgY, POINT ) /*  */
diff --git a/objects/dib.c b/objects/dib.c
index 4947f12..8d5dcc8 100644
--- a/objects/dib.c
+++ b/objects/dib.c
@@ -133,11 +133,11 @@
                        INT heightSrc, const void *bits,
                        const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
 {
-    DC *dc = DC_GetDCPtr( hdc );
+    DC *dc = DC_GetDCUpdate( hdc );
     if(!dc) return FALSE;
 
     if(dc->funcs->pStretchDIBits)
-    	   return dc->funcs->pStretchDIBits(dc, xDst, yDst, widthDst, 
+    	   heightSrc = dc->funcs->pStretchDIBits(dc, xDst, yDst, widthDst, 
 					    heightDst, xSrc, ySrc, widthSrc,
 					    heightSrc, bits, info, wUsage,
 					    dwRop);
@@ -157,8 +157,9 @@
 	SelectObject( hdcMem, hOldBitmap );
 	DeleteDC( hdcMem );
 	DeleteObject( hBitmap );
-	return heightSrc;
     }
+    GDI_ReleaseObj( hdc );
+    return heightSrc;
 }
 
 
@@ -198,16 +199,11 @@
     INT result;
 
     /* Check parameters */
-    dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) 
-    {
-	dc = (DC *) GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
-	if (!dc) return 0;
-    }
+    if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
 
     if (!(bitmap = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
     {
-        GDI_HEAP_UNLOCK( hdc );
+        GDI_ReleaseObj( hdc );
         return 0;
     }
 
@@ -215,8 +211,8 @@
 				       lines, bits, info, 
 				       coloruse, hbitmap);
 
-    GDI_HEAP_UNLOCK( hdc );
-    GDI_HEAP_UNLOCK( hbitmap );
+    GDI_ReleaseObj( hbitmap );
+    GDI_ReleaseObj( hdc );
 
     return result;
 }
@@ -246,7 +242,7 @@
     INT ret;
     DC *dc;
 
-    if (!(dc = DC_GetDCPtr( hdc ))) return 0;
+    if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
 
     if(dc->funcs->pSetDIBitsToDevice)
         ret = dc->funcs->pSetDIBitsToDevice( dc, xDest, yDest, cx, cy, xSrc,
@@ -257,7 +253,7 @@
 	ret = 0;
     }
 
-    GDI_HEAP_UNLOCK( hdc );
+    GDI_ReleaseObj( hdc );
     return ret;
 }
 
@@ -281,15 +277,11 @@
     PALETTEOBJ * palette;
     RGBQUAD *end;
 
-    dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) 
-    {
-	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
-	if (!dc) return 0;
-    }
+    if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
 
     if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
     {
+        GDI_ReleaseObj( hdc );
         return 0;
     }
 
@@ -312,7 +304,8 @@
     } else {
 	entries = 0;
     }
-    GDI_HEAP_UNLOCK( dc->w.hPalette );
+    GDI_ReleaseObj( dc->w.hPalette );
+    GDI_ReleaseObj( hdc );
     return entries;
 }
 
@@ -336,15 +329,11 @@
     PALETTEOBJ * palette;
     RGBQUAD *end;
 
-    dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) 
-    {
-	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
-	if (!dc) return 0;
-    }
+    if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
 
     if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
     {
+        GDI_ReleaseObj( hdc );
         return 0;
     }
 
@@ -365,7 +354,8 @@
     } else {
 	entries = 0;
     }
-    GDI_HEAP_UNLOCK( dc->w.hPalette );
+    GDI_ReleaseObj( dc->w.hPalette );
+    GDI_ReleaseObj( hdc );
     return entries;
 }
 
@@ -456,21 +446,16 @@
     int i;
 
     if (!info) return 0;
-    dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) 
-    {
-	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
-	if (!dc) return 0;
-    }
+    if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
     {
-        GDI_HEAP_UNLOCK( hdc );
+        GDI_ReleaseObj( hdc );
 	return 0;
     }
     if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
     {
-        GDI_HEAP_UNLOCK( hdc );
-        GDI_HEAP_UNLOCK( hbitmap );
+        GDI_ReleaseObj( hdc );
+        GDI_ReleaseObj( hbitmap );
         return 0;
     }
 
@@ -530,7 +515,7 @@
 	}
     }
 
-    GDI_HEAP_UNLOCK( dc->w.hPalette );
+    GDI_ReleaseObj( dc->w.hPalette );
 
     if (bits && lines)
     {
@@ -728,10 +713,10 @@
         /* Otherwise, get bits from the XImage */
         else if(!BITMAP_Driver->pGetDIBits(bmp, dc, startscan, lines, bits, info, coloruse, hbitmap))
         {
-	    GDI_HEAP_UNLOCK( hdc );
-	    GDI_HEAP_UNLOCK( hbitmap );
+	    GDI_ReleaseObj( hdc );
+	    GDI_ReleaseObj( hbitmap );
 
-	    return FALSE;
+	    return 0;
 	}
     }
     else if( info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) ) 
@@ -763,8 +748,8 @@
 	  info->bmiHeader.biSizeImage, info->bmiHeader.biWidth,
 	  info->bmiHeader.biHeight);
 
-    GDI_HEAP_UNLOCK( hdc );
-    GDI_HEAP_UNLOCK( hbitmap );
+    GDI_ReleaseObj( hdc );
+    GDI_ReleaseObj( hbitmap );
 
     return lines;
 }
@@ -870,7 +855,7 @@
 				     SEGPTR *bits, HANDLE section,
 				     DWORD offset)
 {
-    HBITMAP16 hbitmap;
+    HBITMAP16 hbitmap = 0;
     DC *dc;
     BOOL bDesktopDC = FALSE;
 
@@ -881,13 +866,11 @@
         bDesktopDC = TRUE;
     }
 
-    dc = (DC *) GDI_GetObjPtr(hdc, DC_MAGIC);
-    if(!dc) dc = (DC *) GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
-    if(!dc) return (HBITMAP16) NULL;
-
-    hbitmap = dc->funcs->pCreateDIBSection16(dc, bmi, usage, bits, section, offset, 0);
-
-    GDI_HEAP_UNLOCK(hdc);
+    if ((dc = DC_GetDCPtr( hdc )))
+    {
+        hbitmap = dc->funcs->pCreateDIBSection16(dc, bmi, usage, bits, section, offset, 0);
+        GDI_ReleaseObj(hdc);
+    }
 
     if (bDesktopDC)
       DeleteDC(hdc);
@@ -902,7 +885,7 @@
 			     LPVOID *bits, HANDLE section,
 			     DWORD offset, DWORD ovr_pitch)
 {
-    HBITMAP hbitmap;
+    HBITMAP hbitmap = 0;
     DC *dc;
     BOOL bDesktopDC = FALSE;
 
@@ -913,13 +896,11 @@
         bDesktopDC = TRUE;
     }
 
-    dc = (DC *) GDI_GetObjPtr(hdc, DC_MAGIC);
-    if(!dc) dc = (DC *) GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
-    if(!dc) return (HBITMAP) NULL;
-
-    hbitmap = dc->funcs->pCreateDIBSection(dc, bmi, usage, bits, section, offset, ovr_pitch);
-
-    GDI_HEAP_UNLOCK(hdc);
+    if ((dc = DC_GetDCPtr( hdc )))
+    {
+        hbitmap = dc->funcs->pCreateDIBSection(dc, bmi, usage, bits, section, offset, ovr_pitch);
+        GDI_ReleaseObj(hdc);
+    }
 
     if (bDesktopDC)
       DeleteDC(hdc);
@@ -976,6 +957,7 @@
 
     /* Get a pointer to the BITMAPOBJ structure */
     pBmp = (BITMAPOBJ *)GDI_GetObjPtr( hBmp, BITMAP_MAGIC );
+    if (!pBmp) return hPackedDIB;
 
     /* Get the bitmap dimensions */
     width = pBmp->bitmap.bmWidth;
@@ -1042,5 +1024,6 @@
     }
 
 END:
+    GDI_ReleaseObj( hBmp );
     return hPackedDIB;
 }
diff --git a/objects/enhmetafile.c b/objects/enhmetafile.c
index 6828837..60000a0 100644
--- a/objects/enhmetafile.c
+++ b/objects/enhmetafile.c
@@ -35,13 +35,16 @@
 HENHMETAFILE EMF_Create_HENHMETAFILE(ENHMETAHEADER *emh, HFILE hFile, HANDLE
 				     hMapping )
 {
-    HENHMETAFILE hmf = GDI_AllocObject( sizeof(ENHMETAFILEOBJ),
-					ENHMETAFILE_MAGIC );
-    ENHMETAFILEOBJ *metaObj = (ENHMETAFILEOBJ *)GDI_HEAP_LOCK( hmf );
+    HENHMETAFILE hmf = 0;
+    ENHMETAFILEOBJ *metaObj = GDI_AllocObject( sizeof(ENHMETAFILEOBJ),
+                                               ENHMETAFILE_MAGIC, &hmf );
+    if (metaObj)
+    {
     metaObj->emh = emh;
     metaObj->hFile = hFile;
     metaObj->hMapping = hMapping;
-    GDI_HEAP_UNLOCK( hmf );
+        GDI_ReleaseObj( hmf );
+    }
     return hmf;
 }
 
@@ -59,7 +62,7 @@
 	CloseHandle( metaObj->hFile );
     } else
         HeapFree( GetProcessHeap(), 0, metaObj->emh );
-    return GDI_FreeObject( hmf );
+    return GDI_FreeObject( hmf, metaObj );
 }
 
 /******************************************************************
@@ -81,9 +84,9 @@
  *
  * Releases ENHMETAHEADER associated with HENHMETAFILE
  */
-static BOOL EMF_ReleaseEnhMetaHeader( HENHMETAFILE hmf )
+static void EMF_ReleaseEnhMetaHeader( HENHMETAFILE hmf )
 {
-    return GDI_HEAP_UNLOCK( hmf );
+    GDI_ReleaseObj( hmf );
 }
 
 /*****************************************************************************
diff --git a/objects/font.c b/objects/font.c
index 03f1827..66423fe 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -309,15 +309,13 @@
  */
 HFONT16 WINAPI CreateFontIndirect16( const LOGFONT16 *font )
 {
-    HFONT16 hFont = 0;
+    HFONT hFont = 0;
 
     if (font)
     {
-	hFont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
-	if( hFont )
-	{
 	    FONTOBJ* fontPtr;
-	    fontPtr = (FONTOBJ *) GDI_HEAP_LOCK( hFont );
+	if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC, &hFont )))
+	{
 	    memcpy( &fontPtr->logfont, font, sizeof(LOGFONT16) );
 
 	    TRACE("(%i %i %i %i) '%s' %s %s => %04x\n",
@@ -334,7 +332,7 @@
                    "escapement angle %f for new font %04x\n", 
                    font->lfOrientation/10., font->lfEscapement/10., hFont);
 	    }
-	    GDI_HEAP_UNLOCK( hFont );
+	    GDI_ReleaseObj( hFont );
 	}
     }
     else WARN("(NULL) => NULL\n");
@@ -535,10 +533,15 @@
                                    FONTENUMPROCEX16 efproc, LPARAM lParam,
                                    DWORD dwFlags)
 {
+    BOOL (*enum_func)(HDC,LPLOGFONT16,DEVICEFONTENUMPROC,LPARAM);
     INT16	retVal = 0;
-    DC* 	dc = (DC*) GDI_GetObjPtr( hDC, DC_MAGIC );
+    DC* 	dc = DC_GetDCPtr( hDC );
 
-    if( dc && dc->funcs->pEnumDeviceFonts )
+    if (!dc) return 0;
+    enum_func = dc->funcs->pEnumDeviceFonts;
+    GDI_ReleaseObj( hDC );
+
+    if (enum_func)
     {
 	LPNEWTEXTMETRICEX16	lptm16 = SEGPTR_ALLOC( sizeof(NEWTEXTMETRICEX16) );
 	if( lptm16 )
@@ -557,8 +560,7 @@
 		fe16.segTextMetric = SEGPTR_GET(lptm16);
 		fe16.segLogFont = SEGPTR_GET(lplf16);
 
-		retVal = dc->funcs->pEnumDeviceFonts( dc, plf, FONT_EnumInstance16, (LPARAM)&fe16 );
-
+		retVal = enum_func( hDC, plf, FONT_EnumInstance16, (LPARAM)&fe16 );
 		SEGPTR_FREE(lplf16);
 	    }
 	    SEGPTR_FREE(lptm16);
@@ -573,9 +575,15 @@
 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, FONTENUMPROCEXW efproc, 
 					           LPARAM lParam, DWORD dwUnicode)
 {
-    DC*		dc = (DC*) GDI_GetObjPtr( hDC, DC_MAGIC );
+    BOOL (*enum_func)(HDC,LPLOGFONT16,DEVICEFONTENUMPROC,LPARAM);
+    INT ret = 0;
+    DC *dc = DC_GetDCPtr( hDC );
 
-    if( dc && dc->funcs->pEnumDeviceFonts )
+    if (!dc) return 0;
+    enum_func = dc->funcs->pEnumDeviceFonts;
+    GDI_ReleaseObj( hDC );
+
+    if (enum_func)
     {
 	LOGFONT16		lf16;
 	NEWTEXTMETRICEXW 	tm32w;
@@ -602,9 +610,9 @@
 	else lf16.lfFaceName[0] = '\0';
 	lf16.lfCharSet = plf->lfCharSet;
 
-	return dc->funcs->pEnumDeviceFonts( dc, &lf16, FONT_EnumInstance, (LPARAM)&fe32 );
+	ret = enum_func( hDC, &lf16, FONT_EnumInstance, (LPARAM)&fe32 );
     }
-    return 0;
+    return ret;
 }
 
 /***********************************************************************
@@ -708,10 +716,7 @@
  */
 INT16 WINAPI GetTextCharacterExtra16( HDC16 hdc )
 {
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) return 0;
-    return abs( (dc->w.charExtra * dc->wndExtX + dc->vportExtX / 2)
-                 / dc->vportExtX );
+    return (INT16)GetTextCharacterExtra( hdc );
 }
 
 
@@ -720,10 +725,13 @@
  */
 INT WINAPI GetTextCharacterExtra( HDC hdc )
 {
+    INT ret;
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) return 0;
-    return abs( (dc->w.charExtra * dc->wndExtX + dc->vportExtX / 2)
+    ret = abs( (dc->w.charExtra * dc->wndExtX + dc->vportExtX / 2)
                  / dc->vportExtX );
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
@@ -745,11 +753,15 @@
     DC * dc = DC_GetDCPtr( hdc );
     if (!dc) return 0;
     if (dc->funcs->pSetTextCharacterExtra)
-        return dc->funcs->pSetTextCharacterExtra( dc, extra );
-    extra = (extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX;
-    prev = dc->w.charExtra;
-    dc->w.charExtra = abs(extra);
-    return (prev * dc->wndExtX + dc->vportExtX / 2) / dc->vportExtX;
+        prev = dc->funcs->pSetTextCharacterExtra( dc, extra );
+    else
+    {
+        extra = (extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX;
+        prev = (dc->w.charExtra * dc->wndExtX + dc->vportExtX / 2) / dc->vportExtX;
+        dc->w.charExtra = abs(extra);
+    }
+    GDI_ReleaseObj( hdc );
+    return prev;
 }
 
 
@@ -767,26 +779,30 @@
  */
 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
 {
+    BOOL ret = TRUE;
     DC * dc = DC_GetDCPtr( hdc );
-    if (!dc) return 0;
+    if (!dc) return FALSE;
     if (dc->funcs->pSetTextJustification)
-        return dc->funcs->pSetTextJustification( dc, extra, breaks );
-
-    extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
-    if (!extra) breaks = 0;
-    dc->w.breakTotalExtra = extra;
-    dc->w.breakCount = breaks;
-    if (breaks)
-    {
-        dc->w.breakExtra = extra / breaks;
-        dc->w.breakRem   = extra - (dc->w.breakCount * dc->w.breakExtra);
-    }
+        ret = dc->funcs->pSetTextJustification( dc, extra, breaks );
     else
     {
-        dc->w.breakExtra = 0;
-        dc->w.breakRem   = 0;
+        extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
+        if (!extra) breaks = 0;
+        dc->w.breakTotalExtra = extra;
+        dc->w.breakCount = breaks;
+        if (breaks)
+        {
+            dc->w.breakExtra = extra / breaks;
+            dc->w.breakRem   = extra - (dc->w.breakCount * dc->w.breakExtra);
+        }
+        else
+        {
+            dc->w.breakExtra = 0;
+            dc->w.breakRem   = 0;
+        }
     }
-    return 1;
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
@@ -804,18 +820,23 @@
 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
 {
     FONTOBJ *font;
+    INT     ret = 0;
 
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    DC * dc = (DC *) DC_GetDCPtr( hdc );
     if (!dc) return 0;
-    if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
-        return 0;
-    if (name) 
-        lstrcpynA( name, font->logfont.lfFaceName, count );
-    GDI_HEAP_UNLOCK( dc->w.hFont );
-    if (name)
-        return strlen(name);
-    else
-        return strlen(font->logfont.lfFaceName) + 1;
+
+    if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
+    {
+        if (name)
+        {
+            lstrcpynA( name, font->logfont.lfFaceName, count );
+            ret = strlen(name);
+        }
+        else ret = strlen(font->logfont.lfFaceName) + 1;
+        GDI_ReleaseObj( dc->w.hFont );
+    }
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 /***********************************************************************
@@ -825,7 +846,7 @@
 {
     LPSTR nameA = HeapAlloc( GetProcessHeap(), 0, count );
     INT res = GetTextFaceA(hdc,count,nameA);
-    lstrcpyAtoW( name, nameA );
+    if (name) lstrcpyAtoW( name, nameA );
     HeapFree( GetProcessHeap(), 0, nameA );
     return res;
 }
@@ -903,14 +924,17 @@
     INT count,   /* [in]  Number of characters in string */
     LPSIZE size) /* [out] Address of structure for string size */
 {
+    BOOL ret = FALSE;
     DC * dc = DC_GetDCPtr( hdc );
-    if (!dc || !dc->funcs->pGetTextExtentPoint ||
-        !dc->funcs->pGetTextExtentPoint( dc, str, count, size ))
-        return FALSE;
-
+    if (dc)
+    {
+	if(dc->funcs->pGetTextExtentPoint)
+	    ret = dc->funcs->pGetTextExtentPoint( dc, str, count, size );
+        GDI_ReleaseObj( hdc );
+    }
     TRACE("(%08x %s %d %p): returning %d,%d\n",
           hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
-    return TRUE;
+    return ret;
 }
 
 
@@ -966,14 +990,16 @@
 {
     int index, nFit, extent;
     SIZE tSize;
+    BOOL ret = FALSE;
     DC * dc = DC_GetDCPtr( hdc );
+    if (!dc) return FALSE;
 
-    if (!dc || !dc->funcs->pGetTextExtentPoint) return FALSE;
+    if (!dc->funcs->pGetTextExtentPoint) goto done;
 
     size->cx = size->cy = nFit = extent = 0;
     for(index = 0; index < count; index++)
     {
- 	if(!dc->funcs->pGetTextExtentPoint( dc, str, 1, &tSize )) return FALSE;
+ 	if(!dc->funcs->pGetTextExtentPoint( dc, str, 1, &tSize )) goto done;
 	if( extent+tSize.cx < maxExt )
         {
 	    extent+=tSize.cx;
@@ -986,10 +1012,13 @@
     }
     size->cx = extent;
     *lpnFit = nFit;
+    ret = TRUE;
 
     TRACE("(%08x %s %d) returning %d %d %d\n",
           hdc,debugstr_wn(str,count),maxExt,nFit, size->cx,size->cy);
-    return TRUE;
+done:
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 /***********************************************************************
@@ -1009,18 +1038,13 @@
  *           GetTextMetricsA    (GDI32.236)
  */
 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
-{
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc)
     {
-        if (!(dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC )))
-            return FALSE;
-    }
+    BOOL ret = FALSE;
+    DC * dc = DC_GetDCPtr( hdc );
+    if (!dc) return FALSE;
 
-    if (!dc->funcs->pGetTextMetrics ||
-        !dc->funcs->pGetTextMetrics( dc, metrics ))
-        return FALSE;
-
+    if (dc->funcs->pGetTextMetrics && dc->funcs->pGetTextMetrics( dc, metrics ))
+    {
     /* device layer returns values in device units
      * therefore we have to convert them to logical */
 
@@ -1039,6 +1063,7 @@
     metrics->tmAveCharWidth     = WDPTOLP(metrics->tmAveCharWidth);
     metrics->tmMaxCharWidth     = WDPTOLP(metrics->tmMaxCharWidth);
     metrics->tmOverhang         = WDPTOLP(metrics->tmOverhang);
+        ret = TRUE;
 
     TRACE("text metrics:\n"
           "    Weight = %03li\t FirstChar = %03i\t AveCharWidth = %li\n"
@@ -1060,7 +1085,9 @@
           metrics->tmAscent,
           metrics->tmDescent,
           metrics->tmHeight );
-    return TRUE;
+    }
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
@@ -1221,24 +1248,21 @@
                                LPINT buffer )
 {
     UINT i, extra;
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc)
+    BOOL ret = FALSE;
+    DC * dc = DC_GetDCPtr( hdc );
+    if (!dc) return FALSE;
+
+    if (dc->funcs->pGetCharWidth && dc->funcs->pGetCharWidth( dc, firstChar, lastChar, buffer))
     {
-        if (!(dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC )))
-            return FALSE;
+        /* convert device units to logical */
+
+        extra = dc->vportExtX >> 1;
+        for( i = firstChar; i <= lastChar; i++, buffer++ )
+            *buffer = (*buffer * dc->wndExtX + extra) / dc->vportExtX;
+        ret = TRUE;
     }
-
-    if (!dc->funcs->pGetCharWidth ||
-        !dc->funcs->pGetCharWidth( dc, firstChar, lastChar, buffer))
-        return FALSE;
-
-    /* convert device units to logical */
-
-    extra = dc->vportExtX >> 1;
-    for( i = firstChar; i <= lastChar; i++, buffer++ )
-         *buffer = (*buffer * dc->wndExtX + extra) / dc->vportExtX;
-
-    return TRUE;
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
@@ -1276,7 +1300,7 @@
         ret = dc->funcs->pSetMapperFlags( dc, dwFlag );
     else
         FIXME("(0x%04x, 0x%08lx): stub - harmless\n", hDC, dwFlag);
-    GDI_HEAP_UNLOCK( hDC );
+    GDI_ReleaseObj( hDC );
     return ret;
 }
 
diff --git a/objects/gdiobj.c b/objects/gdiobj.c
index b08f395..a94cd15 100644
--- a/objects/gdiobj.c
+++ b/objects/gdiobj.c
@@ -6,9 +6,15 @@
 
 #include "config.h"
 
+#include <assert.h>
 #include <stdlib.h>
 #include <stdio.h>
 
+#include "windef.h"
+#include "wingdi.h"
+#include "winerror.h"
+#include "wine/winbase16.h"
+
 #include "bitmap.h"
 #include "brush.h"
 #include "dc.h"
@@ -21,8 +27,7 @@
 #include "debugtools.h"
 #include "gdi.h"
 #include "tweak.h"
-#include "windef.h"
-#include "wingdi.h"
+#include "syslevel.h"
 
 DEFAULT_DEBUG_CHANNEL(gdi);
 
@@ -177,6 +182,10 @@
 
 HBITMAP hPseudoStockBitmap; /* 1x1 bitmap for memory DCs */
 
+static SYSLEVEL GDI_level;
+static WORD GDI_HeapSel;
+
+
 /******************************************************************************
  *
  *   void  ReadFontInformation(
@@ -308,7 +317,8 @@
  */
 #define FixStockFontSizeW FixStockFontSizeA
 
-
+#define TRACE_SEC(handle,text) \
+   TRACE("(%04x): " text " %ld\n", (handle), GDI_level.crst.RecursionCount)
 
 /***********************************************************************
  *           GDI_Init
@@ -318,6 +328,14 @@
 BOOL GDI_Init(void)
 {
     BOOL systemIsBold = (TWEAK_WineLook == WIN31_LOOK);
+    HPALETTE16 hpalette;
+    HINSTANCE16 instance;
+
+    _CreateSysLevel( &GDI_level, 3 );
+
+    /* create GDI heap */
+    if ((instance = LoadLibrary16( "GDI.EXE" )) < 32) return FALSE;
+    GDI_HeapSel = GlobalHandleToSel16( instance );
 
     /* Kill some warnings.  */
     (void)align_OEMFixedFont;
@@ -340,12 +358,9 @@
     /* Create default palette */
 
     /* DR well *this* palette can't be moveable (?) */
-    {
-    HPALETTE16 hpalette = PALETTE_Init();
-    if( !hpalette )
-        return FALSE;
-    StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *)GDI_HEAP_LOCK( hpalette );
-    }
+    hpalette = PALETTE_Init();
+    if( !hpalette ) return FALSE;
+    StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, hpalette );
 
     hPseudoStockBitmap = CreateBitmap( 1, 1, 1, 1, NULL ); 
     return TRUE;
@@ -355,75 +370,121 @@
 /***********************************************************************
  *           GDI_AllocObject
  */
-HGDIOBJ GDI_AllocObject( WORD size, WORD magic )
+void *GDI_AllocObject( WORD size, WORD magic, HGDIOBJ *handle )
 {
     static DWORD count = 0;
-    GDIOBJHDR * obj;
-    HGDIOBJ16 handle;
-    if ( magic == DC_MAGIC || magic == METAFILE_DC_MAGIC )
-      handle = GDI_HEAP_ALLOC( size );
-    else 
-      handle = GDI_HEAP_ALLOC_MOVEABLE( size );
-    if (!handle) return 0;
-    obj = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
+    GDIOBJHDR *obj;
+
+    _EnterSysLevel( &GDI_level );
+    if (!(*handle = LOCAL_Alloc( GDI_HeapSel, LMEM_MOVEABLE, size )))
+    {
+        _LeaveSysLevel( &GDI_level );
+        return NULL;
+    }
+    obj = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, *handle );
     obj->hNext   = 0;
     obj->wMagic  = magic;
     obj->dwCount = ++count;
-    GDI_HEAP_UNLOCK( handle );
-    return handle;
+
+    TRACE_SEC( *handle, "enter" );
+    return obj;
 }
 
 
 /***********************************************************************
+ *           GDI_ReallocObject
+ *
+ * The object ptr must have been obtained with GDI_GetObjPtr.
+ * The new pointer must be released with GDI_ReleaseObj.
+ */
+void *GDI_ReallocObject( WORD size, HGDIOBJ handle, void *object )
+{
+    HGDIOBJ new_handle;
+
+    LOCAL_Unlock( GDI_HeapSel, handle );
+    if (!(new_handle = LOCAL_ReAlloc( GDI_HeapSel, handle, size, LMEM_MOVEABLE )))
+    {
+        TRACE_SEC( handle, "leave" );
+        _LeaveSysLevel( &GDI_level );
+        return NULL;
+    }
+    assert( new_handle == handle );  /* moveable handle cannot change */
+    return LOCAL_Lock( GDI_HeapSel, handle );
+}
+ 
+
+/***********************************************************************
  *           GDI_FreeObject
  */
-BOOL GDI_FreeObject( HGDIOBJ handle )
+BOOL GDI_FreeObject( HGDIOBJ handle, void *ptr )
 {
-    GDIOBJHDR * object;
+    GDIOBJHDR *object = ptr;
 
-      /* Can't free stock objects */
-    if ((handle >= FIRST_STOCK_HANDLE) && (handle <= LAST_STOCK_HANDLE))
-        return TRUE;
-    
-    object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
-    if (!object) return FALSE;
-    object->wMagic = 0;  /* Mark it as invalid */
- 
-      /* Free object */
-    
-    GDI_HEAP_FREE( handle );
+    /* can't free stock objects */
+    if (handle < FIRST_STOCK_HANDLE)
+    {
+        object->wMagic = 0;  /* Mark it as invalid */
+        LOCAL_Unlock( GDI_HeapSel, handle );
+        LOCAL_Free( GDI_HeapSel, handle );
+    }
+    TRACE_SEC( handle, "leave" );
+    _LeaveSysLevel( &GDI_level );
     return TRUE;
 }
 
+
 /***********************************************************************
  *           GDI_GetObjPtr
  *
  * Return a pointer to the GDI object associated to the handle.
  * Return NULL if the object has the wrong magic number.
- * Movable GDI objects are locked in memory: it is up to the caller to unlock
- * it after the caller is done with the pointer.
+ * The object must be released with GDI_ReleaseObj.
  */
-GDIOBJHDR * GDI_GetObjPtr( HGDIOBJ handle, WORD magic )
+void *GDI_GetObjPtr( HGDIOBJ handle, WORD magic )
 {
-    GDIOBJHDR * ptr = NULL;
+    GDIOBJHDR *ptr = NULL;
+
+    _EnterSysLevel( &GDI_level );
 
     if (handle >= FIRST_STOCK_HANDLE)
     {
         if (handle <= LAST_STOCK_HANDLE) ptr = StockObjects[handle - FIRST_STOCK_HANDLE];
+        if (ptr && (magic != MAGIC_DONTCARE) && (ptr->wMagic != magic)) ptr = NULL;
     }
-    else 
-      ptr = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
-    if (!ptr) return NULL;
-    if ((magic != MAGIC_DONTCARE) && (ptr->wMagic != magic)) 
+    else
     {
-      GDI_HEAP_UNLOCK( handle );
-      return NULL;
+        ptr = (GDIOBJHDR *)LOCAL_Lock( GDI_HeapSel, handle );
+        if (ptr && (magic != MAGIC_DONTCARE) && (ptr->wMagic != magic))
+        {
+            LOCAL_Unlock( GDI_HeapSel, handle );
+            ptr = NULL;
+        }
     }
+
+    if (!ptr)
+    {
+        _LeaveSysLevel( &GDI_level );
+        SetLastError( ERROR_INVALID_HANDLE );
+    }
+    else TRACE_SEC( handle, "enter" );
+
     return ptr;
 }
 
 
 /***********************************************************************
+ *           GDI_ReleaseObj
+ *
+ */
+void GDI_ReleaseObj( HGDIOBJ handle )
+{
+    if (handle < FIRST_STOCK_HANDLE) LOCAL_Unlock( GDI_HeapSel, handle );
+    TRACE_SEC( handle, "leave" );
+    _LeaveSysLevel( &GDI_level );
+}
+
+
+/***********************************************************************
  *           DeleteObject16    (GDI.69)
  */
 BOOL16 WINAPI DeleteObject16( HGDIOBJ16 obj )
@@ -441,10 +502,12 @@
 
     GDIOBJHDR * header;
     if (HIWORD(obj)) return FALSE;
-    if ((obj >= FIRST_STOCK_HANDLE) && (obj <= LAST_STOCK_HANDLE))
+    if ((obj >= FIRST_STOCK_HANDLE) && (obj <= LAST_STOCK_HANDLE)) {
+	TRACE("Preserving Stock object %04x\n", obj );
+	/* NOTE: No GDI_Release is necessary */
         return TRUE;
-    if (obj == hPseudoStockBitmap) return TRUE;
-    if (!(header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj ))) return FALSE;
+    }
+    if (!(header = GDI_GetObjPtr( obj, MAGIC_DONTCARE ))) return FALSE;
 
     TRACE("%04x\n", obj );
 
@@ -452,19 +515,22 @@
 
     switch(header->wMagic)
     {
-      case PEN_MAGIC:     return GDI_FreeObject( obj );
+      case PEN_MAGIC:     return GDI_FreeObject( obj, header );
       case BRUSH_MAGIC:   return BRUSH_DeleteObject( obj, (BRUSHOBJ*)header );
-      case FONT_MAGIC:    return GDI_FreeObject( obj );
+      case FONT_MAGIC:    return GDI_FreeObject( obj, header );
       case PALETTE_MAGIC: return PALETTE_DeleteObject(obj,(PALETTEOBJ*)header);
       case BITMAP_MAGIC:  return BITMAP_DeleteObject( obj, (BITMAPOBJ*)header);
       case REGION_MAGIC:  return REGION_DeleteObject( obj, (RGNOBJ*)header );
-      case DC_MAGIC:      return DeleteDC(obj);
+      case DC_MAGIC:
+          GDI_ReleaseObj( obj );
+          return DeleteDC(obj);
       case 0 :
         WARN("Already deleted\n");
         break;
       default:
         WARN("Unknown magic number (%d)\n",header->wMagic);
     }
+    GDI_ReleaseObj( obj );
     return FALSE;
 }
 
@@ -482,11 +548,12 @@
  */
 HGDIOBJ WINAPI GetStockObject( INT obj )
 {
+    HGDIOBJ ret;
     if ((obj < 0) || (obj >= NB_STOCK_OBJECTS)) return 0;
     if (!StockObjects[obj]) return 0;
-    TRACE("returning %d\n",
-                FIRST_STOCK_HANDLE + obj );
-    return (HGDIOBJ16)(FIRST_STOCK_HANDLE + obj);
+    ret = (HGDIOBJ16)(FIRST_STOCK_HANDLE + obj);
+    TRACE("returning %4x\n", ret );
+    return ret;
 }
 
 
@@ -527,7 +594,7 @@
 	result = PALETTE_GetObject( (PALETTEOBJ *)ptr, count, buffer );
 	break;
       }
-    GDI_HEAP_UNLOCK( handle );
+    GDI_ReleaseObj( handle );
     return result;
 }
 
@@ -585,7 +652,7 @@
           ERR("Invalid GDI Magic %04x\n", ptr->wMagic);
 	  return 0;
     }
-    GDI_HEAP_UNLOCK( handle );
+    GDI_ReleaseObj( handle );
     return result;
 }
 
@@ -630,7 +697,7 @@
                    ptr->wMagic );
           break;
     }
-    GDI_HEAP_UNLOCK( handle );
+    GDI_ReleaseObj( handle );
     return result;
 }
 
@@ -688,7 +755,7 @@
 			   ptr->wMagic );
 	  break;
     }
-    GDI_HEAP_UNLOCK( handle );
+    GDI_ReleaseObj( handle );
     return result;
 }
 
@@ -697,21 +764,25 @@
  */
 HANDLE WINAPI GetCurrentObject(HDC hdc,UINT type)
 {
+    HANDLE ret = 0;
     DC * dc = DC_GetDCPtr( hdc );
 
-    if (!dc) 
-    	return 0;
+    if (dc) 
+    {
     switch (type) {
-    case OBJ_PEN:	return dc->w.hPen;
-    case OBJ_BRUSH:	return dc->w.hBrush;
-    case OBJ_PAL:	return dc->w.hPalette;
-    case OBJ_FONT:	return dc->w.hFont;
-    case OBJ_BITMAP:	return dc->w.hBitmap;
+	case OBJ_PEN:	 ret = dc->w.hPen; break;
+	case OBJ_BRUSH:	 ret = dc->w.hBrush; break;
+	case OBJ_PAL:	 ret = dc->w.hPalette; break;
+	case OBJ_FONT:	 ret = dc->w.hFont; break;
+	case OBJ_BITMAP: ret = dc->w.hBitmap; break;
     default:
     	/* the SDK only mentions those above */
     	WARN("(%08x,%d): unknown type.\n",hdc,type);
-	return 0;
+	    break;
+        }
+        GDI_ReleaseObj( hdc );
     }
+    return ret;
 }
 
 
@@ -729,10 +800,14 @@
  */
 HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle )
 {
-    DC * dc = DC_GetDCPtr( hdc );
-    if (!dc || !dc->funcs->pSelectObject) return 0;
+    HGDIOBJ ret = 0;
+    DC * dc = DC_GetDCUpdate( hdc );
+    if (!dc) return 0;
     TRACE("hdc=%04x %04x\n", hdc, handle );
-    return dc->funcs->pSelectObject( dc, handle );
+    if (dc->funcs->pSelectObject)
+        ret = dc->funcs->pSelectObject( dc, handle );
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 
@@ -753,7 +828,7 @@
     BOOL result = TRUE;
   /* Check if object is valid */
 
-    GDIOBJHDR * header = (GDIOBJHDR *) GDI_HEAP_LOCK( obj );
+    GDIOBJHDR * header = GDI_GetObjPtr( obj, MAGIC_DONTCARE );
     if (!header) return FALSE;
 
     TRACE("%04x\n", obj );
@@ -770,7 +845,7 @@
         /* Windows resets the brush origin. We don't need to. */
         break;
     }
-    GDI_HEAP_UNLOCK( obj );
+    GDI_ReleaseObj( obj );
     return result;
 }
 
@@ -939,54 +1014,13 @@
 {
     UINT16 magic = 0;
 
-    if (handle >= FIRST_STOCK_HANDLE ) 
+    GDIOBJHDR *object = GDI_GetObjPtr( handle, MAGIC_DONTCARE );
+    if (object)
     {
-        switch (handle)
-        {
-        case STOCK_WHITE_BRUSH:
-        case STOCK_LTGRAY_BRUSH:
-        case STOCK_GRAY_BRUSH:
-        case STOCK_DKGRAY_BRUSH:
-        case STOCK_BLACK_BRUSH:
-        case STOCK_HOLLOW_BRUSH:
-            magic = BRUSH_MAGIC;
-            break;
-
-        case STOCK_WHITE_PEN:
-        case STOCK_BLACK_PEN:
-        case STOCK_NULL_PEN :
-            magic = PEN_MAGIC;
-            break;
-
-        case STOCK_OEM_FIXED_FONT:
-        case STOCK_ANSI_FIXED_FONT:
-        case STOCK_ANSI_VAR_FONT:
-        case STOCK_SYSTEM_FONT:
-        case STOCK_DEVICE_DEFAULT_FONT:
-        case STOCK_SYSTEM_FIXED_FONT:
-        case STOCK_DEFAULT_GUI_FONT:
-            magic = FONT_MAGIC;
-            break;
-
-        case STOCK_DEFAULT_PALETTE:
-            magic = PALETTE_MAGIC;
-            break;
-        }
+        magic = object->wMagic - PEN_MAGIC + 1;
+        GDI_ReleaseObj( handle );
     }
-    else
-    {
-	GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK( handle );
-	if (object)
-	{
-	    magic = object->wMagic;
-	    GDI_HEAP_UNLOCK( handle );
-	}
-    }
-
-    if (magic >= PEN_MAGIC && magic <= METAFILE_DC_MAGIC)
-        return magic - PEN_MAGIC + 1;
-    else
-        return FALSE;
+    return magic;
 }
 
 
diff --git a/objects/metafile.c b/objects/metafile.c
index 036144d..172c578 100644
--- a/objects/metafile.c
+++ b/objects/metafile.c
@@ -73,10 +73,13 @@
  */
 HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh)
 {
-    HMETAFILE hmf = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC );
-    METAFILEOBJ *metaObj = (METAFILEOBJ *)GDI_HEAP_LOCK( hmf );
+    HMETAFILE hmf = 0;
+    METAFILEOBJ *metaObj = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC, &hmf );
+    if (metaObj)
+    {
     metaObj->mh = mh;
-    GDI_HEAP_UNLOCK( hmf );
+        GDI_ReleaseObj( hmf );
+    }
     return hmf;
 }
 
@@ -130,9 +133,9 @@
  *
  * Releases METAHEADER associated with HMETAFILE
  */
-static BOOL MF_ReleaseMetaHeader( HMETAFILE hmf )
+static void MF_ReleaseMetaHeader( HMETAFILE hmf )
 {
-    return GDI_HEAP_UNLOCK( hmf );
+    GDI_ReleaseObj( hmf );
 }
 
 /******************************************************************
@@ -162,11 +165,10 @@
 
 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
 {
-    METAHEADER *mh = MF_GetMetaHeader( hmf );
-
-    if(!mh) return FALSE;
-    HeapFree( GetProcessHeap(), 0, mh );
-    GDI_FreeObject( hmf );
+    METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
+    if (!metaObj) return FALSE;
+    HeapFree( GetProcessHeap(), 0, metaObj->mh );
+    GDI_FreeObject( hmf, metaObj );
     return TRUE;
 }
 
@@ -475,7 +477,7 @@
     BOOL loaded = FALSE;
 
     if (!mh) return FALSE;
-    if(mh->mtType == METAFILE_DISK) { /* Create a memoery-based copy */
+    if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
         mh = MF_LoadDiskBasedMetaFile(mh);
 	if(!mh) return FALSE;
 	loaded = TRUE;
@@ -580,7 +582,7 @@
 
 
     if(!mh) return FALSE;
-    if(mh->mtType == METAFILE_DISK) { /* Create a memoery-based copy */
+    if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
         mh = MF_LoadDiskBasedMetaFile(mh);
 	if(!mh) return FALSE;
 	loaded = TRUE;
@@ -668,7 +670,7 @@
     TRACE("(%08x,%08x,%p,%p)\n",
 		     hdc, hmf, lpEnumFunc, (void*)lpData);
     if (!mh) return 0;
-    if(mh->mtType == METAFILE_DISK) { /* Create a memoery-based copy */
+    if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
         mh = MF_LoadDiskBasedMetaFile(mh);
 	if(!mh) return 0;
 	loaded = TRUE;
diff --git a/objects/palette.c b/objects/palette.c
index d8e995c..6b1c2ee 100644
--- a/objects/palette.c
+++ b/objects/palette.c
@@ -17,6 +17,7 @@
 #include "wine/winuser16.h"
 #include "gdi.h"
 #include "color.h"
+#include "dc.h"
 #include "palette.h"
 #include "debugtools.h"
 #include "callback.h"
@@ -71,9 +72,8 @@
     {
         if (!(palObj->mapping = HeapAlloc( GetProcessHeap(), 0, sizeof(int) * 20 )))
             ERR("Can not create palette mapping -- out of memory!");
-        GDI_HEAP_UNLOCK( hpalette );
+        GDI_ReleaseObj( hpalette );
     }
-    	
     return hpalette;
 }
 
@@ -116,15 +116,13 @@
 
     size = sizeof(LOGPALETTE) + (palette->palNumEntries - 1) * sizeof(PALETTEENTRY);
 
-    hpalette = GDI_AllocObject( size + sizeof(int*) +sizeof(GDIOBJHDR) , PALETTE_MAGIC );
-    if (!hpalette) return 0;
-
-    palettePtr = (PALETTEOBJ *) GDI_HEAP_LOCK( hpalette );
+    if (!(palettePtr = GDI_AllocObject( size + sizeof(int*) +sizeof(GDIOBJHDR),
+                                        PALETTE_MAGIC, &hpalette ))) return 0;
     memcpy( &palettePtr->logpalette, palette, size );
     PALETTE_ValidateFlags(palettePtr->logpalette.palPalEntry, 
 			  palettePtr->logpalette.palNumEntries);
     palettePtr->mapping = NULL;
-    GDI_HEAP_UNLOCK( hpalette );
+    GDI_ReleaseObj( hpalette );
 
     TRACE("   returning %04x\n", hpalette);
     return hpalette;
@@ -228,7 +226,7 @@
     { 
       if (start >= numEntries) 
       {
-	GDI_HEAP_UNLOCK( hpalette );
+	GDI_ReleaseObj( hpalette );
 	return 0;
       }
       memcpy( entries, &palPtr->logpalette.palPalEntry[start],
@@ -236,9 +234,9 @@
       for( numEntries = 0; numEntries < count ; numEntries++ )
 	   if (entries[numEntries].peFlags & 0xF0)
 	       entries[numEntries].peFlags = 0;
-      GDI_HEAP_UNLOCK( hpalette );
     }
 
+    GDI_ReleaseObj( hpalette );
     return count;
 }
 
@@ -277,7 +275,7 @@
     numEntries = palPtr->logpalette.palNumEntries;
     if (start >= numEntries) 
     {
-      GDI_HEAP_UNLOCK( hpalette );
+      GDI_ReleaseObj( hpalette );
       return 0;
     }
     if (start+count > numEntries) count = numEntries - start;
@@ -287,7 +285,7 @@
 			  palPtr->logpalette.palNumEntries);
     HeapFree( GetProcessHeap(), 0, palPtr->mapping );
     palPtr->mapping = NULL;
-    GDI_HEAP_UNLOCK( hpalette );
+    GDI_ReleaseObj( hpalette );
     return count;
 }
 
@@ -328,11 +326,7 @@
     size += sizeof(int*) + sizeof(GDIOBJHDR);
     mapping = palPtr->mapping;
     
-    GDI_HEAP_UNLOCK( hPal );
-    
-    hPal = GDI_HEAP_REALLOC( hPal, size );
-    palPtr = (PALETTEOBJ *) GDI_GetObjPtr( hPal, PALETTE_MAGIC );
-    if( !palPtr ) return FALSE;
+    if (!(palPtr = GDI_ReallocObject( size, hPal, palPtr ))) return FALSE;
 
     if( mapping ) 
     {
@@ -341,7 +335,7 @@
 	if(newMap == NULL) 
         {
             ERR("Can not resize mapping -- out of memory!");
-            GDI_HEAP_UNLOCK( hPal );
+            GDI_ReleaseObj( hPal );
             return FALSE;
         }
         palPtr->mapping = newMap;
@@ -357,7 +351,7 @@
     }
     palPtr->logpalette.palNumEntries = cEntries;
     palPtr->logpalette.palVersion = prevVer;
-    GDI_HEAP_UNLOCK( hPal );
+    GDI_ReleaseObj( hPal );
     return TRUE;
 }
 
@@ -403,9 +397,10 @@
 	    PALETTE_Driver->
 	      pSetMapping(palPtr, StartIndex, NumEntries,
 			  hPal != hPrimaryPalette );
-            GDI_HEAP_UNLOCK( hPal );
+            GDI_ReleaseObj( hPal );
 	    return TRUE;
 	}
+	GDI_ReleaseObj( hPal );
     }
     return FALSE;
 }
@@ -489,12 +484,19 @@
     TRACE("hdc=%04x,start=%i,count=%i\n", hdc,start,count);
 
     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
-    if (!entries) return dc->w.devCaps->sizePalette;
+
+    if (!entries)
+    {
+	count = dc->w.devCaps->sizePalette;
+        goto done;
+    }
+
     if (start >= dc->w.devCaps->sizePalette)
       {
-	GDI_HEAP_UNLOCK( hdc );
-	return 0;
+	count = 0;
+        goto done;
       }
+
     if (start+count >= dc->w.devCaps->sizePalette)
 	count = dc->w.devCaps->sizePalette - start;
     for (i = 0; i < count; i++)
@@ -504,7 +506,8 @@
         TRACE("\tidx(%02x) -> RGB(%08lx)\n",
                          start + i, *(COLORREF*)(entries + i) );
     }
-    GDI_HEAP_UNLOCK( hdc );
+ done:
+    GDI_ReleaseObj( hdc );
     return count;
 }
 
@@ -536,12 +539,14 @@
     UINT index  = 0;
 
     if( palObj )
+    {
       index = COLOR_PaletteLookupPixel(palObj->logpalette.palPalEntry, 
 				       palObj->logpalette.palNumEntries,
 				       NULL, color, FALSE );
 
+      GDI_ReleaseObj( hpalette );
+    }
     TRACE("(%04x,%06lx): returning %d\n", hpalette, color, index );
-    GDI_HEAP_UNLOCK( hpalette );
     return index;
 }
 
@@ -558,9 +563,6 @@
 /***********************************************************************
  * GetNearestColor [GDI32.202]  Gets a system color to match
  *
- * NOTES
- *    Should this return CLR_INVALID instead of FadeCafe?
- *
  * RETURNS
  *    Success: Color from system palette that corresponds to given color
  *    Failure: CLR_INVALID
@@ -569,24 +571,26 @@
     HDC hdc,      /* [in] Handle of device context */
     COLORREF color) /* [in] Color to be matched */
 {
-    COLORREF 	 nearest = 0xFADECAFE;
+    COLORREF 	 nearest = CLR_INVALID;
     DC 		*dc;
     PALETTEOBJ  *palObj;
 
     if ( (dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC )) )
     {
-      palObj = (PALETTEOBJ*) 
-	        GDI_GetObjPtr( (dc->w.hPalette)? dc->w.hPalette
-				 	       : STOCK_DEFAULT_PALETTE, PALETTE_MAGIC );
-      if (!palObj) return nearest;
+        HPALETTE hpal = (dc->w.hPalette)? dc->w.hPalette : STOCK_DEFAULT_PALETTE;
+        palObj = GDI_GetObjPtr( hpal, PALETTE_MAGIC );
+        if (!palObj) {
+            GDI_ReleaseObj( hdc );
+            return nearest;
+        }
 
-      nearest = COLOR_LookupNearestColor( palObj->logpalette.palPalEntry,
-					  palObj->logpalette.palNumEntries, color );
-      GDI_HEAP_UNLOCK( dc->w.hPalette );
+        nearest = COLOR_LookupNearestColor( palObj->logpalette.palPalEntry,
+                                            palObj->logpalette.palNumEntries, color );
+        GDI_ReleaseObj( hpal );
+        GDI_ReleaseObj( hdc );
     }
 
     TRACE("(%06lx): returning %06lx\n", color, nearest );
-    GDI_HEAP_UNLOCK( hdc );    
     return nearest;
 }
 
@@ -624,7 +628,7 @@
 {
     HeapFree( GetProcessHeap(), 0, palette->mapping );
     if (hLastRealizedPalette == hpalette) hLastRealizedPalette = 0;
-    return GDI_FreeObject( hpalette );
+    return GDI_FreeObject( hpalette, palette );
 }
 
 
@@ -638,15 +642,10 @@
 
     TRACE("%04x %04x\n", hdc, hpal );
     
-    dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) 
-    {
-	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
-	if (!dc) return 0;
-    }
+    if (!(dc = DC_GetDCPtr( hdc ))) return 0;
     prev = dc->w.hPalette;
     dc->w.hPalette = hpal;
-    GDI_HEAP_UNLOCK( hdc );
+    GDI_ReleaseObj( hdc );
     if (!wBkg) hPrimaryPalette = hpal; 
     return prev;
 }
@@ -659,37 +658,39 @@
 {
     PALETTEOBJ* palPtr;
     int realized = 0;
-    DC*		dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) 
-    {
-	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
-	if (!dc) return 0;
-    }
+    DC* dc = DC_GetDCPtr( hdc );
+
+    if (!dc) return 0;
 
     TRACE("%04x...\n", hdc );
     
-    if( dc &&  dc->w.hPalette != hLastRealizedPalette )
+    if(dc->w.hPalette != hLastRealizedPalette )
     {
-	if( dc->w.hPalette == STOCK_DEFAULT_PALETTE )
-            return RealizeDefaultPalette16( hdc );
+	if( dc->w.hPalette == STOCK_DEFAULT_PALETTE ) {
+            realized = RealizeDefaultPalette16( hdc );
+	    GDI_ReleaseObj( hdc );
+	    return (UINT16)realized;
+	}
+
 
         palPtr = (PALETTEOBJ *) GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC );
 
 	if (!palPtr) {
-		FIXME("invalid selected palette %04x\n",dc->w.hPalette);
-		return 0;
+	    GDI_ReleaseObj( hdc );
+            FIXME("invalid selected palette %04x\n",dc->w.hPalette);
+            return 0;
 	}
         
         realized = PALETTE_Driver->
 	  pSetMapping(palPtr,0,palPtr->logpalette.palNumEntries,
 		      (dc->w.hPalette != hPrimaryPalette) ||
 		      (dc->w.hPalette == STOCK_DEFAULT_PALETTE));
-	GDI_HEAP_UNLOCK( dc->w.hPalette );
 	hLastRealizedPalette = dc->w.hPalette;
+	GDI_ReleaseObj( dc->w.hPalette );
     }
     else TRACE("  skipping (hLastRealizedPalette = %04x)\n",
 			 hLastRealizedPalette);
-    GDI_HEAP_UNLOCK( hdc );
+    GDI_ReleaseObj( hdc );
 
     TRACE("   realized %i colors.\n", realized );
     return (UINT16)realized;
@@ -701,33 +702,26 @@
  */
 UINT16 WINAPI RealizeDefaultPalette16( HDC16 hdc )
 {
+    UINT16 ret = 0;
     DC          *dc;
     PALETTEOBJ*  palPtr;
 
     TRACE("%04x\n", hdc );
 
-    dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) 
+    if (!(dc = DC_GetDCPtr( hdc ))) return 0;
+
+    if (!(dc->w.flags & DC_MEMORY))
     {
-	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
-	if (!dc) return 0;
+        palPtr = (PALETTEOBJ*)GDI_GetObjPtr(STOCK_DEFAULT_PALETTE, PALETTE_MAGIC );
+        if (palPtr)
+        {
+            /* lookup is needed to account for SetSystemPaletteUse() stuff */
+            ret = PALETTE_Driver->pUpdateMapping(palPtr);
+            GDI_ReleaseObj( STOCK_DEFAULT_PALETTE );
+        }
     }
-
-    if ( dc->w.flags & DC_MEMORY ) 
-      {
-	GDI_HEAP_UNLOCK( hdc );
-	return 0;
-      }
-
-    hPrimaryPalette = STOCK_DEFAULT_PALETTE;
-    hLastRealizedPalette = STOCK_DEFAULT_PALETTE;
-
-    palPtr = (PALETTEOBJ*)GDI_GetObjPtr(STOCK_DEFAULT_PALETTE, PALETTE_MAGIC );
-    if (!palPtr) return 0;
-
-    /* lookup is needed to account for SetSystemPaletteUse() stuff */
-
-    return PALETTE_Driver->pUpdateMapping(palPtr);
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
 
 /***********************************************************************
@@ -738,8 +732,9 @@
     DC* dc = (DC *)GDI_GetObjPtr( hDC, DC_MAGIC );
     if (dc) 
     {
-      GDI_HEAP_UNLOCK( hDC );
-      return dc->w.hPalette == hPrimaryPalette;
+      BOOL bRet = dc->w.hPalette == hPrimaryPalette;
+      GDI_ReleaseObj( hDC );
+      return bRet;
     }
     return FALSE;
 }
@@ -798,11 +793,12 @@
 	/* Send palette change notification */
 
 	HWND hWnd;
+	GDI_ReleaseObj( hDC );
  	if( (hWnd = Callout.WindowFromDC( hDC )) )
             Callout.SendMessageA( HWND_BROADCAST, WM_PALETTECHANGED, hWnd, 0L);
     }
+    else GDI_ReleaseObj( hDC );
 
-    GDI_HEAP_UNLOCK( hDC );
     return realized;
 }
 
@@ -814,19 +810,19 @@
 {
     DC *dc;
     HWND hWnd;
+    int size;
 
     if (!(dc = (DC *) GDI_GetObjPtr( hDC, DC_MAGIC ))) return 0;
-
+    size = dc->w.devCaps->sizePalette;
+    GDI_ReleaseObj( hDC );    
     hWnd = Callout.WindowFromDC( hDC );
 
     /* Docs say that we have to remap current drawable pixel by pixel
      * but it would take forever given the speed of XGet/PutPixel.
      */
-    if (hWnd && dc->w.devCaps->sizePalette )
+    if (hWnd && size) 
         Callout.RedrawWindow( hWnd, NULL, 0, RDW_INVALIDATE );
 
-    GDI_HEAP_UNLOCK( hDC );
-
     return 0x666;
 }
 
diff --git a/objects/pen.c b/objects/pen.c
index 5fb6f08..09fcf66 100644
--- a/objects/pen.c
+++ b/objects/pen.c
@@ -54,16 +54,14 @@
 HPEN16 WINAPI CreatePenIndirect16( const LOGPEN16 * pen )
 {
     PENOBJ * penPtr;
-    HPEN16 hpen;
+    HPEN hpen;
 
     if (pen->lopnStyle > PS_INSIDEFRAME) return 0;
-    hpen = GDI_AllocObject( sizeof(PENOBJ), PEN_MAGIC );
-    if (!hpen) return 0;
-    penPtr = (PENOBJ *)GDI_HEAP_LOCK( hpen );
+    if (!(penPtr = GDI_AllocObject( sizeof(PENOBJ), PEN_MAGIC, &hpen ))) return 0;
     penPtr->logpen.lopnStyle = pen->lopnStyle;
     penPtr->logpen.lopnColor = pen->lopnColor;
     CONV_POINT16TO32( &pen->lopnWidth, &penPtr->logpen.lopnWidth );
-    GDI_HEAP_UNLOCK( hpen );
+    GDI_ReleaseObj( hpen );
     return hpen;
 }
 
@@ -77,13 +75,11 @@
     HPEN hpen;
 
     if (pen->lopnStyle > PS_INSIDEFRAME) return 0;
-    hpen = GDI_AllocObject( sizeof(PENOBJ), PEN_MAGIC );
-    if (!hpen) return 0;
-    penPtr = (PENOBJ *)GDI_HEAP_LOCK( hpen );
+    if (!(penPtr = GDI_AllocObject( sizeof(PENOBJ), PEN_MAGIC, &hpen ))) return 0;
     penPtr->logpen.lopnStyle = pen->lopnStyle;
     penPtr->logpen.lopnWidth = pen->lopnWidth;
     penPtr->logpen.lopnColor = pen->lopnColor;
-    GDI_HEAP_UNLOCK( hpen );
+    GDI_ReleaseObj( hpen );
     return hpen;
 }
 
@@ -106,9 +102,7 @@
 	if (brush->lbHatch)
 	    FIXME("Hatches not implemented\n");
 
-    hpen = GDI_AllocObject( sizeof(PENOBJ), PEN_MAGIC );
-    if (!hpen) return 0;
-    penPtr = (PENOBJ *)GDI_HEAP_LOCK( hpen );
+    if (!(penPtr = GDI_AllocObject( sizeof(PENOBJ), PEN_MAGIC, &hpen ))) return 0;
     penPtr->logpen.lopnStyle = style & ~PS_TYPE_MASK; 
     
     /* PS_USERSTYLE and PS_ALTERNATE workaround */   
@@ -119,7 +113,7 @@
     penPtr->logpen.lopnWidth.x = (style & PS_GEOMETRIC) ? width : 1; 
     penPtr->logpen.lopnWidth.y = 0;
     penPtr->logpen.lopnColor = brush->lbColor;
-    GDI_HEAP_UNLOCK( hpen );
+    GDI_ReleaseObj( hpen );
 
     return hpen;
 }
diff --git a/objects/region.c b/objects/region.c
index e644a88..d4d28f7 100644
--- a/objects/region.c
+++ b/objects/region.c
@@ -457,14 +457,12 @@
     HRGN hrgn;
     RGNOBJ *obj;
 
-    if(!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC )))
-        return 0;
-    obj = (RGNOBJ *) GDI_HEAP_LOCK( hrgn );
+    if(!(obj = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC, &hrgn ))) return 0;
     if(!(obj->rgn = REGION_AllocWineRegion(n))) {
-        GDI_FreeObject( hrgn );
+        GDI_FreeObject( hrgn, obj );
         return 0;
     }
-    GDI_HEAP_UNLOCK( hrgn );
+    GDI_ReleaseObj( hrgn );
     return hrgn;
 }
 
@@ -487,7 +485,7 @@
     TRACE(" %04x\n", hrgn );
 
     REGION_DestroyWineRegion( obj->rgn );
-    return GDI_FreeObject( hrgn );
+    return GDI_FreeObject( hrgn, obj );
 }
 
 /***********************************************************************
@@ -530,7 +528,7 @@
 	}
     }
     ret = obj->rgn->type;
-    GDI_HEAP_UNLOCK( hrgn );
+    GDI_ReleaseObj( hrgn );
     return ret;
 }
 
@@ -561,7 +559,7 @@
 	rect->right = obj->rgn->extents.right;
 	rect->bottom = obj->rgn->extents.bottom;
 	ret = obj->rgn->type;
-	GDI_HEAP_UNLOCK(hrgn);
+	GDI_ReleaseObj(hrgn);
 	return ret;
     }
     return ERROR;
@@ -664,7 +662,7 @@
     else
 	EMPTY_REGION(obj->rgn);
 
-    GDI_HEAP_UNLOCK( hrgn );
+    GDI_ReleaseObj( hrgn );
     return TRUE;
 }
 
@@ -717,7 +715,7 @@
 
     d = (ellipse_height < 128) ? ((3 * ellipse_height) >> 2) : 64;
     if (!(hrgn = REGION_CreateRegion(d))) return 0;
-    obj = (RGNOBJ *) GDI_HEAP_LOCK( hrgn );
+    if (!(obj = GDI_GetObjPtr( hrgn, REGION_MAGIC ))) return 0;
     TRACE("(%d,%d-%d,%d %dx%d): ret=%04x\n",
 	  left, top, right, bottom, ellipse_width, ellipse_height, hrgn );
 
@@ -792,7 +790,7 @@
 	REGION_UnionRectWithRegion( &rect, obj->rgn );
     }
     obj->rgn->type = SIMPLEREGION; /* FIXME? */
-    GDI_HEAP_UNLOCK( hrgn );
+    GDI_ReleaseObj( hrgn );
     return hrgn;
 }
 
@@ -857,7 +855,7 @@
     size = obj->rgn->numRects * sizeof(RECT);
     if(count < (size + sizeof(RGNDATAHEADER)) || rgndata == NULL)
     {
-        GDI_HEAP_UNLOCK( hrgn );
+        GDI_ReleaseObj( hrgn );
         return size + sizeof(RGNDATAHEADER);
     }
 
@@ -872,7 +870,7 @@
 
     memcpy( rgndata->Buffer, obj->rgn->rects, size );
 
-    GDI_HEAP_UNLOCK( hrgn );
+    GDI_ReleaseObj( hrgn );
     return 1;
 }
 
@@ -912,13 +910,16 @@
 	RECT *pCurRect, *pEndRect;
 	RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC );
 
-	pEndRect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount;
-	for(pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
-	    REGION_UnionRectWithRegion( pCurRect, obj->rgn );
-	GDI_HEAP_UNLOCK( hrgn );
+	if (obj) {
+            pEndRect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount;
+            for(pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
+                REGION_UnionRectWithRegion( pCurRect, obj->rgn );
+	    GDI_ReleaseObj( hrgn );
 
-	TRACE("%04x\n", hrgn );
-	return hrgn;
+            TRACE("%04x\n", hrgn );
+            return hrgn;
+        }
+	else ERR("Could not get pointer to newborn Region!");
     }
 fail:
     WARN("Failed\n");
@@ -940,20 +941,22 @@
 BOOL WINAPI PtInRegion( HRGN hrgn, INT x, INT y )
 {
     RGNOBJ * obj;
+    BOOL ret = FALSE;
     
     if ((obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC )))
     {
-	BOOL ret = FALSE;
 	int i;
 
 	if (obj->rgn->numRects > 0 && INRECT(obj->rgn->extents, x, y))
 	    for (i = 0; i < obj->rgn->numRects; i++)
 		if (INRECT (obj->rgn->rects[i], x, y))
+                {
 		    ret = TRUE;
-	GDI_HEAP_UNLOCK( hrgn );
-	return ret;
+                    break;
+                }
+	GDI_ReleaseObj( hrgn );
     }
-    return FALSE;
+    return ret;
 }
 
 
@@ -977,11 +980,11 @@
 BOOL WINAPI RectInRegion( HRGN hrgn, const RECT *rect )
 {
     RGNOBJ * obj;
+    BOOL ret = FALSE;
     
     if ((obj = (RGNOBJ *) GDI_GetObjPtr( hrgn, REGION_MAGIC )))
     {
 	RECT *pCurRect, *pRectEnd;
-	BOOL ret = FALSE;
     
     /* this is (just) a useful optimization */
 	if ((obj->rgn->numRects > 0) && EXTENTCHECK(&obj->rgn->extents,
@@ -993,10 +996,8 @@
 	        if (pCurRect->bottom <= rect->top)
 		    continue;             /* not far enough down yet */
 
-		if (pCurRect->top >= rect->bottom) {
-		    ret = FALSE;          /* too far down */
-		    break;
-		}
+		if (pCurRect->top >= rect->bottom)
+		    break;                /* too far down */
 
 		if (pCurRect->right <= rect->left)
 		    continue;              /* not far enough over yet */
@@ -1009,10 +1010,9 @@
 		break;
 	    }
 	}
-	GDI_HEAP_UNLOCK(hrgn);
-	return ret;
+	GDI_ReleaseObj(hrgn);
     }
-    return FALSE;
+    return ret;
 }
 
 /***********************************************************************
@@ -1058,9 +1058,9 @@
 	    }
             ret = TRUE;
         done:
-	    GDI_HEAP_UNLOCK(hrgn2);
+	    GDI_ReleaseObj(hrgn2);
 	}
-	GDI_HEAP_UNLOCK(hrgn1);
+	GDI_ReleaseObj(hrgn1);
     }
     return ret;
 }
@@ -1093,7 +1093,7 @@
 
     if(!obj) return FALSE;
     REGION_UnionRectWithRegion( lpRect, obj->rgn );
-    GDI_HEAP_UNLOCK(hrgn);
+    GDI_ReleaseObj(hrgn);
     return TRUE;
 }
 
@@ -1108,6 +1108,7 @@
     BOOL bRet;
     RGNOBJ *srcObj = (RGNOBJ*) GDI_GetObjPtr( hSrc, REGION_MAGIC );
 
+    if (!srcObj) return FALSE;
     if (srcObj->rgn->numRects != 0) 
     {
 	RGNOBJ* destObj = (RGNOBJ*) GDI_GetObjPtr( hDest, REGION_MAGIC );
@@ -1126,12 +1127,12 @@
 	    REGION_UnionRectWithRegion( &tempRect, destObj->rgn );
 	}
 	REGION_SubtractRegion( destObj->rgn, destObj->rgn, srcObj->rgn );
-	GDI_HEAP_UNLOCK ( hDest );
+	GDI_ReleaseObj ( hDest );
 	bRet = TRUE;
     }
     else
 	bRet = FALSE;
-    GDI_HEAP_UNLOCK( hSrc );
+    GDI_ReleaseObj( hSrc );
     return bRet;
 }
 
@@ -1146,24 +1147,27 @@
     RGNOBJ *srcObj, *destObj;
     DC * dc = DC_GetDCPtr( hdc );
     RECT tmpRect;
+    BOOL ret = FALSE;
 
     TRACE(" hdc=%04x dest=%04x src=%04x\n",
 	  hdc, hDest, hSrc) ;
+    if (!dc) return ret;
     
     if (dc->w.MapMode == MM_TEXT) /* Requires only a translation */
     {
-        if( CombineRgn( hDest, hSrc, 0, RGN_COPY ) == ERROR ) return FALSE;
+        if( CombineRgn( hDest, hSrc, 0, RGN_COPY ) == ERROR ) goto done;
 	OffsetRgn( hDest, dc->vportOrgX - dc->wndOrgX, 
 		     dc->vportOrgY - dc->wndOrgY );
-	return TRUE;
+	ret = TRUE;
+        goto done;
     }
 
     if(!( srcObj = (RGNOBJ *) GDI_GetObjPtr( hSrc, REGION_MAGIC) ))
-        return FALSE;
+        goto done;
     if(!( destObj = (RGNOBJ *) GDI_GetObjPtr( hDest, REGION_MAGIC) ))
     {
-        GDI_HEAP_UNLOCK( hSrc );
-        return FALSE;
+        GDI_ReleaseObj( hSrc );
+        goto done;
     }
     EMPTY_REGION( destObj->rgn );
 
@@ -1178,9 +1182,11 @@
 	REGION_UnionRectWithRegion( &tmpRect, destObj->rgn );
     }
     
-    GDI_HEAP_UNLOCK( hDest );
-    GDI_HEAP_UNLOCK( hSrc );
-    return TRUE;
+    GDI_ReleaseObj( hDest );
+    GDI_ReleaseObj( hSrc );
+ done:
+    GDI_ReleaseObj( hdc );
+    return ret;
 }
     
 /***********************************************************************
@@ -1243,16 +1249,16 @@
 			break;
 		    }
 		    result = destObj->rgn->type;
-		    GDI_HEAP_UNLOCK( hSrc2 );
+		    GDI_ReleaseObj( hSrc2 );
 		}
 	    }
-	    GDI_HEAP_UNLOCK( hSrc1 );
+	    GDI_ReleaseObj( hSrc1 );
 	}
 	TRACE("dump:\n");
 	if(TRACE_ON(region)) 
 	  REGION_DumpRegion(destObj->rgn);
 
-	GDI_HEAP_UNLOCK( hDest );
+	GDI_ReleaseObj( hDest );
     } else {
        ERR("Invalid rgn=%04x\n", hDest);
     }
@@ -2714,7 +2720,7 @@
     {
         SetRectRgn( hrgn, min(Pts[0].x, Pts[2].x), min(Pts[0].y, Pts[2].y), 
 		            max(Pts[0].x, Pts[2].x), max(Pts[0].y, Pts[2].y) );
-	GDI_HEAP_UNLOCK( hrgn );
+	GDI_ReleaseObj( hrgn );
 	return hrgn;
     }
     
@@ -2811,6 +2817,7 @@
 					       sizeof(POINTBLOCK) );
 			if(!tmpPtBlock) {
 			    WARN("Can't alloc tPB\n");
+			    REGION_DeleteObject( hrgn, obj );
 			    return 0;
 			}
                         curPtBlock->next = tmpPtBlock;
@@ -2845,7 +2852,7 @@
 	curPtBlock = tmpPtBlock;
     }
     HeapFree( GetProcessHeap(), 0, pETEs );
-    GDI_HEAP_UNLOCK( hrgn );
+    GDI_ReleaseObj( hrgn );
     return hrgn;
 }
 
@@ -2910,6 +2917,8 @@
 	    DC *dc = DC_GetDCPtr (hDC);
 	    OSVERSIONINFOA vi;
 	    POINT org;
+
+	    if (!dc) return -1;
 	    CombineRgn (hRgn, dc->w.hVisRgn, 0, RGN_COPY);
 	    /*
 	     *     On Windows NT/2000,
@@ -2925,7 +2934,7 @@
 	    org.x -= dc->w.DCOrgX;
 	    org.y -= dc->w.DCOrgY;
 	    OffsetRgn (hRgn, org.x, org.y);
-		
+            GDI_ReleaseObj( hDC );
 	    return 1;
 	}
 /*	case 1:
@@ -3167,7 +3176,7 @@
 	    {
 		if( hDst ) /* existing rgn */
 		{
-		    GDI_HEAP_UNLOCK(hDst);
+		    GDI_ReleaseObj(hDst);
 		    hDst = 0;
 		    goto done;
 		}
@@ -3175,7 +3184,7 @@
 	    }
 	    else if( hDst == 0 )
 	    {
-		if(!(hDst = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC )))
+		if (!(objDst = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC, &hDst )))
 		{
 fail:
 		    if( rgnDst->rects )
@@ -3183,16 +3192,14 @@
 		    HeapFree( GetProcessHeap(), 0, rgnDst );
 		    goto done;
 		}
-
-		objDst = (RGNOBJ *) GDI_HEAP_LOCK( hDst );
 		objDst->rgn = rgnDst;
 	    }
 
-	    GDI_HEAP_UNLOCK(hDst);
+	    GDI_ReleaseObj(hDst);
 	}
 	else hDst = 0;
 done:
-	GDI_HEAP_UNLOCK(hSrc);
+	GDI_ReleaseObj(hSrc);
 	return hDst;
     }
     return 0;
diff --git a/objects/text.c b/objects/text.c
index b5b7cdf..99b9e23 100644
--- a/objects/text.c
+++ b/objects/text.c
@@ -92,9 +92,15 @@
                              const RECT *lprect, LPCWSTR str, UINT count,
                              const INT *lpDx )
 {
-    DC * dc = DC_GetDCPtr( hdc );
-    return dc && dc->funcs->pExtTextOut && 
-        dc->funcs->pExtTextOut(dc,x,y,flags,lprect,str,count,lpDx);
+    BOOL ret = FALSE;
+    DC * dc = DC_GetDCUpdate( hdc );
+    if (dc)
+    {
+	if(dc->funcs->pExtTextOut)
+	    ret = dc->funcs->pExtTextOut(dc,x,y,flags,lprect,str,count,lpDx);
+	GDI_ReleaseObj( hdc );
+    }
+    return ret;
 }
 
 
diff --git a/windows/cursoricon.c b/windows/cursoricon.c
index 437be3a..e025cdd 100644
--- a/windows/cursoricon.c
+++ b/windows/cursoricon.c
@@ -613,8 +613,8 @@
 	GlobalUnlock16( hObj );
     }
 
-    DeleteObject( hXorBits );
     DeleteObject( hAndBits );
+    DeleteObject( hXorBits );
     return hObj;
 }
 
@@ -1897,7 +1897,7 @@
 {
     CURSORICONINFO *ptr = (CURSORICONINFO *)GlobalLock16 (hIcon);
     HDC hDC_off = 0, hMemDC = CreateCompatibleDC (hdc);
-    BOOL result = FALSE, DoOffscreen = FALSE;
+    BOOL result = FALSE, DoOffscreen;
     HBITMAP hB_off = 0, hOld = 0;
 
     if (!ptr) return FALSE;
@@ -1923,17 +1923,8 @@
 	cyWidth = ptr->nHeight;
     }
 
-    if (!(DoOffscreen = (hbr >= STOCK_WHITE_BRUSH) && (hbr <= 
-      STOCK_HOLLOW_BRUSH)))
-    {
-	GDIOBJHDR *object = (GDIOBJHDR *) GDI_HEAP_LOCK(hbr);
-	if (object)
-	{
-	    UINT16 magic = object->wMagic;
-	    GDI_HEAP_UNLOCK(hbr);
-	    DoOffscreen = magic == BRUSH_MAGIC;
-	}
-    }
+    DoOffscreen = (GetObjectType( hbr ) == OBJ_BRUSH);
+
     if (DoOffscreen) {
       RECT r;
 
@@ -1948,7 +1939,7 @@
 	hOld = SelectObject(hDC_off, hB_off);
 	FillRect(hDC_off, &r, hbr);
       }
-    };
+    }
 
     if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
     {
diff --git a/windows/dce.c b/windows/dce.c
index d6492e2..a49d2c7 100644
--- a/windows/dce.c
+++ b/windows/dce.c
@@ -603,7 +603,7 @@
 
     OffsetRgn( hVisRgn, dc->w.DCOrgX, dc->w.DCOrgY );
 
-    GDI_HEAP_UNLOCK( hDC );
+    GDI_ReleaseObj( hDC );
 }
 
 /***********************************************************************
@@ -807,6 +807,8 @@
 
     /* recompute visible region */
     wndPtr->pDriver->pSetDrawable( wndPtr, hdc, flags, bUpdateClipOrigin );
+    dc->w.flags &= ~DC_DIRTY;
+    GDI_ReleaseObj( hdc );
 
     if( bUpdateVisRgn )
     {
@@ -846,7 +848,6 @@
                 DCE_OffsetVisRgn( hdc, hrgnVisible );
             }
 
-	dc->w.flags &= ~DC_DIRTY;
 	dce->DCXflags &= ~DCX_DCEDIRTY;
 	SelectVisRgn16( hdc, hrgnVisible );
     }
@@ -999,7 +1000,7 @@
 
                /* Update stale DC in DCX */
                wndPtr = WIN_FindWndPtr( dce->hwndCurrent);
-	       if (wndPtr) wndPtr->pDriver->pSetDrawable( wndPtr, hDC, dce->DCXflags, TRUE);
+	       if (wndPtr) wndPtr->pDriver->pSetDrawable( wndPtr, dce->hDC, dce->DCXflags, TRUE);
 
 	       SetHookFlags16(hDC, DCHF_VALIDATEVISRGN);
 	       hVisRgn = DCE_GetVisRgn(dce->hwndCurrent, dce->DCXflags, 0, 0);
diff --git a/windows/scroll.c b/windows/scroll.c
index 9bc803c..4eb1760 100644
--- a/windows/scroll.c
+++ b/windows/scroll.c
@@ -81,7 +81,7 @@
 {
     RECT rect, rClip, rSrc;
     POINT src, dest;
-    DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
+    DC *dc = DC_GetDCUpdate( hdc );
 
     TRACE("%04x %d,%d hrgnUpdate=%04x rcUpdate = %p cliprc = (%d,%d-%d,%d), rc=(%d,%d-%d,%d)\n",
                    (HDC16)hdc, dx, dy, hrgnUpdate, rcUpdate, 
@@ -126,7 +126,7 @@
                            rSrc.right - rSrc.left, rSrc.bottom - rSrc.top,
                            hdc, src.x, src.y, SRCCOPY))
             {
-                GDI_HEAP_UNLOCK( hdc );
+                GDI_ReleaseObj( hdc );
                 return FALSE;
             }
         }
@@ -171,7 +171,7 @@
        if (rcUpdate) SetRectEmpty(rcUpdate);
     }
 
-    GDI_HEAP_UNLOCK( hdc );
+    GDI_ReleaseObj( hdc );
     return TRUE;
 }
 
@@ -254,7 +254,6 @@
 
     if (!IsRectEmpty(&cliprc) && (dx || dy))
     {
-	DC*	dc;
 	HDC	hDC;
 	BOOL  bUpdate = (rcUpdate || hrgnUpdate || flags & (SW_INVALIDATE | SW_ERASE));
 	HRGN  hrgnClip = CreateRectRgnIndirect(&cliprc);
@@ -276,13 +275,15 @@
 	hDC = GetDCEx( hwnd, hrgnClip, DCX_CACHE | DCX_USESTYLE |
                          DCX_KEEPCLIPRGN | DCX_INTERSECTRGN |
 		       ((flags & SW_SCROLLCHILDREN) ? DCX_NOCLIPCHILDREN : 0) );
-	if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
+	if (hDC)
 	{
-            if (dc->w.hVisRgn) {
                 wnd->pDriver->pSurfaceCopy(wnd,hDC,dx,dy,&rc,bUpdate);
-
                 if( bUpdate )
                     {
+                DC*	dc;
+
+                if( (dc = DC_GetDCPtr(hDC)) )
+                {
                         OffsetRgn( hrgnTemp, dc->w.DCOrgX, dc->w.DCOrgY );
                         CombineRgn( hrgnTemp, hrgnTemp, dc->w.hVisRgn,
                                       RGN_AND );
@@ -295,10 +296,10 @@
                                           RGN_DIFF );
 
                         if( rcUpdate ) GetRgnBox( hrgnUpdate, rcUpdate );
+                        GDI_ReleaseObj( hDC );
                     }
             }
             ReleaseDC(hwnd, hDC);
-            GDI_HEAP_UNLOCK( hDC );
         }
 
 	if( wnd->hrgnUpdate > 1 )
diff --git a/windows/user.c b/windows/user.c
index 4cfa2e1..3eea645 100644
--- a/windows/user.c
+++ b/windows/user.c
@@ -12,7 +12,6 @@
 #include "winuser.h"
 #include "heap.h"
 #include "user.h"
-#include "gdi.h"
 #include "task.h"
 #include "queue.h"
 #include "class.h"
@@ -43,8 +42,13 @@
  */
 WORD WINAPI GetFreeSystemResources16( WORD resType )
 {
+    HINSTANCE16 gdi_inst;
+    WORD gdi_heap;
     int userPercent, gdiPercent;
 
+    if ((gdi_inst = LoadLibrary16( "GDI" )) < 32) return 0;
+    gdi_heap = GlobalHandleToSel16( gdi_inst );
+
     switch(resType)
     {
     case GFSR_USERRESOURCES:
@@ -54,21 +58,23 @@
         break;
 
     case GFSR_GDIRESOURCES:
-        gdiPercent  = (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
-                               LOCAL_HeapSize( GDI_HeapSel );
+        gdiPercent  = (int)LOCAL_CountFree( gdi_inst ) * 100 /
+                               LOCAL_HeapSize( gdi_inst );
         userPercent = 100;
         break;
 
     case GFSR_SYSTEMRESOURCES:
         userPercent = (int)LOCAL_CountFree( USER_HeapSel ) * 100 /
                                LOCAL_HeapSize( USER_HeapSel );
-        gdiPercent  = (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
-                               LOCAL_HeapSize( GDI_HeapSel );
+        gdiPercent  = (int)LOCAL_CountFree( gdi_inst ) * 100 /
+                               LOCAL_HeapSize( gdi_inst );
         break;
 
     default:
-        return 0;
+        userPercent = gdiPercent = 0;
+        break;
     }
+    FreeLibrary16( gdi_inst );
     return (WORD)min( userPercent, gdiPercent );
 }
 
diff --git a/windows/x11drv/wnd.c b/windows/x11drv/wnd.c
index eec3008..fecf53c 100644
--- a/windows/x11drv/wnd.c
+++ b/windows/x11drv/wnd.c
@@ -890,10 +890,10 @@
                  dst.x, dst.y );
     if (bUpdate)
 	TSXSetGraphicsExposures( display, physDev->gc, False );
+    GDI_ReleaseObj( hdc );
 
     if (bUpdate) /* Make sure exposure events have been processed */
 	EVENT_Synchronize();
-    GDI_HEAP_UNLOCK( hdc );
 }
 
 /***********************************************************************
@@ -975,7 +975,7 @@
 	    TSXSetClipOrigin( display, physDev->gc, dc->w.DCOrgX, dc->w.DCOrgY );
 #endif
     }
-    GDI_HEAP_UNLOCK( hdc );
+    GDI_ReleaseObj( hdc );
 }
 
 /***********************************************************************