gdi32: Add a test for undocumented EnumFontFamiliesEx(NULL), make it pass under Wine

Dmitry Timoshkov dmitry at codeweavers.com
Tue Jan 15 02:02:29 CST 2008


Hello,

this patch should fix a crash in the app I'm working on.

Changelog:
    gdi32: Add a test for undocumented EnumFontFamiliesEx(NULL), make it
    pass under Wine.
---
 dlls/gdi32/font.c        |   62 ++++++++++++++++++++++++++++++---------------
 dlls/gdi32/freetype.c    |    8 ++++++
 dlls/gdi32/tests/font.c  |   12 +++++++++
 dlls/winex11.drv/xfont.c |    9 ++++++
 4 files changed, 70 insertions(+), 21 deletions(-)

diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
index 66ae6d7..2789df5 100644
--- a/dlls/gdi32/font.c
+++ b/dlls/gdi32/font.c
@@ -692,7 +692,8 @@ static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW
     INT ret = 1;
     DC *dc;
 
-    if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
+    if (!pfe->lpLogFontParam ||
+        pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
         pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
     {
         WORD args[7];
@@ -740,7 +741,8 @@ static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *p
     DC *dc;
 
     /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
-    if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
+    if ((!pfe->lpLogFontParam ||
+        pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
         pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
        (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
     {
@@ -785,11 +787,17 @@ INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
     DC* 	dc = DC_GetDCPtr( HDC_32(hDC) );
     NEWTEXTMETRICEX16 tm16;
     ENUMLOGFONTEX16 lf16;
-    LOGFONTW lfW;
+    LOGFONTW lfW, *plfW;
     BOOL enum_gdi_fonts;
 
     if (!dc) return 0;
-    FONT_LogFont16ToW(plf, &lfW);
+
+    if (plf)
+    {
+        FONT_LogFont16ToW(plf, &lfW);
+        plfW = &lfW;
+    }
+    else plfW = NULL;
 
     fe16.hdc = HDC_32(hDC);
     fe16.dc = dc;
@@ -812,10 +820,10 @@ INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
     }
 
     if (enum_gdi_fonts)
-        ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
+        ret = WineEngEnumFonts( plfW, FONT_EnumInstance16, (LPARAM)&fe16 );
     fe16.dwFlags &= ~ENUM_CALLED;
     if (ret && dc->funcs->pEnumDeviceFonts) {
-	ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
+	ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plfW, FONT_EnumInstance16, (LPARAM)&fe16 );
 	if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
 	    ret = ret2;
     }
@@ -888,10 +896,16 @@ INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
                                     FONTENUMPROCA efproc,
                                     LPARAM lParam, DWORD dwFlags)
 {
-    LOGFONTW lfW;
-    FONT_LogFontAToW( plf, &lfW );
+    LOGFONTW lfW, *plfW;
+
+    if (plf)
+    {
+        FONT_LogFontAToW( plf, &lfW );
+        plfW = &lfW;
+    }
+    else plfW = NULL;
 
-    return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
+    return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
 }
 
 /***********************************************************************
@@ -900,17 +914,19 @@ INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
                                  FONTENUMPROC16 efproc, LPARAM lpData )
 {
-    LOGFONT16	lf;
+    LOGFONT16 lf, *plf;
 
-    lf.lfCharSet = DEFAULT_CHARSET;
     if (lpFamily)
     {
         if (!*lpFamily) return 1;
         lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
+        lf.lfCharSet = DEFAULT_CHARSET;
+        lf.lfPitchAndFamily = 0;
+        plf = &lf;
     }
-    else lf.lfFaceName[0] = '\0';
+    else plf = NULL;
 
-    return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
+    return EnumFontFamiliesEx16( hDC, plf, efproc, lpData, 0 );
 }
 
 /***********************************************************************
@@ -919,17 +935,19 @@ INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
                                   FONTENUMPROCA efproc, LPARAM lpData )
 {
-    LOGFONTA	lf;
+    LOGFONTA lf, *plf;
 
-    lf.lfCharSet = DEFAULT_CHARSET;
     if (lpFamily)
     {
         if (!*lpFamily) return 1;
         lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
+        lf.lfCharSet = DEFAULT_CHARSET;
+        lf.lfPitchAndFamily = 0;
+        plf = &lf;
     }
-    else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
+    else plf = NULL;
 
-    return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
+    return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
 }
 
 /***********************************************************************
@@ -938,17 +956,19 @@ INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
                                   FONTENUMPROCW efproc, LPARAM lpData )
 {
-    LOGFONTW  lf;
+    LOGFONTW lf, *plf;
 
-    lf.lfCharSet = DEFAULT_CHARSET;
     if (lpFamily)
     {
         if (!*lpFamily) return 1;
         lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
+        lf.lfCharSet = DEFAULT_CHARSET;
+        lf.lfPitchAndFamily = 0;
+        plf = &lf;
     }
-    else lf.lfFaceName[0] = 0;
+    else plf = NULL;
 
-    return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
+    return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
 }
 
 /***********************************************************************
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
index 562c329..7689cf9 100644
--- a/dlls/gdi32/freetype.c
+++ b/dlls/gdi32/freetype.c
@@ -3371,6 +3371,14 @@ DWORD WineEngEnumFonts(LPLOGFONTW plf, FONTENUMPROCW proc, LPARAM lparam)
     LOGFONTW lf;
     int i;
 
+    if (!plf)
+    {
+        lf.lfCharSet = DEFAULT_CHARSET;
+        lf.lfPitchAndFamily = 0;
+        lf.lfFaceName[0] = 0;
+        plf = &lf;
+    }
+
     TRACE("facename = %s charset %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
 
     if(plf->lfFaceName[0]) {
diff --git a/dlls/gdi32/tests/font.c b/dlls/gdi32/tests/font.c
index 6138731..ee577c6 100644
--- a/dlls/gdi32/tests/font.c
+++ b/dlls/gdi32/tests/font.c
@@ -1287,6 +1287,18 @@ static void test_EnumFontFamilies(const char *font_name, INT font_charset)
         ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
         ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
         ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
+
+        efd.total = 0;
+        SetLastError(0xdeadbeef);
+        ret = EnumFontFamiliesEx(hdc, NULL, arial_enum_proc, (LPARAM)&efd, 0);
+        ok(ret, "EnumFontFamiliesEx error %u\n", GetLastError());
+        get_charset_stats(&efd, &ansi_charset, &symbol_charset, &russian_charset);
+        trace("enumerated ansi %d, symbol %d, russian %d fonts for NULL\n",
+              ansi_charset, symbol_charset, russian_charset);
+        ok(efd.total > 0, "no fonts enumerated: NULL\n");
+        ok(ansi_charset > 0, "NULL family should enumerate ANSI_CHARSET\n");
+        ok(symbol_charset > 0, "NULL family should enumerate SYMBOL_CHARSET\n");
+        ok(russian_charset > 0, "NULL family should enumerate RUSSIAN_CHARSET\n");
     }
 
     efd.total = 0;
diff --git a/dlls/winex11.drv/xfont.c b/dlls/winex11.drv/xfont.c
index 3298818..a55e77d 100644
--- a/dlls/winex11.drv/xfont.c
+++ b/dlls/winex11.drv/xfont.c
@@ -3305,10 +3305,19 @@ BOOL X11DRV_EnumDeviceFonts( X11DRV_PDEVICE *physDev, LPLOGFONTW plf,
     NEWTEXTMETRICEXW	tm;
     fontResource*	pfr = fontList;
     BOOL	  	b, bRet = 0;
+    LOGFONTW lfW;
 
     /* don't enumerate x11 fonts if we're using client side fonts */
     if (physDev->has_gdi_font) return FALSE;
 
+    if (!plf)
+    {
+        lfW.lfCharSet = DEFAULT_CHARSET;
+        lfW.lfPitchAndFamily = 0;
+        lfW.lfFaceName[0] = 0;
+        plf = &lfW;
+    }
+
     if( plf->lfFaceName[0] )
     {
         char facename[LF_FACESIZE+1];
-- 
1.5.3.8






More information about the wine-patches mailing list