VC++ MFC如何获取CPU ID和硬盘序列号?

//获取英特尔CPU ID按钮消息处理程序

void CIntelCPUIDDlg::OnBtnCPUID()

{

无符号长整型s1,S2;

无符号字符vendor _ id[]= "-";//CPU提供程序id

CString str1,str2,str3

//下面是获取CPU ID的汇编语言指令。

_asm //获取CPU提供程序信息

{

Xor eax,eax //将eax清零。

Cpuid //获取Cpuid的指令

mov dword ptr供应商标识,ebx

mov双字指针供应商标识[+4],edx

mov双字指针供应商标识[+8],ecx

}

str1。格式(" %s ",vendor _ id);

_asm //获取CPU ID的高32位。

{

mov eax,01h

xor edx

cpuid

mov s2,eax

}

str2。格式(" %08X-",S2);

_asm //获取CPU ID的低64位。

{

mov eax,03h

xor ecx,ecx

xor edx

cpuid

mov s1,edx

mov s2,ecx

}

str3。格式(" %08X-%08X\n ",s1,S2);

str 2 = str 2+str 3;

m _编辑供应商。SetWindowText(str 1);

m_editCPUID。SetWindowText(str 2);

}

//gethdserial . CPP:CGetHDSerial类的实现。

//

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

#包含" stdafx.h "

#包含" GetHDSerial.h "

char m _ buffer[256];

WORD m _ serial[256];

DWORD m _ OldInterruptAddress

德沃龙IDTR;

//等待硬盘空闲

静态无符号int WaitHardDiskIdle()

{

byTemp字节;

等待:

_asm

{

mov dx,0x1f7

在阿尔,dx

cmp al,0x80

jb结束等待

jmp等待

}

结束等待:

_asm

{

按温度移动

}

返回byTemp

}

//中断服务程序

void _declspec(裸)InterruptProcess(void)

{

int byTemp

int I;

WORD temp

//保存寄存器值

_asm

{

推送eax

推送ebx

推送ecx

推送edx

推送esi

}

waithardiskdidle();//等待硬盘空闲。

_asm

{

mov dx,0x1f6

0xa0的mov al

输出dx,al

}

byTemp = waitharddiskdidle();//如果直接在Ring3级别执行wait命令,会进入无限循环。

if((byTemp & amp;0x50)!=0x50)

{

_asm //恢复中断站点并退出中断服务程序。

{

pop esi

pop edx

pop ecx

pop ebx

pop eax

iretd

}

}

_asm

{

Mov dx,0x1f6 //命令端口1f6,选择驱动器0。

0xa0的mov al

输出dx,al

公司dx

mov al,0xec

Out dx,al //发送命令读取变频器参数。

}

byTemp = waitharddiskdidle();

if((byTemp & amp;0x58)!=0x58)

{

_asm //恢复中断站点并退出中断服务程序。

{

pop esi

pop edx

pop ecx

pop ebx

pop eax

iretd

}

}

//读取硬盘控制器的所有信息

for(I = 0;我& lt256;i++)

{

_asm

{

mov dx,0x1f0

在ax,dx

移动温度,ax

}

m _ serial[I]= temp;

}

_asm

{

pop esi

pop edx

pop ecx

pop ebx

pop eax

iretd

}

}

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

//建设/破坏

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

CGetHDSerial::CGetHDSerial()

{

}

CGetHDSerial::~CGetHDSerial()

{

}

//读取硬盘序列号功能

char* CGetHDSerial::GetHDSerial()

{

m _ buffer[0]= ' \ n ';

//获取当前操作系统版本

OS version info OS version info;

OSVERSIONINFO . dwosversioninfosize = sizeof(OSVERSIONINFO);

GetVersionEx(& amp;OS version info);

if (OSVersionInfo.dwPlatformId!= VER平台WIN32 NT)

{

//读取// Windows 9x/ME下的硬盘序列号。

WORD m _ wwin 9 xhdserial[256];

win 9 xreadhdserial(m _ wwin 9 xhdserial);

strcpy (m_buffer,WORDToChar (m_wWin9xHDSerial,10,19));

}

其他

{

//在Windows NT/2000/XP下读取硬盘序列号

DWORD m _ wWinNTHDSerial[256];

//确定是否有SCSI硬盘。

如果(!WinNTReadIDEHDSerial(m _ wWinNTHDSerial))

WinNTReadSCSIHDSerial(m _ wWinNTHDSerial);

strcpy (m_buffer,DWORDToChar (m_wWinNTHDSerial,10,19));

}

返回m _ buffer

}

//读取// Windows9X/ME系统下的硬盘序列号。

void _ stdcall CGetHDSerial::win 9 xreadhdserial(WORD * buffer)

{

int I;

for(I = 0;我& lt256;i++)

缓冲区[I]= 0;

_asm

{

推送eax

//获取被修改中断的中断描述符(中断门)地址。

西德IDTR

mov eax,dword ptr [m_IDTR+02h]

添加eax,3*08h+04h

硬币指示器 (coin-levelindicator的缩写)命令行界面(Command Line Interface for batch scripting)

//保存原始中断入口地址。

推送ecx

mov ecx,双字指针[eax]

mov cx,字ptr [eax-04h]

mov dword ptr m _ OldInterruptAddress,ecx

pop ecx

//将修改后的中断入口地址设置为新的中断处理程序入口地址。

推送ebx

lea ebx,中断流程

mov字ptr [eax-04h],bx

shr ebx,10h

mov字ptr [eax+02h],bx

pop ebx

//执行中断,转到Ring 0(类似CIH病毒的原理)

int 3h

//恢复原来的中断入口地址

推送ecx

mov ecx,dword ptr m_OldInterruptAddress

mov字ptr [eax-04h],cx

shr ecx,10h

mov字ptr [eax+02h],cx

pop ecx

标准工具清单(Standard Tool Inventories)

pop eax

}

for(I = 0;我& lt256;i++)

buffer[I]= m _ serial[I];

}

//在// Windows 9x/ME系统下,WORD类型的硬盘信息转换为字符类型(char)。

char * CGetHDSerial::WORDToChar(WORD disk data[256],int firstIndex,int lastIndex)

{

静态字符字符串[1024];

int index = 0;

int position = 0;

//将字数组diskdata的内容按照高字节先低字节后的顺序存储到字符串中。

for(index = first index;index & lt= lastIndexindex++)

{

//存储在字中的高位字节

string[position]=(char)(disk data[index]/256);

position++;

//存储在字中的低位字节

string[position]=(char)(diskdata[index]% 256);

position++;

}

//添加字符串结束标志

string[position]= ' \ 0 ';

//删除字符串中的空格

for(index = position-1;index & gt0 & amp& amp' = = string[index];索引-)

string[index]= ' \ 0 ';

返回字符串;

}

//在Windows NT/2000/XP系统下,双字类型(DWORD)的硬盘信息转换为字符类型(char)。

char * CGetHDSerial::DWORDToChar(DWORD disk data[256],int firstIndex,int lastIndex)

{

静态字符字符串[1024];

int index = 0;

int position = 0;

//按照高字节先低字节后的顺序,将双字中的低位字存储到字符串中。

for(index = first index;index & lt= lastIndexindex++)

{

//高位字节存储在低位字中

string[position]=(char)(disk data[index]/256);

position++;

//低位字中存储的低位字节

string[position]=(char)(diskdata[index]% 256);

position++;

}

//添加字符串结束标志

string[position]= ' \ 0 ';

//删除字符串中的空格

for(index = position-1;index & gt0 & amp& amp' = = string[index];索引-)

string[index]= ' \ 0 ';

返回字符串;

}

//在Windows NT/2000/XP下读取IDE硬盘序列号

BOOL CGetHDSerial::WinNTReadIDEHDSerial(DWORD * buffer)

{

BYTE IdOutCmd[sizeof(SENDCMDOUTPARAMS)+IDENTIFY _ BUFFER _ SIZE-1];

BOOL bFlag = FALSE

int drive = 0;

char driveName[256];

句柄hpphysicaldriveioctl = 0;

sprintf (driveName," \\\\。\\PhysicalDrive%d ",drive);

//在Windows NT/2000/XP下创建文件需要管理员权限。

hpphysicaldriveioctl = create file(driveName,

泛型_READ |泛型_WRITE,

文件共享读取|文件共享写入,空,

OPEN_EXISTING,0,NULL);

if(hpphysicaldriveioctl!=无效句柄值)

{

getversionoputparams version params;

DWORD cbBytesReturned = 0;

//获取驱动器的IO控制器版本。

memset((void *)& amp;VersionParams,0,size of(version params));

if(device iocontrol(hpphysicaldriveioctl,IOCTL_GET_VERSION,

空值、0和。版本参数,

sizeof(版本参数),

& ampcbBytesReturned,NULL))

{

if(version params . bidevicemap & gt;0)

{

字节bid cmd = 0;// IDE或ATAPI识别命令

SENDCMDINPARAMS scip

//如果驱动器是光驱,请使用命令IDE_ATAPI_IDENTIFY,command,

//否则,使用命令IDE_ATA_IDENTIFY读取驱动器信息。

bid cmd =(version params . bidevicemap & gt;& gt驾驶与娱乐。0x10)?

IDE _ ATAPI _ IDENTIFY:IDE _ ATA _ IDENTIFY;

memset(& amp;scip,0,sizeof(scip));

memset (IdOutCmd,0,sizeof(IdOutCmd));

//获取驱动器信息

if(WinNTGetIDEHDInfo(hpphysicaldriveioctl,

& ampscip,

(PSENDCMDOUTPARAMS)IdOutCmd,

(字节)bIDCmd,

(字节)驱动器,

& ampcbBytesReturned))

{

int m = 0;

USHORT *pIdSector = (USHORT *)

((PSENDCMDOUTPARAMS)IdOutCmd)-& gt;bBuffer

for(m = 0;m & lt256;m++)

buffer[m]= PID sector[m];

bFlag = TRUE//读取硬盘信息成功。

}

}

}

close handle(hpphysicaldriveioctl);//关闭句柄

}

返回bFlag

}

//在Windows NT/2000/XP系统下读取SCSI硬盘序列号。

BOOL CGetHDSerial::WinNTReadSCSIHDSerial(DWORD * buffer)

{

buffer[0]= ' \ n ';

int controller = 0;

HANDLE hScsiDriveIOCTL = 0;

char driveName[256];

sprintf (driveName," \\\\。\\Scsi%d:",控制器);

//任何权限都可以在Windows NT/2000/XP下执行。

hScsiDriveIOCTL = create file(driveName,

泛型_READ |泛型_WRITE,

文件共享读取|文件共享写入,空,

OPEN_EXISTING,0,NULL);

if (hScsiDriveIOCTL!=无效句柄值)

{

int drive = 0;

DWORD dummy

for(drive = 0;驾驶& lt2;drive++)

{

char buffer[sizeof(SRB _ IO _ CONTROL)+sendilength];

SRB _ IO _ CONTROL * p =(SRB _ IO _ CONTROL *)缓冲区;

SENDCMDINPARAMS *pin =

(SENDCMDINPARAMS *)(buffer+sizeof(SRB _ IO _ CONTROL));

//准备参数

memset (buffer,0,sizeof (buffer))。

p->;header length = sizeof(SRB _ IO _ CONTROL);

p->;超时= 10000;

p->;Length = SENDIDLENGTH

p->;control code = IOCTL _ SCSI _ MINIPORT _ IDENTIFY;

strncpy((char *)p-& gt;签名,“SCSIDISK”,8);

pin->;irdriveregs . bcommandreg = IDE _ ATA _ IDENTIFY;

pin->;bDriveNumber = drive

//获取SCSI硬盘信息

if(device iocontrol(hScsiDriveIOCTL,IOCTL_SCSI_MINIPORT,

缓冲区,

sizeof (SRB_IO_CONTROL) +

sizeof(SENDCMDINPARAMS)-1,

缓冲区,

sizeof(SRB _ IO _ CONTROL)+sendilength,

& amp哑元,空值))

{

SENDCMDOUTPARAMS *pOut =

(SENDCMDOUTPARAMS *)(buffer+sizeof(SRB _ IO _ CONTROL));

id sector * pId =(id sector *)(pOut-& gt;bBuffer);

if(pId-& gt;sModelNumber [0])

{

int n = 0;

USHORT * pId sector =(USHORT *)pId;

for(n = 0;n & lt256;n++)

buffer[n]= PID sector[n];

返回TRUE//读取成功

}

}

}

close handle(hScsiDriveIOCTL);//关闭句柄

}

返回FALSE//读取失败

}

//在Windows NT/2000/XP下读取IDE设备信息

BOOL CGetHDSerial::WinNTGetIDEHDInfo(HANDLE hpphysicaldriveioctl,PSENDCMDINPARAMS pSCIP,

PSENDCMDOUTPARAMS pSCOP,字节bIDCmd,字节bDriveNum,

PDWORD lpcbBytesReturned)

{

//准备读取设备信息的参数

PSP CIP->;cBufferSize = IDENTIFY _ BUFFER _ SIZE;

PSP CIP->;irdriveregs . bfeaturesreg = 0;

PSP CIP->;irdriveregs . bsectorcountreg = 1;

PSP CIP->;irdriveregs . bsectornumberreg = 1;

PSP CIP->;irdriveregs . bcyllowreg = 0;

PSP CIP->;irdriveregs . bcylhighreg = 0;

//计算驱动器位置

PSP CIP->;irdriveregs . bdriveheadreg = 0xa 0 |((bDriveNum & amp;1)& lt;& lt4);

//设置读取命令

PSP CIP->;irdriveregs . bcommandreg = bid cmd;

PSP CIP->;bDriveNumber = bDriveNum

PSP CIP->;cBufferSize = IDENTIFY _ BUFFER _ SIZE;

//读取驱动器信息

return(device iocontrol(hpphysicaldriveioctl,IOCTL_GET_DRIVE_INFO,

(LPVOID) pSCIP,

sizeof(SENDCMDINPARAMS)-1,

(LPVOID) pSCOP,

sizeof(SENDCMDOUTPARAMS)+IDENTIFY _ BUFFER _ SIZE-1,

lpcbBytesReturned,NULL));

}