Определение параметров жёстких дисков
В этой статье мы поговорим не только о жёстких дисках, но и обо всех остальных накопителях. Итак, мы получим список всех запоминющих устройств (ЗУ), подключённых к вашей машине, а также определим для каждого из них количество цилиндров, дорожек и секторов, а также их объём.
Для того, чтобы получить список всех ЗУ, подключённых к машине, в WinAPI предусмотрена функция GetLogicalDriveStrings
:
- DWORD WINAPI GetLogicalDriveStrings(
- DWORD nBufferLength,
- LPTSTR lpBuffer
- );
Рассмотрим поля структуры:
nBufferLenght
— максимальный размер буфера, в который будет помещена строка со списком подключённых ЗУ следующего вида“Drive0\0Drive1\0...DriveN\0\0”
lpBuffer
— буфер, в который будет записана строка со списком
Возвращаемое значение функции — количество записанных в строку символов. В случае неудачи возвращается 0
.
- char buf[100];
- DWORD len = GetLogicalDriveStringsA(sizeof(buf)/sizeof(char), buf);
Теперь, когда нам известен список ЗУ, циклом пройдёмся по каждому диску и определим для него количество цилиндров, дорожек на цилиндр и секторов на дорожку. Позволит нам все это сделать функция DeviceIoControl
:
- BOOL WINAPI DeviceIoControl(
- HANDLE hDevice,
- DWORD dwIoControlCode,
- LPVOID lpInBuffer,
- DWORD nInBufferSize,
- LPVOID lpOutBuffer,
- DWORD nOutBufferSize,
- LPDWORD lpBytesReturned,
- LPOVERLAPPED lpOverlapped
- );
hDevice
— хэндл устройстваdwIoControlCode
— код операции. В нашем случае этоIOCTL_DISK_GET_DRIVE_GEOMETRY
lpInBuffer
— буфер со входными данными. Нам не нужны никакие входные данные, поэтомуNULL
nInBufferSize
— размер буфера со входными данными в байтах. У нас это0
lpOutBuffer
— указатель на буфер для выходных данных. Его тип определяется параметромdwIoControlCode
nOutBufferSize
— размер буфера с выходными данными в байтахlpBytesReturned
— указатель на переменную, в которую вернется количество записанных в выходной буфер байтlpOverlapped
— указатель на структуруOVERLAPPED
- hDevice = CreateFileA(str, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL, OPEN_EXISTING, 0, NULL);
- if (hDevice == INVALID_HANDLE_VALUE)
- return FALSE;
- bResult = DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL,
- 0, pdg, sizeof(*pdg), &junk, (LPOVERLAPPED) NULL);
- CloseHandle(hDevice);
И под конец определим тип каждого устройства, в чем нам поможет функция WinAPI GetDriveType
:
- UINT WINAPI GetDriveType(
- LPCTSTR lpRootPathName
- );
lpRootPathName
– имя диска.
Функция возвращает код типа диска.
- #include <stdio.h>
- #include <tchar.h>
- #include <windows.h>
- #include <winioctl.h>
- #include <stdlib.h>
- #include <string>
- #include <iostream>
- using namespace std;
- struct {
- UINT type;
- LPCSTR name;
- }
- DriveTypeFlags[] = {
- { DRIVE_UNKNOWN, "Unknown" },
- { DRIVE_NO_ROOT_DIR, "Invalid path" },
- { DRIVE_REMOVABLE, "Removable" },
- { DRIVE_FIXED, "Fixed" },
- { DRIVE_REMOTE, "Network drive" },
- { DRIVE_CDROM, "CD-ROM" },
- { DRIVE_RAMDISK, "RAM disk" },
- { 0, NULL},
- };
- BOOL GetDriveGeometry(DISK_GEOMETRY *pdg, const char* driveName) {
- HANDLE hDevice;
- BOOL bResult;
- DWORD junk;
- // формируем строку формата “\\.\C:” для получения хэндла диска
- char str[7];
- str[0] = str[1] = str[3] = '\\';
- str[2] = '.';
- str[4] = driveName[0];
- str[5] = driveName[1];
- str[6] = '\0';
- // получаем хэндл диска
- hDevice = CreateFileA(str, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL, OPEN_EXISTING, 0, NULL);
- if (hDevice == INVALID_HANDLE_VALUE)
- return FALSE;
- // Получаем данные о диске
- bResult = DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY,
- NULL, 0, pdg, sizeof(*pdg), &junk, (LPOVERLAPPED) NULL);
- CloseHandle(hDevice);
- return bResult;
- }
- int _tmain(int argc, _TCHAR* argv[]) {
- DISK_GEOMETRY pdg;
- BOOL bResult;
- ULONGLONG DiskSize;
- char buf[100];
- // Получаем список дисков
- DWORD len = GetLogicalDriveStringsA(sizeof(buf)/sizeof(char), buf);
- LPCSTR sDrivePath;
- for (char* s = buf; *s; s += strlen(s) + 1) {
- sDrivePath = (LPCSTR) s;
- cout << "Disc " << s << "\n";
- bResult = GetDriveGeometry (&pdg, s);
- if (bResult) {
- printf("Cylinders = %I64d\n", pdg.Cylinders);
- cout << "Tracks/cylinder = " << pdg.TracksPerCylinder << "\n";
- cout << "Sectors/track = " << pdg.SectorsPerTrack << "\n";
- cout << "Bytes/sector = " << pdg.BytesPerSector << "\n";
- DiskSize = pdg.Cylinders.QuadPart * ((ULONG) pdg.TracksPerCylinder) *
- ((ULONG) pdg.SectorsPerTrack)*((ULONG) pdg.BytesPerSector);
- cout << "Disk size = " << DiskSize << " (Bytes) = "
- << DiskSize/(1024*1024*1024) << " (Gb)\n";
- }
- else
- cout << "GetDriveGeometry failed. Error " << GetLastError() << "\n";
- // Получаем тип диска
- UINT uDriveType = GetDriveTypeA(sDrivePath);
- for (int i = 0; DriveTypeFlags[i].name; i++) {
- if (uDriveType == DriveTypeFlags[i].type) {
- cout << "Drive type : " << DriveTypeFlags[i].name << "\n";
- cout << "----------------------\n";
- break;
- }
- }
- }
- system("PAUSE");
- return EXIT_SUCCESS;
- }