Windows physical disk image writer in C

My recent project is to write a raw image file into CFast card, and I was looking for a physical disk writer on google. Finally I found this http://m0n0.ch/wall/physdiskwrite.php, but it doesn’t work properly.

  1. GUI is not Englisht
  2. When image size is too big, it doesn’t show the correct size.

Then I decide to make my own physical disk image writer in C.

Be extremely careful to use this tool, incorrect disk number can completely corrupt your disk data! I am not responsible for this.

Download

PhyDiskWrite.zip (4k)

#include <windows.h>

void PrintHelp()
{
    printf("Usage: phydiskwrite [imagefile]\r\n\r\n");
}

HANDLE OpenDisk(int deviceID)
{
    HANDLE hDisk;
    TCHAR diskName[MAX_PATH];
    _stprintf_s(diskName, _T("\\\\.\\PhysicalDrive%d"), deviceID);
    hDisk = CreateFile(diskName, 
        GENERIC_READ | GENERIC_WRITE, 
        FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
    return hDisk;
}

int PrintDisks()
{
    printf("Searching for physical drives...\r\n\r\n");
    DWORD bytes;
    TCHAR diskName[MAX_PATH];
    HANDLE hDisk;
    int selectedDisk = -1;
    for (int i = 0; i < 255; i++)
    {
        hDisk = OpenDisk(i);
        if (hDisk == INVALID_HANDLE_VALUE)
            continue;
        printf("Information for Device %d\r\n", i);

        DISK_GEOMETRY pdg = { 0 };
        if (!DeviceIoControl(hDisk, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &pdg, sizeof(pdg), &bytes, NULL))
        {
            printf("error: Get disk info failed %d\r\n", GetLastError());
            continue;
        }
        ULONGLONG DiskSize = pdg.Cylinders.QuadPart 
            * (ULONG)pdg.TracksPerCylinder 
            * (ULONG)pdg.SectorsPerTrack 
            * (ULONG)pdg.BytesPerSector;
        CloseHandle(hDisk);
        printf("\tByte/Sec %d, Cylinders: %d, Sector/Track %d, Track/Cylinder %d\r\n", 
            pdg.BytesPerSector, pdg.Cylinders, pdg.SectorsPerTrack, pdg.TracksPerCylinder);
        printf("\tDevice:%d, Media Type:%d Disk Size: %.2f (Gb)\r\n\r\n", 
            i, pdg.MediaType, (double)DiskSize / (1024.0f * 1024.0f * 1024.0f));
    }
    printf("Which disk do you want to write?\r\n");
    printf("(Be careful, wrong disk number could corrupt your entire disk!)\r\n");
    scanf("%d", &selectedDisk);
    return selectedDisk;
}

int _tmain(int argc, _TCHAR* argv[])
{   
    if (argc != 2)
    {
        PrintHelp();
        return 0;
    }
    
    int devID = PrintDisks();
    if (devID != -1)
    {
        HANDLE hDisk = OpenDisk(devID);
        BYTE buffer[65536];
        DWORD byteRead, byteWrite, status;
        ULONGLONG totalWrite = 0;
        LARGE_INTEGER fileSize;
        HANDLE hImage = CreateFile(argv[1], 
            GENERIC_READ, FILE_SHARE_READ, NULL, 
            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hImage == INVALID_HANDLE_VALUE)
        {
            printf("error: Open file failed %d", GetLastError());
            return -1;
        }

        GetFileSizeEx(hImage, &fileSize);
        while (ReadFile(hImage, buffer, 65536, &byteRead, NULL) && byteRead > 0)
        {
            if (!WriteFile(hDisk, buffer, byteRead, &byteWrite, NULL))
            {
                printf("error: Write to disk failed %d", GetLastError());
                break;
            }
            else
            {
                printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
                totalWrite += byteRead;
                printf("%f%%", totalWrite * 100.0f / fileSize.QuadPart);
            }
        }
        CloseHandle(hImage);
        CloseHandle(hDisk);
    }
    return 0;
}

2 thoughts on “Windows physical disk image writer in C”

Comments are closed.