获取计算机硬件信息的类

转自:http://www.seacha.com/article.php/knowledge/windows/mfc/2011/0423/319.html
获取计算机硬件信息的类
//头文件

#pragma once
#include <stdio.h>
#include <tchar.h>
//#include <afx.h>
#include <iostream
//#include <winioctl.h>
#include <Windows.h>
#include <string
#include <map
//#include <WinSock2.h>
#include <IPHlpApi.h>
using namespace std;
#pragma comment(lib, “Iphlpapi.lib”)

#define FILE_DEVICE_SCSI 0x0000001b
#define IOCTL_SCSI_MINIPORT_IDENTIFY ( ( FILE_DEVICE_SCSI << 16 ) + 0x0501 )
#define IOCTL_SCSI_MINIPORT 0x0004D008 // see NTDDSCSI.H for definition
#define IDENTIFY_BUFFER_SIZE 512
#define SENDIDLENGTH (sizeof( SENDCMDOUTPARAMS )+IDENTIFY_BUFFER_SIZE )
#define IDE_ATAPI_IDENTIFY 0xA1 // Returns ID sector for ATAPI.
#define IDE_ATA_IDENTIFY 0xEC // Returns ID sector for ATA.
#define DFP_RECEIVE_DRIVE_DATA 0x0007c088

typedef unsigned long DWORD;
typedef unsigned char BYTE;
typedef unsigned short WORD;

//用到的结构予定义
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;

typedef struct _DRIVERSTATUS DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS;

typedef struct _SRB_IO_CONTROL
{
ULONG HeaderLength;
UCHAR Signature[8];
ULONG Timeout;
ULONG ControlCode;
ULONG ReturnCode;
ULONG Length;
} SRB_IO_CONTROL, *PSRB_IO_CONTROL;

typedef struct _IDEREGS IDEREGS, *PIDEREGS, *LPIDEREGS;

typedef struct _SENDCMDINPARAMS SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;

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 _UNICODE_STRING
{
unsigned short Length;//长度
unsigned short MaximumLength;//最大长度
PWSTR Buffer;//缓存指针
} UNICODE_STRING,*PUNICODE_STRING;

typedef struct _OBJECT_ATTRIBUTES
{
ULONG Length;//长度 18h
HANDLE RootDirectory;// 00000000
PUNICODE_STRING ObjectName;//指向对象名的指针
ULONG Attributes;//对象属性00000040h
PVOID SecurityDescriptor; // Points to type SECURITY_DESCRIPTOR,0
PVOID SecurityQualityOfService; // Points to type SECURITY_QUALITY_OF_SERVICE,0
} OBJECT_ATTRIBUTES;

typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES;
//函数指针变量类型
typedef DWORD (__stdcall *ZWOS )( PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES);
typedef DWORD (__stdcall *ZWMV )
(HANDLE,HANDLE,PVOID,ULONG,ULONG,PLARGE_INTEGER,PSIZE_T,DWORD,ULONG,ULONG);
typedef DWORD (__stdcall *ZWUMV )( HANDLE,PVOID);

//---------cpuinfo

#ifndef CPUID_H
#define CPUID_H

// Cache Information
struct CacheInfo
{
int level; // level
int size; // size
int way; // way
int linesize; // linesize

CacheInfo() // constructor
{
level = 0;
size = 0;
way = 0;
linesize = 0;
}

CacheInfo(int clevel, int csize, int cway, int clinesize) //constructor
{
level = clevel;
size = csize;
way = cway;
linesize = clinesize;
}
};

// CPU SerialNumber
// comprise 6 WORD nibble, fommatting xxxx-xxxx-xxxx-xxxx-xxxx-xxxx
/*struct CpuSerialNumber
{
WORD nibble[6]; // 6 WORD nibble;

void SerialNumber() //constructor
{
memset(nibble, 0, sizeof(nibble));
}
};

*/
// singleton class CPUID
// Get CPU information

class computerInfo
{

public:
computerInfo(void);
~computerInfo(void);
public:
std::string GetMacAddress( );
std::string GetDiskID( );
std::string GetBiosID();

string GetVID(); // Get Vender ID String
string GetBrand(); // Get Brand String

//bool GetSerialNumber(CpuSerialNumber& serial); // Get CPU Serial Number

bool IsHyperThreading(); // Check if hyper-threading is supported
bool IsEST(); // Check if Enhanced Speed Step is supported
bool IsMMX(); // Check if MMX is supported

// Get cache information
DWORD GetCacheInfo(CacheInfo& L1, CacheInfo& L2, CacheInfo& L3);

//BOOL WinNTHDSerialNumAsScsiRead(BYTE* dwSerial, UINT* puSerialLen, UINT uMaxSerialLen);
//BOOL DoIdentify(HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
// PSENDCMDOUTPARAMS pSCOP, BYTE bIDCmd, BYTE bDriveNum,
// PDWORD lpcbBytesReturned);
//BOOL WinNTHDSerialNumAsPhysicalRead(BYTE* dwSerial, UINT* puSerialLen, UINT uMaxSerialLen);
UINT FindAwardBios( BYTE** ppBiosAddr);
UINT FindAmiBios(BYTE** ppBiosAddr);
UINT FindPhoenixBios( BYTE** ppBiosAddr );

std::string WCharToChar(UINT PageCode, std::wstring strWChar);
std::wstring CharToWChar(UINT PageCode, std::string strChar);
private:

DWORD m_eax; // value eax after cpuid
DWORD m_ebx; // value ebx after cpuid
DWORD m_ecx; // value ecx after cpuid
DWORD m_edx; // value edx after cpuid

map<int, CacheInfo> m_cache; // Cache information table

void Executecpuid(DWORD eax); // Execute cpuid
};
#endif

/////////////////////////////////////////////////////////////

//CPP文件

#include “computerInfo.h”
using namespace std;
computerInfo::computerInfo(void)
:m_eax(0)
,m_ebx(0)
,m_ecx(0)
,m_edx(0)
{
m_cache[0x06] = CacheInfo(1, 8, 4, 32);
m_cache[0x08] = CacheInfo(1, 16, 4, 32);
m_cache[0x0a] = CacheInfo(1, 8, 2, 32);
m_cache[0x0c] = CacheInfo(1, 16, 4, 32);
m_cache[0x2c] = CacheInfo(1, 32, 8, 64);
m_cache[0x30] = CacheInfo(1, 32, 8, 64);
m_cache[0x60] = CacheInfo(1, 16, 8, 64);
m_cache[0x66] = CacheInfo(1, 8, 4, 64);
m_cache[0x67] = CacheInfo(1, 16, 4, 64);
m_cache[0x68] = CacheInfo(1, 32, 4, 64);

m_cache[0x39] = CacheInfo(2, 128, 4, 64);
m_cache[0x3b] = CacheInfo(2, 128, 2, 64);
m_cache[0x3c] = CacheInfo(2, 256, 4, 64);
m_cache[0x41] = CacheInfo(2, 128, 4, 32);
m_cache[0x42] = CacheInfo(2, 256, 4, 32);
m_cache[0x43] = CacheInfo(2, 512, 4, 32);
m_cache[0x44] = CacheInfo(2, 1024, 4, 32);
m_cache[0x45] = CacheInfo(2, 2048, 4, 32);
m_cache[0x79] = CacheInfo(2, 128, 8, 64);
m_cache[0x7a] = CacheInfo(2, 256, 8, 64);
m_cache[0x7b] = CacheInfo(2, 512, 8, 64);
m_cache[0x7c] = CacheInfo(2, 1024, 8, 64);
m_cache[0x82] = CacheInfo(2, 256, 8, 32);
m_cache[0x83] = CacheInfo(2, 512, 8, 32);
m_cache[0x84] = CacheInfo(2, 1024, 8, 32);
m_cache[0x85] = CacheInfo(2, 2048, 8, 32);
m_cache[0x86] = CacheInfo(2, 512, 4, 64);
m_cache[0x87] = CacheInfo(2, 1024, 8, 64);

m_cache[0x22] = CacheInfo(3, 512, 4, 64);
m_cache[0x23] = CacheInfo(3, 1024, 8, 64);
m_cache[0x25] = CacheInfo(3, 2048, 8, 64);
m_cache[0x29] = CacheInfo(3, 4096, 8, 64);
}

computerInfo::~computerInfo(void)
{
}
//以下代码可以取得系统特征码(网卡MAC、硬盘序列号、CPU ID、BIOS编号)

// 网卡 MAC 地址,注意: MAC 地址是可以在注册表中修改的

std::string computerInfo::GetMacAddress()
{
BYTE szMacAddress[128];
memset(szMacAddress,0,sizeof(szMacAddress));
UINT uMacAddressLen=0;
UINT uErrorCode = 0;
IP_ADAPTER_INFO iai;
ULONG uSize = 0;
DWORD dwResult = GetAdaptersInfo( &iai, &uSize );
if( dwResult == ERROR_BUFFER_OVERFLOW )
{
IP_ADAPTER_INFO* piai = ( IP_ADAPTER_INFO* )HeapAlloc( GetProcessHeap( ),0, uSize );
if( piai != NULL )
{
dwResult = GetAdaptersInfo( piai, &uSize );
if( ERROR_SUCCESS == dwResult )
{
IP_ADAPTER_INFO* piai2 = piai;
while( piai2 != NULL && ( uMacAddressLen + piai2->AddressLength ) < 4096U )
{
CopyMemory( szMacAddress + uMacAddressLen, piai2->Address, piai2->AddressLength );
uMacAddressLen += piai2->AddressLength;
piai2 = piai2->Next;
}

}
else
{
uErrorCode = 0xF0000000U + dwResult;
}
//VERIFY( HeapFree( GetProcessHeap( ), 0, piai ) );
}
else
{
return “\0”;
}
}
else
{
uErrorCode = 0xE0000000U + dwResult;
}
if( uErrorCode != 0U )
{
return “\0”;
}

char *buf=new char[2];
std::string strMacAddress;

for(UINT i=0;i<uMacAddressLen;i++)
{
if (szMacAddress[i]==0)
{
strMacAddress+=“00”;
}
else
{
itoa(szMacAddress[i],buf,16);//得到的MAC为10进制数,要转换成16进制

if (szMacAddress[i]<10)//小于10的要补0
{
 strMacAddress+='0';
}
strMacAddress+=buf;

}

}

return strMacAddress;
}

// 硬盘序列号,注意:有的硬盘没有序列号

std::string computerInfo::GetDiskID( )
{

LPCTSTR lpRootPathName=_T(“c:\”); //取C盘
LPTSTR lpVolumeNameBuffer=new WCHAR[12];//磁盘卷标
DWORD nVolumeNameSize=12;// 卷标的字符串长度
DWORD VolumeSerialNumber;//硬盘序列号
DWORD MaximumComponentLength;// 最大的文件长度
LPTSTR lpFileSystemNameBuffer=new WCHAR[10];// 存储所在盘符的分区类型的长指针变量
DWORD nFileSystemNameSize=10;// 分区类型的长指针变量所指向的字符串长度
DWORD FileSystemFlags;// 文件系统的一此标志
::GetVolumeInformation(lpRootPathName,
lpVolumeNameBuffer, nVolumeNameSize,
&VolumeSerialNumber, &MaximumComponentLength,
&FileSystemFlags,
lpFileSystemNameBuffer, nFileSystemNameSize);

// string str=(string)VolumeSerialNumber;
//str.Format(_T("%lx "),VolumeSerialNumber);
//AfxMessageBox(str);

std::string strDiskID;
char s_tmp[20];
sprintf(s_tmp,"%u",VolumeSerialNumber);
strDiskID=strDiskID+s_tmp;
// strDiskID=WCharToChar( CP_ACP, str.GetBuffer());//Unicode 下 CString转string
//str.ReleaseBuffer();

return strDiskID;
}

// BIOS 编号,支持 AMI, AWARD, PHOENIX
std::string computerInfo::GetBiosID()
{
BYTE szBiosID[100];
UINT uBiosIDLen=0;
SIZE_T ssize;

LARGE_INTEGER so;
so.LowPart=0x000f0000;
so.HighPart=0x00000000;
ssize=0xffff;
WCHAR strPH[30]=_T(“L\device\physicalmemory”);

DWORD ba=0;

UNICODE_STRING struniph;
struniph.Buffer=strPH;
struniph.Length=0x2c;
struniph.MaximumLength =0x2e;

OBJECT_ATTRIBUTES obj_ar;
obj_ar.Attributes =64;
obj_ar.Length =24;
obj_ar.ObjectName=&struniph;
obj_ar.RootDirectory=0;
obj_ar.SecurityDescriptor=0;
obj_ar.SecurityQualityOfService =0;

HMODULE hinstLib = LoadLibrary(_T(“ntdll.dll”));
ZWOS ZWopenS=(ZWOS)GetProcAddress(hinstLib,“ZwOpenSection”);
ZWMV ZWmapV=(ZWMV)GetProcAddress(hinstLib,“ZwMapViewOfSection”);
ZWUMV ZWunmapV=(ZWUMV)GetProcAddress(hinstLib,“ZwUnmapViewOfSection”);

//调用函数,对物理内存进行映射
HANDLE hSection;
if( 0 == ZWopenS(&hSection,4,&obj_ar) &&
0 == ZWmapV(
( HANDLE )hSection, //打开Section时得到的句柄
( HANDLE )0xFFFFFFFF, //将要映射进程的句柄,
&ba, //映射的基址
0,
0xFFFF, //分配的大小
&so, //物理内存的地址
&ssize, //指向读取内存块大小的指针
1, //子进程的可继承性设定
0, //分配类型
2 //保护类型
) )
//执行后会在当前进程的空间开辟一段64k的空间,并把f000:0000到f000:ffff处的内容映射到这里
//映射的基址由ba返回,如果映射不再有用,应该用ZwUnmapViewOfSection断开映射
{
BYTE* pBiosSerial = ( BYTE* )ba;
UINT uBiosSerialLen = FindAwardBios( &pBiosSerial );
if( uBiosSerialLen == 0U )
{
uBiosSerialLen = FindAmiBios( &pBiosSerial );
if( uBiosSerialLen == 0U )
{
uBiosSerialLen = FindPhoenixBios( &pBiosSerial );
}
}
if( uBiosSerialLen != 0U )
{
CopyMemory( szBiosID + uBiosIDLen, pBiosSerial, uBiosSerialLen );
uBiosIDLen += uBiosSerialLen;
}
ZWunmapV( ( HANDLE )0xFFFFFFFF, ( void* )ba );
}

char *buf=new char[2];
std::string strBiosID;

for(UINT i=0;i<uBiosIDLen;i++)
{

itoa(szBiosID[i],buf,16);//得到的MAC为10进制数,要转换成16进制
strBiosID+=buf;

}
return strBiosID;
}

UINT computerInfo::FindAwardBios( BYTE** ppBiosAddr )
{
BYTE* pBiosAddr = * ppBiosAddr + 0xEC71;
BYTE szBiosData[128];
CopyMemory( szBiosData, pBiosAddr, 127 );
szBiosData[127] = 0;
int iLen = lstrlen( ( LPCWSTR )szBiosData );
if( iLen > 0 && iLen < 128 )
{
//AWard: 07/08/2002-i845G-ITE8712-JF69VD0CC-00
//Phoenix-Award: 03/12/2002-sis645-p4s333
if( szBiosData[2] == ‘/’ && szBiosData[5] == ‘/’ )
{
BYTE* p = szBiosData;
while( * p )
{
if( * p < ’ ’ || * p >= 127 )
{
break;
}
++ p;
}
if( * p == 0 )
{
* ppBiosAddr = pBiosAddr;
return ( UINT )iLen;
}
}
}
return 0;
}

UINT computerInfo::FindAmiBios( BYTE** ppBiosAddr )
{
BYTE* pBiosAddr = * ppBiosAddr + 0xF478;
BYTE szBiosData[128];
CopyMemory( szBiosData, pBiosAddr, 127 );
szBiosData[127] = 0;
int iLen = lstrlen( (LPCWSTR )szBiosData );
if( iLen > 0 && iLen < 128 )
{
// Example: “AMI: 51-2300-000000-00101111-030199-”
if( szBiosData[2] == ‘-’ && szBiosData[7] == ‘-’ )
{
BYTE* p = szBiosData;
while( * p )
{
if( * p < ’ ’ || * p >= 127 )
{
break;
}
++ p;
}
if( * p == 0 )
{
* ppBiosAddr = pBiosAddr;
return ( UINT )iLen;
}
}
}
return 0;
}

UINT computerInfo::FindPhoenixBios( BYTE** ppBiosAddr )
{
UINT uOffset[3] = { 0x6577, 0x7196, 0x7550 };
for( UINT i = 0; i < 3; ++ i )
{
BYTE* pBiosAddr = * ppBiosAddr + uOffset[i];
BYTE szBiosData[128];
CopyMemory( szBiosData, pBiosAddr, 127 );
szBiosData[127] = 0;
int iLen = lstrlen( (LPCWSTR )szBiosData );

if( iLen > 0 && iLen < 128 )
{
// Example: Phoenix “NITELT0.86B.0044.P11.9910111055”
if( szBiosData[7] == ‘.’ && szBiosData[11] == ‘.’ )
{
BYTE* p = szBiosData;
while( * p )
{
if( * p < ’ ’ || * p >= 127 )
{
break;
}
++ p;
}
if( * p == 0 )
{
* ppBiosAddr = pBiosAddr;
return ( UINT )iLen;
}
}
}
}
return 0;
}

string computerInfo::GetVID()
{
char cVID[13]; // Store Vender ID String, contain 12 chars
memset(cVID, 0, 13); // Initialize all chars to 0
Executecpuid(0); // Execute cpuid instruction with eax = 0
memcpy(cVID, &m_ebx, 4); // ebx contains the first 4 chars
memcpy(cVID+4, &m_edx, 4); // edx contains the middle 4 chars
memcpy(cVID+8, &m_ecx, 4); // ecx contains the last 4 chars;

return string(cVID); // convert to string and return
}

string computerInfo::GetBrand()
{
const DWORD BRANDID = 0x80000002; // brand parameter start at 0x80000002
char cBrand[49]; // Store Brand String, contain 48 chars
memset(cBrand, 0, 49); // Initialize all chars to 0

for (DWORD i = 0; i < 3; i++) // Execute cpuid instruction with
{ // eax = 0x80000002 to 0x80000004
Executecpuid(BRANDID + i);
memcpy(cBrand + i*16, &m_eax, 16); // eax, ebx, ecx, edx contain the brand string
}

return string(cBrand); // convert to string and return
}

DWORD computerInfo::GetCacheInfo(CacheInfo& L1, CacheInfo& L2, CacheInfo& L3)
{
BYTE cValues[16]; // Totally 16 byte information
DWORD result = 0; // Cache number
Executecpuid(2); // Execute cpuid instruction with eax = 2
memcpy(cValues, &m_eax, 16); // copy return value

for (int i = 1; i < 16; i++)
{
if (m_cache.find(cValues[i]) != m_cache.end()) // if this information is about cache
{
switch (m_cache[cValues[i]].level) // Get cache information from table
{
case 1: // L1 cache
L1 = m_cache[cValues[i]];
break;
case 2: // L2 cache
L2 = m_cache[cValues[i]];
break;
case 3: // L3 cache
L3 = m_cache[cValues[i]];
break;
default:
break;
}
result++;
}

}

return result;
}
/*
bool computerInfo::GetSerialNumber(CpuSerialNumber& serial)
{
Executecpuid(1); // Execute cpuid instruction with eax = 1
bool isSupport = m_edx & (1<<18); // Check if Serial Number is supported
if (false == isSupport) // not support
{
return false;
}
memcpy(&serial.nibble[4], &m_eax, 4); // eax is the higher 2 nibble

Executecpuid(3); // Execute cpuid instruction with eax = 3
memcpy(&serial.nibble[0], &m_ecx, 8); // ecx and edx constains the middle and first 4 nibble

return true;
}
*/
void computerInfo::Executecpuid(DWORD veax)
{
// The following 4 DWORD variable store the four registers values after cpuid
DWORD deax;
DWORD debx;
DWORD decx;
DWORD dedx;

__asm
{
mov eax, veax
cpuid
mov deax, eax
mov debx, ebx
mov decx, ecx
mov dedx, edx
}

m_eax = deax; // store in class member
m_ebx = debx;
m_ecx = decx;
m_edx = dedx;
}

bool computerInfo::IsHyperThreading()
{
Executecpuid(1); // Execute cpuid instruction with eax = 1

return m_edx & (1<<28); // bit 28 be set represent hyper-threading is supported
}

bool computerInfo::IsEST()
{
Executecpuid(1); // Execute cpuid instruction with eax = 1

return m_ecx & (1<<7); // bit 7 be set represent Enhanced Speed Step is supported
}

bool computerInfo::IsMMX()
{
Executecpuid(1); // Execute cpuid instruction with eax = 1

return m_edx & (1<<23); // bit 28 be set represent MMX is supported
}
std::string computerInfo::WCharToChar(UINT PageCode, std::wstring strWChar)
{
std::string strChar="";
strChar.clear();
int ret = 0;
int nSize = (int)strWChar.length()2;
static char pszDest[1024
10];
if( pszDest )
{
memset( pszDest, 0, nSize+1 );
ret = WideCharToMultiByte(PageCode,NULL,strWChar.c_str(),-1,pszDest,nSize,NULL,FALSE);
pszDest[nSize] = ‘\0’;
strChar = pszDest;
}
return strChar;

}

std::wstring computerInfo::CharToWChar(UINT PageCode, std::string strChar)
{
std::wstring strWChar=_T("");
strWChar.clear();
int ret = 0;
//wchar_t pszDest = new wchar_t[strChar.length()+1];
static wchar_t pszDest[1024
10];
if( pszDest )
{
memset( pszDest, 0, (strChar.length()+1)*sizeof(wchar_t) );
ret = MultiByteToWideChar(PageCode, 0, strChar.c_str(), -1, pszDest, (int)strChar.length());
pszDest[strChar.length()] = L’\0’;
strWChar = pszDest;
}
return strWChar;
}

猜你喜欢

转载自blog.csdn.net/networmrlc/article/details/86530989