Как получить путь из символической ссылки
Начиная с Windows Vista, в системе появились так называемые символические ссылки, специальные файлы, в которых вместо каких-либо данных содержится путь к другому файлу или каталогу, открываемому при обращении к этой ссылке. Это позволяет, например, иметь для одного и того же файла сразу несколько разных имен.Чтобы получить целевой путь, на который указывает символическая ссылка, есть несколько методов. Обычно в этих ваших интернетах рекомендуют сложный путь через использование функции DeviceIoControl. Штука интересная, с нее и начнем. Но сперва пачка структур и констант, которые нам понадобятся для работы.
Code (Assembler) : Убрать нумерацию
- struct SymbolicLinkReparseBuffer
- SubstituteNameOffset dw ?
- SubstituteNameLength dw ?
- PrintNameOffset dw ?
- PrintNameLength dw ?
- Flags dd ?
- PathBuffer rw MAX_PATH*2
- ends
- struct MountPointReparseBuffer
- SubstituteNameOffset dw ?
- SubstituteNameLength dw ?
- PrintNameOffset dw ?
- PrintNameLength dw ?
- PathBuffer rw MAX_PATH*2
- ends
- struct GenericReparseBuffer
- DataBuffer db ?
- ends
- struct REPARSE_DATA_BUFFER
- ReparseTag dd ?
- ReparseDataLength dw ?
- Reserved dw ?
- union
- SymbolicLink SymbolicLinkReparseBuffer
- MountPoint MountPointReparseBuffer
- Generic GenericReparseBuffer
- ends
- ends
- FSCTL_GET_REPARSE_POINT = 0x000900A8
- FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
- FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000
- IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003
- IO_REPARSE_TAG_SYMLINK = 0xA000000C
Получив привилегии, с помощью функции CreateFile открываем символическую ссылку с указанием флагов FILE_FLAG_BACKUP_SEMANTICS и FILE_FLAG_OPEN_REPARSE_POINT.
Code (Assembler) : Убрать нумерацию
- ; Открыть файл символической ссылки
- invoke CreateFile,dir_name,\
- 0,FILE_SHARE_READ,\
- NULL,OPEN_EXISTING,\
- FILE_FLAG_BACKUP_SEMANTICS+FILE_FLAG_OPEN_REPARSE_POINT,\
- NULL
- cmp eax,INVALID_HANDLE_VALUE
- je loc_exit
- ; Сохранить хэндл
- mov [hDirectory],eax
- ; Зарезервировать память
- invoke GlobalAlloc,GMEM_MOVEABLE+GMEM_DDESHARE+GMEM_ZEROINIT,\
- sizeof.REPARSE_DATA_BUFFER
- mov [mem],eax
- invoke GlobalLock,[mem]
- mov [memp],eax
- ; Получить данные объекта
- invoke DeviceIoControl,[hDirectory],\
- FSCTL_GET_REPARSE_POINT,\
- 0,0,\
- [memp],sizeof.REPARSE_DATA_BUFFER,\
- tmp,NULL
- or eax,eax
- jz loc_close
- ; Проверить тип данных
- mov eax,[memp]
- mov ecx,[eax+REPARSE_DATA_BUFFER.ReparseTag]
- ; Выбрать источник строки на основании типа
- cmp ecx,IO_REPARSE_TAG_MOUNT_POINT
- jne @f
- lea ebx,[eax+REPARSE_DATA_BUFFER.MountPoint.PathBuffer]
- jmp loc_message
- @@:
- cmp ecx,IO_REPARSE_TAG_SYMLINK
- jne loc_close
- lea ebx,[eax+REPARSE_DATA_BUFFER.SymbolicLink.PathBuffer]
- loc_message:
- ...
- ...
- ; EBX -> строка с названием целевого пути
- ...
- ...
- loc_close:
- ; Прибраться за собой
- invoke CloseHandle,[hDirectory]
- ; Освободить память
- invoke GlobalUnlock,[mem]
- invoke GlobalFree,[mem]
Со сложным путем закончили, теперь рассмотрим простой и приятный. Вместе с символическими ссылками в Windows Vista появилась функция GetFinalPathNameByHandle, с помощью которой также можно получить путь символической ссылки. Об обратной совместимости в этом случае можно не заботиться, так как и технология, и инструментарий, все появилось одновременно.
Code (Assembler) : Убрать нумерацию
- FILE_READ_EA = 0x0008
- FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
Code (Assembler) : Убрать нумерацию
- ; Открыть файл символической ссылки
- invoke CreateFile,dir_name,\
- FILE_READ_EA,\
- FILE_SHARE_READ+FILE_SHARE_WRITE,\
- NULL,OPEN_EXISTING,\
- FILE_FLAG_BACKUP_SEMANTICS,\
- NULL
- cmp eax,INVALID_HANDLE_VALUE
- je loc_exit
- ; Сохранить хэндл
- mov [hDirectory],eax
- ; Зарезервировать память
- invoke GlobalAlloc,GMEM_MOVEABLE+GMEM_DDESHARE+GMEM_ZEROINIT,\
- MAX_PATH*2
- mov [mem],eax
- invoke GlobalLock,[mem]
- mov [memp],eax
- ; Получить целевой объект символической ссылки
- invoke GetFinalPathNameByHandle,[hDirectory],[memp],MAX_PATH,0
- ...
- ...
- ; [memp] -> строка с названием целевого пути
- ...
- ...
- ; Прибраться за собой
- invoke CloseHandle,[hDirectory]
- ; Освободить память
- invoke GlobalUnlock,[mem]
- invoke GlobalFree,[mem]
В приложении примеры программ с исходными текстами, которые определяют путь из символической ссылки двумя разными способами.
Просмотров: 580 | Комментариев: 2
Метки: Assembler
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
евгений
(23.02.2024 в 18:06):
Да пригодилось, спасибо
Серый
(13.11.2022 в 02:09):
Спасибо огромное!
Добавить комментарий
Заполните форму для добавления комментария