现在,我已经熟悉DeviceIoControl(ioctl)进程,并且可以按顺序从磁盘读取,一次512字节。
我从\。\ PhysicalDrive列表中创建一个句柄,并通过IOCTL_STORAGE_QUERY_PROPERTY命令识别它。然后处理所需的数据设备。
此时,我可以通过创建一个循环来逐步读取它,每次使用此代码(Qt C ++环境)推进读取区域1扇区
load ("file.RData")
Encoding(df1$TEAM)<-"latin1"
Encoding(df2$TEAM)<-"latin1"
Encoding(df3$Team)<-"latin1"
按顺序执行此操作意味着我必须一个接一个地遍历各个扇区,直到达到我想要访问的扇区号。而且这在表现上并不是最优的。
如果我想直接访问特定区域,例如“转到扇区45535并读取512字节”,该怎么办? IOCTL操作是否允许这样的随机访问?我知道#include <minwindef.h>
#include <devioctl.h>
#include <ntdddisk.h>
#include <ntddscsi.h>
#include <ioapiset.h>
#include <fileapi.h>
#include <handleapi.h>
#include <winbase.h>
...
HANDLE devHandle = NULL;
devHandle = CreateFile(charArray, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0 ,NULL);
unsigned long secCount = 0;
while(true)
{
bSuccess = ReadFile(devHandle, lpSecBuf, 512, &dwRead, NULL);
if (bSuccess & (dwRead < 512))
{
qDebug()<<"EOF";
break;
}
if(!bSuccess)
{
qDebug()<<"No data could be read from the device.";
break;
}
if(bSuccess && dwRead>0)
{
qDebug()<<"Sector "<<secCount<<" data : "<<lpSecBuf;
}
secCount++;
}
电话有随机访问标志,但在那之后,什么?就我所见,read函数仍然不允许我将任何参数作为“目标”或类似的东西传递。
例如,HxD十六进制编辑器可以立即计算磁盘中总扇区的数量,并且可以随时转到某个扇区。我需要的功能与此功能类似。
我已经收集了关于如何做到的各种提示,但我实际上陷入僵局。
欢迎任何想法。
答案 0 :(得分:3)
读取功能仍然不允许我传递任何参数 &#34;目的地&#34;或者类似的东西,据我所见。
这不是真的 - 再次阅读ReadFile
lpOverlapped [in,out,optional]
对于支持字节偏移的hFile,如果您使用此参数 必须指定一个字节偏移量,从该文件开始读取文件或 设备。通过设置偏移和偏移高来指定此偏移 OVERLAPPED结构的成员。
和此:
使用文件句柄的注意事项:
•如果lpOverlapped不为NULL,则读取操作从偏移处开始 在OVERLAPPED结构中指定...
I / O管理器维护当前文件位置。 (查找FILE_OBJECT
的LARGE_INTEGER CurrentByteOffset
成员)。 ReadFile
和WriteFile
通过添加完成操作时读取或写入的字节数来更新当前文件位置。我们也可以通过电话SetFilePointer[Ex]
如果我们以同步模式打开文件(没有FILE_FLAG_OVERLAPPED
标志),所有带文件的操作都是顺序的 - 任何新操作都不会开始执行,直到之前没有完成。
在这种情况下,我们有两个选择:
NULL
指针来实现
lpOverlapped
lpOverlapped
来重置此位置
价值为ReadFile
或WriteFile
。这样做会自动更改
当前文件位置为(Offset, OffsetHigh)
值,
执行读(写)操作,然后更新位置
根据实际读取的字节数(写入)。这个
技术为调用者提供原子搜索和读取(写入)服务。所以通过代码我们有两个变种:
BOOL _ReadFile(HANDLE hFile, LARGE_INTEGER ByteOffset, PVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead)
{
#if 1
OVERLAPPED ov = {};
ov.Offset = ByteOffset.LowPart;
ov.OffsetHigh = ByteOffset.HighPart;
return ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, &ov);
#else
if (SetFilePointerEx(hFile, ByteOffset, 0, FILE_BEGIN))
{
return ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, 0);
}
return FALSE;
#endif
}
当然,使用SetFilePointer[Ex]
(对内核的额外API调用)比较原子搜索和读取(写入)更有效。
如果我们以异步模式打开文件(带有FILE_FLAG_OVERLAPPED
标志) - 可以同时执行多个带文件的读/写操作。在这种情况下,I / O管理器无法使用FILE_OBJECT
中的文件位置 - 因为这里存在未定义的行为。
因此我们必须始终使用有效偏移量明确传递lpOverlapped
。如果我们为lpOverlapped传递NULL
指针 - 我们得到ERROR_INVALID_PARAMETER
错误
最后但很重要。来自MSDN(ReadFile和WriteFile页)
系统在 ReadFile 之前更新 OVERLAPPED 偏移量( WriteFile ) 回报。
这不是真的,也不是文档中的错误 - 您可以检查一下OVERLAPPED
偏移量在操作后是否未更新。可能意味着更新当前文件位置(CurrentByteOffset
中的FILE_OBJECT
)。但操作后再次OVERLAPPED
偏移未更新