GetFullPathNameW和长Windows文件路径

时间:2016-06-26 09:14:42

标签: c++ windows winapi ntfs

在我当前个人项目的Windows版本中,我希望支持extended length filepaths。因此,我对如何使用GetFullPathNameW API来解析长文件路径的全名感到困惑。

根据MSDN(关于lpFileName参数):

  

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

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

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

2 个答案:

答案 0 :(得分:9)

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

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

  3. 如果您将lpBuffer用于CreateFileW等功能,则此功能会在内部将Win32Name转换为NtName。结果将取决于nape类型(RTL_PATH_TYPE)。如果名称不以\\?\前缀开头,则转换失败,因为RtlDosPathNameToRelativeNtPathName_U[_WithStatus]失败(因为如果路径不以\\?\开头,则会在内部调用GetFullPathName_U(相同的功能)由GetFullPathNameW调用,nBufferLength硬编码为MAX_PATH(字节精确2*MAX_PATH - NTDLL函数使用缓冲区大小,以字节为单位,而不是WCHAR s。)如果名称以{开头} {1}}前缀,\\?\中的另一个案例已执行 - RtlDosPathNameToRelativeNtPathName_U[_WithStatus],将RtlpWin32NtNameToNtPathName替换为\\?\且没有\??\限制

    < / LI>

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

    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

答案 1 :(得分:-1)

只需更新当前状态即可:

  

从Windows 10版本1607开始,MAX_PATH限制已从常见的Win32文件和目录功能中删除。但是,您必须选择加入新行为。若要启用新的长路径行为,必须满足以下两个条件:...

对于其他情况,请在这里查看我的答案:https://stackoverflow.com/a/57624626/3736444