[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