Идентификатор файлового объекта $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
Расширенная часть

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



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


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