在我当前个人项目的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
一起使用,或者我是否需要自己处理所有文件路径解析?
答案 0 :(得分:9)
GetFullPathNameA
仅限于MAX_PATH
个字符,因为它使用硬编码UNICODE
大小(以字符为单位)事先将ANSI名称转换为MAX_PATH
名称UNICODE
缓冲区。如果转换因长度限制而未失败,则调用GetFullPathNameW
(或直接GetFullPathName_U[Ex]
),并将生成的UNICODE
名称转换为ANSI。
GetFullPathNameW
是一个非常薄的GetFullPathName_U
外壳。它在WCHAR中的长度限制为MAXSHORT (0x7fff)
,与\\?\
文件前缀无关。即使没有\\?\
,它也适用于长(> MAX_PATH
)相对名称。但是,如果lpFileName
参数不以\\?\
前缀开头,则lpBuffer
参数中的结果名称也不会以\\?\
开头。
如果您将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
替换为\\?\
且没有\??\
限制
所以解决方案可能如下所示:
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