以下是“讀取硬盤序列號、型號、修訂版本號”的完整代碼(win32 C++控制臺程序),開發(fā)環(huán)境:win XP SP2 + VC6.0
頭文件:Struct_Def.h
// 其實(shí)以下的定義多數(shù)是來自高版本VC(我機(jī)器上是VS2010)的頭文件:C:\Program Files\Microsoft SDKs\Windows\v7.0A\Include\WinIoCtl.htypedef struct _DRIVERSTATUS {BYTE bDriverError; // Error code from driver,// or 0 if no error.BYTE bIDEError; // 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 _IDEREGS {BYTE bFeaturesReg; // Used for specifying SMART "commands".BYTE bSectorCountReg; // IDE sector count registerBYTE bSectorNumberReg; // IDE sector number registerBYTE bCylLowReg; // IDE low order cylinder valueBYTE bCylHighReg; // IDE high order cylinder valueBYTE bDriveHeadReg; // IDE drive/head registerBYTE bCommandReg; // Actual IDE command.BYTE bReserved; // reserved for future use. Must be zero.
} IDEREGS, *PIDEREGS, *LPIDEREGS;typedef struct _SENDCMDOUTPARAMS {DWORD cBufferSize; // Size of bBuffer in bytesDRIVERSTATUS DriverStatus; // Driver status structure.BYTE bBuffer[1]; // Buffer of arbitrary length in which to store the data read from the // drive.
} SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;typedef struct _SENDCMDINPARAMS {DWORD cBufferSize; // Buffer size in bytesIDEREGS 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.BYTE bBuffer[1]; // Input buffer.
} SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;typedef struct _GETVERSIONINPARAMS {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.
} GETVERSIONINPARAMS, *PGETVERSIONINPARAMS, *LPGETVERSIONINPARAMS;#define SMART_GET_VERSION CTL_CODE(IOCTL_DISK_BASE, 0x0020, METHOD_BUFFERED, FILE_READ_ACCESS)
#define SMART_RCV_DRIVE_DATA CTL_CODE(IOCTL_DISK_BASE, 0x0022, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define DFP_SEND_DRIVE_COMMAND SMART_SEND_DRIVE_COMMAND
#define GETVERSIONOUTPARAMS GETVERSIONINPARAMS
#define DFP_RCV_DRIVE_DATA SMART_RCV_DRIVE_DATA
#define DFP_GET_VERSION SMART_GET_VERSION
#define IDENTIFY_BUFFER_SIZE 512
主程序:m.cpp
/*功能:VC6獲取硬盤序列號、型號、修訂版本號
*/#include <iostream>
#include <windows.h>
#include <winioctl.h>
#include "Struct_Def.h"using namespace std;const WORD IDE_ATAPI_IDENTIFY = 0xA1; //讀取ATAPI設(shè)備的命令
const WORD IDE_ATA_IDENTIFY = 0xEC; //讀取ATA設(shè)備的命令
const int MAX_IDE_DRIVES = 1; //最多IDE設(shè)備數(shù)string Trim(string str) // cut off leading and tailing blanks
{string::size_type pos = str.find_last_not_of(' ');if(pos != string::npos){str.erase(pos + 1);pos = str.find_first_not_of(' ');if(pos != string::npos) str.erase(0, pos);}else str.erase(str.begin(), str.end());return str;
}// fetch characters what we need from DiskData[FirstIndex ... LastIndex]
string __fastcall ConvertToString(DWORD DiskData[256], int FirstIndex, int LastIndex)
{int i = 0;char ResBuf[1024] = {0};for(char *p = (char*)(DiskData + FirstIndex); p <= (char*)(DiskData + LastIndex); p += sizeof(DiskData)){ResBuf[i++] = *(p+1);ResBuf[i++] = *p;}return Trim(ResBuf); // cut off leading and tailing blanks
}BOOL __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP, PSENDCMDOUTPARAMS pSCOP, byte bIDCmd, byte bDriveNum, PDWORD lpcbBytesReturned)
{// Set up data structures for IDENTIFY command.pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;pSCIP->irDriveRegs.bFeaturesReg = 0;pSCIP->irDriveRegs.bSectorCountReg = 1;pSCIP->irDriveRegs.bSectorNumberReg = 1;pSCIP->irDriveRegs.bCylLowReg = 0;pSCIP->irDriveRegs.bCylHighReg = 0;//Compute the drive number.(主盤和從盤所對應(yīng)的值是不一樣的)pSCIP->irDriveRegs.bDriveHeadReg = (bDriveNum & 1) ? 0xB0 : 0xA0;// The command can either be IDE identify or ATAPI identify.pSCIP->irDriveRegs.bCommandReg = bIDCmd;pSCIP->bDriveNumber = bDriveNum;pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;return DeviceIoControl(hPhysicalDriveIOCTL, DFP_RCV_DRIVE_DATA, (LPVOID)pSCIP, sizeof(SENDCMDINPARAMS) - 1, (LPVOID)pSCOP, sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1, lpcbBytesReturned, NULL);
}// 獲取硬盤型號、序列號、修訂版本號
void __fastcall ReadPhysicalDriveOnNT()
{//IDENTIFY_BUFFER_SIZE = 512byte IdOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];char serialNo[21], modelNo[21], revisionNo[21];for(int Drive=0; Drive < 4; Drive++){HANDLE hPhysicalDriveIOCTL;char DriveName[32];sprintf(DriveName, "\\\\.\\PhysicalDrive%d", Drive);hPhysicalDriveIOCTL = CreateFile(DriveName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);if(hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE){DWORD cbBytesReturned = 0;GETVERSIONOUTPARAMS VersionParams;// Get the version, etc of PhysicalDrive IOCTLZeroMemory(&VersionParams, sizeof(GETVERSIONOUTPARAMS));if(!DeviceIoControl(hPhysicalDriveIOCTL, DFP_GET_VERSION, NULL, 0, &VersionParams, sizeof(VersionParams), &cbBytesReturned, NULL)){continue;}if(VersionParams.bIDEDeviceMap > 0){// IDE or ATAPI IDENTIFY cmdbyte bIDCmd = 0;SENDCMDINPARAMS InParams;// Now, get the ID sector for all IDE devices in the system.// If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,// otherwise use the IDE_ATA_IDENTIFY command// 具體所得結(jié)果請參考上面的說明bIDCmd = (VersionParams.bIDEDeviceMap >> Drive & 0x10) ? IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;ZeroMemory(&InParams, sizeof(SENDCMDINPARAMS));ZeroMemory(IdOutCmd, sizeof(IdOutCmd));if(DoIdentify(hPhysicalDriveIOCTL, &InParams, (PSENDCMDOUTPARAMS)IdOutCmd, (BYTE)bIDCmd,(BYTE)Drive, &cbBytesReturned)){DWORD DiskData[256];USHORT *pIDSector; // 對應(yīng)結(jié)構(gòu)IDSECTOR,見頭文件pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)IdOutCmd)->bBuffer;for(int i=0; i < 256; i++)DiskData[i] = pIDSector[i];FILE *fp = NULL;if(NULL != (fp = fopen("a.log", "w"))){fwrite(DiskData, sizeof(DiskData), 1, fp);fclose(fp);cout<<"Write file successful"<<endl;}strcpy(serialNo, ConvertToString(DiskData, 10, 19).c_str()); // get serial numberstrcpy(modelNo, ConvertToString(DiskData, 27, 46).c_str()); // get model typestrcpy(revisionNo, ConvertToString (DiskData, 23, 26).c_str()); // 獲取修訂版本號printf("SerialNo=%s\nModelNo=%s\nRevisionNo=%s\n", serialNo, modelNo, revisionNo);}}CloseHandle(hPhysicalDriveIOCTL);}}
}int main()
{ReadPhysicalDriveOnNT();return 0;
}
運(yùn)行結(jié)果:
Write file successful
SerialNo=6VMSHFW9
ModelNo=ST3500418AS
RevisionNo=CC68
Press any key to continue