如何解决在 Windows 上以编程方式对文件进行碎片整理
我正在尝试学习本教程:Defragmenting Files。
我在 DeviceIoControl()
卷的句柄上使用 FSCTL_GET_VOLUME_BITMAP
调用 C:
,我得到了正确的响应。
然后我成功打开另一个文件的句柄(我尝试了从 10KB 到几 MB 的文件),然后我用 DeviceIoControl()
调用 FSCTL_GET_RETRIEVAL_POINTERS
,它成功了,没有最后的错误或失败的结果,但 RETRIEVAL_POINTERS_BUFFER
未填充。
我还尝试在 C:
卷句柄上调用它,但即使在尝试将 ERROR_HANDLE_EOF
偏移量设置为 0 并将文件指针设置为 {{ 1}} 到 0 相对于文件的开头。
OVERLAPPED
解决方法
您没有检查第一个 HeapAlloc()
是否失败。并且 HeapFree()
可以在打印之前擦除 DeviceIoControl()
中的最后一个错误代码。
但更重要的是,您没有正确地将 out
数据传回给调用者,因此您正在泄漏分配的内存,而调用者最终会输出垃圾。
由于调用者传入自己的RETRIEVAL_POINTERS_BUFFER
来接收数据,所以需要将分配内存的内容复制到那个缓冲区中,例如:
BOOL dic(HANDLE dev,DWORD code,LPVOID in,DWORD ins,LPVOID out,LPDWORD outs)
{
if (!in || !out || !outs)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
*outs = 0;
HANDLE h = GetProcessHeap();
DWORD s = 1000;
LPVOID buf = HeapAlloc(h,HEAP_ZERO_MEMORY,s);
if (!buf)
return FALSE;
DWORD r = 0;
while (!DeviceIoControl(dev,code,in,ins,buf,s,&r,0))
{
if (ERROR_INSUFFICIENT_BUFFER == GetLastError() || ERROR_MORE_DATA == GetLastError())
{
s *= 10;
LPVOID t = HeapReAlloc(h,s);
if (!t)
{
HeapFree(h,buf);
return FALSE;
}
buf = t;
}
else
{
printf("dic unk: %u\n",GetLastError());
HeapFree(h,buf);
return FALSE;
}
}
if (s > *outs)
{
HeapFree(h,buf);
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
CopyMemory(out,s);
*outs = s;
HeapFree(h,buf);
return TRUE;
}
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);
}
HANDLE fi = openfile("C:\\Windows\\System32\\Kernel32.dll");
if (INVALID_HANDLE_VALUE == fi)
{
printf("failed to open file! (%u)\n",GetLastError());
getchar();
}
else
{
RETRIEVAL_POINTERS_BUFFER rpb = { 0 };
DWORD rpbs = sizeof(rpb);
if (!getvolptr(fi,&rpb,&rpbs))
{
printf("failed to get vol ptrs! (%u)\n",GetLastError());
getchar();
}
else
{
ULONGLONG cluster_cnt = 0;
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);
}
}
closefile(fi);
}
或者,您可以将指向已分配内存的指针返回给调用者,调用者在使用完内存后必须释放内存,例如:
BOOL dic(HANDLE dev,LPVOID* out,LPDWORD outs)
{
if (!in || !out || !outs)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
*out = NULL;
*outs = 0;
HANDLE h = GetProcessHeap();
DWORD s = 1000;
LPVOID buf = HeapAlloc(h,buf);
return FALSE;
}
}
*out = buf;
*outs = s;
return TRUE;
}
BOOL getvolptr(HANDLE volh,PRETRIEVAL_POINTERS_BUFFER* rpb,(void**)rpb,GetLastError());
getchar();
}
else
{
PRETRIEVAL_POINTERS_BUFFER rpb = NULL;
DWORD rpbs = 0;
if (!getvolptr(fi,GetLastError());
getchar();
}
else
{
ULONGLONG cluster_cnt = 0;
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",rpb->Extents[i].Lcn.QuadPart);
}
HeapFree(GetProcessHeap(),rpb);
}
closefile(fi);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。