[PATCH] gdiplus: In GdipPrivateAddMemoryFont allow loading fonts with long names

Fabian Maurer dark.shadow4 at web.de
Sun Nov 12 12:35:33 CST 2017


Fixes Bug 43956.

Signed-off-by: Fabian Maurer <dark.shadow4 at web.de>
---
 dlls/gdiplus/font.c | 38 ++++++++++++++++++++++----------------
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/dlls/gdiplus/font.c b/dlls/gdiplus/font.c
index ccf93ed395..f99b026b25 100644
--- a/dlls/gdiplus/font.c
+++ b/dlls/gdiplus/font.c
@@ -1393,33 +1393,36 @@ static int match_name_table_language( const tt_name_record *name, LANGID lang )
     return 0;
 }
 
-static WCHAR *copy_name_table_string( const tt_name_record *name, const BYTE *data, WCHAR *ret, DWORD len )
+static WCHAR *copy_name_table_string( const tt_name_record *name, const BYTE *data )
 {
     WORD name_len = GET_BE_WORD(name->length);
     WORD codepage;
+    WCHAR *ret;
+    int len;
 
     switch (GET_BE_WORD(name->platform_id))
     {
     case TT_PLATFORM_APPLE_UNICODE:
     case TT_PLATFORM_MICROSOFT:
-        if (name_len >= len*sizeof(WCHAR))
-            return NULL;
+        ret = heap_alloc((name_len / 2 + 1) * sizeof(WCHAR));
         for (len = 0; len < name_len / 2; len++)
             ret[len] = (data[len * 2] << 8) | data[len * 2 + 1];
         ret[len] = 0;
         return ret;
     case TT_PLATFORM_MACINTOSH:
         codepage = get_mac_code_page( name );
-        len = MultiByteToWideChar( codepage, 0, (char *)data, name_len, ret, len-1 );
+        len = MultiByteToWideChar( codepage, 0, (char *)data, name_len, NULL, 0 ) + 1;
         if (!len)
             return NULL;
+        ret = heap_alloc(len * sizeof(WCHAR));
+        len = MultiByteToWideChar( codepage, 0, (char *)data, name_len, ret, len - 1 );
         ret[len] = 0;
         return ret;
     }
     return NULL;
 }
 
-static WCHAR *load_ttf_name_id( const BYTE *mem, DWORD_PTR size, DWORD id, WCHAR *ret, DWORD len )
+static WCHAR *load_ttf_name_id( const BYTE *mem, DWORD_PTR size, DWORD id )
 {
     LANGID lang = GetSystemDefaultLangID();
     const tt_header *header;
@@ -1480,8 +1483,9 @@ static WCHAR *load_ttf_name_id( const BYTE *mem, DWORD_PTR size, DWORD id, WCHAR
 
     if (best_lang)
     {
+        WCHAR *ret;
         name_record = (const tt_name_record*)(name_table + 1) + best_index;
-        ret = copy_name_table_string( name_record, mem+ofs+GET_BE_WORD(name_record->offset), ret, len );
+        ret = copy_name_table_string( name_record, mem+ofs+GET_BE_WORD(name_record->offset) );
         TRACE( "name %u found platform %u lang %04x %s\n", GET_BE_WORD(name_record->name_id),
                 GET_BE_WORD(name_record->platform_id), GET_BE_WORD(name_record->language_id), debugstr_w( ret ));
         return ret;
@@ -1497,43 +1501,45 @@ static INT CALLBACK add_font_proc(const LOGFONTW *lfw, const TEXTMETRICW *ntm, D
 GpStatus WINGDIPAPI GdipPrivateAddMemoryFont(GpFontCollection* fontCollection,
         GDIPCONST void* memory, INT length)
 {
-    WCHAR buf[32], *name;
+    WCHAR *name;
     DWORD count = 0;
     HANDLE font;
+    GpStatus ret = Ok;
     TRACE("%p, %p, %d\n", fontCollection, memory, length);
 
     if (!fontCollection || !memory || !length)
         return InvalidParameter;
 
-    name = load_ttf_name_id(memory, length, NAME_ID_FULL_FONT_NAME, buf, sizeof(buf)/sizeof(*buf));
+    name = load_ttf_name_id(memory, length, NAME_ID_FULL_FONT_NAME);
     if (!name)
         return OutOfMemory;
 
     font = AddFontMemResourceEx((void*)memory, length, NULL, &count);
     TRACE("%s: %p/%u\n", debugstr_w(name), font, count);
     if (!font || !count)
-        return InvalidParameter;
-
-    if (count)
+        ret = InvalidParameter;
+    else
     {
         HDC hdc;
         LOGFONTW lfw;
 
         hdc = CreateCompatibleDC(0);
 
+        /* Truncate name if necessary, GDI32 can't deal with long names */
+        if(lstrlenW(name) > LF_FACESIZE - 1)
+            name[LF_FACESIZE - 1] = 0;
+
         lfw.lfCharSet = DEFAULT_CHARSET;
         lstrcpyW(lfw.lfFaceName, name);
         lfw.lfPitchAndFamily = 0;
 
         if (!EnumFontFamiliesExW(hdc, &lfw, add_font_proc, (LPARAM)fontCollection, 0))
-        {
-            DeleteDC(hdc);
-            return OutOfMemory;
-        }
+            ret = OutOfMemory;
 
         DeleteDC(hdc);
     }
-    return Ok;
+    heap_free(name);
+    return ret;
 }
 
 /*****************************************************************************
-- 
2.15.0




More information about the wine-devel mailing list