C++ 硬件信息 获取硬盘序列号

这里介绍的是获取硬盘的序列号,不是获取硬盘分区的序列号。核心是通过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_)


【2】cpp文件

#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);
}


【3】测试

	char lpszMac[128] = {0};
	GetHDSerial(lpszMac);
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郎涯技术

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值