在新建的工程里面添加一个类
即:以下一个类
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获取电脑硬盘序列号(附源码)相关推荐

  1. VC++获取磁盘剩余空间(附源码)

      VC++开发常用功能一系列文章 (欢迎订阅,持续更新...) 第23章:VC++获取磁盘剩余空间(附源码) 源代码demo已上传到百度网盘:永久生效  ,代码实现了获取任一磁盘的剩余空间,返回MB ...

  2. VC++电脑锁屏(附源码)

      VC++开发常用功能一系列文章 (欢迎订阅,持续更新...) 第14章:VC++电脑锁屏(附源码) 源代码demo已上传到百度网盘:永久生效 ,文章尾部附 百度链接 源代码demo已上传到百度网盘 ...

  3. MFC Windows 程序设计(三)-锦上添花(附源码)

    MFC Windows 程序设计(三)-锦上添花(附源码) 程序之美 所话说,爱美之心人皆有之,不管是对于男人,女人,还是小孩,都有对美的一种向往,美好的事物,给人一种动力,一种希望,一种期盼,一种留 ...

  4. js 获取电脑 硬盘序列号_来将何人报上名来!解密电脑是如何识别硬盘的

    电脑可以搭配和兼容各种不同品牌的硬盘,是因为他们都遵循了ATA/ATAPI标准,使用共同的语言沟通.这个标准都有什么有趣的功能和作用呢?一起来看存储极客的介绍. ATA/ATAPI是存储设备(硬盘.移 ...

  5. 【转】百度API获取城市名地名(附源码)

    在做一个软件时,用到了定位功能.网上有很多关于google 的GPS定位,但网上关于google定位都没有用, 搜索下原因:(这里建议大家在中国就尽量不使用系统自带的定位) 因为Google的服务器不 ...

  6. 【Android App】获取照片里的位置信息及使用全球卫星导航系统(GNSS)获取位置实战(附源码和演示 超详细)

    需要全部代码请点赞关注收藏后评论区留言私信~~~ 一.获取照片里的位置信息 手机拍摄的相片还保存着时间.地点.镜头参数等信息,这些信息由相片接口工具ExifInterface管理,它的常用方法说明如下 ...

  7. ESP32运行MicroPython通过MQTT上报温湿度到中移OneNET物联网平台(附源码)

    前言:MQTT是当下物联网用的比较多的协议,本篇聊一聊用esp32通过MQTT连接到中移OneNET物联网平台. OneNET平台创建产品和设备 1.​创建产品:开发者中心->全部产品-> ...

  8. vc++6.0:MFC写的一个汉字取模软件(附源码)

    vc++6.0:MFC写的一个汉字取模软件(附源码) 一.毕业有九年了,突然想起以前在大学时候用MFC写的一个汉字取模软件.主要的功能是在PC上获取汉字16X16点阵数据然后通过串口把点阵数据发送给A ...

  9. 手把手教你使用Python网络爬虫获取B站视频选集内容(附源码)

    点击上方"Python爬虫与数据挖掘",进行关注 回复"书籍"即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 位卑未敢忘忧国,事定犹须待阖棺. ...

  10. FIO测试硬盘性能参数和实例详细总结(附源码)

    目录 一.简介 二.源码下载及参数解析 2.1 源码下载方式 2.2 参数解析 2.3 测试实例 三.其他相关链接 [3.1 Linux下stream内存带宽测试总结附源码](https://blog ...

最新文章

  1. 六大“未来式”存储器,谁将脱颖而出?
  2. centos升级mysql到5.5
  3. 怎样能做好百度竞价推广?不妨参考下这篇竞价推广的日常工作流程
  4. 借花献佛!成都java工程师培训
  5. 寒假打工去,不能继续写博客,表示好心痛啊。。。
  6. PHP开发中涉及到emoji表情的几种处理方法
  7. rhel7.0安装篇
  8. 分享优秀的微信答题小程序
  9. vb.net 实现编辑某列并回车后不换行,查询数据进行相关处理
  10. 新型安卓木马SpyNote生成器遭泄露
  11. c语言isfinite用法,C# Single.IsFinite()用法及代码示例
  12. Microsoft 文本转语音应用
  13. Barcode Reader在45毫秒内实现条码识别
  14. 银河麒麟系统飞腾CPU安装达梦数据库
  15. Git简明入土教程2.4万字-转自廖雪峰Git
  16. 神经架构搜索(NAS)2020最新综述:挑战与解决方案
  17. 【COPOD】Suppressing Poisoning Attacks on Federated Learning for Medical Imaging
  18. oracle 数据库如何建立索引 如何用索引?
  19. Camtasia Studio 6录制视频时鼠标闪烁的解决办法
  20. Ai机器人可以入国籍、可以当主播,当然也可以当电销精英

热门文章

  1. 《Redis开发与运维》学习第一章
  2. 关于芯片或者功率模块热相关计算
  3. brew的安装以及使用
  4. 软件工程造价师和软件造价评估师有什么区别?
  5. maven项目中配置pom.xml引用ojdbc14.jar出错
  6. html中车牌号省份简称输入键盘
  7. VS2015编译OpenDDS
  8. WEB前端助手FeHelper|前端人员的神器
  9. Python: 模糊综合评价法
  10. 五大常用算法实例列举