From 88a2620b149b3fa82b20cca2aff3b2088026456e Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Fri, 30 Mar 2012 12:38:04 +0100 Subject: [PATCH] gdi32: Add support for loading scalable font resources. --- dlls/gdi32/font.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c index 1abb6ae379e..230d4217dcb 100644 --- a/dlls/gdi32/font.c +++ b/dlls/gdi32/font.c @@ -3446,12 +3446,85 @@ static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR return TRUE; } +static void *map_file( const WCHAR *filename, LARGE_INTEGER *size ) +{ + HANDLE file, mapping; + void *ptr; + + file = CreateFileW( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); + if (file == INVALID_HANDLE_VALUE) return NULL; + + GetFileSizeEx( file, size ); + mapping = CreateFileMappingW( file, NULL, PAGE_READONLY, 0, 0, NULL ); + CloseHandle( file ); + if (mapping == NULL) return NULL; + + ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 ); + CloseHandle( mapping ); + + return ptr; +} + +static WCHAR *get_scalable_filename( const WCHAR *res ) +{ + LARGE_INTEGER size; + BYTE *ptr = map_file( res, &size ); + const IMAGE_DOS_HEADER *dos; + const IMAGE_OS2_HEADER *ne; + WCHAR *name = NULL; + WORD rsrc_off, align, type_id, count; + DWORD res_off, res_len, i; + int len; + + if (!ptr) return NULL; + + if (size.u.HighPart) goto fail; + if (size.u.LowPart < sizeof( *dos )) goto fail; + dos = (const IMAGE_DOS_HEADER *)ptr; + if (dos->e_magic != IMAGE_DOS_SIGNATURE) goto fail; + if (size.u.LowPart < dos->e_lfanew + sizeof( *ne )) goto fail; + ne = (const IMAGE_OS2_HEADER *)(ptr + dos->e_lfanew); + rsrc_off = dos->e_lfanew + ne->ne_rsrctab; + if (size.u.LowPart < rsrc_off + 10) goto fail; + align = *(WORD *)(ptr + rsrc_off); + rsrc_off += 2; + type_id = *(WORD *)(ptr + rsrc_off); + while (type_id && type_id != 0x80cc) + { + count = *(WORD *)(ptr + rsrc_off + 2); + rsrc_off += 8 + count * 12; + if (size.u.LowPart < rsrc_off + 8) goto fail; + type_id = *(WORD *)(ptr + rsrc_off); + } + if (!type_id) goto fail; + count = *(WORD *)(ptr + rsrc_off + 2); + if (size.u.LowPart < rsrc_off + 8 + count * 12) goto fail; + + res_off = *(WORD *)(ptr + rsrc_off + 8) << align; + res_len = *(WORD *)(ptr + rsrc_off + 10) << align; + if (size.u.LowPart < res_off + res_len) goto fail; + + for (i = 0; i < res_len; i++) + if (ptr[ res_off + i ] == 0) break; + if (i == res_len) goto fail; + + len = MultiByteToWideChar( CP_ACP, 0, (char *)ptr + res_off, -1, NULL, 0 ); + name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); + if (name) MultiByteToWideChar( CP_ACP, 0, (char *)ptr + res_off, -1, name, len ); + +fail: + UnmapViewOfFile( ptr ); + return name; +} + /*********************************************************************** * AddFontResourceExW (GDI32.@) */ INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv ) { int ret = WineEngAddFontResourceEx(str, fl, pdv); + WCHAR *filename; + if (ret == 0) { /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */ @@ -3467,6 +3540,11 @@ INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv ) ret = num_resources; FreeLibrary(hModule); } + else if ((filename = get_scalable_filename( str )) != NULL) + { + ret = WineEngAddFontResourceEx( filename, fl, pdv ); + HeapFree( GetProcessHeap(), 0, filename ); + } } return ret; } -- 2.11.4.GIT