从物理硬盘读取数据

时间:2017-03-24 14:51:59

标签: winapi visual-c++ file-io hard-drive

我正在尝试开发一个程序,找到2个连接的无格式物理驱动器和读取字节。该程序目前以管理员模式运行,因为这是我猜程序可以看到未格式化硬盘的唯一方法。我正在使用visual studio 2015,它在Windows 7机器上运行。

问题是它只能读取512的倍数(512是扇区大小)。目前,未格式化的硬盘驱动器位于磁盘2和3插槽中(它们都是SSD)。它首先读取512个字节(工作没有问题),如果它是格式化的硬盘驱动器,则不再执行任何读取操作。如果它是未格式化的硬盘驱动器,它会继续读取更多字节。如果它的硬盘驱动器A然后读取下一个1024字节并且它工作(read_amount = 1024)。如果它的硬盘驱动器B然后读取下一个1025字节并且它不起作用(read_amount = 0)。我不知道为什么它不能读取512 /扇区大小的倍数。我的理解是,当你打电话给" CreateFile()"函数与dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL,我应该能够读取不是扇区大小倍数的大小(如果你使用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的倍数的大小。有关如何修复此程序的任何想法?我正确使用旗帜吗?

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:2)

documentation for CreateFile说:

  

即使未在CreateFile中指定非高速缓存选项,也可以根据特定文件系统的判断将卷句柄打开为非高速缓存。您应该假设所有Microsoft文件系统都将未处理的卷句柄打开。对文件的非高速缓存I / O的限制也适用于卷。

虽然它没有明确说明,但这适用于驱动器和卷。

在实践中,这不是问题。编写一个辅助函数是很简单的,该函数从任意偏移量返回任意数量的数据,同时只执行对齐的读取。

答案 1 :(得分:1)

  

我必须阅读的尺寸不是512的倍数。

这是不可能的。对于磁盘的直接访问,您只能读取和写入扇区大小的倍数。此外,您必须对齐读写操作。也就是说,文件指针必须是扇区大小的倍数。

如果您想提供一个允许任意搜索,读取和写入的界面,那么您需要在对齐的原始磁盘访问之上实现自己的缓冲。