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