[FFmpeg-devel] [PATCH 1/2] avutil/wchar_filename, file_open: Support long file names on Windows

nil-admirari at mailo.com nil-admirari at mailo.com
Sun May 15 22:02:36 EEST 2022


> diff --git a/libavutil/wchar_filename.h b/libavutil/wchar_filename.h
> ...
> +static inline int path_is_extended(const wchar_t *path)
> ...

Why path handling functions ended up in wchar_filename.h?
Isn't it better to move them to file_open or os_support?

> +    num_chars = GetFullPathNameW(*ppath_w, num_chars, temp_w, NULL);

Turns out that GetFullPathNameW handles long path names without the manifest
or a prefix \\?\. Other WinAPI functions, require either a prefix or a manifest,
which is why I thought that path normalisation must be done by hand.

> +static inline int path_normalize(wchar_t **ppath_w)
> +{
> +    int ret;
> +
> +    // see .NET6: PathHelper.Normalize()
> +    if ((ret = get_full_path_name(ppath_w)) < 0)
> +        return ret;
> +
> +    /* What .NET does at this point is to call PathHelper.TryExpandShortFileName()
> +       in case the path contains a '~' character.
> +       We don't need to do this as we don't need to normalize the file name
> +       for presentation, and the extended path prefix works with 8.3 path
> +       components as well */
> +    return 0;
> +}

This function simply forwards the return code of get_full_path_name().
The only non-trivial part of it is a comment.

> +static inline int path_is_extended(const wchar_t *path)
> +{
> +    // see .NET6: PathInternal.IsExtended()
> +    size_t len = wcslen(path);
> +    if (len >= 4  && path[0] == L'\\' && (path[1] == L'\\' || path[1] == L'?') && path[2] == L'?' && path[3] == L'\\')
> +        return 1;
> +
> +    return 0;
> +}
>
> +static inline int add_extended_prefix(wchar_t **ppath_w)
> +{
> +    const wchar_t *unc_prefix           = L"\\\\?\\UNC\\";
> ...
> +    // see .NET6: PathInternal.EnsureExtendedPrefix()
> +    if (path_w[0] == L'\\' && path_w[1] == L'\\') {
> ...
> +        wcscpy(temp_w, unc_prefix);
> +        wcscat(temp_w, path_w + 2);
> 
> +static inline int get_extended_win32_path(const char *path, wchar_t **ppath_w)
> +{
> ...
> +    if (path_is_extended(*ppath_w)) {
> +        ...
> +        return 0;
> +    }
> ...
> +        if ((ret = add_extended_prefix(ppath_w)) < 0)

Actual PathInternal.EnsureExtendedPrefix
(https://github.com/dotnet/runtime/blob/main/src/libraries/Common/src/System/IO/PathInternal.Windows.cs)
checks for

            if (IsPartiallyQualified(path.AsSpan()) || IsDevice(path.AsSpan()))
                return path;

where IsDevice handles \\.\, which you do not handle. If I'm not mistaken,
the code paths presented above will turn such paths into \\?\UNC\\.\,
which is an error.

> +static inline int add_extended_prefix(wchar_t **ppath_w)
> +{
> +    const wchar_t *unc_prefix           = L"\\\\?\\UNC\\";
> ...
> +        temp_w = (wchar_t *)av_calloc(len + 6 + 1, sizeof(wchar_t));

Wouldn't it be better to use sizeof unc_prefix instead of magic numbers?





More information about the ffmpeg-devel mailing list