MFC获取电脑硬盘序列号(附源码)
在新建的工程里面添加一个类
即:以下一个类
GetHDSerial.cpp
// GetHDSerial.cpp: implementation of the CGetHDSerial class.
// Download by http://www.newxing.com/
//////////////////////////////////////////////////////////////////////
#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, 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}
}
//////////////////////////////////////////////////////////////////////
// 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+04hcli//保存原先的中断入口地址push ecxmov ecx,dword ptr [eax]mov cx,word ptr [eax-04h]mov dword ptr m_OldInterruptAddress,ecxpop ecx//设置修改的中断入口地址为新的中断处理程序入口地址push ebxlea ebx,InterruptProcess mov word ptr [eax-04h],bxshr ebx,10hmov word ptr [eax+02h],bxpop ebx//执行中断,转到Ring 0(类似CIH病毒原理)int 3h//恢复原先的中断入口地址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)
{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 = CreateFileA (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 = 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) );
}
GetHDSerial.h
// GetHDSerial.h: interface for the CGetHDSerial class.
// Download by http://www.newxing.com/
//////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <stdio.h>#define SENDIDLENGTH sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE
#define IDENTIFY_BUFFER_SIZE 512
#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 IDE_ATAPI_IDENTIFY 0xA1 // Returns ID sector for ATAPI.
#define IDE_ATA_IDENTIFY 0xEC // Returns ID sector for ATA.
#define IOCTL_GET_DRIVE_INFO 0x0007c088
#define IOCTL_GET_VERSION 0x00074080
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
{BYTE bDriverError; // Error code from driver, or 0 if no error.BYTE bIDEStatus; // Contents of IDE Error register.// Only valid when bDriverError is SMART_IDE_ERROR.BYTE bReserved[2]; // Reserved for future expansion.DWORD dwReserved[2]; // Reserved for future expansion.
} DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS;typedef struct _SENDCMDOUTPARAMS
{DWORD cBufferSize; // Size of bBuffer in bytesDRIVERSTATUS DriverStatus; // Driver status structure.BYTE bBuffer[1]; // Buffer of arbitrary length in which to store the data read from the // drive.
} SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;
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
{BYTE bFeaturesReg; // Used for specifying SMART "commands".BYTE bSectorCountReg; // IDE sector count registerBYTE bSectorNumberReg; // IDE sector number registerBYTE bCylLowReg; // IDE low order cylinder valueBYTE bCylHighReg; // IDE high order cylinder valueBYTE bDriveHeadReg; // IDE drive/head registerBYTE bCommandReg; // Actual IDE command.BYTE bReserved; // reserved for future use. Must be zero.
} IDEREGS, *PIDEREGS, *LPIDEREGS;typedef struct _SENDCMDINPARAMS
{DWORD cBufferSize; // Buffer size in bytesIDEREGS irDriveRegs; // Structure with drive register values.BYTE bDriveNumber; // Physical drive number to send // command to (0,1,2,3).BYTE bReserved[3]; // Reserved for future expansion.DWORD dwReserved[4]; // For future use.BYTE bBuffer[1]; // Input buffer.
} 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;// 获取硬盘序列号的类
class CGetHDSerial
{
public:CGetHDSerial();virtual ~CGetHDSerial();void _stdcall Win9xReadHDSerial(WORD * buffer);char* GetHDSerial();char* WORDToChar (WORD diskdata [256], int firstIndex, int lastIndex);char* DWORDToChar (DWORD diskdata [256], int firstIndex, int lastIndex);BOOL WinNTReadSCSIHDSerial(DWORD * buffer);BOOL WinNTReadIDEHDSerial (DWORD * buffer);BOOL WinNTGetIDEHDInfo (HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,PSENDCMDOUTPARAMS pSCOP, BYTE bIDCmd, BYTE bDriveNum,PDWORD lpcbBytesReturned);
};
源码下载
MFC获取电脑硬盘序列号(附源码)相关推荐
- VC++获取磁盘剩余空间(附源码)
VC++开发常用功能一系列文章 (欢迎订阅,持续更新...) 第23章:VC++获取磁盘剩余空间(附源码) 源代码demo已上传到百度网盘:永久生效 ,代码实现了获取任一磁盘的剩余空间,返回MB ...
- VC++电脑锁屏(附源码)
VC++开发常用功能一系列文章 (欢迎订阅,持续更新...) 第14章:VC++电脑锁屏(附源码) 源代码demo已上传到百度网盘:永久生效 ,文章尾部附 百度链接 源代码demo已上传到百度网盘 ...
- MFC Windows 程序设计(三)-锦上添花(附源码)
MFC Windows 程序设计(三)-锦上添花(附源码) 程序之美 所话说,爱美之心人皆有之,不管是对于男人,女人,还是小孩,都有对美的一种向往,美好的事物,给人一种动力,一种希望,一种期盼,一种留 ...
- js 获取电脑 硬盘序列号_来将何人报上名来!解密电脑是如何识别硬盘的
电脑可以搭配和兼容各种不同品牌的硬盘,是因为他们都遵循了ATA/ATAPI标准,使用共同的语言沟通.这个标准都有什么有趣的功能和作用呢?一起来看存储极客的介绍. ATA/ATAPI是存储设备(硬盘.移 ...
- 【转】百度API获取城市名地名(附源码)
在做一个软件时,用到了定位功能.网上有很多关于google 的GPS定位,但网上关于google定位都没有用, 搜索下原因:(这里建议大家在中国就尽量不使用系统自带的定位) 因为Google的服务器不 ...
- 【Android App】获取照片里的位置信息及使用全球卫星导航系统(GNSS)获取位置实战(附源码和演示 超详细)
需要全部代码请点赞关注收藏后评论区留言私信~~~ 一.获取照片里的位置信息 手机拍摄的相片还保存着时间.地点.镜头参数等信息,这些信息由相片接口工具ExifInterface管理,它的常用方法说明如下 ...
- ESP32运行MicroPython通过MQTT上报温湿度到中移OneNET物联网平台(附源码)
前言:MQTT是当下物联网用的比较多的协议,本篇聊一聊用esp32通过MQTT连接到中移OneNET物联网平台. OneNET平台创建产品和设备 1.创建产品:开发者中心->全部产品-> ...
- vc++6.0:MFC写的一个汉字取模软件(附源码)
vc++6.0:MFC写的一个汉字取模软件(附源码) 一.毕业有九年了,突然想起以前在大学时候用MFC写的一个汉字取模软件.主要的功能是在PC上获取汉字16X16点阵数据然后通过串口把点阵数据发送给A ...
- 手把手教你使用Python网络爬虫获取B站视频选集内容(附源码)
点击上方"Python爬虫与数据挖掘",进行关注 回复"书籍"即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 位卑未敢忘忧国,事定犹须待阖棺. ...
- FIO测试硬盘性能参数和实例详细总结(附源码)
目录 一.简介 二.源码下载及参数解析 2.1 源码下载方式 2.2 参数解析 2.3 测试实例 三.其他相关链接 [3.1 Linux下stream内存带宽测试总结附源码](https://blog ...
最新文章
- 六大“未来式”存储器,谁将脱颖而出?
- centos升级mysql到5.5
- 怎样能做好百度竞价推广?不妨参考下这篇竞价推广的日常工作流程
- 借花献佛!成都java工程师培训
- 寒假打工去,不能继续写博客,表示好心痛啊。。。
- PHP开发中涉及到emoji表情的几种处理方法
- rhel7.0安装篇
- 分享优秀的微信答题小程序
- vb.net 实现编辑某列并回车后不换行,查询数据进行相关处理
- 新型安卓木马SpyNote生成器遭泄露
- c语言isfinite用法,C# Single.IsFinite()用法及代码示例
- Microsoft 文本转语音应用
- Barcode Reader在45毫秒内实现条码识别
- 银河麒麟系统飞腾CPU安装达梦数据库
- Git简明入土教程2.4万字-转自廖雪峰Git
- 神经架构搜索(NAS)2020最新综述:挑战与解决方案
- 【COPOD】Suppressing Poisoning Attacks on Federated Learning for Medical Imaging
- oracle 数据库如何建立索引 如何用索引?
- Camtasia Studio 6录制视频时鼠标闪烁的解决办法
- Ai机器人可以入国籍、可以当主播,当然也可以当电销精英