WIN32 API读取硬盘信息
打开硬盘句柄
使用CreateFile方式打开硬盘。
QString filePath = QString("\\\\.\\PhysicalDrive%1").arg(index);
fileHandler = CreateFileA(filePath.toLocal8Bit().data(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0, 0 );
IDSECTOR方式读取
结构体声明。我没找到官方的定义。
#define IDENTIFY_BUFFER_SIZE 512
#define IDE_ATAPI_IDENTIFY 0xA0
#define IDE_ATA_IDENTIFY 0xEC
#define DFP_RECEIVE_DRIVE_DATA 0x0007c088
#pragma pack(1)
typedef struct _IDSECTOR
{
USHORT wGenConfig;
USHORT wNumCyls;
USHORT wReserved;
USHORT wNumHeads;
USHORT wBytesPerTrack;
USHORT wBytesPerSector;
USHORT wSectorsPerTrack;
USHORT wVendorUnique[3];
CHAR sSerialNumber[20];
USHORT wBufferType;
USHORT wBufferSize;
USHORT wECCSize;
CHAR sFirmwareRev[8];
CHAR sModelNumber[40];
USHORT wMoreVendorUnique;
USHORT wDoubleWordIO;
USHORT wCapabilities;
USHORT wReserved1;
USHORT wPIOTiming;
USHORT wDMATiming;
USHORT wBS;
USHORT wNumCurrentCyls;
USHORT wNumCurrentHeads;
USHORT wNumCurrentSectorsPerTrack;
ULONG ulCurrentSectorCapacity;
USHORT wMultSectorStuff;
ULONG ulTotalAddressableSectors;
USHORT wSingleWordDMA;
USHORT wMultiWordDMA;
BYTE bReserved[128];
}IDSECTOR, *PIDSECTOR;
#pragma pack()
BOOL bResult;
DWORD dwBytesRet;
//获取硬盘详细信息 序列号等情况
GETVERSIONINPARAMS gVersionParsams;
bResult = DeviceIoControl(fileHandler,
SMART_GET_VERSION,
NULL,
NULL,
&gVersionParsams,
sizeof(gVersionParsams),
&dwBytesRet,
NULL);
if(bResult && gVersionParsams.bIDEDeviceMap > 0){
SENDCMDINPARAMS scip;
ZeroMemory( &scip,sizeof(SENDCMDINPARAMS));
scip.cBufferSize=IDENTIFY_BUFFER_SIZE;
scip.irDriveRegs.bSectorCountReg=1;
scip.irDriveRegs.bSectorNumberReg=1;
scip.irDriveRegs.bDriveHeadReg= IDE_ATAPI_IDENTIFY;
scip.irDriveRegs.bCommandReg= IDE_ATA_IDENTIFY;
scip.bDriveNumber = index & 0xFF;
BYTE btBuffer[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE]={ 0 };
bResult = DeviceIoControl(fileHandler,
SMART_RCV_DRIVE_DATA,
&scip,
sizeof(scip) - 1,
btBuffer,
sizeof(btBuffer),
&dwBytesRet,NULL);
if(bResult){
PSENDCMDOUTPARAMS pOut = (PSENDCMDOUTPARAMS)btBuffer;
PIDSECTOR pIdSec = (PIDSECTOR)(pOut->bBuffer);
ChangeByteOrder(pIdSec->sSerialNumber, sizeof(pIdSec->sSerialNumber));
ChangeByteOrder(pIdSec->sModelNumber, sizeof(pIdSec->sModelNumber));
sn = QString::fromLocal8Bit(pIdSec->sSerialNumber,
sizeof(pIdSec->sSerialNumber)).trimmed();
model = QString::fromLocal8Bit(pIdSec->sModelNumber,
sizeof(pIdSec->sModelNumber)).trimmed();
}
}else{
qDebug() << "错误码:" <<GetLastError();
}
void ChangeByteOrder(LPSTR lpString, int nLen)
{
USHORT i;
CHAR c;
// 63 63 72 75 6E 2E 63 6F 6D
for(int i = 0; i < nLen; i += 2)
{
c = lpString[i];
lpString[i] = lpString[i+1];
lpString[i+1] = c;
}
}
这种方式读取,需要转换字节顺序。USB硬盘有点读不到。
STORAGE_PROPERTY_QUERY方式读取
STORAGE_PROPERTY_QUERY query;
query.PropertyId = StorageDeviceProperty;
query.QueryType = PropertyStandardQuery;
char buffer[sizeof(STORAGE_DEVICE_DESCRIPTOR) + 512 - 1];
STORAGE_DEVICE_DESCRIPTOR *pDevDesc = (STORAGE_DEVICE_DESCRIPTOR *)buffer;
pDevDesc->Size = sizeof(STORAGE_DEVICE_DESCRIPTOR) + 512 - 1;
bResult = DeviceIoControl(fileHandler, IOCTL_STORAGE_QUERY_PROPERTY,
&query,
sizeof(query),
pDevDesc,
pDevDesc->Size,
&dwBytesRet, NULL);
if (bResult){
removableMedia = pDevDesc->RemovableMedia;
bus = pDevDesc->BusType;
char temp[512];
strcpy(temp,&buffer[pDevDesc->ProductIdOffset]);//此即为producter
qDebug() << QString::fromLocal8Bit(temp);
strcpy(temp,&buffer[pDevDesc->ProductRevisionOffset]);//此即为version
qDebug() << QString::fromLocal8Bit(temp);
strcpy(temp ,&buffer[pDevDesc->VendorIdOffset]);//此即为vendor
qDebug() << QString::fromLocal8Bit(temp);
strcpy(temp,&buffer[pDevDesc->SerialNumberOffset]);
qDebug() << QString::fromLocal8Bit(temp);
}
参考
https://blog.youkuaiyun.com/helptome/article/details/2047063
https://bbs.pediy.com/thread-221514.htm