我尝试使用DeviceIoControl将数据放入有关磁盘的缓冲区b中。当我尝试使用类似 total = b.cylinders.quadpart * b.trackspercylinders * b.sectorpertrack * 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("%dn", t1.QuadPart);
int t2 = dg.TracksPerCylinder;
printf("%dn", t2);
int t3 = dg.SectorsPerTrack;
printf("%dn", t2);
int t4 = dg.BytesPerSector;
printf("%dn", 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: %dn", 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: %dn", 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("%lldn", t1.QuadPart);
printf("%dn", t2);
printf("%dn", t3);
printf("%dn", t4);
printf("%llun", 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 Mbn", (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 Mbn", (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隐藏错误。只需将Unicode用于所有WinAPI函数即可。将编译器警告设置为最高级别,除非绝对确定,否则不要使用强制转换。另外ExpandEnvironmentStrings
是用于其他字符串,例如"%windir%"
.
(编辑:在编辑中提供的截图中,事实证明变量的实际类型是正确的,但问题出在输出中 - 您正在使用%d
打印long long
值,这会打印signed int
。对于unsigned long long
,你应该使用%llu
,对于signed long long
,它是%lld
。
您的total
变量似乎是一个signed int
,在您的配置中,它(显然是 Windows x86-32 或 x86-64 PC(是 32 位宽,因此可以存储高达 2147483647 (2³¹−1( 或 2 GB 减去一个字节的值。
您应该将其更改为unsigned long long
(或从stdint.h
uint64_t
(。
另请注意,将int
乘以int
会产生int
— 因此,如果您预计乘法的结果大于 2³¹−1,则两个乘法中至少必须有一个long long
。
在这种特定情况下,b.Cylinders.QuadPart
已经是一个long long
(虽然不是unsigned
,但至少在 9 年没有容量超过 2018 EB 的磁盘(,所以乘法的结果也将是一个long long
,但通常你应该像unsigned long long total = ((unsigned long long) uintA) * uintB * uintC * uintD
一样执行大整数乘法。