GetFullPathNameW和长Windows文件路径 [英] GetFullPathNameW and long Windows file paths

查看:218
本文介绍了GetFullPathNameW和长Windows文件路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我当前个人项目的Windows版本中,我希望支持扩展长度文件路径。结果,我对如何使用 GetFullPathNameW API来解析长文件路径的全名。

In the Windows version of my current personal project, I'm looking to support extended length filepaths. As a result, I'm a little confused with how to use the GetFullPathNameW API to resolve the full name of a long filepath.

根据MSDN(带有关于lpFileName参数):

According to the MSDN (with regards to the lpFileName parameter):


在此函数的ANSI版本中,名称限于MAX_PATH字符。若要将此限制扩展为32,767个宽字符,请调用该函数的Unicode版本,并在路径前添加 ?? \。有关更多信息,请参见命名文件。

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无法用于解析相对路径的全名

If I'm understanding this correctly, in order to use an extended length filepath with GetFullPathNameW, I need to specify a path with the \\?\ prefix attached. Since the \\?\ prefix is only valid before volume letters or UNC paths, this would mean that the API is unusable for resolving the full name of a path relative to the current directory.

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

If that's the case, is there another API I can use to resolve the full name of a filepath like ..\somedir\somefile.txt if the resulting name's length exceeds MAX_PATH? If not, would I be able to combine GetCurrentDirectory with the relative filepath (\\?\C:\my\cwd\..\somedir\somefile.txt) and use it with GetFullPathNameW, or would I need to handle all of the filepath resolution on my own?

推荐答案


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

  1. GetFullPathNameA is limited to MAX_PATH characters, because it converts the ANSI name to a UNICODE name beforehand using a hardcoded MAX_PATH-sized (in chars) UNICODE buffer. If the conversion doesn't fail due to the length restrictions, then GetFullPathNameW (or direct GetFullPathName_U[Ex]) is called and the resulting UNICODE name is converted to ANSI.

GetFullPathNameW 是在 GetFullPathName_U 上非常薄的外壳。 WCHAR中的长度限制为 MAXSHORT(0x7fff)的长度,与 \\?\ 文件前缀无关。即使没有 \\?\ ,也可以使用较长的相对名称(> MAX_PATH )。但是,如果 lpFileName 参数不是以 \\?\ 前缀开头,则结果名称为 lpBuffer 参数也不以 \\?\ 开头。

GetFullPathNameW is a very thin shell over GetFullPathName_U. It is limited to MAXSHORT (0x7fff) length in WCHARs, independent of the \\?\ file prefix. Even without \\?\, it will be work for long (> MAX_PATH) relative names. However, if the lpFileName parameter does not begin with the \\?\ prefix, the result name in the lpBuffer parameter will not begin with \\?\ either.

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

if you will be use lpBuffer with functions like CreateFileW - this function internally convert Win32Name to NtName. and result will be depended from nape type (RTL_PATH_TYPE). if the name does not begin with \\?\ prefix, the conversion fails because RtlDosPathNameToRelativeNtPathName_U[_WithStatus] fails (because if the path not begin with \\?\ it will be internally call GetFullPathName_U (same function called by GetFullPathNameW) with nBufferLength hardcoded to MAX_PATH (exactly 2*MAX_PATH in bytes – NTDLL functions use buffer size in bytes, not in WCHARs). If name begin with \\?\ prefix, another case in RtlDosPathNameToRelativeNtPathName_U[_WithStatus] is executed – RtlpWin32NtNameToNtPathName, which replaces \\?\ with \??\ and has no MAX_PATH limitation

所以解决方案如下:

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之前-后面!

So we need to specify a path with the \\?\ prefix attached, but not before GetFullPathName - after!

有关更多信息,请阅读此内容- Win32到NT路径转换的权威指南

For more info, read this - The Definitive Guide on Win32 to NT Path Conversion

这篇关于GetFullPathNameW和长Windows文件路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆