2015-09-11 2 views
2

Я использую FindFirstFile() и сопутствующие функции для просмотра содержимого C:\example\dir. Я знаю, что чтение файла может представлять собой символическую ссылку, соединение и т. Д., Проверяя, d.dwAttributes & FILE_ATTRIBUTE_REPARSE_POINT != 0. Тем не менее, я не нашел способ следить за ссылкой и видеть местоположение, на которое оно указывает. Возможно ли это?Поиск ссылки на символическую ссылку (Windows)

ответ

3

Чтобы найти цель символической ссылки, вам нужно открыть символическую ссылку. Диспетчер объектов разыгрывает ссылку и возвращает дескриптор в целевое местоположение. Вызов GetFinalPathNameByHandle на этом дескрипторе возвращает путь к цели.

Следующая реализация возвращает местоположение цели, учитывая символическую ссылку:

std::wstring GetLinkTarget(const std::wstring& a_Link) { 
    // Define smart pointer type for automatic HANDLE cleanup. 
    typedef std::unique_ptr<std::remove_pointer<HANDLE>::type, 
          decltype(&::CloseHandle)> FileHandle; 
    // Open file for querying only (no read/write access). 
    FileHandle h(::CreateFileW(a_Link.c_str(), 0, 
           FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 
           nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr), 
        &::CloseHandle); 
    if (h.get() == INVALID_HANDLE_VALUE) { 
     h.release(); 
     throw std::runtime_error("CreateFileW() failed."); 
    } 

    const size_t requiredSize = ::GetFinalPathNameByHandleW(h.get(), nullptr, 0, 
                  FILE_NAME_NORMALIZED); 
    if (requiredSize == 0) { 
     throw std::runtime_error("GetFinalPathNameByHandleW() failed."); 
    } 
    std::vector<wchar_t> buffer(requiredSize); 
    ::GetFinalPathNameByHandleW(h.get(), buffer.data(), 
           static_cast<DWORD>(buffer.size()), 
           FILE_NAME_NORMALIZED); 

    return std::wstring(buffer.begin(), buffer.end() - 1); 
} 


Примечание: Для получения дополнительной информации о RAII обертки на основе std::unique_ptr см std::unique_ptr, deleters and the Win32 API.

+0

В коде есть ошибка: дескриптор файла не закрыт в конце функции. Он только закрывается, если GetFinalPathNameByHandleW() возвращается 0. – Andy

+0

@Andy: Это правда. Там также есть еще одна ошибка, это менее заметно: если 'std :: vector' выдает исключение, дескриптор файла также не закрывается. Это можно решить, используя библиотеку, которая реализует RAII над 'HANDLE'. Я добавлю соответствующие комментарии. – IInspectable

+0

@IInpectable: в C++ 11 вы можете использовать 'std :: unique_ptr' или' std :: shared_ptr' (или эквиваленты форсирования) в качестве оболочки RAII, они поддерживают пользовательские удалители, а 'CloseHandle()' может используется для деэфира. –

Смежные вопросы