实战DeviceIoControl 之四:获取硬盘的详细信息

通过实战示例,介绍如何使用ATA/APAPI的IDENTIFY DEVICE指令来获取硬盘的详细信息,包括硬盘序列号。文章指出,IOCTL_DISK_GET_DRIVE_GEOMETRY和IOCTL_STORAGE_GET_MEDIA_TYPES_EX只能提供基本参数,而IDENTIFY DEVICE指令可以获取更全面的数据。但要注意,这种方法可能不适用于所有类型的存储设备,如SCSI、USB硬盘和某些可移动设备。
摘要由CSDN通过智能技术生成

Q 用IOCTL_DISK_GET_DRIVE_GEOMETRY或IOCTL_STORAGE_GET_MEDIA_TYPES_EX只能得到很少的磁盘参数,我想获得包括硬盘序列号在内的更加详细的信息,有什么办法呀?

A 确实,用你所说的I/O控制码,只能得到最基本的磁盘参数。获取磁盘出厂信息的I/O控制码,微软在VC/MFC环境中没有开放,在DDK中可以发现一些线索。早先,Lynn McGuire写了一个很出名的获取IDE硬盘详细信息的程序DiskID32,下面的例子是在其基础上经过增删和改进而成的。

本例中,我们要用到ATA/APAPI的IDENTIFY DEVICE指令。ATA/APAPI是国际组织T13起草和发布的IDE/EIDE/UDMA硬盘及其它可移动存储设备与主机接口的标准,至今已经到了ATA/APAPI-7版本。该接口标准规定了ATA/ATAPI设备的输入输出寄存器和指令集。欲了解更详细的ATA/ATAPI技术资料,可访问T13的站点。

用到的常量及数据结构有以下一些:

// IOCTL控制码
// #define  DFP_SEND_DRIVE_COMMAND   0x0007c084
#define  DFP_SEND_DRIVE_COMMAND   CTL_CODE(IOCTL_DISK_BASE, 0x0021, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
// #define  DFP_RECEIVE_DRIVE_DATA   0x0007c088
#define  DFP_RECEIVE_DRIVE_DATA   CTL_CODE(IOCTL_DISK_BASE, 0x0022, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#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
  
// ATA/ATAPI指令
#define  IDE_ATA_IDENTIFY           0xEC     // ATA的ID指令(IDENTIFY DEVICE)
  
// IDE命令寄存器
typedef struct _IDEREGS
{
    BYTE bFeaturesReg;       // 特征寄存器(用于SMART命令)
    BYTE bSectorCountReg;    // 扇区数目寄存器
    BYTE bSectorNumberReg;   // 开始扇区寄存器
    BYTE bCylLowReg;         // 开始柱面低字节寄存器
    BYTE bCylHighReg;        // 开始柱面高字节寄存器
    BYTE bDriveHeadReg;      // 驱动器/磁头寄存器
    BYTE bCommandReg;        // 指令寄存器
    BYTE bReserved;          // 保留
} IDEREGS, *PIDEREGS, *LPIDEREGS;
  
// 从驱动程序返回的状态
typedef struct _DRIVERSTATUS
{
    BYTE bDriverError;      // 错误码
    BYTE bIDEStatus;        // IDE状态寄存器
    BYTE bReserved[2];      // 保留
    DWORD dwReserved[2];    // 保留
} DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS;
  
// IDE设备IOCTL输入数据结构
typedef struct _SENDCMDINPARAMS
{
    DWORD cBufferSize;      // 缓冲区字节数
    IDEREGS irDriveRegs;    // IDE寄存器组
    BYTE bDriveNumber;      // 驱动器号
    BYTE bReserved[3];      // 保留
    DWORD dwReserved[4];    // 保留
    BYTE bBuffer[1];        // 输入缓冲区(此处象征性地包含1字节)
} SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;
  
// IDE设备IOCTL输出数据结构
typedef struct _SENDCMDOUTPARAMS
{
    DWORD cBufferSize;          // 缓冲区字节数
    DRIVERSTATUS DriverStatus;  // 驱动程序返回状态
    BYTE bBuffer[1];            // 输入缓冲区(此处象征性地包含1字节)
} SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;
  
// IDE的ID命令返回的数据
// 共512字节(256个WORD),这里仅定义了一些感兴趣的项(基本上依据ATA/ATAPI-4)
typedef struct _IDINFO
{
    USHORT  wGenConfig;                 // WORD 0: 基本信息字
    USHORT  wNumCyls;                   // WORD 1: 柱面数
    USHORT  wReserved2;                 // WORD 2: 保留
    USHORT  wNumHeads;                  // WORD 3: 磁头数
    USHORT  wReserved4;                 // WORD 4: 保留
    USHORT  wReserved5;                 // WORD 5: 保留
    USHORT  wNumSectorsPerTrack;        // WORD 6: 每磁道扇区数
    USHORT  wVendorUnique[3];           // WORD 7-9: 厂家设定值
    CHAR    sSerialNumber[20];          // WORD 10-19:序列号
    USHORT  wBufferType;                // WORD 20: 缓冲类型
    USHORT  wBufferSize;                // WORD 21: 缓冲大小
    USHORT  wECCSize;                   // WORD 22: ECC校验大小
    CHAR    sFirmwareRev[8];            // WORD 23-26: 固件版本
    CHAR    sModelNumber[40];           // WORD 27-46: 内部型号
    USHORT  wMoreVe
  • 0
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值