C++ GetFullPathNameW和长Windows文件路径

C++ GetFullPathNameW和长Windows文件路径,c++,windows,winapi,ntfs,C++,Windows,Winapi,Ntfs,在我当前个人项目的Windows版本中,我希望获得支持。因此,我对如何使用API解析长文件路径的全名有点困惑 根据MSDN(关于lpFileName参数): 在该函数的ANSI版本中,名称仅限于MAX_路径字符。要将此限制扩展到32767个宽字符,请调用Unicode版本的函数,并在路径前加上“\?\”。有关详细信息,请参见命名文件 如果我正确理解了这一点,为了使用扩展长度的文件路径和GetFullPathNameW,我需要指定一个带有\\?\前缀的路径。由于\\?\前缀仅在卷号或UNC路径之前

在我当前个人项目的Windows版本中,我希望获得支持。因此,我对如何使用API解析长文件路径的全名有点困惑

根据MSDN(关于lpFileName参数):

在该函数的ANSI版本中,名称仅限于MAX_路径字符。要将此限制扩展到32767个宽字符,请调用Unicode版本的函数,并在路径前加上“\?\”。有关详细信息,请参见命名文件

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

如果是这种情况,是否有其他API可用于解析文件路径的全名,如
。\somedir\somefile.txt
,如果结果名称的长度超过
MAX\u PATH
?如果没有,我是否能够将
GetCurrentDirectory
与相对文件路径(
\?\C:\my\cwd\..\somedir\somefile.txt
)结合使用,或者需要自己处理所有文件路径解析

  • GetFullPathNameA
    仅限于
    MAX\u PATH
    个字符,因为它预先使用硬编码的
    MAX\u PATH
    缓冲区将ANSI名称转换为
    UNICODE
    名称。如果转换没有由于长度限制而失败,则调用
    GetFullPathNameW
    (或direct
    GetFullPathName\U[Ex]
    )并将生成的
    UNICODE
    名称转换为ANSI

  • GetFullPathName w
    GetFullPathName\U
    之上的一个非常薄的外壳。它被限制为WCHARs中的
    MAXSHORT(0x7fff)
    长度,与
    \\?\
    文件前缀无关。即使没有
    \\?\
    ,它也会对长(>
    MAX\u PATH
    )相对名称起作用。但是,如果
    lpFileName
    参数不是以
    \\?\
    前缀开头,则
    lpBuffer
    参数中的结果名称也不会以
    \\?\
    开头

  • 如果将
    lpBuffer
    CreateFileW
    等函数一起使用,则此函数将
    Win32Name
    内部转换为
    NtName
    。结果将取决于nape类型(
    RTL\u PATH\u类型
    )。如果名称不以前缀
    \\?\
    开头,转换将失败,因为
    rtldospathnametorerelativentpathname\U[\U with status]
    失败(因为如果路径不以
    \\?\
    开头,它将在内部调用
    GetFullPathName\U
    (与
    GetFullPathNameW
    调用的函数相同)使用
    nBufferLength
    硬编码到MAX\U PATH(精确地说是
    2*MAX\U PATH
    以字节为单位–NTDLL函数使用以字节为单位的缓冲区大小,而不是以
    WCHAR
    s为单位)。如果名称以
    \\?\
    前缀开头,则在
    rtldospathname torelativentpathname\U[\U with status]中使用另一种情况执行
    -
    RtlpWin32NtNameToNtPathName
    ,它将
    \\?\
    替换为
    \??\
    ,并且没有
    最大路径
    限制

  • 因此,解决方案可能如下所示:

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

    有关更多信息,请阅读以下内容-

  • GetFullPathNameA
    仅限于
    MAX\u PATH
    字符,因为它预先使用硬编码的
    MAX\u PATH
    大小(以字符为单位)的
    UNICODE
    缓冲区将ANSI名称转换为
    UNICODE
    名称。如果转换没有由于长度限制而失败,则
    GetFullPathNameW
    (或直接调用
    GetFullPathName\U[Ex]
    )并将生成的
    UNICODE
    名称转换为ANSI

  • GetFullPathName w
    GetFullPathName\U
    之上的一个非常薄的外壳。它在WCHARs中仅限于
    MAXSHORT(0x7fff)
    长度,与
    \?\
    文件前缀无关。即使没有
    \?\
    ,它也会工作很长时间(>
    MAX\U PATH
    )相对名称。但是,如果
    lpFileName
    参数不是以
    \\?\
    前缀开头,则
    lpBuffer
    参数中的结果名称也不会以
    \\?\
    开头

  • 如果将
    lpBuffer
    CreateFileW
    等函数一起使用,则此函数将
    Win32Name
    内部转换为
    NtName
    。结果将取决于nape类型(
    RTL\u PATH\u type
    )。如果名称不以前缀
    \\?\
    开头,转换将失败,因为
    rtldospathname to relativentpathname\U[\U with status]
    失败(因为如果路径不以
    \?\
    开头,它将在内部调用
    GetFullPathName\U
    (与
    GetFullPathName
    调用的函数相同)使用
    nBufferLength
    硬编码到MAX\U PATH(精确地说是
    2*MAX\U PATH
    以字节为单位–NTDLL函数使用以字节为单位的缓冲区大小,而不是以
    WCHAR
    s为单位)。如果名称以
    \\?\
    前缀开头,则在
    rtldospathname torelativentpathname\U[\U with status]中使用另一种情况执行
    -
    RtlpWin32NtNameToNtPathName
    ,它将
    \\?\
    替换为
    \??\
    ,并且没有
    最大路径
    限制

  • 因此,解决方案可能如下所示:

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


    有关更多信息,请阅读此-

    以更新当前状态:

    从Windows10版本1607开始,已取消最大路径限制