GetFullPathNameW 和长 Windows 文件路径

GetFullPathNameW and long Windows file paths

在我当前个人项目的 Windows 版本中,我希望支持 extended length filepaths. As a result, I'm a little confused with how to use the GetFullPathNameW API 来解析长文件路径的全名。

根据 MSDN(关于 lpFileName 参数):

In the ANSI version of this function, the name is limited to MAX_PATH characters. To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\?\" to the path. For more information, see Naming a File.

如果我理解正确,为了在 GetFullPathNameW 中使用扩展长度的文件路径,我需要指定一个附加了 \?\ 前缀的路径。由于 \?\ 前缀仅在卷号或 UNC 路径之前有效,这意味着 API 无法用于解析相对于当前目录的路径的全名。

如果是这样,如果结果名称的长度超过 MAX_PATH,是否还有另一个 API 我可以用来解析文件路径的全名,例如 ..\somedir\somefile.txt?如果没有,我是否能够将 GetCurrentDirectory 与相对文件路径 (\?\C:\my\cwd\..\somedir\somefile.txt) 结合使用并与 GetFullPathNameW 一起使用,还是我需要自己处理所有文件路径解析?

  1. GetFullPathNameA 限制为 MAX_PATH 个字符,因为它事先使用硬编码的 MAX_PATH 大小将 ANSI 名称转换为 UNICODE 名称(以字符为单位)UNICODE 缓冲区。如果转换没有因长度限制而失败,则调用 GetFullPathNameW(或直接 GetFullPathName_U[Ex])并将生成的 UNICODE 名称转换为 ANSI。

  2. GetFullPathNameWGetFullPathName_U 更薄 shell。它在 WCHAR 中限制为 MAXSHORT (0x7fff) 长度,与 \?\ 文件前缀无关。即使没有 \?\,它也适用于长 (> MAX_PATH) 的相对名称。但是,如果 lpFileName 参数不以 \?\ 前缀开头,则 lpBuffer 参数中的结果名称也不会以 \?\ 开头。

  3. 如果您将 lpBufferCreateFileW 等函数一起使用 - 此函数在内部将 Win32Name 转换为 NtName。结果将取决于颈背类型 (RTL_PATH_TYPE)。如果名称不以 \?\ 前缀开头,则转换失败,因为 RtlDosPathNameToRelativeNtPathName_U[_WithStatus] 失败(因为如果路径不以 \?\ 开头,它将在内部调用 GetFullPathName_U (相同的功能由 GetFullPathNameW 调用),nBufferLength 硬编码为 MAX_PATH(恰好 2*MAX_PATH 字节 – NTDLL 函数使用缓冲区大小,而不是 WCHARs)。如果名称以 \?\ 前缀开头,执行 RtlDosPathNameToRelativeNtPathName_U[_WithStatus] 中的另一种情况 – RtlpWin32NtNameToNtPathName,它将 \?\ 替换为 \??\ 并且没有 MAX_PATH 限制

所以解决方案可能如下所示:

if(ULONG len = GetFullPathNameW(FileName, 0, 0, 0))
{
    PWSTR buf = (PWSTR)_alloca((4 + len) * sizeof(WCHAR));
    buf[0] = L'\', buf[1] = L'\',  buf[2] = L'?', buf[3] = L'\';
    if (len - 1 == GetFullPathName(FileName, len, buf + 4, &c))
    {
        CreateFile(buf, ...);
    }
}

所以我们需要指定一个带有 \?\ 前缀的路径,但不是在 GetFullPathName 之前 - 之后!

有关详细信息,请阅读此 - The Definitive Guide on Win32 to NT Path Conversion

仅更新​​当前状态:

Starting in Windows 10, version 1607, MAX_PATH limitations have been removed from common Win32 file and directory functions. However, you must opt-in to the new behavior. To enable the new long path behavior, both of the following conditions must be met: ...

其他的请看我的回答: