Фальстарт

Определение параметров жёстких дисков

Александр Анохин, 18 ноября 2007

В этой статье мы поговорим не только о жёстких дисках, но и обо всех остальных накопителях. Итак, мы получим список всех запоминющих устройств (ЗУ), подключённых к вашей машине, а также определим для каждого из них количество цилиндров, дорожек и секторов, а также их объём.

Для того, чтобы получить список всех ЗУ, подключённых к машине, в WinAPI предусмотрена функция GetLogicalDriveStrings:

  1. DWORD WINAPI GetLogicalDriveStrings(
  2. DWORD nBufferLength,
  3. LPTSTR lpBuffer
  4. );

Рассмотрим поля структуры:

Возвращаемое значение функции — количество записанных в строку символов. В случае неудачи возвращается 0.

  1. char buf[100];
  2. DWORD len = GetLogicalDriveStringsA(sizeof(buf)/sizeof(char), buf);

Теперь, когда нам известен список ЗУ, циклом пройдёмся по каждому диску и определим для него количество цилиндров, дорожек на цилиндр и секторов на дорожку. Позволит нам все это сделать функция DeviceIoControl:

  1. BOOL WINAPI DeviceIoControl(
  2. HANDLE hDevice,
  3. DWORD dwIoControlCode,
  4. LPVOID lpInBuffer,
  5. DWORD nInBufferSize,
  6. LPVOID lpOutBuffer,
  7. DWORD nOutBufferSize,
  8. LPDWORD lpBytesReturned,
  9. LPOVERLAPPED lpOverlapped
  10. );
  1. hDevice = CreateFileA(str, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
  2. NULL, OPEN_EXISTING, 0, NULL);
  3. if (hDevice == INVALID_HANDLE_VALUE)
  4. return FALSE;
  5. bResult = DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL,
  6. 0, pdg, sizeof(*pdg), &junk, (LPOVERLAPPED) NULL);
  7. CloseHandle(hDevice);

И под конец определим тип каждого устройства, в чем нам поможет функция WinAPI GetDriveType:

  1. UINT WINAPI GetDriveType(
  2. LPCTSTR lpRootPathName
  3. );

Функция возвращает код типа диска.

  1. #include <stdio.h>
  2. #include <tchar.h>
  3. #include <windows.h>
  4. #include <winioctl.h>
  5. #include <stdlib.h>
  6. #include <string>
  7. #include <iostream>
  8. using namespace std;
  9. struct {
  10. UINT type;
  11. LPCSTR name;
  12. }
  13. DriveTypeFlags[] = {
  14. { DRIVE_UNKNOWN, "Unknown" },
  15. { DRIVE_NO_ROOT_DIR, "Invalid path" },
  16. { DRIVE_REMOVABLE, "Removable" },
  17. { DRIVE_FIXED, "Fixed" },
  18. { DRIVE_REMOTE, "Network drive" },
  19. { DRIVE_CDROM, "CD-ROM" },
  20. { DRIVE_RAMDISK, "RAM disk" },
  21. { 0, NULL},
  22. };
  23. BOOL GetDriveGeometry(DISK_GEOMETRY *pdg, const char* driveName) {
  24. HANDLE hDevice;
  25. BOOL bResult;
  26. DWORD junk;
  27. // формируем строку формата “\\.\C:” для получения хэндла диска
  28. char str[7];
  29. str[0] = str[1] = str[3] = '\\';
  30. str[2] = '.';
  31. str[4] = driveName[0];
  32. str[5] = driveName[1];
  33. str[6] = '\0';
  34. // получаем хэндл диска
  35. hDevice = CreateFileA(str, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
  36. NULL, OPEN_EXISTING, 0, NULL);
  37. if (hDevice == INVALID_HANDLE_VALUE)
  38. return FALSE;
  39. // Получаем данные о диске
  40. bResult = DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY,
  41. NULL, 0, pdg, sizeof(*pdg), &junk, (LPOVERLAPPED) NULL);
  42. CloseHandle(hDevice);
  43. return bResult;
  44. }
  45. int _tmain(int argc, _TCHAR* argv[]) {
  46. DISK_GEOMETRY pdg;
  47. BOOL bResult;
  48. ULONGLONG DiskSize;
  49. char buf[100];
  50. // Получаем список дисков
  51. DWORD len = GetLogicalDriveStringsA(sizeof(buf)/sizeof(char), buf);
  52. LPCSTR sDrivePath;
  53. for (char* s = buf; *s; s += strlen(s) + 1) {
  54. sDrivePath = (LPCSTR) s;
  55. cout << "Disc " << s << "\n";
  56. bResult = GetDriveGeometry (&pdg, s);
  57. if (bResult) {
  58. printf("Cylinders = %I64d\n", pdg.Cylinders);
  59. cout << "Tracks/cylinder = " << pdg.TracksPerCylinder << "\n";
  60. cout << "Sectors/track = " << pdg.SectorsPerTrack << "\n";
  61. cout << "Bytes/sector = " << pdg.BytesPerSector << "\n";
  62. DiskSize = pdg.Cylinders.QuadPart * ((ULONG) pdg.TracksPerCylinder) *
  63. ((ULONG) pdg.SectorsPerTrack)*((ULONG) pdg.BytesPerSector);
  64. cout << "Disk size = " << DiskSize << " (Bytes) = "
  65. << DiskSize/(1024*1024*1024) << " (Gb)\n";
  66. }
  67. else
  68. cout << "GetDriveGeometry failed. Error " << GetLastError() << "\n";
  69. // Получаем тип диска
  70. UINT uDriveType = GetDriveTypeA(sDrivePath);
  71. for (int i = 0; DriveTypeFlags[i].name; i++) {
  72. if (uDriveType == DriveTypeFlags[i].type) {
  73. cout << "Drive type : " << DriveTypeFlags[i].name << "\n";
  74. cout << "----------------------\n";
  75. break;
  76. }
  77. }
  78. }
  79. system("PAUSE");
  80. return EXIT_SUCCESS;
  81. }