Определение параметров жестких дисков
Автор: Александр Анохин
Сайт: http://www.zahodi-ka.ru
Копирование материала разрешено только с сохранением авторства и прямой ссылки на сайт
В этой статье мы поговорим не только о жестких дисках, но и обо всех остальных накопителях. Итак, мы получим список всех запоминющих устройств(ЗУ), подключенных к Вашей машине, а также определим для каждого из них количество цилиндров, дорожек и секторов, а также их объем.
Для того, чтобы получить список всех ЗУ, подключенных к машине, в 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;
}