當前位置:編程學習大全網 - 源碼下載 - VC++ MFC如何獲取CPU ID及硬盤的序列號?

VC++ MFC如何獲取CPU ID及硬盤的序列號?

// “獲得Intel CPU ID”按鈕消息處理函數

void CIntelCPUIDDlg::OnBtnCPUID()

{

unsigned long s1,s2;

unsigned char vendor_id[]="------------";//CPU提供商ID

CString str1,str2,str3;

// 以下為獲得CPU ID的匯編語言指令

_asm // 得到CPU提供商信息

{

xor eax,eax // 將eax清0

cpuid // 獲取CPUID的指令

mov dword ptr vendor_id,ebx

mov dword ptr vendor_id[+4],edx

mov dword ptr vendor_id[+8],ecx

}

str1.Format("%s",vendor_id);

_asm // 得到CPU ID的高32位

{

mov eax,01h

xor edx,edx

cpuid

mov s2,eax

}

str2.Format("%08X-",s2);

_asm // 得到CPU ID的低64位

{

mov eax,03h

xor ecx,ecx

xor edx,edx

cpuid

mov s1,edx

mov s2,ecx

}

str3.Format("%08X-%08X\n",s1,s2);

str2=str2+str3;

m_editVendor.SetWindowText(str1);

m_editCPUID.SetWindowText(str2);

}

// GetHDSerial.cpp: implementation of the CGetHDSerial class.

//

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

#include "stdafx.h"

#include "GetHDSerial.h"

char m_buffer[256];

WORD m_serial[256];

DWORD m_OldInterruptAddress;

DWORDLONG m_IDTR;

// 等待硬盤空閑

static unsigned int WaitHardDiskIdle()

{

BYTE byTemp;

Waiting:

_asm

{

mov dx, 0x1f7

in al, dx

cmp al, 0x80

jb Endwaiting

jmp Waiting

}

Endwaiting:

_asm

{

mov byTemp, al

}

return byTemp;

}

//中斷服務程序

void _declspec( naked )InterruptProcess(void)

{

int byTemp;

int i;

WORD temp;

//保存寄存器值

_asm

{

push eax

push ebx

push ecx

push edx

push esi

}

WaitHardDiskIdle();//等待硬盤空閑狀態

_asm

{

mov dx, 0x1f6

mov al, 0xa0

out dx, al

}

byTemp = WaitHardDiskIdle(); //若直接在Ring3級執行等待命令,會進入死循環

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

{

_asm // 恢復中斷現場並退出中斷服務程序

{

pop esi

pop edx

pop ecx

pop ebx

pop eax

iretd

}

}

_asm

{

mov dx, 0x1f6 //命令端口1f6,選擇驅動器0

mov al, 0xa0

out dx, al

inc dx

mov al, 0xec

out dx, al //發送讀驅動器參數命令

}

byTemp = WaitHardDiskIdle();

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

{

_asm // 恢復中斷現場並退出中斷服務程序

{

pop esi

pop edx

pop ecx

pop ebx

pop eax

iretd

}

}

//讀取硬盤控制器的全部信息

for (i=0;i<256;i++)

{

_asm

{

mov dx, 0x1f0

in ax, dx

mov temp, ax

}

m_serial[i] = temp;

}

_asm

{

pop esi

pop edx

pop ecx

pop ebx

pop eax

iretd

}

}

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

// Construction/Destruction

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

CGetHDSerial::CGetHDSerial()

{

}

CGetHDSerial::~CGetHDSerial()

{

}

// 讀取硬盤序列號函數

char* CGetHDSerial::GetHDSerial()

{

m_buffer[0]='\n';

// 得到當前操作系統版本

OSVERSIONINFO OSVersionInfo;

OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

GetVersionEx( &OSVersionInfo);

if (OSVersionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)

{

// Windows 9x/ME下讀取硬盤序列號

WORD m_wWin9xHDSerial[256];

Win9xReadHDSerial(m_wWin9xHDSerial);

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

}

else

{

// Windows NT/2000/XP下讀取硬盤序列號

DWORD m_wWinNTHDSerial[256];

// 判斷是否有SCSI硬盤

if ( ! WinNTReadIDEHDSerial(m_wWinNTHDSerial))

WinNTReadSCSIHDSerial(m_wWinNTHDSerial);

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

}

return m_buffer;

}

// Windows9X/ME系統下讀取硬盤序列號

void _stdcall CGetHDSerial::Win9xReadHDSerial(WORD * buffer)

{

int i;

for(i=0;i<256;i++)

buffer[i]=0;

_asm

{

push eax

//獲取修改的中斷的中斷描述符(中斷門)地址

sidt m_IDTR

mov eax,dword ptr [m_IDTR+02h]

add eax,3*08h+04h

cli

//保存原先的中斷入口地址

push ecx

mov ecx,dword ptr [eax]

mov cx,word ptr [eax-04h]

mov dword ptr m_OldInterruptAddress,ecx

pop ecx

//設置修改的中斷入口地址為新的中斷處理程序入口地址

push ebx

lea ebx,InterruptProcess

mov word ptr [eax-04h],bx

shr ebx,10h

mov word ptr [eax+02h],bx

pop ebx

//執行中斷,轉到Ring 0(類似CIH病毒原理)

int 3h

//恢復原先的中斷入口地址

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

sti

pop eax

}

for(i=0;i<256;i++)

buffer[i]=m_serial[i];

}

// Windows 9x/ME系統下,將字類型(WORD)的硬盤信息轉換為字符類型(char)

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

{

static char string [1024];

int index = 0;

int position = 0;

// 按照高字節在前,低字節在後的順序將字數組diskdata 中內容存入到字符串string中

for (index = firstIndex; index <= lastIndex; index++)

{

// 存入字中的高字節

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

position++;

// 存入字中的低字節

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

position++;

}

// 添加字符串結束標誌

string [position] = '\0';

// 刪除字符串中空格

for (index = position - 1; index > 0 && ' ' == string [index]; index--)

string [index] = '\0';

return string;

}

// Windows NT/2000/XP系統下,將雙字類型(DWORD)的硬盤信息轉換為字符類型(char)

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

{

static char string [1024];

int index = 0;

int position = 0;

// 按照高字節在前,低字節在後的順序將雙字中的低字存入到字符串string中

for (index = firstIndex; index <= lastIndex; index++)

{

// 存入低字中的高字節

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

position++;

// 存入低字中的低字節

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

position++;

}

// 添加字符串結束標誌

string [position] = '\0';

// 刪除字符串中空格

for (index = position - 1; index > 0 && ' ' == string [index]; index--)

string [index] = '\0';

return string;

}

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

HANDLE hPhysicalDriveIOCTL = 0;

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

// Windows NT/2000/XP下創建文件需要管理員權限

hPhysicalDriveIOCTL = CreateFile (driveName,

GENERIC_READ | GENERIC_WRITE,

FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,

OPEN_EXISTING, 0, NULL);

if (hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)

{

GETVERSIONOUTPARAMS VersionParams;

DWORD cbBytesReturned = 0;

// 得到驅動器的IO控制器版本

memset ((void*) &VersionParams, 0, sizeof(VersionParams));

if(DeviceIoControl (hPhysicalDriveIOCTL, IOCTL_GET_VERSION,

NULL, 0, &VersionParams,

sizeof(VersionParams),

&cbBytesReturned, NULL) )

{

if (VersionParams.bIDEDeviceMap > 0)

{

BYTE bIDCmd = 0; // IDE或者ATAPI識別命令

SENDCMDINPARAMS scip;

// 如果驅動器是光驅,采用命令IDE_ATAPI_IDENTIFY, command,

// 否則采用命令IDE_ATA_IDENTIFY讀取驅動器信息

bIDCmd = (VersionParams.bIDEDeviceMap >> drive & 0x10)?

IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;

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

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

// 獲取驅動器信息

if (WinNTGetIDEHDInfo (hPhysicalDriveIOCTL,

&scip,

(PSENDCMDOUTPARAMS)&IdOutCmd,

(BYTE) bIDCmd,

(BYTE) drive,

&cbBytesReturned))

{

int m = 0;

USHORT *pIdSector = (USHORT *)

((PSENDCMDOUTPARAMS) IdOutCmd) -> bBuffer;

for (m = 0; m < 256; m++)

buffer[m] = pIdSector [m];

bFlag = TRUE; // 讀取硬盤信息成功

}

}

}

CloseHandle (hPhysicalDriveIOCTL); // 關閉句柄

}

return bFlag;

}

// WindowsNT/2000/XP系統下讀取SCSI硬盤序列號

BOOL CGetHDSerial::WinNTReadSCSIHDSerial (DWORD * buffer)

{

buffer[0]='\n';

int controller = 0;

HANDLE hScsiDriveIOCTL = 0;

char driveName [256];

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

// Windows NT/2000/XP下任何權限都可以進行

hScsiDriveIOCTL = CreateFile (driveName,

GENERIC_READ | GENERIC_WRITE,

FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,

OPEN_EXISTING, 0, NULL);

if (hScsiDriveIOCTL != INVALID_HANDLE_VALUE)

{

int drive = 0;

DWORD dummy;

for (drive = 0; drive < 2; drive++)

{

char buffer [sizeof (SRB_IO_CONTROL) + SENDIDLENGTH];

SRB_IO_CONTROL *p = (SRB_IO_CONTROL *) buffer;

SENDCMDINPARAMS *pin =

(SENDCMDINPARAMS *) (buffer + sizeof (SRB_IO_CONTROL));

// 準備參數

memset (buffer, 0, sizeof (buffer));

p -> HeaderLength = sizeof (SRB_IO_CONTROL);

p -> Timeout = 10000;

p -> Length = SENDIDLENGTH;

p -> ControlCode = IOCTL_SCSI_MINIPORT_IDENTIFY;

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

pin -> irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY;

pin -> bDriveNumber = drive;

// 得到SCSI硬盤信息

if (DeviceIoControl (hScsiDriveIOCTL, IOCTL_SCSI_MINIPORT,

buffer,

sizeof (SRB_IO_CONTROL) +

sizeof (SENDCMDINPARAMS) - 1,

buffer,

sizeof (SRB_IO_CONTROL) + SENDIDLENGTH,

&dummy, NULL))

{

SENDCMDOUTPARAMS *pOut =

(SENDCMDOUTPARAMS *) (buffer + sizeof (SRB_IO_CONTROL));

IDSECTOR *pId = (IDSECTOR *) (pOut -> bBuffer);

if (pId -> sModelNumber [0])

{

int n = 0;

USHORT *pIdSector = (USHORT *) pId;

for (n = 0; n < 256; n++)

buffer[n] =pIdSector [n];

return TRUE; // 讀取成功

}

}

}

CloseHandle (hScsiDriveIOCTL); // 關閉句柄

}

return FALSE; // 讀取失敗

}

// Windows NT/2000/XP下讀取IDE設備信息

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

PSENDCMDOUTPARAMS pSCOP, BYTE bIDCmd, BYTE bDriveNum,

PDWORD lpcbBytesReturned)

{

// 為讀取設備信息準備參數

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;

// 計算驅動器位置

pSCIP -> irDriveRegs.bDriveHeadReg = 0xA0 | ((bDriveNum & 1) << 4);

// 設置讀取命令

pSCIP -> irDriveRegs.bCommandReg = bIDCmd;

pSCIP -> bDriveNumber = bDriveNum;

pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE;

// 讀取驅動器信息

return ( DeviceIoControl (hPhysicalDriveIOCTL, IOCTL_GET_DRIVE_INFO,

(LPVOID) pSCIP,

sizeof(SENDCMDINPARAMS) - 1,

(LPVOID) pSCOP,

sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,

lpcbBytesReturned, NULL) );

}

  • 上一篇:《Spark大數據分析實戰》epub下載在線閱讀,求百度網盤雲資源
  • 下一篇:魔獸人族戰法
  • copyright 2024編程學習大全網