Вверх ↑
Этот топик читают: Гость
Ответов: 2344
Рейтинг: 682
#1: 2025-03-25 15:10:03 ЛС | профиль | цитата
В Windows есть файлы(папки) символических ссылок (подробней можно поискать информацию в сети: NTFS Reparse Points). В проводнике отображаются с характерным ярлыком и особо не отличаются от папок.

В файловых менеджерах они уже называются как Ссылки, чем по сути и являются.

Сама Windows не много дает информации о них.

В HiAsm нет возможности определить что это именно ссылка. Ни FileSearch, ни FileAttribute нет возможности определить даже нужный атрибут, не говоря уже о том куда ссылается такая папка.

Внес следующие изменения.
hiFileSearch.pas:
-Выдает на точку Attr число где 9 бит говорит о том что это ссылка
FileSearch.ini
-Дополнил описание к данной точке о битах

hiFileAttribute.pas:
-добавлено doGetReparsePoint и onGetReparsePoint с помощь которых можно получить данные о символической ссылке. На onError выдаются ошибки если что-то пойдет не так (чтение файла, получение данных)
-внесены изменения в работу doGetFileIcon позволяющие получать иконку не только файла и папки, но и привязанного расширения (.bmp,.txt). Так же с иконкой можно получить описание типа файла (свойство TypeNameIcon). Иконка можно получить залитой цветом как выделенная (свойство SelectIcon) и/или как ссылочную с стрелкой в нижнем левом углу (свойство LinkIcon).


Внесенные не вредят совместимости с предыдущими версиями и лишь дополняют функционал.

В простой тестовой схеме можно ввести в ручную или перетащить любую папку/файл символической ссылки из проводника или любого файлового менеджера для получения данных. Желательно хорошенько протестировать.


Скачать архив (31_03_2025)

Редактировалось 7 раз(а), последний 2025-04-08 21:50:52
карма: 11

0
Ответов: 182
Рейтинг: 4
#2: 2025-03-26 08:49:45 ЛС | профиль | цитата
Если кто-то владеет информацией почему некоторые ссылки начинаются на \??\ или заканчиваются на \? . Не нашел внятного описания этого вопроса. В многих примерах это тупо отрезали, что и сделано мной. Но возможно есть более правильное решение.


sla8a, может это? https://habr.com/ru/articles/731628/

Редактировалось 1 раз(а), последний 2025-03-26 08:50:48
карма: 1

0
Ответов: 2344
Рейтинг: 682
#3: 2025-03-26 13:07:54 ЛС | профиль | цитата
strannik_nebes, эта тема о другом.
карма: 11

0
Ответов: 182
Рейтинг: 4
#4: 2025-03-28 13:09:38 ЛС | профиль | цитата
sla8a, про слои ни слова какой версии
Подготовка к сборке проекта...
Генерация кода целевого языка
Компоновка проекта...
Command line: dcc32.exe "D:\Soft\HiAsm 4 AltBuild\Elements\delphi\code\TEST_GET_REPARSE_POINT.dpr" "-UD:\Soft\Updete_For_GET_REPARSE_POINT_25_03_2025\test\." -Q
Borland Delphi Version 12.0 Copyright (c) 1983,98 Inprise Corporation

D:\Soft\HiAsm 4 AltBuild\Elements\delphi\code\hiVBoxLayout.pas(10) Hint: Overriding virtual method 'THIVBoxLayout.Sort' has a lower visibility than base class 'TWinLayout'

D:\Soft\HiAsm 4 AltBuild\Elements\delphi\code\hiMainForm_8BB6620.pas(506) Error: Undeclared identifier: '_event_onGetReparsePoint'

D:\Soft\HiAsm 4 AltBuild\Elements\delphi\code\hiMainForm_8BB6620.pas(518) Error: Undeclared identifier: '_work_doGetReparsePoint'

D:\Soft\HiAsm 4 AltBuild\Elements\delphi\code\TEST_GET_REPARSE_POINT.dpr(7) Fatal: Could not compile used unit 'hiMainForm_8BB6620.pas'
Сборка завершена.


Редактировалось 2 раз(а), последний 2025-03-28 13:10:47
карма: 1

0
Ответов: 2344
Рейтинг: 682
#5: 2025-03-29 12:42:41 ЛС | профиль | цитата
strannik_nebes, можно поточнее о чем речь?
карма: 11

0
Ответов: 1118
Рейтинг: 80
#6: 2025-03-29 22:42:25 ЛС | профиль | цитата
Не выводит путь целиком, обрезает конечные символы.

sla8a писал(а):
заканчиваются на \?

Чего начинаются фиг знает, что-то там тянется с досовских времен. Походу, как всегда, для совместимости оставили хлам в ядре.
А вот по поводу заканчиваются скажу.
Не спроста REPARSE_DATA_BUFFER имеет поля "хххххOffset"
"\?" в конце, это начало следующей строки "\??\путь кудато там"


Для примера чуток подравил ваше решение.

Не вникал, нет времени, да и с англяцким не дружу. Но чтобы довести до ума надо вникнуть в это


клац

procedure THIFileAttributes._work_doGetReparsePoint;//add sla8a 25_03_2025
...
var cnt:integer;
...

//_debug(int2str(Buf.SubstituteNameOffset) + ' : ' + int2str(Buf.SubstituteNameLength) + ' : ' + int2str(Buf.PrintNameOffset) + ' : ' + int2str(Buf.PrintNameLength));
iCounter := 0;
cnt:=0;

While cnt < Buf.SubstituteNameLength div 2 do
begin
if Char(Buf.DataBuffer[iCounter*2]) <> chr(0) then
begin
cnt:=cnt+1;
path := path + Char(Buf.DataBuffer[iCounter*2]);
end;
iCounter:=iCounter+1;
end;


//for iCounter := 0 to Buf.SubstituteNameLength div 2 - 1 do
// path := path + Char(Buf.DataBuffer[iCounter * 2]);
//Replace(path,#0,'');
if Copy(path, 1, 4) = '\??\' then Delete(path, 1, 4);
l := Length(path);
//if Copy(path, l - 1, 2) = '\?' then Delete(path, l - 1, 2);
if Copy(path, l - 3, 4) = '\??\' then Delete(path, l - 3, 4);
_hi_onEvent(_event_onGetReparsePoint,path);
end;

--- Добавлено в 2025-03-29 22:52:24

P.S.

The path string contains the substitute name string and print name string. The substitute name and print name strings can appear in any order in the PathBuffer. To locate the substitute name and print name strings in the PathBuffer, use the SubstituteNameOffset, SubstituteNameLength, PrintNameOffset, and PrintNameLength members.

Если почитать, что полезно, то все становится на свои места
Тоесть "в любом порядке", вот и оффсет пригодился. Я только не понял, а чем отличаются SubstituteName и PrintName. Вроде как они всегда одинаковые.
Вобщем читать не перечитать этот msdn

так лучше

  CloseHandle(lFileHandle);

//(* for PrintName
for iCounter := 0 to Buf.ReparseDataLength - 1 do
if Char(Buf.DataBuffer[iCounter]) <> chr(0) then path := path + Char(Buf.DataBuffer[iCounter]);
path:= Copy(path, Buf.PrintNameOffset div 2, Buf.PrintNameLength div 2); //*)

(* for SubstituteName
for iCounter := 0 to Buf.ReparseDataLength - 1 do
if Char(Buf.DataBuffer[iCounter]) <> chr(0) then path := path + Char(Buf.DataBuffer[iCounter]);
path:= Copy(path, Buf.SubstituteNameOffset div 2+1, Buf.SubstituteNameLength div 2);
//if Copy(path, 1, 4) = '\??\' then Delete(path, 1, 4); //*)

(*
for iCounter := 0 to Buf.SubstituteNameLength div 2 - 1 do
path := path + Char(Buf.DataBuffer[iCounter * 2]);
Replace(path,#0,'');
if Copy(path, 1, 4) = '\??\' then Delete(path, 1, 4);
l := Length(path);
if Copy(path, l - 1, 2) = '\?' then Delete(path, l - 1, 2); //*)

_hi_onEvent(_event_onGetReparsePoint,path);


Редактировалось 3 раз(а), последний 2025-03-30 19:12:20
карма: 1

1
Голосовали:sla8a
Ответов: 2344
Рейтинг: 682
#7: 2025-03-30 21:19:04 ЛС | профиль | цитата
tom-it, спасибо что откликнулся! Это помогло посмотреть еще раз и понять проблему. Код переделал все работает, но добавились вопросы по оформлению вывода данных из элемента.
sla8a писал(а):
так лучше
Нет никаких обрезаний или замен не нужно точно.

И так что имеем.
Во первых, символическая ссылка может быть:
- MOUNT_POINT
- SYMLINK
Если глубоко не копать то это одни и те же данные о пути. Вопрос в том нужно ли эта информация в событии.

Во вторых, если ссылка SYMLINK, то в данных есть флаг который говорит о том что содержащийся в ссылки путь:
- (значение 0) полный путь
- (значение 1) путь относительно каталога, содержащего символическую ссылку
У меня ни на одном компьютере нет символической ссылки SYMLINK с значением 1 (см. test_screenshot строки 2,4 колонка FL) . В теории то понятно как она выглядит, но вот хотелось бы протестировать. И опять таки вопрос надо ли выдавать эти данные.

В третьих, символическая ссылка содержит две строки:
-одна строка (от SubstituteNameOffset и длинной SubstituteNameLength ) путь с дополнительными символами \??\ (да возможно и не только с этими символами)
-вторая строка (от PrintNameOffset и длинной PrintNameLength) путь без лишнего
Вот это меня по первому времени и запутало так как они могут идти и не по порядку (см. test_screenshot выделенную строку). Как по мне то достаточно будет PrintName.

На данный момент тестовая схема выдает только PrintName Arg(path). Нужно ли выдавать другие данные? К примеру Arg(Path,SubPath,TypeLink,SubFlag), где Path - PrintName, SubPath - SubstituteName, TypeLink - тип символическая ссылки (скорее всего число) и SubFlag - 0 - полный путь SubstituteName или 1 - относительный.

test_screenshot

Символ # заменяет \0.
На мусор в конце строк не обращайте внимание, это для тестирования.
Ref.. - это полный объем данных
SNO - SubstituteNameOffset
SNL - SubstituteNameLength
PNO - PrintNameOffset
PNL - PrintNameLength
FL - флаг (описание "во вторых")

Архив в первом посте перезалил.

Редактировалось 3 раз(а), последний 2025-03-30 21:27:19
карма: 11

0
Ответов: 1118
Рейтинг: 80
#8: 2025-03-30 21:57:21 ЛС | профиль | цитата
sla8a писал(а):
Нужно ли выдавать другие данные?

если таковы имеются значит они кому-то нужны. Погрузились в тему и реализация не потребует больших усилий, тогда выдавать.

sla8a писал(а):
Как по мне то достаточно будет PrintName

Знать бы что оно в реальности означает, а не просто догадки. У меня PrintName ассоциируется с выводом чего-то приятного на глаз

Редактировалось 1 раз(а), последний 2025-04-07 20:59:37
карма: 1

0
Ответов: 876
Рейтинг: 187
#9: 2025-03-30 22:11:05 ЛС | профиль | цитата
sla8a писал(а):
Сама Windows не много дает информации о них.

Команда dir /AL /S C:\ найдет все ссылочные папки и файлы на диске C:
Hard Links, Junction Points, Symbolic Links
У меня на компьютере это занимает минуты две

Редактировалось 2 раз(а), последний 2025-03-30 22:14:11
карма: 18

1
Голосовали:sla8a
Ответов: 182
Рейтинг: 4
#10: 2025-03-31 08:03:31 ЛС | профиль | цитата
можно поточнее о чем речь?

После обновления ошибка компиляции пропала. Обнаружилась другая с FPC x32 (с x64 проблема с ZIP):
Add(MainForm,2953706,21,105)
{
}
Add(FileSearch,12681969,336,196)
{
Ext="*.zip"
Point(onOtherFiles)
link(onOtherFiles,1079989:doOrder,[(404,216)(404,132)])
}
Add(Zipper,1079989,441,119)
{
@Color=16755285
Method=1
UpdateMode=2
Point(doPassword)
}


Редактировалось 5 раз(а), последний 2025-03-31 08:38:38
карма: 1

0
Ответов: 2344
Рейтинг: 682
#11: 2025-03-31 16:30:49 ЛС | профиль | цитата
Обновил архив в первом посте. onGetReparsePoint выдает все данные о символической ссылки. Изменил тестовую схему, можно запустить поиск ссылок на диске.


tom-it писал(а):
Знать бы что оно в реальности означает
Тоже интересно чем Substitute Name отличается от Print Name. На тестируемых мной двух компьютерах это две одинаковые строки, только с добавлением у одной впереди: \??\. Возможно в каких-то случаях они несут разные строки.

Gunta, командная строка это хорошо, но речь шла об проводнике, которым и пользуются подавляющее большинство пользователей. И почему система скрывает путь символической ссылки мне не понятно. По тем же ярлыкам система и предоставляет всю информацию и разрешает ее менять. В чем большая тайна вывести в свойствах что С:\Documents and Settings это ссылка на C:\Users, без возможности это менять.
Gunta, если с Symbolic Links понятно, оно и в коде так же называется. То Junction в коде как MOUNT_POINT. На данный момент оставил JUNKTION и SYMLINKD. А как лучше обозвать?

strannik_nebes, эти файлы еще в тестовом режиме и еще вопрос нужны ли будут эти доработки в основном пакете. Все на стадии тестировании и подгонять их под FPC x32 (с x64 проблема с ZIP) на данный момент нет смысла. Если очень нужно то:
-выделить элемент FileSearch, нажать Ctrl+F
-нажать Ctrl+F для запуска она поиска, ввести ToString, найти строку и добавить Share. чтоб получилось:
 _prop_Format := Share.ToString(_Data);
-нажать Ctrl+S чтоб сохранить изменения в файле, вкладку с кодом можно закрыть и проверить
Насколько понял то ошибка только в этом.

Редактировалось 3 раз(а), последний 2025-03-31 16:34:56
карма: 11

0
Ответов: 1118
Рейтинг: 80
#12: 2025-03-31 18:01:23 ЛС | профиль | цитата
sla8a писал(а):
JUNKTION и SYMLINKD

Если SYMLINKD тогда и JUNKTION как в оригинале на JUNCTION

sla8a писал(а):
Share.ToString

Нужно уже сейчас привыкать. В штатном пакете ToString всеравно в Share живет. А при переносе на порядок меньше правок будет, а то и вовсе без правок
Темболее что со штатным fpc, данная реализация, не работает.

Да, на новом компиляторе filesearch вылетает, но сегодня лень, уже пупком к верху пивасик тяну
карма: 1

0
Ответов: 876
Рейтинг: 187
#13: 2025-03-31 18:15:05 ЛС | профиль | цитата
sla8a писал(а):
если с Symbolic Links понятно, оно и в коде так же называется. То Junction в коде как MOUNT_POINT. На данный момент оставил JUNKTION и SYMLINKD. А как лучше обозвать?

Как я это понимаю:
HARD LiINK– указывает только на локальный файл(не на папку). Выглядит как обычный файл, но реальное место на диске не занимает
JUNCTION – разновидность Hard Links но указывают только на папку
SYMLINKD – может указывать на локальный файл, папку и сетевой каталог, поддерживаются относительные пути. По сути являются обычным ярлыком.
Всё это справедливо только для NTFS

Редактировалось 2 раз(а), последний 2025-03-31 18:17:43
карма: 18

0
Ответов: 1118
Рейтинг: 80
#14: 2025-03-31 18:25:44 ЛС | профиль | цитата
Gunta писал(а):
HARD LiINK– указывает только на локальный файл(не на папку). Выглядит как обычный файл, но реальное место на диске не занимает
JUNCTION – разновидность Hard Links но указывают только на папку

+ только в пределах раздела.
карма: 1

0
Ответов: 1118
Рейтинг: 80
#15: 2025-03-31 20:16:20 ЛС | профиль | цитата
sla8a писал(а):
Насколько понял то ошибка только в этом.

Походу не только

strannik_nebes добавил правки от sla8a для fpc 3.2.2

мютекс из тестовой схемы пока что изъять, не работает. Хотя вроде как проблем с ним не наблюдалось.

Редактировалось 1 раз(а), последний 2025-03-31 20:20:34
карма: 1

0
файлы: 1hiFileSearch_hiFileAttributes.zip [5.4KB] [38]
Сообщение
...
Прикрепленные файлы
(файлы не залиты)