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 );