[PATCH] gdi32: Collapse relative paths inside true type fonts file names in registry.

Huw Davies huw at codeweavers.com
Wed Oct 16 05:03:52 CDT 2019


On Mon, Oct 07, 2019 at 02:19:18PM +0300, Paul Gofman wrote:
> Signed-off-by: Paul Gofman <gofmanp at gmail.com>
> ---
>     The motivation under this patch is fixing the crash in Halo Online which
>     originates from libcef.dll with Wine Staging. The crash scenario is the
>     following.
> 
>     A staging patch puts a 'Times New Roman' font replacement to
>     <datadir>/fonts/times.ttf. This is the only relevant difference introduced by
>     Staging. When the font file is found there, gdi32 uses wine_get_data_dir()
>     for a directory prefix to construct font file name. Later libcef.dll works
>     with fonts through dwrite, and somehow gets confused by a "\\..\\" inside the
>     font file name which it gets with IDWriteLocalFontFileLoader_GetFilePathFromKey()
>     from system font file enumerator object.
> 
>  dlls/gdi32/freetype.c | 24 +++++++++++++++++++++++-
>  1 file changed, 23 insertions(+), 1 deletion(-)
> 
> diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
> index e3cff25b76..2f21ba40a0 100644
> --- a/dlls/gdi32/freetype.c
> +++ b/dlls/gdi32/freetype.c
> @@ -3168,11 +3168,33 @@ static void update_reg_entries(void)
>              HeapFree( GetProcessHeap(), 0, buffer );
>  
>              if (path)
> -                file = path;
> +            {
> +                len = GetFullPathNameW(path, 0, NULL, NULL);
> +                if (!(file = HeapAlloc(GetProcessHeap(), 0, len * sizeof(*file))))
> +                {
> +                    HeapFree(GetProcessHeap(), 0, path);
> +                    HeapFree(GetProcessHeap(), 0, valueW);
> +                    continue;
> +                }
> +                if (GetFullPathNameW(path, len, file, NULL) != len - 1)
> +                {
> +                    ERR("Could not get full path name, path %s.\n", debugstr_w(path));
> +                    HeapFree(GetProcessHeap(), 0, file);
> +                    HeapFree(GetProcessHeap(), 0, path);
> +                    HeapFree(GetProcessHeap(), 0, valueW);
> +                    continue;
> +                }
> +                HeapFree(GetProcessHeap(), 0, path);
> +                path = file;
> +            }

All of these error paths are clumsy.  Let's add a helper:

WCHAR *get_full_path_name(const WCHAR *name)

Note it should also check the return value of the first GetFullPathNameW call
unlike the above.

It would be used instead of the above if block something like:

               if (path)
               {
                   if (fullpath = get_full_path_name(path))
                   {
                       HeapFree(GetProcessHeap(), 0, path);
                       path = fullpath;
                   }
                   file = path;
               }

>              else if ((file = strrchrW(face->file, '/')))
> +            {
>                  file++;
> +            }
>              else
> +            {
>                  file = face->file;
> +            }


Huw.



More information about the wine-devel mailing list