我已经尝试使用 DeviceIoControl 将数据放入磁盘的缓冲区 b 中。当我尝试使用诸如 total = b.cylinders.quadpart * b.trackspercylinds * b.sectorspertrack * b.bytespersector 之类的东西时,我最终得到一个负数。现在我不知道如何评估磁盘中的扇区总数来运行 for 循环并使用 readfile 函数打印出内容。 相同的代码片段将非常有用。
TCHAR cOutputPath0[32000];
char strPath[] = "\\\\.\\PhysicalDrive0";
ExpandEnvironmentStrings((LPCTSTR)strPath, cOutputPath0, (sizeof(cOutputPath0) / sizeof(*cOutputPath0)));
HANDLE drive = CreateFile(cOutputPath0, GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
DWORD br = 0;
DISK_GEOMETRY dg;
DeviceIoControl(drive, IOCTL_DISK_GET_DRIVE_GEOMETRY, 0, 0, &dg, sizeof(dg), &br, 0);
TCHAR sectorData[32000];
LARGE_INTEGER t1 = dg.Cylinders;
printf("%d\n", t1.QuadPart);
int t2 = dg.TracksPerCylinder;
printf("%d\n", t2);
int t3 = dg.SectorsPerTrack;
printf("%d\n", t2);
int t4 = dg.BytesPerSector;
printf("%d\n", t2);
unsigned long long total = t1.QuadPart*t2*t3*t4;
unsigned long long j;
printf("%d", total);
for (j = 0; j < total; j++) {
LARGE_INTEGER pos;
pos.QuadPart = j* dg.BytesPerSector;
SetFilePointerEx(drive, pos, 0, FILE_BEGIN);
if (ReadFile(drive, sectorData, dg.BytesPerSector, &br, NULL) && br == dg.BytesPerSector) {
printf("%s", sectorData);
}
}
这段代码看起来正确吗?因为我似乎仍然得到一个负数!
最佳答案
CreateFile
在这种情况下很容易失败,要么是因为需要管理员访问权限,要么是因为 "\\\\.\\PhysicalDrive0"
是错误的磁盘。强烈建议对任何文件操作进行基本错误检查。
以管理员权限运行程序,并确保 "\\\\.\\PhysicalDrive0"
是正确的磁盘(它并不总是 C:\
)
SetFilePointerEx
。文件指针在每次 ReadFile
#define UNICODE
#include <stdio.h>
#include <Windows.h>
int main(void)
{
HANDLE handle = CreateFile(L"\\\\.\\PhysicalDrive0",
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL);
if(handle == INVALID_HANDLE_VALUE)
{
//wrong disk, or admin access required
DWORD err = GetLastError();
printf("!CreateFile, GetLastError: %d\n", err);
CloseHandle(handle);
return 0;
}
DWORD br = 0;
DISK_GEOMETRY dg;
if(!DeviceIoControl(handle, IOCTL_DISK_GET_DRIVE_GEOMETRY,
0, 0, &dg, sizeof(dg), &br, 0))
{
DWORD err = GetLastError();
printf("!DeviceIoControl, GetLastError: %d\n", err);
return 0;
}
LARGE_INTEGER t1 = dg.Cylinders;
int t2 = dg.TracksPerCylinder;
int t3 = dg.SectorsPerTrack;
int t4 = dg.BytesPerSector;
unsigned long long total = t1.QuadPart*t2*t3*t4;
printf("%lld\n", t1.QuadPart);
printf("%d\n", t2);
printf("%d\n", t3);
printf("%d\n", t4);
printf("%llu\n", total);
//setup a counter
long long i = 0;
int bufsize = dg.BytesPerSector;
char *buf = malloc(bufsize);
while(ReadFile(handle, buf, bufsize, &br, NULL))
{
if(!br)
break;
//print update
if((i % 1000) == 0)
printf("%.2f Mb\n", (double)i * bufsize / 1000000.0f);
i++;
}
free(buf);
CloseHandle(handle);
return 0;
}
请注意,上面的代码一次读取一个扇区。如果您想分别检查每个扇区,这很有用,但速度也很慢。
下面的方法显示一次读取 100 个扇区。这更快但更复杂一些,因为它包括不一定相关的扇区。要检查,您可以将 buf
分成不同的扇区。
//read N number of dg.BytesPerSector for each pass
int N = 100;
int bufsize = dg.BytesPerSector * N;
char *buf = malloc(bufsize);
while(ReadFile(handle, buf, bufsize, &br, NULL))
{
if(!br)
break;
//print update
if((i % 1000) == 0)
printf("%.2f Mb\n", (double)i * bufsize / 1000000.0f);
i++;
//look for *.cpp files which have the string `#include` in them:
//buf includes N sectors
//look for `#include` in each sector and print the first 100 characters
for(int j = 0; j < N * dg.BytesPerSector; j += dg.BytesPerSector)
if(strstr(&buf[j], "#include"))
printf("%.100s ...\n", &buf[j]);
}
旁注:您正在使用
(LPCTSTR)strPath
这表明该程序是使用定义的 UNICODE
编译的(应该如此)但是您使用 ANSI 字符串作为参数,然后使用 cast隐藏错误。只需对所有 WinAPI 函数使用 Unicode。将编译器警告设置为最高级别,除非您绝对确定,否则不要使用强制转换。此外,ExpandEnvironmentStrings
用于其他字符串,例如 "%windir%"
。
关于c - 在C中逐位读取整个磁盘的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50541731/