I am attempting to follow this tutorial: Defragmenting Files.
I call DeviceIoControl()
with FSCTL_GET_VOLUME_BITMAP
on a handle to the C:
volume, and I get a proper response.
I then open a handle to another file (I tried files from 10KB to a few MB) successfully, then I call DeviceIoControl()
with FSCTL_GET_RETRIEVAL_POINTERS
, and it succeeds with no last error or failed result, but the RETRIEVAL_POINTERS_BUFFER
is not filled.
I also tried calling it on the C:
volume handle, but it keeps returning ERROR_HANDLE_EOF
even after trying to set the OVERLAPPED
offset to 0, and setting the file pointer with SetFilePointer()
to 0 relative to the beginning of the file.
BOOL dic(HANDLE dev, DWORD code, LPVOID in, DWORD ins, LPVOID out, LPDWORD outs)
{
HANDLE h = GetProcessHeap();
DWORD s = 1000;
DWORD r = 0;
out = HeapAlloc(h,HEAP_ZERO_MEMORY,s);
while (!DeviceIoControl(dev, code, in, ins, out, s, &r, 0))
{
if (ERROR_INSUFFICIENT_BUFFER == GetLastError() || ERROR_MORE_DATA == GetLastError())
{
s *= 10;
LPVOID t = HeapReAlloc(h, HEAP_ZERO_MEMORY, out, s);
if(!t){
HeapFree(h, 0, out);
return 0;
}
out = t;
}
else
{
HeapFree(h, 0, out);
printf("dic unk: %d\n", GetLastError());
return 0;
}
}
*outs = s;
return 1;
}
BOOL getvolptr(HANDLE volh, PRETRIEVAL_POINTERS_BUFFER rpb, LPDWORD rpbs)
{
STARTING_VCN_INPUT_BUFFER vcn = { 0 };
return dic(volh, FSCTL_GET_RETRIEVAL_POINTERS, &vcn, sizeof(vcn), rpb, rpbs);
}
RETRIEVAL_POINTERS_BUFFER rpb = { 0 };
DWORD rpbs = 0;
ULONGLONG cluster_cnt=0;
HANDLE fi = openfile("C:\\Windows\\System32\\Kernel32.dll");
if (INVALID_HANDLE_VALUE == fi)
{
printf("failed to open file! (%d)\n", GetLastError());
getchar();
}
r = getvolptr(fi, &rpb, &rpbs);
if (!r)
{
printf("failed to get vol ptrs! (%d)\n", GetLastError());
getchar();
}
for (int i = 0; i < rpb.ExtentCount; ++i)
{
cluster_cnt = (ULONGLONG)(rpb.Extents[i].NextVcn.QuadPart) - (ULONGLONG)(rpb.StartingVcn.QuadPart);
printf("%d) size: %llu clusters (0x%016X)\n", i, cluster_cnt, rpb.Extents[i].Lcn.QuadPart);
}