hex.pp.ua

Идентификатор файлового объекта $OBJECT_ID

Создание и удаление идентификаторов файлов на NTFS




Уникальный идентификатор файла (object id) это буфер данных размером 64 байта, однозначно идентифицирующий файл в пределах локального тома NTFS. Он может присутствовать или отсутствовать у каждого файла на диске NTFS, а также имеется у каждого тома. Если он присутствует у файла, то он может быть открыт по этому идентификатору, даже если неизвестен путь.

$OBJECT_ID в списке
Идентификатор $OBJECT_ID

Уникальный идентификатор хранится в файловой записи NTFS в специальном системном потоке с именем ::$OBJECT_ID. Этот системный поток не может быть прочитан напрямую. Так, попытка прочитать его консольной командой more потерпит неудачу:

D:\TMP>more < file1::$OBJECT_ID
Отказано в доступе.

У тома 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.

Просмотр $OBJECT_ID
Просмотр идентификатора файла

Использование идентификатора в системе

В операционной системе 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. На картинке расширенная часть, подсвеченная жёлтым, переписана значениями, загруженными из внешнего файла:

Расширенная часть $OBJECT_ID
Расширенная часть

По теме идентификаторов также есть следующее:

система комментирования CACKLE

Автор: амдф
Дата: 01.04.2011


Разделы сайта
Главная
Блог
Native API
NTFS и ReFS
Микроконтроллеры
Справочник NTDLL
Коды NTSTATUS
Разное

Избранное
NTFS Stream Explorer
Native Shell
Тенгвар

Остальное
nvpnhcknn (архив)
English pages
Контакты

Ленты atom
Лента Atom сайта Лента Atom блога



При копировании материалов хорошим тоном будет указание авторства и ссылка на сайт.