GetFullPathNameW和长Windows文件路径 [英] GetFullPathNameW and long Windows file paths
问题描述
在我当前个人项目的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?
推荐答案
-
GetFullPathNameA
限制为MAX_PATH
个字符,因为它事先使用硬编码的<$将ANSI名称转换为UNICODE
名称。 c $ c> MAX_PATH 大小(以字符为单位)UNICODE
缓冲区。如果由于长度限制转换没有失败,则GetFullPathNameW
(或直接GetFullPathName_U [Ex]
)为调用,结果UNICODE
名称将转换为ANSI。
GetFullPathNameA
is limited toMAX_PATH
characters, because it converts the ANSI name to aUNICODE
name beforehand using a hardcodedMAX_PATH
-sized (in chars)UNICODE
buffer. If the conversion doesn't fail due to the length restrictions, thenGetFullPathNameW
(or directGetFullPathName_U[Ex]
) is called and the resultingUNICODE
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 WCHAR
s). 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屋!