Создание и удаление идентификаторов файлов на NTFS
Уникальный идентификатор файла (object id) это буфер данных размером 64 байта, однозначно идентифицирующий файл в пределах локального тома NTFS. Он может присутствовать или отсутствовать у каждого файла на диске NTFS, а также имеется у каждого тома. Если он присутствует у файла, то он может быть открыт по этому идентификатору, даже если неизвестен путь.
Уникальный идентификатор хранится в файловой записи NTFS в специальном системном потоке с именем ::$OBJECT_ID. Этот системный поток не может быть прочитан напрямую. Так, попытка прочитать его консольной командой more потерпит неудачу:
D:\TMP>moreУ тома NTFS существует специальный файл $ObjId, находящий в специальном каталоге $Extend. Этот файл отвечает за поддержку идентификаторов object id. Дополнительная информация в статье «Специальные файлы NTFS».
Формат $OBJECT_ID
Идентификатор состоит из четырёх GUID, которые определены в виде структуры OBJECTID_ATTRIBUTE:
typedef struct { GUID ObjectId; union { struct { GUID BirthVolumeId; GUID BirthObjectId; GUID DomainId; }; UCHAR Extended[48]; }; } OBJECTID_ATTRIBUTE, *POBJECTID_ATTRIBUTE;
-
ObjectId
Идентификатор объекта файловой системы. Уникален в пределах тома. -
BirthVolumeId
Идентификатор тома, на котором был создан файл. -
BirthObjectId
Идентификатор файла при создании. Значение может отличаться от ObjectId. -
DomainId
Зарезервировано. Не используется.
Поле ObjectId собственно и является идентификатором файла, а три других поля — дополнительные. Их содержимое можно в совокупности рассматривать просто как буфер данных размером 48 байт, в котором можно хранить произвольную информацию.
Просмотр данных $OBJECT_ID
Просмотр содержимого идентификатора файла можно произвести в программе NTFS Stream Explorer. Для этого нужно открыть в ней файл, найти в списке потоков $OBJECT_ID и открыть его двойным кликом. Откроется окно просмотра, в котором можно увидеть содержимое четырёх GUID.
Использование идентификатора в системе
В операционной системе Windows 7 идентификатор появляется у файла, если создать обыкновенный ярлык, указывающий на него. После этого файл можно переместить в любое место в пределах тома. При запуске ярлыка файл не потеряется, он откроется из нового расположения. При запуске ярлыка система сначала пытается запустить файл по пути, который прописан в ярлыке. Если по этому пути файла уже нет, выполняется получение нового пути файла по его идентификатору и успешное открытие, если файл не покидал пределы диска.
Создание и удаление $OBJECT_ID
Управление идентификаторами файлов в системе происходит с помощью WinAPI функции DeviceIoControl. Для некоторых операций потребуются привилегии SE_BACKUP_PRIVILEGE и SE_RESTORE_PRIVILEGE, а файлы нужно открывать с флагом FILE_FLAG_BACKUP_SEMANTICS.
Для создания или получения существующего идентификатора файла есть код FSCTL_CREATE_OR_GET_OBJECT_ID.
HANDLE hNew = CreateFile("file", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); OBJECTID_ATTRIBUTE Obj; DeviceIoControl(hNew, FSCTL_CREATE_OR_GET_OBJECT_ID, NULL, 0, &Obj, sizeof(OBJECTID_ATTRIBUTE), &dwRet, NULL) CloseHandle(hNew);
Если у файла нет идентификатора, он будет создан и помещён в Obj, если идентификатор есть, он будет прочитан и тоже помещён в Obj.
Если необходимо создать файловый идентификатор вручную, то есть полностью самостоятельно задать все 64 байта, не доверяя генерацию идентификатора системе, нужно воспользоваться методом записи данных в идентификатор через FSCTL_SET_OBJECT_ID
Идентификатор можно удалить. Делается это при помощи кода FSCTL_DELETE_OBJECT_ID.
HANDLE hNew = CreateFile("file", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_FLAG_BACKUP_SEMANTICS, NULL); OBJECTID_ATTRIBUTE Obj; DeviceIoControl(hDel, FSCTL_DELETE_OBJECT_ID, NULL, 0, NULL, 0, &dwRet, NULL); CloseHandle(hDel);
Расширенную часть идентификатора (поле Extended структуры OBJECTID_ATTRIBUTE) можно переписать своими собственными данными. Для этого есть код FSCTL_SET_OBJECT_ID_EXTENDED. Таким образом становится возможно использовать object id как хранилище небольшого объёма метаданных.
HANDLE hNew = CreateFile("file", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_FLAG_BACKUP_SEMANTICS, NULL); OBJECTID_ATTRIBUTE Obj; DeviceIoControl(hNew, FSCTL_SET_OBJECT_ID_EXTENDED, &Obj.Extended, 48, NULL, 0, &dwRet, NULL) CloseHandle(hNew);
Такую операцию позволяет выполнять NTFS Stream Explorer, начиная с версии 1.06. На картинке расширенная часть, подсвеченная жёлтым, переписана значениями, загруженными из внешнего файла:
По теме идентификаторов также есть следующее:
- Запись данных в идентификатор через FSCTL_SET_OBJECT_ID.
- Object Id Removal Tool — программа для удаления идентификаторов.
- ObjIdLib v0.2 Win32 и x64 dll, исходный код и справка.
Автор: амдф
Дата: 01.04.2011
По вопросам сотрудничества и другим вопросам по работе сайта пишите на cleogroup[собака]yandex.ru