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];
BYTE bReserved2[512];
} IDSECTOR, * PIDSECTOR;
//这里我把SENDCMDOUTPARAMS跟IDSECTOR直接合并来了,这样的操作方便传入输参
typedef struct _HARDDISKINFO
{
//SENDCMDOUTPARAMS
DWORD cBufferSize; // Size of bBuffer in bytes
DRIVERSTATUS DriverStatus; // Driver status structure.
IDSECTOR info;
}HARDDISKINFO ,*PHARDDISKINFO;
string get_HardDiskSerialNumber_1(int harddiskindex)//硬盘序列号索引,第一个硬盘=0,第二个硬盘=1
{
char objName[50] = {0};
wsprintfA(objName, "\\\\.\\PhysicalDrive%d", harddiskindex);
HANDLE hDevice = ::CreateFileA(objName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
if (hDevice == INVALID_HANDLE_VALUE)return "-1";
SENDCMDINPARAMS scip;//输入
ZeroMemory(&scip, sizeof(SENDCMDINPARAMS));
scip.cBufferSize = IDENTIFY_BUFFER_SIZE;
scip.irDriveRegs.bSectorCountReg = 1;
scip.irDriveRegs.bSectorNumberReg = 1;
scip.irDriveRegs.bDriveHeadReg = 0xA0;
scip.irDriveRegs.bCommandReg = 0xEC;
HARDDISKINFO hdinfo = {0};//输出,把SENDCMDOUTPARAMS ,IDSECTOR直接合并成一个结构了
DWORD dwBytesReturned = 0;
if (!DeviceIoControl(hDevice, SMART_RCV_DRIVE_DATA, &scip, sizeof(SENDCMDINPARAMS),&hdinfo, sizeof(HARDDISKINFO), &dwBytesReturned, NULL))
{
::CloseHandle(hDevice);
return "-2";
}
ConvertSerialString(hdinfo.info.sSerialNumber, sizeof(hdinfo.info.sSerialNumber));//转换格式
::CloseHandle(hDevice);
return string(hdinfo.info.sSerialNumber);
}
方法二, 0x2D1400
网上找到不资料,根据硬盘分区工具DiskGenius.exe逆出来的,其中的结构体我也不懂是啥,随便构造了一个
代码如下:
typedef struct _HARDDISKINFO2
{
ULONG of_name1;//名称1偏移
ULONG unknown1[3];//未知数据
ULONG of_name2;//名称2偏移
ULONG of_FirmwareRev; // 固件版本偏移
ULONG of_SerialNumber; // 序列号偏移
ULONG unknown2;//未知数据
char outdata[520];//硬盘数据
PCHAR get_FirmwareRev()
{
if (of_FirmwareRev
{
return (PCHAR)this + of_FirmwareRev;
}
return "";
}
PCHAR get_name1()
{
if (((PCHAR)this)[of_name1] == 0)
return (PCHAR)this + of_name1+8;
else
return (PCHAR)this + of_name1;
return NULL;
}
PCHAR get_name2()
{
if (of_name2
{
return (PCHAR)this + of_name2;
}
return "";
}
PCHAR get_SerialNumber()
{
if (of_SerialNumber
{
return (PCHAR)this + of_SerialNumber;
}
return "";
}
}HARDDISKINFO2, * PHARDDISKINFO2;
string get_HardDiskSerialNumber_2(int harddiskindex)
{
char objName[50] = { 0 };
wsprintfA(objName, "\\\\.\\PhysicalDrive%d", harddiskindex);
HANDLE hDevice = ::CreateFileA(objName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
if (hDevice == INVALID_HANDLE_VALUE)return "-1";
char inputdata[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00 };//不知道这个是什么结构,格式就这样
HARDDISKINFO2 hdinfo = {0};
DWORD dwBytesReturned = 0;
if (!DeviceIoControl(hDevice, 0x2D1400, inputdata, sizeof(inputdata), &hdinfo, sizeof(HARDDISKINFO2), &dwBytesReturned , NULL))
{
::CloseHandle(hDevice);
return "-2";
}
::CloseHandle(hDevice);
return string(hdinfo.get_SerialNumber());
}
方法一获取的硬盘数据多一些,但是硬盘型号名称获取有时候不太对,而且序列号,名字这些字符要转换,转换方式我这么写:
VOID DiskSerialConvert(PCHAR DiskSerial, PCHAR newDiskSerial)
{
int len = strlen(DiskSerial);
int i = 0;
if (len > 20)
{
len = 20;
}
if (len % 2 == 1)
{
len = len + 1;
}
for (i = 0; i
{
if (i % 2 == 0)
{
newDiskSerial[i] = DiskSerial[i + 1];
}
else
{
newDiskSerial[i] = DiskSerial[i - 1];
}
}
}
void ConvertSerialString(PCHAR str,int len)
{
char* strTemp = new char[len];
DiskSerialConvert(str, strTemp);
RtlCopyMemory(str, strTemp, len);
delete[] strTemp;
}
如果只是要序列号跟名称,还是方法二好用一点,名称获取完整.
调用过程已经运行结果:
还有什么奇葩读取硬盘ID的方法,发出来学习呗!