Запись данных в идентификатор через 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):
Изменение только 48 байт расширенной части идентификатора описано здесь.
По теме идентификаторов также есть следующее:
- Идентификатор файлового объекта $OBJECT_ID
- Object Id Removal Tool — программа для удаления идентификаторов.
- ObjIdLib v0.2 Win32 и x64 dll, исходный код и справка.
Автор: амдф
Дата: 27.09.2011
Избранное
Остальное
По вопросам сотрудничества и другим вопросам по работе сайта пишите на cleogroup[собака]yandex.ru