1

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?

dspaces1
  • 193
  • 1
  • 3
  • 15

1 Answers1

2

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.

Ivan
  • 2,007
  • 11
  • 15
  • I tried you method and for some reason at LARGE_INTEGER lastExtentN = retrievalBuffer->ExtentCount - 1; it says that ExtentCount is suppose to be unsigned long? Also in the extent size did you mean to use NextVcn as opposed to Vcn? – dspaces1 Jun 05 '14 at 21:20
  • There seems to be another error now because you are trying to subtract a DWORD from a Large INTERGER when trying to find out the extent size. I'm a little bit lost in a logic. – dspaces1 Jun 09 '14 at 14:33