MFC获取电脑硬盘序列号(附源码)

在新建的工程里面添加一个类 即:以下一个类 GetHDSerial.cpp

/m_buffer[256];WORD m_serial[256];DWORD m_OldInterruptAddress;DWORDLONG m_IDTR;// 等待硬盘空闲static unsigned int WaitHardDiskIdle() {BYTE byTemp;Waiting:_asm{mov dx, 0x1f7in al, dxcmp al, 0x80jb Endwaitingjmp Waiting}Endwaiting:_asm{mov byTemp, al}return byTemp; } //中断服务程序void _declspec( naked )InterruptProcess(void){int byTemp;int i;WORD temp;//保存寄存器值_asm{push eaxpush ebxpush ecxpush edxpush esi}WaitHardDiskIdle();//等待硬盘空闲状态_asm{mov dx, 0x1f6mov al, 0xa0out dx, al}byTemp = WaitHardDiskIdle(); //若直接在Ring3级执行等待命令,会进入死循环if ((byTemp&0x50)!=0x50){_asm // 恢复中断现场并退出中断服务程序{pop esipop edxpop ecxpop ebxpop eaxiretd}}_asm{mov dx, 0x1f6 //命令端口1f6,选择驱动器0mov al, 0xa0out dx, alinc dxmov al, 0xecout dx, al //发送读驱动器参数命令}byTemp = WaitHardDiskIdle();if ((byTemp&0x58)!=0x58){_asm // 恢复中断现场并退出中断服务程序{pop esipop edxpop ecxpop ebxpop eaxiretd}}//读取硬盘控制器的全部信息for (i=0;i<256;i++){_asm{mov dx, 0x1f0in ax, dxmov temp, ax}m_serial[i] = temp;}_asm{pop esipop edxpop ecxpop ebxpop eaxiretd} }//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_IDTRmov eax,dword ptr [m_IDTR+02h]add eax,3*08h+04hcli//保存原先的中断入口地址push ecxmov ecx,dword ptr [eax]mov cx,word ptr [eax-04h]mov dword ptr m_OldInterruptAddress,ecxpop ecx//设置修改的中断入口地址为新的中断处理程序入口地址push ebxlea ebx,InterruptProcessmov word ptr [eax-04h],bxshr ebx,10hmov word ptr [eax+02h],bxpop ebxh//恢复原先的中断入口地址push ecxmov ecx,dword ptr m_OldInterruptAddressmov word ptr [eax-04h],cxshr ecx,10hmov word ptr [eax+02h],cxpop ecxstipop 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){ [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){ [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 = CreateFileA (driveName,GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,OPEN_EXISTING, 0, NULL);if (hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE) {GETVERSIONOUTPARAMS VersionParams;DWORDcbBytesReturned = 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){BYTEbIDCmd = 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 = CreateFileA (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) );}夫妇一条心,泥土变黄金。

MFC获取电脑硬盘序列号(附源码)

相关文章:

你感兴趣的文章:

标签云: