这里介绍的是获取硬盘的序列号,不是获取硬盘分区的序列号。核心是通过DeviceIoControl接口获取硬盘的版本与数据信息,很
简单。
【1】h头文件
//如果编译有问题,添加#include <afxwin.h> #if !defined(AFX_HDSERIAL_H__1F6D2512_EBA9_4443_9FEF_DE78D7A28AFB__INCLUDED_) #define AFX_HDSERIAL_H__1F6D2512_EBA9_4443_9FEF_DE78D7A28AFB__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include <iostream> #include <windows.h> #define DFP_GET_VERSION 0x00074080 #define DFP_SEND_DRIVE_COMMAND 0x0007c084 #define DFP_RECEIVE_DRIVE_DATA 0x0007c088 typedef struct _GETVERSIONOUTPARAMS { BYTE bVersion; // Binary driver version. BYTE bRevision; // Binary driver revision. BYTE bReserved; // Not used. BYTE bIDEDeviceMap; // Bit map of IDE devices. DWORD fCapabilities; // Bit mask of driver capabilities. DWORD dwReserved[4]; // For future use. } GETVERSIONOUTPARAMS, *PGETVERSIONOUTPARAMS, *LPGETVERSIONOUTPARAMS; typedef struct _IDEREGS { BYTE bFeaturesReg; // Used for specifying SMART "commands". BYTE bSectorCountReg; // IDE sector count register BYTE bSectorNumberReg; // IDE sector number register BYTE bCylLowReg; // IDE low order cylinder value BYTE bCylHighReg; // IDE high order cylinder value BYTE bDriveHeadReg; // IDE drive/head register BYTE bCommandReg; // Actual IDE command. BYTE bReserved; // reserved for future use. Must be zero. } IDEREGS, *PIDEREGS, *LPIDEREGS; typedef struct _SENDCMDINPARAMS { DWORD cBufferSize; // Buffer size in bytes IDEREGS irDriveRegs; // Structure with drive register values. BYTE bDriveNumber; // Physical drive number to send command to (0,1,2,3). BYTE bReserved[3]; // Reserved for future expansion. DWORD dwReserved[4]; // For future use. } SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS; typedef struct _DRIVERSTATUS { BYTE bDriverError; // Error code from driver, // or 0 if no error. BYTE bIDEStatus; // Contents of IDE Error register. // Only valid when bDriverError // is SMART_IDE_ERROR. BYTE bReserved[2]; // Reserved for future expansion. DWORD dwReserved[2]; // Reserved for future expansion. } DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS; typedef struct _SENDCMDOUTPARAMS { DWORD cBufferSize; // Size of bBuffer in bytes DRIVERSTATUS DriverStatus; // Driver status structure. BYTE bBuffer[512]; // Buffer of arbitrary length // in which to store the data read from the drive. } SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS; 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; //-------------------------------------------------------------- // 硬盘序列号 //-------------------------------------------------------------- BOOL GetHDSerial(char *lpszHD, int len=128); #endif // !defined(AFX_HDSERIAL_H__1F6D2512_EBA9_4443_9FEF_DE78D7A28AFB__INCLUDED_)
#include "stdafx.h" #include "HDSerial.h" void ChangeByteOrder(PCHAR szString, USHORT uscStrSize) { USHORT i = 0; CHAR temp= '\0'; for (i = 0; i < uscStrSize; i+=2) { temp = szString[i]; szString[i] = szString[i+1]; szString[i+1] = temp; } } //-------------------------------------------------------------- // 硬盘序列号 //-------------------------------------------------------------- BOOL GetHDSerial(char *lpszHD, int len/*=128*/) { BOOL bRtn = FALSE; DWORD bytesRtn = 0; char szhd[80] = {0}; PIDSECTOR phdinfo; HANDLE hDrive = NULL; GETVERSIONOUTPARAMS vers; SENDCMDINPARAMS in; SENDCMDOUTPARAMS out; ZeroMemory(&vers, sizeof(vers)); ZeroMemory(&in , sizeof(in)); ZeroMemory(&out , sizeof(out)); //搜索四个物理硬盘,取第一个有数据的物理硬盘 for (int j=0; j<4; j++) { sprintf(szhd, "\\\\.\\PhysicalDrive%d", j); hDrive = CreateFileA(szhd, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); if (NULL == hDrive) { continue; } if (!DeviceIoControl(hDrive, DFP_GET_VERSION, 0, 0, &vers, sizeof(vers), &bytesRtn,0)) { goto FOREND; } //If IDE identify command not supported, fails if (!(vers.fCapabilities&1)) { goto FOREND; } //Identify the IDE drives if (j&1) { in.irDriveRegs.bDriveHeadReg = 0xb0; } else { in.irDriveRegs.bDriveHeadReg = 0xa0; } if (vers.fCapabilities&(16>>j)) { //We don't detect a ATAPI device. goto FOREND; } else { in.irDriveRegs.bCommandReg = 0xec; } in.bDriveNumber = j; in.irDriveRegs.bSectorCountReg = 1; in.irDriveRegs.bSectorNumberReg = 1; in.cBufferSize = 512; if (!DeviceIoControl(hDrive, DFP_RECEIVE_DRIVE_DATA, &in, sizeof(in), &out, sizeof(out), &bytesRtn,0)) { //"DeviceIoControl failed:DFP_RECEIVE_DRIVE_DATA"<<endl; goto FOREND; } phdinfo=(PIDSECTOR)out.bBuffer; char s[21] = {0}; memcpy(s, phdinfo->sSerialNumber, 20); s[20] = 0; ChangeByteOrder(s, 20); //删除空格字符 int ix = 0; for (ix=0; ix<20; ix++) { if (s[ix] == ' ') { continue; } break; } memcpy(lpszHD, s+ix, 20); bRtn = TRUE; break; FOREND: CloseHandle(hDrive); hDrive = NULL; } CloseHandle(hDrive); hDrive = NULL; return(bRtn); }
char lpszMac[128] = {0}; GetHDSerial(lpszMac);