Страницы

Поиск по вопросам

среда, 13 марта 2019 г.

C++ Определение физического расположения файла на диске

Для начала, мне не даётся использование DeviceIoControl. Говорит, что hFile неверный, хотя он не NULL. С какими атрибутами открывать?
ANDLE hFile = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
RETRIEVAL_POINTERS_BUFFER rpb; STARTING_VCN_INPUT_BUFFER startingVcn; DWORD dwBytesReturned; OVERLAPPED overlapped;
DWORD dwFragments = 0, dwTotalClusters = 0;
// ...
DeviceIoControl(hFile, FSCTL_GET_REPARSE_POINT, &startingVcn, sizeof startingVcn, &rpb, sizeof rpb, &dwBytesReturned, &overlapped);
// ... while(dwError == ERROR_MORE_DATA);
Далее алгоритм будет следующий: Вызвать GetLastError и по коду ошибки определить дальнейшие действия.
Если это первая итерация и ERROR_HANDLE_EOF, значит файл резидентный, если не первая, то выход из цикла. Если NO_ERROR, файл занимает 1 фрагмент кластеров (т.е. все по-порядку, а не в разброс по диску). Если ERROR_MORE_DATA, есть ещё на диске фрагменты этого файла.
Таким образом, будем иметь список всех фрагментов файла на диске ввиде списка пар StartLCN-ClustersLength.
Так же, понятия не имею, что делать, если файл резидентный. Как вытащить его положение на диске?
Работать всё это должно под FAT, FAT32 и NTFS (с поддержкой SPARSE, COMPRESSED и ENCRYPTED файлов).
Нужно это положение для программы безопасного удаления данных, т.е. потом я полученные кластеры затру.


Ответ

HANDLE hFile = CreateFile(lpFilePath, FILE_READ_EA, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
if (hFile == INVALID_HANDLE_VALUE) { wcout << "Open file error: " << GetLastError() << endl; system("pause"); return -1; }
PSTARTING_VCN_INPUT_BUFFER startingVcn = new STARTING_VCN_INPUT_BUFFER(); PRETRIEVAL_POINTERS_BUFFER prpb = new RETRIEVAL_POINTERS_BUFFER();
DWORD dwBytesReturned = 0; DWORD dwExtentNumber = 0, dwTotalClusters = 0; DWORD dwError;
do { DeviceIoControl(hFile, FSCTL_GET_RETRIEVAL_POINTERS, startingVcn, sizeof *startingVcn, prpb, sizeof *prpb, &dwBytesReturned, NULL);
dwError = GetLastError();
switch (dwError) { case ERROR_HANDLE_EOF:
if (dwExtentNumber == 0) cout << "MFT Table..." << endl; else wcout << endl << "Total clusters: " << dwTotalClusters << endl << "Fragments: " << dwExtentNumber << endl;
break; case NO_ERROR:
wcout << "Fragment 0:" << endl << "\tStart LCN: " << prpb->Extents->Lcn.QuadPart << endl << "\tClusters: " << prpb->Extents->NextVcn.QuadPart - prpb->StartingVcn.QuadPart << endl << endl;
wcout << "Total clusters: " << prpb->Extents->NextVcn.QuadPart - prpb->StartingVcn.QuadPart << endl << "Fragments: " << dwExtentNumber;
break; case ERROR_MORE_DATA:
wcout << "Fragment " << dwExtentNumber << ":" << endl << "\tStart LCN: " << prpb->Extents->Lcn.QuadPart << endl << "\tClusters: " << prpb->Extents->NextVcn.QuadPart - prpb->StartingVcn.QuadPart << endl << endl;
dwTotalClusters += prpb->Extents->NextVcn.QuadPart - prpb->StartingVcn.QuadPart; startingVcn->StartingVcn.QuadPart = prpb->Extents->NextVcn.QuadPart;
break; default:
wcout << "DeviceIoControl error: " << dwError << endl; system("pause"); return -1; }
dwExtentNumber++;
} while (dwError == ERROR_MORE_DATA);
CloseHandle(hFile);
system("pause"); return 0;

Комментариев нет:

Отправить комментарий