How does VC++ MFC get CPU ID and hard disk serial number?

//Get the Intel CPU ID button message handler.

void CIntelCPUIDDlg::OnBtnCPUID()

{

Unsigned long integer s 1, S2;

Unsigned character vendor _ id[]= "-";-"; //CPU provider id

CString str 1,str2,str3

//The following is the assembly language instruction to get the CPU ID.

_asm // Get CPU provider information

{

Xor eax, eax // clear eax.

Cpuid // instruction to get cpuid

Mov dword ptr supplier identification, ebx

Mov double-word pointer supplier identification [+4], edx

Mov double-word pointer supplier ID [+8], ecx

}

str 1。 Format ("%s", vendor _ id);

_asm // Get the upper 32 bits of the CPU ID.

{

mov eax,0 1h

xor edx

cpuid

mov s2,eax

}

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

_asm // Get the lower 64 bits of the CPU ID.

{

mov eax,03h

xor ecx,ecx

xor edx

cpuid

mov s 1,edx

mov s2,ecx

}

str3。 Format ("%08X-%08X\n", s 1, S2);

str 2 = str 2+str 3;

M _ Edit supplier. SetWindowText(str 1);

m_editCPUID。 SetWindowText(str 2);

}

//gethdserial.cpp: implementation of cgethdserial class.

//

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

# contains "stdafx.h"

# contains "GetHDSerial.h"

char m _ buffer[256];

WORD m _ serial[256];

DWORD m _ OldInterruptAddress

Dvoron IDTR;;

//Wait for the hard disk to be free

Static unsigned int WaitHardDiskIdle ()

{

ByTemp bytes;

Wait:

_asm

{

mov dx,0x 1f7

In Al, dx

cmp al,0x80

Jb end wait

Jmp waiting

}

End wait:

_asm

{

Move by temperature

}

Return to byTemp

}

//Interrupt service program

Void _declspec (naked) InterruptProcess(void)

{

int byTemp

int I;

WORD temp

//Save the register value

_asm

{

Push eax

Push ebx

Push ecx

Push edx

Push esi

}

waithardiskdidle(); //Wait for the hard disk to be free.

_asm

{

mov dx,0x 1f6

Mov al of 0xa0

Output dx, al

}

byTemp = waitharddiskdidle(); //If you execute the wait command directly at the Ring3 level, you will enter an infinite loop.

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

{

_asm // Resume the interrupt site and exit the interrupt service program.

{

pop esi

pop edx

pop ecx

pop ebx

pop eax

iretd

}

}

_asm

{

Mov dx, 0x 1f6 // command port 1f6, select drive 0.

Mov al of 0xa0

Output dx, al

Company dx

mov al,0xec

Out dx, al // Send command to read inverter parameters.

}

byTemp = waitharddiskdidle();

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

{

_asm // Resume the interrupt site and exit the interrupt service program.

{

pop esi

pop edx

pop ecx

pop ebx

pop eax

iretd

}

}

//Read all information of the hard disk controller.

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

{

_asm

{

mov dx,0x 1f0

In ax, dx

Moving temperature, ax

}

m _ serial[I]= temp;

}

_asm

{

pop esi

pop edx

pop ecx

pop ebx

pop eax

iretd

}

}

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

//Construction/Destruction

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

CGetHDSerial::CGetHDSerial()

{

}

CGetHDSerial::~CGetHDSerial()

{

}

//Read hard disk serial number function

char* CGetHDSerial::GetHDSerial()

{

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

//Get the current operating system version

OS version info OS version info;

OSVERSIONINFO . dwosversioninfosize = sizeof(OSVERSIONINFO);

GetVersionEx(& amp; OS version info);

if (OSVersionInfo.dwPlatformId! = VER platform WIN32 NT)

{

//Read the serial number of the hard disk under // Windows 9x/ME.

WORD m _ wwin 9 xhdserial[256];

win 9 xreadhdserial(m _ wwin 9 xhdserial);

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

}

other

{

//Read the serial number of the hard disk under Windows NT/2000/XP.

DWORD m _ wWinNTHDSerial[256];

//Determine if there is a SCSI hard disk.

If (! WinNTReadIDEHDSerial(m _ wWinNTHDSerial))

WinNTReadSCSIHDSerial(m _ wWinNTHDSerial);

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

}

Returns m _ buffer.

}

//Read the serial number of the hard disk under // Windows9X/ME system.

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

{

int I;

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

Buffer [i] = 0;

_asm

{

Push eax

//Get the address of the interrupt descriptor (interrupt gate) of the modified interrupt.

IDTR in west Germany

mov eax,dword ptr [m_IDTR+02h]

Add eax, 3*08h+04h.

Coin indicator (short for coin-levelindicator) command line interface for batch scripting.

//Save the original interrupt entry address.

Push ecx

Mov ecx, double-word pointer [eax]

Mov cx, word ptr [eax-04h]

mov dword ptr m _ OldInterruptAddress,ecx

pop ecx

//Set the modified interrupt entry address as the new interrupt handler entry address.

Push ebx

Lea ebx, interrupt the process

Mov word ptr [eax-04h], bx

shr ebx, 10h

Mov word ptr [eax+02h], bx

pop ebx

//Execute the interrupt and go to Ring 0 (similar to the principle of CIH virus)

int 3h

//Restore the original interrupt entry address

Push ecx

mov ecx,dword ptr m_OldInterruptAddress

Mov word ptr [eax-04h], cx

shr ecx, 10h

Mov word ptr [eax+02h], cx

pop ecx

List of standard tools (Standard Tool Inventories)

pop eax

}

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

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

}

//In // Windows 9x/ME system, the hard disk information of WORD type is converted into character type (char).

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

{

Static character string [1024];

int index = 0;

int position = 0;

//Store the contents of the word array diskdata into the string in the order of high bytes first and low bytes later.

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

{

//High-order bytes stored in a word

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

position++;

//Low-order bytes stored in a word

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

position++;

}

//Add end of string flag

string[position]= ' \ 0 ';

//Delete spaces in the string

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

string[index]= ' \ 0 ';

Returns a string;

}

//Under Windows NT/2000/XP system, the hard disk information of double word type (DWORD) is converted into character type (char).

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

{

Static character string [1024];

int index = 0;

int position = 0;

//According to the order of high bytes first and low bytes later, the low-order words in the doubleword are stored in the string.

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

{

//The upper byte is stored in the lower word.

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

position++;

//Low byte stored in low word

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

position++;

}

//Add end of string flag

string[position]= ' \ 0 ';

//Delete spaces in the string

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

string[index]= ' \ 0 ';

Returns a string;

}

//Read the serial number of IDE hard disk under Windows NT/2000/XP.

BOOL CGetHDSerial::WinNTReadIDEHDSerial(DWORD * buffer)

{

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

BOOL bFlag = FALSE

int drive = 0;

char driveName[256];

Handle hpphysicaldriveioctl = 0;;

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

//Administrator permissions are required to create files under Windows NT/2000/XP.

hpphysicaldriveioctl = create file(driveName,

Generic _READ | generic _WRITE,

File share read | file share write, empty,

OPEN_EXISTING,0,NULL);

if(hpphysicaldriveioctl! = Invalid handle value)

{

getversionoputparams version params;

DWORD cbBytesReturned = 0;

//Get the IO controller version of the drive.

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

if(device iocontrol(hpphysicaldriveioctl,IOCTL_GET_VERSION,

Null, 0 and. Version parameter,

Sizeof (version parameter),

& ampcbBytesReturned,NULL))

{

if(version params . bidevicemap & gt; 0)

{

Byte bidcmd = 0; // IDE or ATAPI recognition command

SENDCMDINPARAMS scip

//If the drive is an optical drive, use the command IDE_ATAPI_IDENTIFY, command,

//Otherwise, use the command IDE_ATA_IDENTIFY to read the drive information.

bid cmd =(version params . bidevicemap & gt; & gt driving and entertainment. 0x 10)?

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

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

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

//Get the drive information

if(WinNTGetIDEHDInfo(hpphysicaldriveioctl,

& ampscip,

(PSENDCMDOUTPARAMS)IdOutCmd,

(bytes) bIDCmd,

(byte) drive,

& ampcbBytesReturned))

{

int m = 0;

USHORT *pIdSector = (USHORT *)

((PSENDCMDOUTPARAMS)IdOutCmd)-& gt; bBuffer

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

buffer[m]= PID sector[m];

BFlag = TRUE// Reading hard disk information succeeded.

}

}

}

close handle(hpphysicaldriveioctl); //Close the handle

}

Return to bFlag

}

//Read the serial number of SCSI hard disk under Windows NT/2000/XP system.

BOOL CGetHDSerial::WinNTReadSCSIHDSerial(DWORD * buffer)

{

buffer[0]= ' \ n ';

int controller = 0;

HANDLE hScsiDriveIOCTL = 0;

char driveName[256];

sprintf (driveName," \\\\。 \\Scsi%d: ",controller);

//Any permission can be executed under Windows NT/2000/XP.

hScsiDriveIOCTL = create file(driveName,

Generic _READ | generic _WRITE,

File share read | file share write, empty,

OPEN_EXISTING,0,NULL);

if (hScsiDriveIOCTL! = Invalid handle value)

{

int drive = 0;

DWORD dummy

for(drive = 0; Driving & lt2; drive++)

{

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

SRB _ IO _ Control * p = (SRB _ IO _ Control *) buffer;

SENDCMDINPARAMS *pin =

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

//Prepare parameters

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

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

p->; Timeout =10000;

p->; Length = SENDIDLENGTH

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

strncpy((char *)p-& gt; Signature, "SCSIDISK", 8);

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

pin->; bDriveNumber = drive

//Get SCSI hard disk information

if(device iocontrol(hScsiDriveIOCTL,IOCTL_SCSI_MINIPORT,

Buffer,

sizeof (SRB_IO_CONTROL) +

sizeof(SENDCMDINPARAMS)- 1,

Buffer,

sizeof(SRB _ IO _ CONTROL)+sendilength,

& dummy, null))

{

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];

Returns TRUE// Read successfully.

}

}

}

close handle(hScsiDriveIOCTL); //Close the handle

}

Returns FALSE// Reading failed.

}

//Read IDE device information under Windows NT/2000/XP.

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

PSENDCMDOUTPARAMS pSCOP, byte bIDCmd, byte bDriveNum,

PDWORD lpcbBytesReturned)

{

//Prepare parameters for reading device information.

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;

//Calculate the drive position

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

//Set the read command

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

PSP CIP->; bDriveNumber = bDriveNum

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

//Read the drive information

return(device iocontrol(hpphysicaldriveioctl,IOCTL_GET_DRIVE_INFO,

(LPVOID) pSCIP,

sizeof(SENDCMDINPARAMS)- 1,

(LPVOID) pSCOP,

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

lpcbBytesReturned,NULL));

}