代码之家  ›  专栏  ›  技术社区  ›  Brandon Kohn

如何使用GetFinalPathNameByHandle解析指向本地目录的符号链接?

  •  4
  • Brandon Kohn  · 技术社区  · 6 年前

    我有以下代码:

    std::wstring GetSymbolicLinkTarget(std::wstring const& linkPath)
    {
        TCHAR path[MAX_PATH];
        CAutoFile hFile = CreateFile( linkPath.c_str(),
            FILE_READ_EA,
            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
            0,
            OPEN_EXISTING,
            FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_REPARSE_POINT | FILE_FLAG_OPEN_REPARSE_POINT,
            0);
        if (INVALID_HANDLE_VALUE != hFile)
        {
            auto rcode = GetFinalPathNameByHandle(hFile, path, MAX_PATH, FILE_NAME_NORMALIZED);
            switch (rcode)
            {
            case ERROR_PATH_NOT_FOUND:
                return std::wstring();
            case ERROR_NOT_ENOUGH_MEMORY:
                return std::wstring();
            case ERROR_INVALID_PARAMETER:
                return std::wstring();
            case ERROR_ACCESS_DENIED:
                return std::wstring();
            default:
                break;
            };
    
            if (path[0] == '\\' && path[1] == '\\' && path[2] == '?' && path[3] == '\\')
                return std::wstring(path + 4, path + MAX_PATH);
            else
                return std::wstring(path, path + MAX_PATH);
        }
    
        return std::wstring();
    }
    

    我创建了一个符号链接,如下所示:

    e:
    cd Projects\ProjectA\IDE_Files
    mklink /D src ..
    

    然后在一些代码中,我调用了上述函数,根据文档,该函数表示:

    e:\Projects\ProjectA\IDE_Files\src
    

    应决心:

    e:\Projects\ProjectA
    

    相反,它只返回输入路径:

    e: \项目\项目A\IDE\U文件\src
    

    这个 rcode result保存路径中的字符数。不是错误代码。

    为什么这不能返回我期望的结果?

    1 回复  |  直到 6 年前
        1
  •  3
  •   Brandon Kohn    6 年前

    这个答案来自 Hans Passant :

    问题主要是由于使用 FILE_FLAG_OPEN_REPARSE_POINT 执行以下操作的标志:

    OpenFileById函数将打开文件或重新分析 点,具体取决于FILE\u FLAG\u OPEN\u REPARSE\u点标志的使用。 [source]

    以下是最终代码(上面的注释中有多个修复):

    std::wstring GetSymbolicLinkTarget(std::wstring const& linkPath)
    {
        TCHAR path[MAX_PATH];
        CAutoFile hFile = CreateFile( linkPath.c_str(),
            0,
            0,  
            0,
            OPEN_EXISTING,
            FILE_FLAG_BACKUP_SEMANTICS,
            0);
        if (INVALID_HANDLE_VALUE != hFile)
        {
            auto rcode = GetFinalPathNameByHandle(hFile, path, MAX_PATH, FILE_NAME_NORMALIZED);
            if (rcode)
            {
                if (path[0] == '\\' && path[1] == '\\' && path[2] == '?' && path[3] == '\\')
                    return std::wstring(path + 4, path + rcode);
                else
                    return std::wstring(path, path + rcode);
            }
        }
    
        return std::wstring();
    }