tags:

views:

1187

answers:

3

In C, using the standard Windows API, what is the best way to read an unformatted disk? Specifically, I have an MMC or SD card with data, but no file system (not FAT16, not FAT32, just raw data). If there was a simple way to open the entire card for byte by byte binary access, that would be great.

Thanks!

+1  A: 

You have to open the device file with CreateFile and then use ReadFile/readFileEx. Don't forget to close the file with CloseHandle

Kasprzol
+1  A: 

CreateFile function reference on MSDN

Scroll down to "Physical Disks and Volumes" - note the security restrictions on Vista do not apply for voulmes without a filesystem, so you'll be fine even on Vista under the conditions you have given.

szevvy
+4  A: 

I would go with

HANDLE drive = CreateFile(_T("\\.\PhysicalDrive0"), GENERIC_READ, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
// error handling
DWORD br = 0;
DISK_GEOMETRY dg;
DeviceIOControl(drive, IOCTL_DISK_GET_DRIVE_GEOMETRY, 0, 0, &dg, sizeof(dg), &br, 0);
//
LARGE_INTEGER pos;
pos.QuadPart = static_cast<LONGLONG>(sectorToRead) * dg.BytesPerSector;
SetFilePointerEx(drive, pos, 0, FILE_BEGIN);
const bool success = ReadFile(drive, sectorData, dg.BytesPerSector, &br) && br == dg.BytesPerSector;
//
CloseHandle(drive);

Please note that in order to verify that you've successfully read a sector you must verify that the read byte count corresponds to the number of bytes you wanted to read, i.e. in my experience ReadFile() on a physical disk can return TRUE even when no bytes are read (or maybe I just have a buggy driver).

The problem that remains is to determine your drive number (0 as is used in my example refers to C: which is probably not what you want). I don't know how to do that, but if you only have one drive connected which is not formatted, it ought to be possible by calling opening each PhysicalDrive in order and calling DeviceIOControl() with IOCTL_DISK_GET_DRIVE_LAYOUT_EX as a command:

DRIVE_LAYOUT_INFORMATION_EX dl;
DeviceIOControl(drive, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, 0, 0, &dl, sizeof(dl), &br, 0);
if(dl.PartitionStyle == PARTITION_STYLE_RAW)
{
  // found correct disk
}

But that's just a guess.

Andreas Magnusson