C语言读取硬盘序列号
// IOCTL
#define DFP_GET_VERSION 0x00074080
#define DFP_RECEIVE_DRIVE_DATA 0x0007c088
// IDEREGS bCommandReg
#define IDE_ATAPI_IDENTIFY 0xA1
#define IDE_ATA_IDENTIFY 0xEC
#define IDENTIFY_BUFFER_SIZE 512
// struct to save disk dirver info
typedef struct _GETVERSIONOUTPARAMS
{
BYTE bVersion;
BYTE bRevision;
BYTE bReserved;
BYTE bIDEDeviceMap;
DWORD fCapabilities;
DWORD dwReserved[4];
}GETVERSIONOUTPARAMS, *PGETVERSIONOUTPARAMS, *LPGETVERSIONOUTPARAMS;
// IDE register
typedef struct _IDEREGS
{
BYTE bFeaturesReg;
BYTE bSectorCountReg;
BYTE bSectorNumberReg;
BYTE bCylLowReg;
BYTE bCylHighReg;
BYTE bDriveHeadReg;
BYTE bCommandReg;
BYTE bReserved;
}IDEREGS, *PIDEREGS, *LPIDEREGS;
// struct to send cmd input parameters
typedef struct _SENDCMDINPARAMS
{
DWORD cBufferSize;
IDEREGS irDriveRegs;
BYTE bDriveNumber;
BYTE bReserved[3];
DWORD dwReserved[4];
BYTE bBuffer[1];
}SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;
// sturct for driver status
typedef struct _DRIVERSTATUS
{
BYTE bDriverError;
BYTE bIDEStatus;
BYTE bReserved[2];
DWORD dwReserved[2];
}DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS;
// struct to send cmd output parameters
typedef struct _SENDCMDOUTPARAMS
{
DWORD cBufferSize;
DRIVERSTATUS DriverStatus;
BYTE bBuffer[1];
}SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;
void GetDiskSequenceNum(void)
{
BYTE IdOutCmd[530];
// 打开文件
HANDLE drive = CreateFile ("\\\\.\\PhysicalDrive0", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (drive == INVALID_HANDLE_VALUE)
// 打开文件失败,返回
return;
GETVERSIONOUTPARAMS VersionParams;
DWORD cbBytesReturned = 0;
memset((void*) &VersionParams, 0, sizeof (VersionParams));
if (! DeviceIoControl(drive, DFP_GET_VERSION, NULL, 0, &VersionParams, sizeof (VersionParams), &cbBytesReturned, NULL))
// 调用失败,返回
return;
if (VersionParams.bIDEDeviceMap <= 0)
// 获取失败,返回
return;
BYTE bIDCmd = 0;
SENDCMDINPARAMS scip;
bIDCmd = (VersionParams.bIDEDeviceMap >> 0 & 0x10) ?IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
memset(&scip, 0, sizeof (scip));
memset(IdOutCmd, 0, sizeof (IdOutCmd));
scip.cBufferSize = IDENTIFY_BUFFER_SIZE;
scip.irDriveRegs.bFeaturesReg = 0;
scip.irDriveRegs.bSectorCountReg = 1;
scip.irDriveRegs.bSectorNumberReg = 1;
scip.irDriveRegs.bCylLowReg = 0;
scip.irDriveRegs.bCylHighReg = 0;
scip.irDriveRegs.bDriveHeadReg = 0xA0 | (((BYTE)drive & 1) << 4);
scip.irDriveRegs.bCommandReg = bIDCmd;
scip.bDriveNumber = (BYTE)drive;
scip.cBufferSize = IDENTIFY_BUFFER_SIZE;
if (! DeviceIoControl(drive, DFP_RECEIVE_DRIVE_DATA, &scip, sizeof (SENDCMDINPARAMS) - 1, (LPVOID)&IdOutCmd, sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1, &cbBytesReturned, NULL))
// 调用失败,返回
return;
USHORT *pIdSector = (USHORT *) ((PSENDCMDOUTPARAMS) IdOutCmd)->bBuffer;
// 关闭文件句柄
CloseHandle(drive);
int nIndex = 0, nPosition = 0;
// 以写追加的方式打开用来保存结果的文件
FILE *pf = fopen("disk_info.txt", "a+");
// 检测文件指针的合法性
assert(NULL != pf);
if (NULL == pf)
// 文件打开失败,返回
return;
char szSeq[256] = { 0 };
// 把序列号信息保存到临时变量中
for (nIndex = 13; nIndex < 20; nIndex++)
{
szSeq[nPosition++] = (unsigned char) (pIdSector[nIndex] / 256);
szSeq[nPosition++] = (unsigned char) (pIdSector[nIndex] % 256);
}
// 把临时变量中序列号写入文件
fprintf(pf, "\ndisk sequence num info is %s\n", szSeq);
// 关闭文件指针
fclose(pf);
}