hex.pp.ua

Запись собственных данных в ObjectId

Запись данных в идентификатор через FSCTL_SET_OBJECT_ID




Уникальный идентификатор файла (object id) в NTFS является необязательным элементом файла. У большинства файлов в нормальных условиях он отсутствует. В некоторых условиях идентификатор у файла создаёт сама система. Иногда требуется самому создать ObjectID у файла, в этом случае можно сделать так, чтобы он был сгенерирован системой, а можно создать идентификатор полностью самому, используя вызов DeviceIoControl с параметром FSCTL_SET_OBJECT_ID.

Для создания объектного идентификатора файла на NTFS программе необходимо иметь привилегию SE_RESTORE_NAME. Получить эту привилегию можно с помощью такого кода:

static BOOL EnableRestorePrivilege(void)
{
  HANDLE hToken;
  LUID sedebugnameValue;
  TOKEN_PRIVILEGES tp;

  if (!OpenProcessToken(GetCurrentProcess(), 
    TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
  {
    return FALSE;
  }

  if (!LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &sedebugnameValue))
  {
    CloseHandle( hToken );
    return FALSE;
  }

  tp.PrivilegeCount = 1;
  tp.Privileges[0].Luid = sedebugnameValue;
  tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

  if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL))
  {
    CloseHandle(hToken);
    return FALSE;
  }

  CloseHandle(hToken);
  return TRUE;
}

Дальше необходимо инициализировать файловый идентификатор — структуру типа OBJECTID_ATTRIBUTE. В ней нужно обязательно заполнить поле ObjectId уникальным идентификатором (GUID). Если на локальном томе уже есть файл, имеющий такое же значение ObjectId, то дальнейший вызов DeviceIoControl завершится неудачей. Нужно обеспечить уникальность задаваемого идентификатора. В остальных полях структуры могут быть произвольные значения.

Дальше нужно вызвать DeviceIoControl с параметром FSCTL_SET_OBJECT_ID, передавая функции структуру OBJECTID_ATTRIBUTE. Файл должен быть открыт с флагом FILE_FLAG_BACKUP_SEMANTICS, что позволяет также получать хэндл каталога. Код функции установки идентификатора:

static BOOL SetObjectId(IN LPCWSTR sFileName, IN POBJECTID_ATTRIBUTE pObjId)
{
  if (NULL == pObjId)
  {
    return FALSE;
  }

  DWORD dwRet;
  HANDLE hNew = CreateFile(sFileName, GENERIC_WRITE, FILE_SHARE_WRITE, 
    NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);

  if (hNew == INVALID_HANDLE_VALUE)
  {    
    return FALSE;
  }  

  if (!DeviceIoControl(hNew, FSCTL_SET_OBJECT_ID, pObjId, 64, NULL, 0, &dwRet, NULL))
  {
    CloseHandle(hNew);
    return FALSE;
  }

  CloseHandle(hNew);
  return TRUE;
}

Выполнение следующего кода

int _tmain(int argc, _TCHAR* argv[])
{
  OBJECTID_ATTRIBUTE ObjId;  
  GUID FileId = // {B9AEAB96-3D73-456B-895D-29E55DE6C2E8}
    { 0xb9aeab96, 0x3d73, 0x456b, 
      { 0x89, 0x5d, 0x29, 0xe5, 0x5d, 0xe6, 0xc2, 0xe8 } 
    };
  ObjId.ObjectId = FileId;

  EnableRestorePrivilege();
  SetObjectId(L"D:\\tmp\\a.txt", &ObjId);

  return 0;
}

приводит к установке у файла такого идентификатора (до вызова кода файл не содержал ObjectID):

Просмотр ObjectID в NTFS Stream Explorer
Просмотр ObjectID в NTFS Stream Explorer

Изменение только 48 байт расширенной части идентификатора описано здесь.

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



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


При копировании материалов хорошим тоном будет указание авторства и ссылка на сайт. По поводу рекламы обращайтесь на почту [email protected]