I'm trying to find the last cluster of a target file and read the binary data off of it. I started off with CreateFile() and used that result in DeviceIoControl() with control code FSCTL_GET_RETRIEVAL_POINTERS.
hfile = CreateFile(result,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
RETRIEVAL_POINTERS_BUFFER retrievalBuffer;
const DWORD Clusters = 1000;
const DWORD rpBufferSize = sizeof(RETRIEVAL_POINTERS_BUFFER) + (2 * (Clusters - 1) *sizeof(LARGE_INTEGER));
BYTE output[rpBufferSize];
STARTING_VCN_INPUT_BUFFER startVcn;
startVcn.StartingVcn.QuadPart = 0;
returns = DeviceIoControl(hfile,
FSCTL_GET_RETRIEVAL_POINTERS,
&startVcn,
sizeof(startVcn),
&output,
sizeof(output),
&bytesReturned,
NULL);
So I don't really know what to do next. If I display LARGE_INTEGER Lcn
from the RETRIEVAL_POINTERS_BUFFER
I get a huge number which represents the current extent. I also have a switch error case which comes up as NO_ERROR
so I am assuming that all the cluster data was read successfully. What can I do which the Lcn number to help me find the last cluster of the file?
retrievalBuffer
should be a pointer:
RETRIEVAL_POINTERS_BUFFER *retrievalBuffer = (RETRIEVAL_POINTERS_BUFFER *) output;
So the last extent starts at
DWORD lastExtentN = retrievalBuffer->ExtentCount - 1;
LARGE_INTEGER extentLcn = retrievalBuffer->Extents[ lastExtentN ].Lcn;
The extent size is
LARGE_INTEGER extentClusters = retrievalBuffer->Extents[ lastExtentN ].NextVcn
- lastExtentN ? retrievalBuffer->Extents[ lastExtentN - 1 ].NextVcn
: retrievalBuffer->StartingVcn;
Thus, last logical cluster number (LCN) of the file is:
LARGE_INTEGER lastLcn = extentLcn + extentClusters - 1;
Now you can open logical volume using CreateFile()
and read this cluster using ReadFile()
NOTE: you need to check extentLcn
against -1
to support sparse files.