Jacek Caban : gdi32: Handle scalable fonts directly in AddFontResourceExW and RemoveFontResourceExW.

Alexandre Julliard julliard at winehq.org
Mon Sep 20 16:26:20 CDT 2021


Module: wine
Branch: master
Commit: c332707df4b90803ff2e814f7f6d7bc2464300ea
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=c332707df4b90803ff2e814f7f6d7bc2464300ea

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Mon Sep 20 13:14:47 2021 +0200

gdi32: Handle scalable fonts directly in AddFontResourceExW and RemoveFontResourceExW.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/gdi32/font.c | 101 --------------------------------------------------
 dlls/gdi32/text.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 107 insertions(+), 103 deletions(-)

diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c
index 224dc6b3a77..07b4d248261 100644
--- a/dlls/gdi32/font.c
+++ b/dlls/gdi32/font.c
@@ -5560,91 +5560,6 @@ 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;
-
-    if (!GetFileSizeEx( file, size ) || size->u.HighPart)
-    {
-        CloseHandle( file );
-        return NULL;
-    }
-
-    mapping = CreateFileMappingW( file, NULL, PAGE_READONLY, 0, 0, NULL );
-    CloseHandle( file );
-    if (!mapping) return NULL;
-
-    ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
-    CloseHandle( mapping );
-
-    return ptr;
-}
-
-static void *find_resource( BYTE *ptr, WORD type, DWORD rsrc_off, DWORD size, DWORD *len )
-{
-    WORD align, type_id, count;
-    DWORD res_off;
-
-    if (size < rsrc_off + 10) return NULL;
-    align = *(WORD *)(ptr + rsrc_off);
-    rsrc_off += 2;
-    type_id = *(WORD *)(ptr + rsrc_off);
-    while (type_id && type_id != type)
-    {
-        count = *(WORD *)(ptr + rsrc_off + 2);
-        rsrc_off += 8 + count * 12;
-        if (size < rsrc_off + 8) return NULL;
-        type_id = *(WORD *)(ptr + rsrc_off);
-    }
-    if (!type_id) return NULL;
-    count = *(WORD *)(ptr + rsrc_off + 2);
-    if (size < rsrc_off + 8 + count * 12) return NULL;
-    res_off = *(WORD *)(ptr + rsrc_off + 8) << align;
-    *len = *(WORD *)(ptr + rsrc_off + 10) << align;
-    if (size < res_off + *len) return NULL;
-    return ptr + res_off;
-}
-
-static WCHAR *get_scalable_filename( const WCHAR *res, BOOL *hidden )
-{
-    LARGE_INTEGER size;
-    BYTE *ptr = map_file( res, &size );
-    const IMAGE_DOS_HEADER *dos;
-    const IMAGE_OS2_HEADER *ne;
-    WORD *fontdir;
-    char *data;
-    WCHAR *name = NULL;
-    DWORD len;
-
-    if (!ptr) return NULL;
-
-    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);
-
-    fontdir = find_resource( ptr, 0x8007, dos->e_lfanew + ne->ne_rsrctab, size.u.LowPart, &len );
-    if (!fontdir) goto fail;
-    *hidden = (fontdir[35] & 0x80) != 0;  /* fontdir->dfType */
-
-    data = find_resource( ptr, 0x80cc, dos->e_lfanew + ne->ne_rsrctab, size.u.LowPart, &len );
-    if (!data) goto fail;
-    if (!memchr( data, 0, len )) goto fail;
-
-    len = MultiByteToWideChar( CP_ACP, 0, data, -1, NULL, 0 );
-    name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
-    if (name) MultiByteToWideChar( CP_ACP, 0, data, -1, name, len );
-
-fail:
-    UnmapViewOfFile( ptr );
-    return name;
-}
-
 static int add_system_font_resource( const WCHAR *file, DWORD flags )
 {
     WCHAR path[MAX_PATH];
@@ -5967,8 +5882,6 @@ INT WINAPI NtGdiAddFontResourceW( const WCHAR *str, ULONG size, ULONG files, DWO
                                   DWORD tid, void *dv )
 {
     int ret;
-    WCHAR *filename;
-    BOOL hidden;
 
     if (!font_funcs) return 1;
     if (!(ret = add_font_resource( str, flags )))
@@ -5986,12 +5899,6 @@ INT WINAPI NtGdiAddFontResourceW( const WCHAR *str, ULONG size, ULONG files, DWO
                 ret = num_resources;
             FreeLibrary(hModule);
         }
-        else if ((filename = get_scalable_filename( str, &hidden )) != NULL)
-        {
-            if (hidden) flags |= FR_PRIVATE | FR_NOT_ENUM;
-            ret = add_font_resource( filename, flags );
-            HeapFree( GetProcessHeap(), 0, filename );
-        }
     }
     return ret;
 }
@@ -6061,8 +5968,6 @@ BOOL WINAPI NtGdiRemoveFontResourceW( const WCHAR *str, ULONG size, ULONG files,
                                       DWORD tid, void *dv )
 {
     int ret;
-    WCHAR *filename;
-    BOOL hidden;
 
     if (!font_funcs) return TRUE;
 
@@ -6075,12 +5980,6 @@ BOOL WINAPI NtGdiRemoveFontResourceW( const WCHAR *str, ULONG size, ULONG files,
             WARN("Can't unload resources from PE file %s\n", wine_dbgstr_w(str));
             FreeLibrary(hModule);
         }
-        else if ((filename = get_scalable_filename( str, &hidden )) != NULL)
-        {
-            if (hidden) flags |= FR_PRIVATE | FR_NOT_ENUM;
-            ret = remove_font_resource( filename, flags );
-            HeapFree( GetProcessHeap(), 0, filename );
-        }
     }
     return ret;
 }
diff --git a/dlls/gdi32/text.c b/dlls/gdi32/text.c
index b7c6706ef22..41333903c0c 100644
--- a/dlls/gdi32/text.c
+++ b/dlls/gdi32/text.c
@@ -2300,12 +2300,107 @@ BOOL WINAPI RemoveFontResourceExA( const char *str, DWORD fl, void *pdv )
     return ret;
 }
 
+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;
+
+    if (!GetFileSizeEx( file, size ) || size->u.HighPart)
+    {
+        CloseHandle( file );
+        return NULL;
+    }
+
+    mapping = CreateFileMappingW( file, NULL, PAGE_READONLY, 0, 0, NULL );
+    CloseHandle( file );
+    if (!mapping) return NULL;
+
+    ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
+    CloseHandle( mapping );
+
+    return ptr;
+}
+
+static void *find_resource( BYTE *ptr, WORD type, DWORD rsrc_off, DWORD size, DWORD *len )
+{
+    WORD align, type_id, count;
+    DWORD res_off;
+
+    if (size < rsrc_off + 10) return NULL;
+    align = *(WORD *)(ptr + rsrc_off);
+    rsrc_off += 2;
+    type_id = *(WORD *)(ptr + rsrc_off);
+    while (type_id && type_id != type)
+    {
+        count = *(WORD *)(ptr + rsrc_off + 2);
+        rsrc_off += 8 + count * 12;
+        if (size < rsrc_off + 8) return NULL;
+        type_id = *(WORD *)(ptr + rsrc_off);
+    }
+    if (!type_id) return NULL;
+    count = *(WORD *)(ptr + rsrc_off + 2);
+    if (size < rsrc_off + 8 + count * 12) return NULL;
+    res_off = *(WORD *)(ptr + rsrc_off + 8) << align;
+    *len = *(WORD *)(ptr + rsrc_off + 10) << align;
+    if (size < res_off + *len) return NULL;
+    return ptr + res_off;
+}
+
+static WCHAR *get_scalable_filename( const WCHAR *res, BOOL *hidden )
+{
+    LARGE_INTEGER size;
+    BYTE *ptr = map_file( res, &size );
+    const IMAGE_DOS_HEADER *dos;
+    const IMAGE_OS2_HEADER *ne;
+    WORD *fontdir;
+    char *data;
+    WCHAR *name = NULL;
+    DWORD len;
+
+    if (!ptr) return NULL;
+
+    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);
+
+    fontdir = find_resource( ptr, 0x8007, dos->e_lfanew + ne->ne_rsrctab, size.u.LowPart, &len );
+    if (!fontdir) goto fail;
+    *hidden = (fontdir[35] & 0x80) != 0;  /* fontdir->dfType */
+
+    data = find_resource( ptr, 0x80cc, dos->e_lfanew + ne->ne_rsrctab, size.u.LowPart, &len );
+    if (!data) goto fail;
+    if (!memchr( data, 0, len )) goto fail;
+
+    len = MultiByteToWideChar( CP_ACP, 0, data, -1, NULL, 0 );
+    name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
+    if (name) MultiByteToWideChar( CP_ACP, 0, data, -1, name, len );
+
+fail:
+    UnmapViewOfFile( ptr );
+    return name;
+}
+
 /***********************************************************************
  *           AddFontResourceExW    (GDI32.@)
  */
 INT WINAPI AddFontResourceExW( const WCHAR *str, DWORD flags, void *dv )
 {
-    return NtGdiAddFontResourceW( str, 0, 1, flags, 0, dv );
+    WCHAR *filename = NULL;
+    BOOL hidden;
+    INT ret;
+
+    if ((ret = NtGdiAddFontResourceW( str, 0, 1, flags, 0, dv ))) return ret;
+
+    if (!(filename = get_scalable_filename( str, &hidden ))) return 0;
+    if (hidden) flags |= FR_PRIVATE | FR_NOT_ENUM;
+    ret = NtGdiAddFontResourceW( filename, 0, 1, flags, 0, dv );
+    HeapFree( GetProcessHeap(), 0, filename );
+    return ret;
 }
 
 /***********************************************************************
@@ -2313,7 +2408,17 @@ INT WINAPI AddFontResourceExW( const WCHAR *str, DWORD flags, void *dv )
  */
 BOOL WINAPI RemoveFontResourceExW( const WCHAR *str, DWORD flags, void *dv )
 {
-    return NtGdiRemoveFontResourceW( str, 0, 1, flags, 0, dv );
+    WCHAR *filename = NULL;
+    BOOL hidden;
+    INT ret;
+
+    if ((ret = NtGdiRemoveFontResourceW( str, 0, 1, flags, 0, dv ))) return ret;
+
+    if (!(filename = get_scalable_filename( str, &hidden ))) return 0;
+    if (hidden) flags |= FR_PRIVATE | FR_NOT_ENUM;
+    ret = NtGdiRemoveFontResourceW( filename, 0, 1, flags, 0, dv );
+    HeapFree( GetProcessHeap(), 0, filename );
+    return ret;
 }
 
 /***********************************************************************




More information about the wine-cvs mailing list