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

时间:2018-05-04 15:03:13

标签: c++ windows winapi visual-c++

我有以下代码:

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:\Projects\ProjectA\IDE_Files\src

rcode结果保存路径中的字符数。不是错误代码。

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

1 个答案:

答案 0 :(得分:1)

这个答案来自Hans Passant

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

  

OpenFileById函数将打开文件或重新分析   点,取决于使用FILE_FLAG_OPEN_REPARSE_POINT标志。 [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();
}