Как получить программный доступ к целевому пути символьной ссылки Windows?

Windows 6 (Vista и Server 2008) поддерживает правильные символические ссылки, которые можно создавать с помощью функции CreateSymbolicLink. Но, похоже, нет соответствующей функции для опроса символической ссылки для получения пути к цели ссылки.

Я обнаружил, что символические ссылки являются реализацией точек повторной обработки, и поэтому функции точечной обработки могут использоваться для получения целевого пути. Но заголовочные файлы, которые мне нужны, чтобы использовать точки повторной обработки, похоже, поставляются с Windows Driver Kit. Настройка этого комплекта с VS2008 представляется нетривиальной задачей.

Есть ли хорошая простая функция, которую я пропустил для получения цели ссылки, или мне действительно нужно настроить среду разработки драйверов Windows, чтобы писать код для доступа к этой информации?

РЕДАКТИРОВАТЬ: Адам Митц выступил с предложением GetFinalPathNameByHandle. Эта функция прекрасно работает с локальными символическими ссылками, но, похоже, не работает для разрешения удаленных ссылок (по пути UNC).

РЕДАКТИРОВАТЬ 2: По просьбе Адама, вот более подробная информация о том, что я пытался:

Я изначально пошел вниз FSCTL_GET_REPARSE_POINT/ DeviceIoControl маршрут, но это дает REPARSE_DATA_BUFFER состав. Заголовки, которые определяют эту структуру, похоже, существуют исключительно в Windows Driver Kit.

GetFinalPathNameByHandle() отлично работает, когда ссылка существует на локальном диске (C:\...\link так далее). Любопытно, что я обнаружил, что могу получить указатель на ссылку - и, таким образом, получить цель - используя CreateFileW() будь то FILE_FLAG_OPEN_REPARSE_POINT Флаг был указан или нет, независимо от того, существует ли целевой файл.

когда CreateFileW() а также GetFinalPathNameByHandle() используются для опроса удаленной ссылки, хотя (\\?\UNC\....), вещи начинают распадаться. Если FILE_FLAG_OPEN_REPARSE_POINT указано, GetFinalPathNameByHandle() всегда возвращает путь ссылки, а не целевой путь. Если FILE_FLAG_OPEN_REPARSE_POINT не указывается, тогда целевой путь возвращается, но только если целевой объект существует и находится на том же компьютере, что и ссылка. Если ссылка указывает на другую машину, я получаю ошибку сетевых разрешений. Если ссылка указывает на локальный - несуществующий - файл, я получаю ошибку "файл не найден".

2 ответа

Решение

GetFinalPathNameByHandle

Конечный путь - это путь, который возвращается, когда путь полностью разрешен. Например, для символической ссылки с именем "C:\tmp\mydir", которая указывает на "D:\yourdir", конечный путь к файловой системе будет "D:\yourdir".

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

Правильный ответ, по-видимому, заключается в использовании С++17std::filesystem::read_symlinkфункция, это фактически прочитает данные точки повторной обработки и даст вам точный путь, который содержит символическая ссылка, будь то абсолютный или относительный, и даже работает, если путь назначения не существует. Кроме того, он работает и в приложениях UWP, несмотря на то, что базовые API-интерфейсы Windows, по-видимому, не поддерживаются в приложениях UWP.

Другие вопросы по тегам