获取符号链接目标的卷名的最佳方法[NTFS]

时间:2015-03-28 01:05:05

标签: c++ c visual-c++ visual-studio-2013 ntfs

我想要一种可靠的方法来获取非常复杂的符号链接目标的卷名。

所以看起来FILE_NAME_INFO结构不包含有关文件所在卷的任何信息。我能够从这个结构中获取符号链接目标的路径,但是现在我只假设目标位于同一个卷上。但是,我知道符号链接允许其他卷上的目标。

#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <ole2.h>

struct FILE_NAME_INFO_AND_BUF {
    FILE_NAME_INFO fni;
    WCHAR buf[260];
};

WCHAR* getReparseTarget(WCHAR* linkFileName) {
    HANDLE hFile;
    WCHAR *szGuid = (WCHAR *)malloc(sizeof(WCHAR) * MAX_PATH);
    BOOL result;
    FILE_NAME_INFO_AND_BUF fnib = { 0 };

    hFile = ::CreateFile(linkFileName, FILE_READ_ATTRIBUTES,
        FILE_SHARE_READ |
        FILE_SHARE_WRITE,
        0,
        OPEN_EXISTING,
        FILE_FLAG_BACKUP_SEMANTICS, 0);
    if (hFile == INVALID_HANDLE_VALUE) {
        ::CloseHandle(hFile);
        return NULL;
    }

    result = ::GetFileInformationByHandleEx(hFile, FileNameInfo, &fnib, sizeof(fnib));
    if (!result) {
        fprintf(stderr, "GetFileInformationByHandleEx Error %d\n", ::GetLastError());
        ::CloseHandle(hFile);
        return NULL;
    }

    WCHAR *targetFileName = (WCHAR *)malloc(sizeof(WCHAR) * MAX_PATH);
    wmemset(targetFileName, 0, MAX_PATH);
    wcsncpy(targetFileName, linkFileName, 2);
    wcscat(targetFileName, fnib.fni.FileName);

    return targetFileName;
}

正如您所看到的那样,我正在作弊并从输入字符串中获取卷名称(在本例中为驱动器号),但如果目标位于另一个卷上,则无效。另外,我更喜欢使用GUID获取卷名称,例如其中\\?\Volume{f993747a-5d7a-4de1-a97a-c20c1af1ba02}\比驱动器号码例如C:\ {{1}}

1 个答案:

答案 0 :(得分:1)

绝对最简单的方法,只要您可以定位Vista或更高版本,就是使用GetFinalPathNameByHandle功能。

如果您还需要定位XP,那么您可以通过使用FILE_FLAG_OPEN_REPARSE_POINT标志打开链接本身(而不是它指向的文件)找到符号链接的目标,然后使用{{ 3}} IO控制代码,用于查找链接的目标。

因为链接的目标可能包含其他链接(我相信最多31个链接),您必须在路径的每个元素上执行此操作,以确保您已找到最终目标