2015-03-28 2 views
0

Я хочу надежный способ получить имя тома цели символической ссылки, которая не слишком сложна.Лучший способ получить имя тома символической ссылки [NTFS]

Так выглядит, как структура FILE_NAME_INFO не содержит информации о томе, в котором находится файл. Я могу получить путь к объектам symlink из этой структуры, но на данный момент я просто предполагаю, что цель находится на том же томе. Тем не менее, я знаю, что символические ссылки разрешают задачи на других томах.

#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

Абсолютным простейшим способом, если вы можете ориентироваться на Vista или более позднюю версию, является использование функции GetFinalPathNameByHandle.

Если вам нужна целевая установка XP, то вы можете найти цель символической ссылки, открыв саму ссылку (а не файл, на которую она указывает), используя флаг FILE_FLAG_OPEN_REPARSE_POINT, а затем используйте код управления FSCTL_GET_REPARSE_POINT, чтобы найти цель связь.

Поскольку цель ссылки потенциально может содержать другие ссылки (до 31 мая), вы должны сделать это на каждом элементе пути, чтобы убедиться, что вы нашли конечную цель.

+0

Я не пробовал GetFinalPathNameByHandle и отдам его, но я попробовал второй предложенный вами метод. К сожалению, иногда это создавало относительные пути вместо абсолютных путей, и мне нужен последний. – Wes

+0

@Wes Если вы закончите с относительным путем, преобразуйте его в абсолютное значение с помощью 'GetFullPathName' (или просто выполните синтаксический анализ) –

+0

Это, кажется, идеально подходит для меня (используя GetFinalPathNameByHandle): http://pastebin.com/6PgGDttC – Wes