From: Fabian Maurer Subject: [PATCH] gdiplus: In GdipPrivateAddMemoryFont allow loading fonts with long names Message-Id: <20171112183533.2805-1-dark.shadow4@web.de> Date: Sun, 12 Nov 2017 19:35:33 +0100 Fixes Bug 43956. Signed-off-by: Fabian Maurer --- 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