void GetFileClusters(
PCHAR lpFileName, //имя файла
ULONG ClusterSize //размер кластера на диске
)
{
HANDLE hFile; //хэндл нерезидентного файла
ULONG OutSize; //размер буфера OutBuf
ULONG FileSize; //размер файла
ULONG Bytes, //количество байт. возвращаемых DeviceIoControl
ClCount, //количество кластеров в файле
r, //счетчики
CnCount; //количество кластеров в файле
LARGE_INTEGER PrevVCN, Lcn;
STARTING_VCN_INPUT_BUFFER InBuf;
//номер начального виртуального кластера
PRETRIEVAL_POINTERS_BUFFER OutBuf;
//буфер структуры, описывающей размещение файла
//на диске
hFile = CreateFile(lpFileName, FILE_READ_ATTRIBUTES,
FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, 0);
//открываем нерезидентный файл
if (hFile != INVALID_HANDLE_VALUE)
{
FileSize = GetFileSize(hFile, NULL);
//определяем размер файла
//определяем размер буфера OutBuf
OutSize = sizeof(RETRIEVAL_POINTERS_BUFFER) + (FileSize / ClusterSize) *
sizeof(OutBuf->Extents);
//выделяем память для структуры
OutBuf = (PRETRIEVAL_POINTERS_BUFFER)malloc(OutSize);
InBuf.StartingVcn.QuadPart = 0; //номер VCN начального экстента файла
//заполняем структуру, описывающую размещение файла
if (DeviceIoControl(hFile, FSCTL_GET_RETRIEVAL_POINTERS, &InBuf,
sizeof(InBuf), OutBuf, OutSize, &Bytes, NULL))
{
//количество кластеров в файле
ClCount = (FileSize + ClusterSize - 1) / ClusterSize;
//начальный VCN экстента (равен 0)
PrevVCN = OutBuf->StartingVcn;
//цикл перемещения по экстентам файла
for (r = 0; r < OutBuf->ExtentCount; r++)
{ //LCN кластера начала экстента
Lcn = OutBuf->Extents[r].Lcn;
//количество кластеров в текущем экстенте:
for(CnCount=OutBuf->Extents[r].NextVcn.QuadPart-PrevVCN.QuadPart;
CnCount; CnCount--, Lcn.QuadPart++)
//печатаем номер кластера
printf("%I64x ",Lcn.QuadPart);
//переходим к следующему экстенту
PrevVCN = OutBuf->Extents[r].NextVcn;
}
}
free(OutBuf);
CloseHandle(hFile);
}
}