Pass a PHYSDEV to EnumDeviceFont and release the GDI lock in
FONT_EnumInstance instead.

diff --git a/dlls/gdi/win16drv/font.c b/dlls/gdi/win16drv/font.c
index 73fc73c..6af457a 100644
--- a/dlls/gdi/win16drv/font.c
+++ b/dlls/gdi/win16drv/font.c
@@ -194,22 +194,16 @@
  *           WIN16DRV_EnumDeviceFonts
  */
 
-BOOL	WIN16DRV_EnumDeviceFonts( HDC hdc, LPLOGFONTW plf, 
-				  DEVICEFONTENUMPROC proc, LPARAM lp )
+BOOL WIN16DRV_EnumDeviceFonts( PHYSDEV dev, LPLOGFONTW plf,
+                               DEVICEFONTENUMPROC proc, LPARAM lp )
 {
-    WIN16DRV_PDEVICE *physDev;
+    WIN16DRV_PDEVICE *physDev = (WIN16DRV_PDEVICE *)dev;
     WORD wRet;
     WEPFC wepfc;
-    DC *dc;
     char *FaceNameA = NULL;
    /* EnumDFontCallback is GDI.158 */
     FARPROC16 pfnCallback = GetProcAddress16( GetModuleHandle16("GDI"), (LPCSTR)158 );
 
-    if (!(dc = DC_GetDCPtr( hdc ))) return 0;
-    physDev = (WIN16DRV_PDEVICE *)dc->physDev;
-    /* FIXME!! */
-    GDI_ReleaseObj( hdc );
-
     wepfc.proc = proc;
     wepfc.lp = lp;
 
diff --git a/dlls/gdi/win16drv/win16drv.h b/dlls/gdi/win16drv/win16drv.h
index dbf9439..0b56d5f 100644
--- a/dlls/gdi/win16drv/win16drv.h
+++ b/dlls/gdi/win16drv/win16drv.h
@@ -279,7 +279,8 @@
 extern BOOL WIN16DRV_PatBlt( PHYSDEV dev, INT left, INT top,
                                INT width, INT height, DWORD rop );
 extern BOOL WIN16DRV_Ellipse(PHYSDEV dev, INT left, INT top, INT right, INT bottom);
-extern BOOL WIN16DRV_EnumDeviceFonts( HDC hdc, LPLOGFONTW plf, DEVICEFONTENUMPROC proc, LPARAM lp );
+extern BOOL WIN16DRV_EnumDeviceFonts( PHYSDEV dev, LPLOGFONTW plf,
+                                      DEVICEFONTENUMPROC proc, LPARAM lp );
 
 extern INT WIN16DRV_ExtDeviceMode(LPSTR lpszDriver, HWND hwnd,
 				  LPDEVMODEA lpdmOutput,
diff --git a/dlls/wineps/font.c b/dlls/wineps/font.c
index 2c09aeb..84b7598 100644
--- a/dlls/wineps/font.c
+++ b/dlls/wineps/font.c
@@ -386,8 +386,8 @@
 /***********************************************************************
  *           PSDRV_GetFontMetric
  */
-static UINT PSDRV_GetFontMetric(HDC hdc, const AFM *afm,
-    	NEWTEXTMETRICEXW *ntmx, ENUMLOGFONTEXW *elfx)
+static UINT PSDRV_GetFontMetric( PSDRV_PDEVICE *physDev, const AFM *afm,
+                                 NEWTEXTMETRICEXW *ntmx, ENUMLOGFONTEXW *elfx)
 {
     /* ntmx->ntmTm is NEWTEXTMETRICW; compatible w/ TEXTMETRICW per Win32 doc */
 
@@ -417,7 +417,7 @@
 /***********************************************************************
  *           PSDRV_EnumDeviceFonts
  */
-BOOL PSDRV_EnumDeviceFonts( HDC hdc, LPLOGFONTW plf, 
+BOOL PSDRV_EnumDeviceFonts( PSDRV_PDEVICE *physDev, LPLOGFONTW plf,
 			    DEVICEFONTENUMPROC proc, LPARAM lp )
 {
     ENUMLOGFONTEXW	lf;
@@ -425,14 +425,7 @@
     BOOL	  	b, bRet = 0;
     AFMLISTENTRY	*afmle;
     FONTFAMILY		*family;
-    PSDRV_PDEVICE	*physDev;
     char                FaceName[LF_FACESIZE];
-    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] ) {
         WideCharToMultiByte(CP_ACP, 0, plf->lfFaceName, -1,
@@ -446,9 +439,7 @@
 	if(family) {
 	    for(afmle = family->afmlist; afmle; afmle = afmle->next) {
 	        TRACE("Got '%s'\n", afmle->afm->FontName);
-		if( (b = (*proc)( &lf, &tm, 
-			PSDRV_GetFontMetric( hdc, afmle->afm, &tm, &lf ),
-				  lp )) )
+		if( (b = proc( &lf, &tm, PSDRV_GetFontMetric(physDev, afmle->afm, &tm, &lf), lp )) )
 		     bRet = b;
 		else break;
 	    }
@@ -459,9 +450,7 @@
         for(family = physDev->pi->Fonts; family; family = family->next) {
 	    afmle = family->afmlist;
 	    TRACE("Got '%s'\n", afmle->afm->FontName);
-	    if( (b = (*proc)( &lf, &tm, 
-		   PSDRV_GetFontMetric( hdc, afmle->afm, &tm, &lf ), 
-			      lp )) )
+	    if( (b = proc( &lf, &tm, PSDRV_GetFontMetric(physDev, afmle->afm, &tm, &lf), lp )) )
 	        bRet = b;
 	    else break;
 	}
diff --git a/dlls/wineps/psdrv.h b/dlls/wineps/psdrv.h
index 3a6ff72..4ed007c 100644
--- a/dlls/wineps/psdrv.h
+++ b/dlls/wineps/psdrv.h
@@ -401,7 +401,7 @@
 			     INT bottom );
 extern INT PSDRV_EndDoc( PSDRV_PDEVICE *physDev );
 extern INT PSDRV_EndPage( PSDRV_PDEVICE *physDev );
-extern BOOL PSDRV_EnumDeviceFonts( HDC hdc, LPLOGFONTW plf, 
+extern BOOL PSDRV_EnumDeviceFonts( PSDRV_PDEVICE *physDev, LPLOGFONTW plf,
 				   DEVICEFONTENUMPROC proc, LPARAM lp );
 extern BOOL PSDRV_ExtTextOut( PSDRV_PDEVICE *physDev, INT x, INT y, UINT flags,
 				const RECT *lprect, LPCWSTR str, UINT count,
diff --git a/dlls/wineps/wineps.spec b/dlls/wineps/wineps.spec
index be7bbb8..d9440a2 100644
--- a/dlls/wineps/wineps.spec
+++ b/dlls/wineps/wineps.spec
@@ -22,7 +22,7 @@
 @ cdecl Ellipse(ptr long long long long) PSDRV_Ellipse
 @ cdecl EndDoc(ptr) PSDRV_EndDoc
 @ cdecl EndPage(ptr) PSDRV_EndPage
-@ cdecl EnumDeviceFonts(long ptr ptr long) PSDRV_EnumDeviceFonts
+@ cdecl EnumDeviceFonts(ptr ptr ptr long) PSDRV_EnumDeviceFonts
 @ cdecl ExtDeviceMode(ptr long ptr ptr ptr ptr ptr long) PSDRV_ExtDeviceMode
 @ cdecl ExtEscape(ptr long long ptr long ptr) PSDRV_ExtEscape
 @ cdecl ExtTextOut(ptr long long long ptr ptr long ptr) PSDRV_ExtTextOut
diff --git a/dlls/x11drv/x11drv.spec b/dlls/x11drv/x11drv.spec
index 49978b0..d305a9a 100644
--- a/dlls/x11drv/x11drv.spec
+++ b/dlls/x11drv/x11drv.spec
@@ -25,7 +25,7 @@
 @ cdecl DeleteObject(long) X11DRV_DeleteObject
 @ cdecl DescribePixelFormat(ptr long long ptr) X11DRV_DescribePixelFormat
 @ cdecl Ellipse(ptr long long long long) X11DRV_Ellipse
-@ cdecl EnumDeviceFonts(long ptr ptr long) X11DRV_EnumDeviceFonts
+@ cdecl EnumDeviceFonts(ptr ptr ptr long) X11DRV_EnumDeviceFonts
 @ cdecl ExtEscape(ptr long long ptr long ptr) X11DRV_ExtEscape
 @ cdecl ExtFloodFill(ptr long long long long) X11DRV_ExtFloodFill
 @ cdecl ExtTextOut(ptr long long long ptr ptr long ptr) X11DRV_ExtTextOut
diff --git a/graphics/x11drv/xfont.c b/graphics/x11drv/xfont.c
index ab81a5e..8297a1b 100644
--- a/graphics/x11drv/xfont.c
+++ b/graphics/x11drv/xfont.c
@@ -3313,23 +3313,17 @@
  *
  *           X11DRV_EnumDeviceFonts
  */
-BOOL X11DRV_EnumDeviceFonts( HDC hdc, LPLOGFONTW plf, 
+BOOL X11DRV_EnumDeviceFonts( X11DRV_PDEVICE *physDev, LPLOGFONTW plf,
 			     DEVICEFONTENUMPROC proc, LPARAM lp )
 {
     ENUMLOGFONTEXW	lf;
     NEWTEXTMETRICEXW	tm;
     fontResource*	pfr = fontList;
-    BOOL	  	b, bRet = 0, using_gdi = 0;
+    BOOL	  	b, bRet = 0;
     LOGFONT16           lf16;
-    DC *dc;
-
-    dc = DC_GetDCPtr(hdc);
-    if(!dc) return FALSE;
-    if(dc->gdiFont) using_gdi = TRUE;
-    GDI_ReleaseObj(hdc);
 
     /* don't enumerate x11 fonts if we're using client side fonts */
-    if(using_gdi) return FALSE;
+    if (physDev->dc->gdiFont) return FALSE;
 
     FONT_LogFontWTo16(plf, &lf16);
 
diff --git a/include/gdi.h b/include/gdi.h
index 58052f3..38eaf36 100644
--- a/include/gdi.h
+++ b/include/gdi.h
@@ -162,7 +162,7 @@
     INT      (*pEndDoc)(PHYSDEV);
     INT      (*pEndPage)(PHYSDEV);
     BOOL     (*pEndPath)(PHYSDEV);
-    BOOL     (*pEnumDeviceFonts)(HDC,LPLOGFONTW,DEVICEFONTENUMPROC,LPARAM);
+    BOOL     (*pEnumDeviceFonts)(PHYSDEV,LPLOGFONTW,DEVICEFONTENUMPROC,LPARAM);
     INT      (*pExcludeClipRect)(PHYSDEV,INT,INT,INT,INT);
     INT      (*pExtDeviceMode)(LPSTR,HWND,LPDEVMODEA,LPSTR,LPSTR,LPDEVMODEA,LPSTR,DWORD);
     INT      (*pExtEscape)(PHYSDEV,INT,INT,LPCVOID,INT,LPVOID);
diff --git a/include/x11drv.h b/include/x11drv.h
index 4331815..83037b3 100644
--- a/include/x11drv.h
+++ b/include/x11drv.h
@@ -108,7 +108,7 @@
 extern BOOL X11DRV_BitBlt( X11DRV_PDEVICE *physDevDst, INT xDst, INT yDst,
                              INT width, INT height, X11DRV_PDEVICE *physDevSrc,
                              INT xSrc, INT ySrc, DWORD rop );
-extern BOOL X11DRV_EnumDeviceFonts( HDC hdc, LPLOGFONTW plf,
+extern BOOL X11DRV_EnumDeviceFonts( X11DRV_PDEVICE *physDev, LPLOGFONTW plf,
 				    DEVICEFONTENUMPROC dfeproc, LPARAM lp );
 extern BOOL X11DRV_GetCharWidth( X11DRV_PDEVICE *physDev, UINT firstChar,
                                    UINT lastChar, LPINT buffer );
diff --git a/objects/font.c b/objects/font.c
index ecadda5..17ecc9f 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -46,6 +46,9 @@
   LPENUMLOGFONTEX16     lpLogFont;
   SEGPTR                segTextMetric;
   SEGPTR                segLogFont;
+  HDC                   hdc;
+  DC                   *dc;
+  PHYSDEV               physDev;
 } fontEnum16;
 
 typedef struct
@@ -54,6 +57,9 @@
   FONTENUMPROCEXW     lpEnumFunc;
   LPARAM              lpData;
   DWORD               dwFlags;
+  HDC                 hdc;
+  DC                 *dc;
+  PHYSDEV             physDev;
 } fontEnum32;
  
 /*
@@ -642,18 +648,29 @@
 static INT FONT_EnumInstance16( LPENUMLOGFONTEXW plf, LPNEWTEXTMETRICEXW ptm,
 				DWORD fType, LPARAM lp )
 {
-#define pfe ((fontEnum16*)lp)
+    fontEnum16 *pfe = (fontEnum16*)lp;
+    INT ret = 1;
+    DC *dc;
+
     if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET || 
 	pfe->lpLogFontParam->lfCharSet == plf->elfLogFont.lfCharSet )
     {
         FONT_EnumLogFontExWTo16(plf, pfe->lpLogFont);
 	FONT_NewTextMetricExWTo16(ptm, pfe->lpTextMetric);
+        GDI_ReleaseObj( pfe->hdc );  /* release the GDI lock */
 
-        return FONT_CallTo16_word_llwl( pfe->lpEnumFunc, pfe->segLogFont, pfe->segTextMetric,
-                                        (UINT16)fType, (LPARAM)pfe->lpData );
+        ret = FONT_CallTo16_word_llwl( pfe->lpEnumFunc, pfe->segLogFont, pfe->segTextMetric,
+                                       (UINT16)fType, (LPARAM)pfe->lpData );
+        /* get the lock again and make sure the DC is still valid */
+        dc = DC_GetDCPtr( pfe->hdc );
+        if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
+        {
+            if (dc) GDI_ReleaseObj( pfe->hdc );
+            pfe->hdc = 0;  /* make sure we don't try to release it later on */
+            ret = 0;
+        }
     }
-#undef pfe
-    return 1;
+    return ret;
 }
 
 /***********************************************************************
@@ -662,34 +679,40 @@
 static INT FONT_EnumInstance( LPENUMLOGFONTEXW plf, LPNEWTEXTMETRICEXW ptm,
 			      DWORD fType, LPARAM lp )
 {
-    /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
+    fontEnum32 *pfe = (fontEnum32*)lp;
+    INT ret = 1;
+    DC *dc;
 
-#define pfe ((fontEnum32*)lp)
+    /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
     if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET || 
 	pfe->lpLogFontParam->lfCharSet == plf->elfLogFont.lfCharSet )
     {
 	/* convert font metrics */
+        ENUMLOGFONTEXA logfont;
+        NEWTEXTMETRICEXA tmA;
 
         pfe->dwFlags |= ENUM_CALLED;
-	if( pfe->dwFlags & ENUM_UNICODE )
-	{
-	    return pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
-	}
-	else
-	{
-	    ENUMLOGFONTEXA logfont;
-	    NEWTEXTMETRICEXA tmA;
+        if (!(pfe->dwFlags & ENUM_UNICODE))
+        {
+            FONT_EnumLogFontExWToA( plf, &logfont);
+            FONT_NewTextMetricExWToA( ptm, &tmA );
+            plf = (LPENUMLOGFONTEXW)&logfont;
+            ptm = (LPNEWTEXTMETRICEXW)&tmA;
+        }
+        GDI_ReleaseObj( pfe->hdc );  /* release the GDI lock */
 
-	    FONT_EnumLogFontExWToA( plf, &logfont);
-	    FONT_NewTextMetricExWToA( ptm, &tmA );
+        ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
 
-	    return pfe->lpEnumFunc( (LPENUMLOGFONTEXW)&logfont, 
-				    (LPNEWTEXTMETRICEXW)&tmA, fType,
-				    pfe->lpData );
-	}
+        /* get the lock again and make sure the DC is still valid */
+        dc = DC_GetDCPtr( pfe->hdc );
+        if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
+        {
+            if (dc) GDI_ReleaseObj( pfe->hdc );
+            pfe->hdc = 0;  /* make sure we don't try to release it later on */
+            ret = 0;
+        }
     }
-#undef pfe
-    return 1;
+    return ret;
 }
 
 /***********************************************************************
@@ -699,19 +722,19 @@
                                    FONTENUMPROCEX16 efproc, LPARAM lParam,
                                    DWORD dwFlags)
 {
-    BOOL (*enum_func)(HDC,LPLOGFONTW,DEVICEFONTENUMPROC,LPARAM);
+    fontEnum16 fe16;
     INT16	retVal = 0;
     DC* 	dc = DC_GetDCPtr( hDC );
 
     if (!dc) return 0;
-    enum_func = dc->funcs->pEnumDeviceFonts;
-    GDI_ReleaseObj( hDC );
+    fe16.hdc = hDC;
+    fe16.dc = dc;
+    fe16.physDev = dc->physDev;
 
-    if (enum_func)
+    if (dc->funcs->pEnumDeviceFonts)
     {
         NEWTEXTMETRICEX16 tm16;
         ENUMLOGFONTEX16 lf16;
-        fontEnum16 fe16;
         LOGFONTW lfW;
         FONT_LogFont16ToW(plf, &lfW);
 
@@ -723,10 +746,12 @@
         fe16.segTextMetric = MapLS( &tm16 );
         fe16.segLogFont = MapLS( &lf16 );
 
-        retVal = enum_func( hDC, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
+        retVal = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW,
+                                              FONT_EnumInstance16, (LPARAM)&fe16 );
         UnMapLS( fe16.segTextMetric );
         UnMapLS( fe16.segLogFont );
     }
+    if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
     return retVal;
 }
 
@@ -737,7 +762,6 @@
 				    FONTENUMPROCEXW efproc, 
 				    LPARAM lParam, DWORD dwUnicode)
 {
-    BOOL (*enum_func)(HDC,LPLOGFONTW,DEVICEFONTENUMPROC,LPARAM);
     INT ret = 1, ret2;
     DC *dc = DC_GetDCPtr( hDC );
     fontEnum32 fe32;
@@ -751,21 +775,28 @@
     fe32.lpEnumFunc = efproc;
     fe32.lpData = lParam;
     fe32.dwFlags = dwUnicode;
+    fe32.hdc = hDC;
+    fe32.dc = dc;
+    fe32.physDev = dc->physDev;
 
-    enum_func = dc->funcs->pEnumDeviceFonts;
-    GDI_ReleaseObj( hDC );
     enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
 
-    if (!enum_func && !enum_gdi_fonts) return 0;
-    
+    if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
+    {
+        ret = 0;
+        goto done;
+    }
+
     if (enum_gdi_fonts)
         ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
     fe32.dwFlags &= ~ENUM_CALLED;
-    if (ret && enum_func) {
-	ret2 = enum_func( hDC, plf, FONT_EnumInstance, (LPARAM)&fe32 );
+    if (ret && dc->funcs->pEnumDeviceFonts) {
+	ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
 	if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
 	    ret = ret2;
     }
+ done:
+    if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
     return ret;
 }