【发布时间】:2017-08-17 13:49:35
【问题描述】:
我正在尝试开发一个程序来查找 2 个连接的未格式化物理驱动器并读取字节。该程序当前以管理员模式运行,因为这是我猜该程序可以看到未格式化的硬盘驱动器的唯一方法。我正在使用 Visual Studio 2015,它在 Windows 7 机器上运行。
问题是它只能读取 512 的倍数(512 是扇区大小)。目前未格式化的硬盘位于磁盘 2 和 3 插槽中(它们都是 SSD)。它首先读取 512 字节(正常工作),如果它是格式化的硬盘驱动器,则不再进行读取。如果它是未格式化的硬盘,它会继续读取更多字节。如果它是硬盘驱动器 A,它会读取接下来的 1024 个字节并且它可以工作(read_amount = 1024)。如果它是硬盘驱动器 B,它会读取接下来的 1025 个字节并且它不起作用(read_amount = 0)。我不确定为什么它不能读取 512/扇区大小的倍数。我的理解是,当您使用 dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL 调用“CreateFile()”函数时,我应该能够读取不是扇区大小倍数的大小(如果您使用 FILE_FLAG_NO_BUFFERING 那么您只能读取 512 的倍数而我没有使用那面旗帜)。请参阅下面的代码。
// Hard_Drive_Read.cpp : 定义控制台应用程序的入口点。
// 该程序假定您有两个未格式化的硬盘驱动器连接到您的计算机。
#include <Windows.h>
#include <io.h>
#include <fcntl.h>
#include <fstream>
#include <iostream>
#include <iomanip>
using namespace std;
int main(int argc, char *argv[])
{
if (argc != 3)
{
cout << "Need to enter 2 arguments" << endl;
exit(0);
}
int frames_to_process = atoi(argv[2]);
if (frames_to_process < 1)
{
cout << "invalid argument 2" << endl;
exit(0);
}
//HANDLE hDisk_A;
//HANDLE hDisk_B;
LPCTSTR dsksrc = L"\\\\.\\PhysicalDrive";
wchar_t dsk[512] = L"";
bool channel_A_found = false;
bool channel_B_found = false;
char frame_header_A[1024];
char frame_header_B[1025];
HANDLE hDisk;
char buff_read[512];
DWORD read_amount = 0;
for (int i = 0; i < 4; i++)
{
swprintf(dsk, 511, L"%s%d", dsksrc, i);
hDisk = CreateFile(dsk, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hDisk == INVALID_HANDLE_VALUE)
{
printf("%s%d%s", "couldn't open the drive ", i, "\n");
CloseHandle(hDisk);
}
else
{
printf("%s%d%s", "successfully open the drive ", i, "\n");
BOOL read_success_1 = ReadFile(hDisk, buff_read, 512, &read_amount, NULL);
cout << "read amount 1 - " << read_amount << endl;
if ((read_success_1 == TRUE) && (read_amount == 512))
{
if ((buff_read[510] == (char)0x55) && (buff_read[511] == (char)0xAA)) // test for a formatted drive; is there other identifiers?
{
cout << i << " is a formatted drive" << endl;
}
else
{
cout << "Not a formatted drive, trying to find sync " << endl;
ofstream writeBinary_Test;
if (i == 2)
{
writeBinary_Test.open("file_A_test.bin", ofstream::out | ofstream::binary);
ReadFile(hDisk, frame_header_A, 1024, &read_amount, NULL);
cout << "read amount " << read_amount << endl;
writeBinary_Test.write(frame_header_A, 1024);
writeBinary_Test.close();
}
else if(i == 3)
{
writeBinary_Test.open("file_B_test.bin", ofstream::out | ofstream::binary);
ReadFile(hDisk, frame_header_B, 1025, &read_amount, NULL);
cout << "read amount " << read_amount << endl;
writeBinary_Test.write(frame_header_B, 1025);
writeBinary_Test.close();
}
LARGE_INTEGER distanceToMove;
SetFilePointerEx(hDisk, distanceToMove, NULL, FILE_BEGIN);
}
}
else
{
}
}
if (channel_A_found && channel_B_found)
{
cout << "both drives found" << endl;
break;
}
}
if ((channel_A_found == false) || (channel_B_found == false))
{
cout << "Couldn't Find Hard Drive A or Drive B or Both" << endl;
cout << "Exiting the program" << endl;
exit(0);
}
CloseHandle(hDisk);
return 0;
}
最后,我想使用 SetFilePointerEx() 在硬盘驱动器上移动,我的程序必须使用和数据大小(不是 512 的倍数)。因此,我必须能够读取不是 512 倍数的大小。关于如何修复这个程序的任何想法?我是否正确使用了我的标志?
非常感谢任何帮助!
【问题讨论】:
-
ReadFile检查FO_NO_INTERMEDIATE_BUFFERING中的FILE_OBJECT标志,如果它将检查缓冲区大小和偏移量设置为多个DeviceObject->SectorSize。FO_NO_INTERMEDIATE_BUFFERING标志何时设置? I/O 子系统在CreateFile中使用FILE_NO_INTERMEDIATE_BUFFERING选项时设置它但 设备本身也可以设置它。FileSystem\Raw设备(当你打开它并处理你的文件对象时它会挂载物理磁盘)总是设置这个标志。
标签: winapi visual-c++ file-io hard-drive