• ベストアンサー

物理ドライブの全容量を取得する方法

現在、HDDを物理的に読み書きするソフトウェアを製作しております。 その際HDDをドライブレターではなく物理ドライブ番号で判断する必要があり、 全容量を取得する方法がわからず困っています。 環境はWindows2000Pro(VisualC++ V6/API)です。 ドライブレターが使用できる場合GetDiskFreeSpace(Ex)にて取得できるようですが、 試しに第一引数に「\\.\PhysicalDrive0」と渡し失敗することを確認しました。 指定方法や順序の問題かも知れませんが、 この状態でフォーマットされていないHDDの全容量を知る方法があれば、是非、ご教示ください。

質問者が選んだベストアンサー

  • ベストアンサー
  • noocyte
  • ベストアンサー率58% (171/291)
回答No.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 */

N_flick
質問者

お礼

ご連絡が遅くなってしまい申し訳ありませんでした。 お忙しい中、そのもののご回答をいただき心より感謝いたします。 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 を使用させていただきました。 詰まっておりましたので大変助かりました。ご回答、感謝いたします。

その他の回答 (2)

  • davidfox
  • ベストアンサー率58% (21/36)
回答No.2

DeviceIoControl で DISK_GEOMETRY構造体を取得して計算すれば良いのでは。 ただ、昔の話なので、現在どんなHDDでも通用するかは判りませんが。

N_flick
質問者

お礼

連絡が遅くなってしまい申し訳ありません。 DeviceIoControl 関数を使用することで取得できるとのことで、 試しに上記の様にテストしてみたところ、問題なく取得できました。 (2G以下のHDDを対象として、キャストが強引ではありますが…) 今回はPC-98時代の"昔の"HDDを読み書きする必要があり、 ご回答はズバリのものです。ご回答、感謝いたします。

  • Tasuke22
  • ベストアンサー率33% (1799/5383)
回答No.1

使ったことはありませんが、参考URLの ライブラリはどうでしょうか。

参考URL:
http://www.vector.co.jp/soft/dl/win95/prog/se116476.html
N_flick
質問者

お礼

ご連絡が遅くなってしまい申し訳ありません。 ライブラリ、拝見いたしました。 ライブラリとのことで今回は使用できませんが、 次回、その他リソースを取得する際参考にさせていただきます。 ご回答、有り難うございました。

関連するQ&A