カタバミさんのプログラミングノート

日曜プログラマーがプログラミング関係のメモを記録するブログです。

ドライブのジオメトリ情報(物理的なサイズ情報)の取得(IOCTL_DISK_GET_DRIVE_GEOMETRY)

DeviceIoControl関数を用いてドライブの物理ディスクジオメトリ情報(物理的なサイズ情報)を取得するサンプルコードです。この投稿ではIOCTL_DISK_GET_DRIVE_GEOMETRYを用いた場合を紹介します。詳細な説明はいつか。

シンプルなコード

#define STRICT
#include <Windows.h>
#include <strsafe.h>

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    HANDLE volumeHandle = CreateFile(
        TEXT("\\\\.\\C:"),
        GENERIC_READ,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        nullptr,
        OPEN_EXISTING,
        0,
        nullptr);
    if (volumeHandle == INVALID_HANDLE_VALUE) {
        return 0;
    }

    DISK_GEOMETRY diskGeometry;
    DWORD returnedBytes = 0;
    BOOL succeeded = DeviceIoControl(
        volumeHandle,
        IOCTL_DISK_GET_DRIVE_GEOMETRY,
        nullptr, 0,
        &diskGeometry, sizeof diskGeometry,
        &returnedBytes,
        nullptr);

    TCHAR buffer[1024];
    succeeded = SUCCEEDED(StringCbPrintf(buffer, sizeof buffer,
        TEXT("シリンダ数: %lld\n")
        TEXT("メディアの種類: %ld\n")
        TEXT("シリンダ当たりのトラック数: %ld\n")
        TEXT("トラック当たりのセクタ数: %ld\n")
        TEXT("セクタ当たりのバイト数: %ld"),
        diskGeometry.Cylinders,
        diskGeometry.MediaType,
        diskGeometry.TracksPerCylinder,
        diskGeometry.SectorsPerTrack,
        diskGeometry.BytesPerSector));
    MessageBox(HWND_DESKTOP, buffer, TEXT("Cドライブのジオメトリ情報"), MB_ICONINFORMATION);

    CloseHandle(volumeHandle);

    return 0;
}

ヘルパー関数を追加したコード

#define STRICT
#include <Windows.h>
#include <StrSafe.h>

inline DWORD BytesPerTrack(const DISK_GEOMETRY& diskGeometry) {
    return diskGeometry.BytesPerSector * diskGeometry.SectorsPerTrack;
}

inline DWORD BytesPerClinder(const DISK_GEOMETRY& diskGeometry) {
    return BytesPerTrack(diskGeometry) * diskGeometry.TracksPerCylinder;
}

inline LARGE_INTEGER BytesPerDisk(const DISK_GEOMETRY& diskGeometry) {
    LARGE_INTEGER ret;
    ret.QuadPart = BytesPerClinder(diskGeometry) * diskGeometry.Cylinders.QuadPart;
    return ret;
}

// DISK_GEOMETRY構造体のMediaTypeの値からMEDIA_TYPE列挙体での名前を返します。
// MicrosoftのWinIoCtl.h BUILD Version: 0016から引用しています。
inline LPCTSTR MediaTypeValueName(const DISK_GEOMETRY& diskGeometry) {
    switch (diskGeometry.MediaType) {
    case Unknown: return TEXT("Unknown");
    case F5_1Pt2_512: return TEXT("F5_1Pt2_512");
    case F3_1Pt44_512: return TEXT("F3_1Pt44_512");
    case F3_2Pt88_512: return TEXT("F3_2Pt88_512");
    case F3_20Pt8_512: return TEXT("F3_20Pt8_512");
    case F3_720_512: return TEXT("F3_720_512");
    case F5_360_512: return TEXT("F5_360_512");
    case F5_320_512: return TEXT("F5_320_512");
    case F5_320_1024: return TEXT("F5_320_1024");
    case F5_180_512: return TEXT("F5_180_512");
    case F5_160_512: return TEXT("F5_160_512");
    case RemovableMedia: return TEXT("RemovableMedia");
    case FixedMedia: return TEXT("FixedMedia");
    case F3_120M_512: return TEXT("F3_120M_512");
    case F3_640_512: return TEXT("F3_640_512");
    case F5_640_512: return TEXT("F5_640_512");
    case F5_720_512: return TEXT("F5_720_512");
    case F3_1Pt2_512: return TEXT("F3_1Pt2_512");
    case F3_1Pt23_1024: return TEXT("F3_1Pt23_1024");
    case F5_1Pt23_1024: return TEXT("F5_1Pt23_1024");
    case F3_128Mb_512: return TEXT("F3_128Mb_512");
    case F3_230Mb_512: return TEXT("F3_230Mb_512");
    case F8_256_128: return TEXT("F8_256_128");
    case F3_200Mb_512: return TEXT("F3_200Mb_512");
    case F3_240M_512: return TEXT("F3_240M_512");
    case F3_32M_512: return TEXT("F3_32M_512");
    default: return nullptr;
    }
}

// DISK_GEOMETRY構造体のMediaTypeの値からMEDIA_TYPE列挙体での説明を返します。
// MicrosoftのWinIoCtl.h BUILD Version: 0016から引用しています。
inline LPCTSTR MediaTypeDescription(const DISK_GEOMETRY& diskGeometry) {
    switch (diskGeometry.MediaType) {
    case Unknown: return TEXT("Format is unknown");
    case F5_1Pt2_512: return TEXT("5.25\", 1.2MB, 512 bytes / sector");
    case F3_1Pt44_512: return TEXT("3.5\", 1.44MB, 512 bytes / sector");
    case F3_2Pt88_512: return TEXT("3.5\", 2.88MB, 512 bytes / sector");
    case F3_20Pt8_512: return TEXT("3.5\", 20.8MB, 512 bytes / sector");
    case F3_720_512: return TEXT("3.5\", 720KB, 512 bytes / sector");
    case F5_360_512: return TEXT("5.25\", 360KB, 512 bytes / sector");
    case F5_320_512: return TEXT("5.25\", 320KB, 512 bytes / sector");
    case F5_320_1024: return TEXT("5.25\", 320KB, 1024 bytes / sector");
    case F5_180_512: return TEXT("5.25\", 180KB, 512 bytes / sector");
    case F5_160_512: return TEXT("5.25\", 160KB, 512 bytes / sector");
    case RemovableMedia: return TEXT("Removable media other than floppy");
    case FixedMedia: return TEXT("Fixed hard disk media");
    case F3_120M_512: return TEXT("3.5\", 120M Floppy");
    case F3_640_512: return TEXT("3.5\", 640KB, 512 bytes / sector");
    case F5_640_512: return TEXT("5.25\", 640KB, 512 bytes / sector");
    case F5_720_512: return TEXT("5.25\", 720KB, 512 bytes / sector");
    case F3_1Pt2_512: return TEXT("3.5\", 1.2Mb, 512 bytes / sector");
    case F3_1Pt23_1024: return TEXT("3.5\", 1.23Mb, 1024 bytes / sector");
    case F5_1Pt23_1024: return TEXT("5.25\", 1.23MB, 1024 bytes / sector");
    case F3_128Mb_512: return TEXT("3.5\" MO 128Mb   512 bytes / sector");
    case F3_230Mb_512: return TEXT("3.5\" MO 230Mb   512 bytes / sector");
    case F8_256_128: return TEXT("8\", 256KB, 128 bytes / sector");
    case F3_200Mb_512: return TEXT("3.5\", 200M Floppy(HiFD)");
    case F3_240M_512: return TEXT("3.5\", 240Mb Floppy(HiFD)");
    case F3_32M_512: return TEXT("3.5\", 32Mb Floppy");
    default: return nullptr;
    }
}

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    HANDLE volumeHandle = CreateFile(
        TEXT("\\\\.\\C:"),
        GENERIC_READ,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        nullptr,
        OPEN_EXISTING,
        0,
        nullptr);
    if (volumeHandle == INVALID_HANDLE_VALUE) {
        return 0;
    }

    DISK_GEOMETRY diskGeometry;
    DWORD returnedBytes = 0;
    BOOL succeeded = DeviceIoControl(
        volumeHandle,
        IOCTL_DISK_GET_DRIVE_GEOMETRY,
        nullptr, 0,
        &diskGeometry, sizeof diskGeometry,
        &returnedBytes,
        nullptr);

    TCHAR buffer[1024];
    succeeded = SUCCEEDED(StringCbPrintf(buffer, sizeof buffer,
        TEXT("シリンダ数: %llu\n")
        TEXT("メディアの種類: %ld (%s) - \"%s\"\n")
        TEXT("シリンダ当たりのトラック数: %lu\n")
        TEXT("トラック当たりのセクタ数: %lu\n")
        TEXT("セクタ当たりのバイト数: %lu\n")
        TEXT("-----\n")
        TEXT("トラック当たりのバイト数: %lu\n")
        TEXT("シリンダ当たりのバイト数: %lu\n")
        TEXT("ディスク当たりのバイト数: %lu"),
        diskGeometry.Cylinders,
        diskGeometry.MediaType,
        MediaTypeValueName(diskGeometry),
        MediaTypeDescription(diskGeometry),
        diskGeometry.TracksPerCylinder,
        diskGeometry.SectorsPerTrack,
        diskGeometry.BytesPerSector,
        // -----,
        BytesPerTrack(diskGeometry),
        BytesPerClinder(diskGeometry),
        BytesPerDisk(diskGeometry)));
    MessageBox(HWND_DESKTOP, buffer, TEXT("Cドライブのジオメトリ情報"), MB_ICONINFORMATION);

    CloseHandle(volumeHandle);

    return 0;
}