C/C++ 实现获取硬盘序列号

获取硬盘的序列号、型号和固件版本号,此类功能通常用于做硬盘绑定或硬件验证操作,通过使用Windows APIDeviceIoControl函数与物理硬盘驱动程序进行通信,发送ATA命令来获取硬盘的信息。

以下是该程序的主要功能和流程:

定义常量 IDE_ATAPI_IDENTIFYIDE_ATA_IDENTIFY 分别表示读取 ATAPI 设备和 ATA 设备信息的命令。

  • 实现 Trim 函数,用于去除字符串首尾的空格。
  • 实现 ConvertToString 函数,用于将 DWORD 数组转换为字符串,并通过 Trim 函数去除首尾空格。
  • 实现 DoIdentify 函数,该函数通过 DeviceIoControl 发送 SMART 命令,获取硬盘的详细信息。
  • 实现 GetDiskInfo 函数,该函数打开物理硬盘设备,并调用 DoIdentify 获取硬盘序列号、型号和固件版本号。

main 函数中,通过调用 GetDiskInfo 获取硬盘信息,并输出到控制台。

#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <iostream>
#include <winioctl.h>
#include <string>const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 读取ATAPI设备的命令
const WORD IDE_ATA_IDENTIFY = 0xEC;     // 读取ATA设备的命令// 去除字符串首尾的空格
BOOL Trim(char* szStr)
{int i = 0, j = 0, iFirst = -1, iLast = -1;int iLen = strlen(szStr);char szTemp[256] = { 0 };// 从前往后遍历,获取第一个不为 空格 的下标for (i = 0; i < iLen; i++){if (' ' != szStr[i]){iFirst = i;break;}}// 从后往前遍历,获取第一个不为 空格 的下标for (i = (iLen - 1); 0 <= i; i--){if (' ' != szStr[i]){iLast = i;break;}}// 字符串全为 空格if (-1 == iFirst || -1 == iLast){return FALSE;}// 获取去除 空格 部分for (i = iFirst; i <= iLast; i++){szTemp[j] = szStr[i];j++;}szTemp[j] = '\0';strcpy(szStr, szTemp);return TRUE;
}// 数据转换
char* __fastcall ConvertToString(DWORD dwDiskData[256],int iFirstIndex,int iLastIndex)
{static char szResBuf[256];int iIndex = 0;int iPosition = 0;for (iIndex = iFirstIndex; iIndex <= iLastIndex; iIndex++){szResBuf[iPosition] = (char)(dwDiskData[iIndex] / 256);iPosition++;// Get low BYTE for 2nd characterszResBuf[iPosition] = (char)(dwDiskData[iIndex] % 256);iPosition++;}szResBuf[iPosition] = '\0';// 删除首尾的空格Trim(szResBuf);return szResBuf;
}BOOL __fastcall DoIdentify(HANDLE hPhysicalDriveIOCTL,PSENDCMDINPARAMS pSCIP,PSENDCMDOUTPARAMS pSCOP,BYTE btIDCmd,BYTE btDriveNum,PDWORD pdwBytesReturned)
{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 = (btDriveNum & 1) ? 0xB0 : 0xA0;pSCIP->irDriveRegs.bCommandReg = btIDCmd;pSCIP->bDriveNumber = btDriveNum;return DeviceIoControl(hPhysicalDriveIOCTL,SMART_RCV_DRIVE_DATA,(LPVOID)pSCIP,sizeof(SENDCMDINPARAMS) - 1,(LPVOID)pSCOP,sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,pdwBytesReturned,NULL);return FALSE;
}int GetDiskInfo(int iDriver, char* szSerialNumber, char* szModelNumber, char* szFirmwareNumber)
{char szFilePath[64] = { 0 };sprintf(szFilePath, "\\\\.\\PHYSICALDRIVE%d", iDriver);// 打开设备HANDLE hFile = CreateFileA(szFilePath,GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);if (INVALID_HANDLE_VALUE == hFile){return -1;}// 发送控制代码到指定设备驱动程序DWORD dwBytesReturned = 0;GETVERSIONINPARAMS gvopVersionParam;DeviceIoControl(hFile,SMART_GET_VERSION,NULL,0,&gvopVersionParam,sizeof(gvopVersionParam),&dwBytesReturned,NULL);if (0 >= gvopVersionParam.bIDEDeviceMap){return -2;}// IDE or ATAPI IDENTIFY cmdunsigned int uiIDCmd = 0;SENDCMDINPARAMS InParams;unsigned int uiDrive = 0;uiIDCmd = (gvopVersionParam.bIDEDeviceMap >> uiDrive & 0x10) ? IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;// 输出参数BYTE btOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];if (FALSE == DoIdentify(hFile,&InParams,(SENDCMDOUTPARAMS*)btOutCmd,(BYTE)uiIDCmd,(BYTE)uiDrive,&dwBytesReturned)){return -3;}// 关闭设备CloseHandle(hFile);DWORD dwDiskData[256];USHORT* pIDSector = NULL;// 对应结构IDSECTOR 见头文件pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btOutCmd)->bBuffer;for (int i = 0; i < 256; i++){dwDiskData[i] = pIDSector[i];}// 获取序列号strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));// 获取型号strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));// 获取固件版本号strcpy(szFirmwareNumber, ConvertToString(dwDiskData, 23, 26));return 0;
}int main(int argc,char *argv[])
{char SerialNumber[64];          // 硬盘序列号char ModelNumber[64];           // 硬盘型号char FirmwareNumber[64];        // 硬盘固件版本号if (0 == GetDiskInfo(0, SerialNumber, ModelNumber, FirmwareNumber)){std::cout << "序列号: " << SerialNumber << std::endl;std::cout << "硬盘型号: " << ModelNumber << std::endl;std::cout << "固件版本:" << FirmwareNumber << std::endl;}system("pause");return 0;
}

输出效果;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/144086.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023版Idea创建JavaWeb时,右键new没有Servlet快捷键选项

问题&#xff1a;右键时&#xff0c;没有创建servlet的快捷键&#xff0c;如下图&#xff1a; 解决方法&#xff1a; 1.打开idea&#xff0c;点击File>settings(设置)&#xff0c;进入settings页面&#xff0c;如下 从上图中的Files选项中没看到有servlet选项&#xff0c;…

正则表达式入门教程

一、本文目标 让你明白正则表达式是什么&#xff0c;并对它有一些基本的了解&#xff0c;让你可以在自己的程序或网页里使用它。 二、如何使用本教程 文本格式约定&#xff1a;专业术语 元字符/语法格式 正则表达式 正则表达式中的一部分(用于分析) 对其进行匹配的源字符串 …

线程锁的应用与示例代码

为了解决这个问题&#xff0c;可以使用线程锁来确保在提取zip文件中的每个文件时&#xff0c;同一时间只有一个线程可以访问文件。这样可以避免多个线程同时访问和写入文件&#xff0c;从而解决race condition的问题。以下是修改后的示例代码&#xff1a; python import reque…

提升pip速度!设置pip全局镜像源,速度飞起!

文章目录 💢 问题 💢💯 解决方案 💯🐾 镜像源🐾 镜像全局配置🍄 Windows系统🍄 Linux和macOS系统🍄 添加环境变量的方式💢 问题 💢 由于“某些网络限制”原因,我们在使用pip安装python模块的时候速度会比较慢,这个时候我们就需要用到一些镜像源,本文将…

R语言提取文字(字符串)中的内容--正则式(2)

科学研究中有时候咱们收集到的数据很乱&#xff0c;不能马上进行分析&#xff0c;如SEER数据&#xff0c;用过都知道&#xff0c;咱们需要对数据进行清洗&#xff0c;从数据中提取咱们需要的东西&#xff0c;才能进行分析&#xff0c;这时候有个有用的东西叫正则式&#xff0c;…

2023年05月 Python(五级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试(1~6级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 有列表L=[‘UK’,‘china’,‘lili’,“张三”],print(L[-2])的结果是?( ) A: UK B: ‘lili’,‘张三’ C: lili D: ‘UK’,‘china’,‘lili’ 答案:C 列表元素定位 第2题 …

最新宝塔反代openai官方API开发接口详细搭建教程,解决502 Bad Gateway问题

一、前言 宝塔反代openai官方API接口详细教程&#xff0c;实现国内使用ChatGPT502 Bad Gateway问题解决&#xff0c; 此方法最简单快捷&#xff0c;没有复杂步骤&#xff0c;不容易出错&#xff0c;即最简单&#xff0c;零代码、零部署的方法。 二、实现前提 一台海外服务器…

正版软件|Soundop 专业音频编辑器,实现无缝的音频制作工作流程

关于Soundop Soundop 音频编辑器 直观而专业的音频编辑软件&#xff0c;用于录制、编辑、混合和掌握音频内容。 Soundop 是一款适用于 Windows 的专业音频编辑器&#xff0c;可在具有高级功能的直观灵活的工作区中录制、编辑和掌握音频并混音轨道。音频文件编辑器支持波形和频谱…

在Python中使用sqlite3进行数据持久化操作

目录 引言 一、安装sqlite3模块 二、创建数据库连接 三、创建游标对象 四、执行SQL命令 五、提交更改 六、关闭连接 七、使用参数化查询 八、使用ORM进行数据操作 九、备份和恢复数据库 十、处理大量数据 十一、优化查询性能 十二、处理并发访问 十三、处理数据持…

【C++高阶(二)】熟悉STL中的map和set --了解KV模型和pair结构

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:C从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习C   &#x1f51d;&#x1f51d; map和set 1. 前言2. map和set介绍3. pair结构介…

一起学docker系列之二深入理解Docker:基本概念、工作原理与架构

目录 前言1 Docker的基本概念2 Docker的基本组成3 docker工作原理4 docker架构5 Docker详细工作过程结语 前言 在当今的软件开发和部署中&#xff0c;Docker已经成为一种不可或缺的工具。它简化了应用程序的打包、交付和运行&#xff0c;同时提供了强大的隔离性和可移植性。本…

Java学习笔记(七)——面向对象编程(中级)

一、IDEA &#xff08;一&#xff09;常用的快捷键 &#xff08;二&#xff09;模版/自定义模版 二、包 &#xff08;一&#xff09;包的命名 &#xff08;二&#xff09;常用的包 &#xff08;三&#xff09;如何引入&#xff08;导入&#xff09;包 &#xff08;四&am…

「Verilog学习笔记」用优先编码器①实现键盘编码电路

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 分析 用此编码器实现键盘的编码电路。 注意&#xff1a;编码器的输出是低电平有效&#xff0c;而键盘编码电路输出的是正常的8421BCD码&#xff0c;是高电平有效。因此将编…

ElasticSearch 安装(单机版本)

文章目录 ElasticSearch 安装&#xff08;单机版本&#xff09;环境配置下载安装包调整系统参数安装启动并验证 ElasticSearch 安装&#xff08;单机版本&#xff09; 此文档演示 ElasticSearch 的单机版本在 CentOS 7 环境下的安装方式以及相关的配置。 环境配置 Linux 主机一…

OpenAI暂停ChatGPT Plus新用户注册;迷宫与图神经网络

&#x1f989; AI新闻 &#x1f680; OpenAI暂停ChatGPT Plus新用户注册&#xff0c;考虑用户体验 摘要&#xff1a;OpenAI决定暂停ChatGPT Plus新用户注册&#xff0c;以应对开发日后使用量激增带来的压力&#xff0c;确保每个人都能享受良好的体验。根据调查机构Writerbudd…

下载huggingface预训练模型到本地并调用

写在前面 在大模型横行的时代&#xff0c;无法在服务器上连接外网的研究僧真的是太苦逼了&#xff0c;每次想尝试类似于CLIP&#xff0c;BLIP之类的大模型都会得到“requests.exceptions.ConnectionError: (MaxRetryError("HTTPSConnectionPool(host‘huggingface.co’, …

Datawhale智能汽车AI挑战赛

1.赛题解析 赛题地址&#xff1a;https://tianchi.aliyun.com/competition/entrance/532155 任务&#xff1a; 输入&#xff1a;元宇宙仿真平台生成的前视摄像头虚拟视频数据&#xff08;8-10秒左右&#xff09;&#xff1b;输出&#xff1a;对视频中的信息进行综合理解&…

【解决方案】危化品厂区安防系统EasyCVR+AI智能监控

危化品属于危险、易燃易爆、易中毒行类&#xff0c;一旦在生产运输过程中发生泄漏后果不堪想象&#xff0c;所以危化品的生产储存更需要严密、精细的监控&#xff0c;来保障危化品的安全。EasyCVRTSINGSEE青犀AI智能分析网关搭建的危化品智能监控方案就能很好的为危化品监管保驾…

基于STC12C5A60S2系列1T 8051单片机的数模芯片DAC0832实现数模转换应用

基于STC12C5A60S2系列1T 8051单片的数模芯片DAC0832实现数模转换应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍数模芯片DAC0832介绍通过按键调节数模芯片DAC0832…

WPF下实现拖动任意地方都可以拖动窗口

首先在xaml中添加事件 <Window PreviewMouseLeftButtonDown"Window_PreviewMouseLeftButtonDown"PreviewMouseMove"Window_PreviewMouseMove"PreviewMouseLeftButtonUp"Window_PreviewMouseLeftButtonUp"/>然后脚本输入 Point _pressedP…