- ベストアンサー
物理ドライブの全容量を取得する方法
現在、HDDを物理的に読み書きするソフトウェアを製作しております。 その際HDDをドライブレターではなく物理ドライブ番号で判断する必要があり、 全容量を取得する方法がわからず困っています。 環境はWindows2000Pro(VisualC++ V6/API)です。 ドライブレターが使用できる場合GetDiskFreeSpace(Ex)にて取得できるようですが、 試しに第一引数に「\\.\PhysicalDrive0」と渡し失敗することを確認しました。 指定方法や順序の問題かも知れませんが、 この状態でフォーマットされていないHDDの全容量を知る方法があれば、是非、ご教示ください。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
パーティション (ドライブレター) ごとではなく, 物理ドライブごとでいいんでしょうか? ちょっと調べて作ってみましたのでご参考まで. (CreateFile の引数がこれでいいのか,十分マニュアルを 熟読していませんが,とりあえずそれらしい結果は出ました.) //-------------------------------------------------------------------------- #define _WIN32_WINNT 0x0501 #include <stdio.h> #include <windows.h> /*-------------------------------------------------------------------------- 機能 :物理ドライブごとのディスク容量を出力する. --------------------------------------------------------------------------*/ void PrintPhysicalDriveCapacities(void) { HANDLE hDrive; GET_LENGTH_INFORMATION length; unsigned driveNo; DWORD nBytes; char fileName[29]; for(driveNo = 0; ; driveNo++) { // 物理ドライブ driveNo をオープンする. sprintf(fileName, "\\\\.\\PHYSICALDRIVE%u", driveNo); hDrive = CreateFile(fileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(hDrive == INVALID_HANDLE_VALUE) break; // 物理ドライブの全容量を取得する. if(DeviceIoControl(hDrive, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &length, (DWORD)sizeof(length), &nBytes, NULL)) { printf("Physical Drive #%u: %I64u bytes\n", driveNo, length.Length); } CloseHandle(hDrive); } } //-------------------------------------------------------------------------- int main(void) { PrintPhysicalDriveCapacities(); return EXIT_SUCCESS; } // 実行結果 ---------------------------------------------------------------- Physical Drive #0: 120034123776 bytes /* 120GB HDD */ Physical Drive #1: 2086535168 bytes /* 2GB USB Memory */
その他の回答 (2)
- davidfox
- ベストアンサー率58% (21/36)
DeviceIoControl で DISK_GEOMETRY構造体を取得して計算すれば良いのでは。 ただ、昔の話なので、現在どんなHDDでも通用するかは判りませんが。
お礼
連絡が遅くなってしまい申し訳ありません。 DeviceIoControl 関数を使用することで取得できるとのことで、 試しに上記の様にテストしてみたところ、問題なく取得できました。 (2G以下のHDDを対象として、キャストが強引ではありますが…) 今回はPC-98時代の"昔の"HDDを読み書きする必要があり、 ご回答はズバリのものです。ご回答、感謝いたします。
- Tasuke22
- ベストアンサー率33% (1799/5383)
使ったことはありませんが、参考URLの ライブラリはどうでしょうか。
お礼
ご連絡が遅くなってしまい申し訳ありません。 ライブラリ、拝見いたしました。 ライブラリとのことで今回は使用できませんが、 次回、その他リソースを取得する際参考にさせていただきます。 ご回答、有り難うございました。
お礼
ご連絡が遅くなってしまい申し訳ありませんでした。 お忙しい中、そのもののご回答をいただき心より感謝いたします。 noocyte氏のコードを参考に、No.2 davidfox氏の示された方法で取得してみました。 同じく取り敢えずの結果ではありますが、テスト中のコードを記載いたします。 --------------------- #include <windows.h> #include <stdio.h> #include <winioctl.h> --------------------- --------------------- 引数 DWORD numdrv( = 0); --------------------- char devicename[64]; sprintf(devicename, "\\\\.\\PhysicalDrive%u", numdrv); HANDLE hDevice; // デバイスを開く hDevice = CreateFile(devicename, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); // デバイスが開けない if(!hDevice){ fprintf(stdout, "failed to open device %d.\n", numdrv); return 0; } DISK_GEOMETRY geo; BOOL res; DWORD res_bytes; // ジオメトリ取得 res = DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &geo, sizeof(geo), &res_bytes, NULL); // 取得に失敗 if(!res){ fprintf(stdout, "failed to get device status.\n"); return 0; } // 全容量割り出し fprintf(stdout, "SecSize : %u\nSecNum : %u\nCls : %I64u \nTrk : %u\n", geo.BytesPerSector, geo.SectorsPerTrack, geo.Cylinders, geo.TracksPerCylinder); ULONGLONG totalsize; totalsize = geo.SectorsPerTrack * geo.BytesPerSector * geo.TracksPerCylinder; totalsize = (totalsize * geo.Cylinders.QuadPart) / 1048576; fprintf(stdout, "Total : %I64u MB\n", totalsize); CloseHandle(hDevice); 今回はWinNT上で動作し、またセクタサイズ等も可能であれば必要なため GET_DRIVE_GEOMETRY を使用させていただきました。 詰まっておりましたので大変助かりました。ご回答、感謝いたします。