• VC获取硬盘物理序列号


    本文转自:本文来自CSDN博客:http://blog.csdn.net/ablo_zhou/archive/2006/07/19/942625.aspx  

    以下完整内容:

    最近才做完了这个获取 IDE 硬盘物理序列号的程序。声明一下,这个程序是我根据 Lynn McGuire 的那个 DiskID32 的源代码做了些自以为是的改动得到的,只能在 NT 平台下获得第一块 IDE 硬盘的物理序列号。同时,这个程序用到了不少未公开的 Windows 的结构和常量......
     
    下面就是相应的 C++ 代码,在 XP SP2 + VC 2005 Express 下调试通过。
    void GetDiskPhysicalSN(char pchDiskPhysicalSN[14])
    {
    BYTE IdOutCmd[530];
     HANDLE drive=CreateFile (L"\\\\.\\PhysicalDrive0", GENERIC_READ |
    GENERIC_WRITE,
           
    FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
           
    OPEN_EXISTING, 0, NULL);
     if (drive == INVALID_HANDLE_VALUE)
     {
      // 错误处理
      return ;
     }
     GETVERSIONOUTPARAMS VersionParams;
     DWORD cbBytesReturned = 0;
     memset ((void*) &VersionParams, 0, sizeof(VersionParams));
     if (!DeviceIoControl(drive, DFP_GET_VERSION, NULL, 0,
    &VersionParams,
           sizeof
    (VersionParams), &cbBytesReturned, NULL))
     {
      // 错误处理
      return ;
     }
     if (VersionParams.bIDEDeviceMap<=0)
     {
      // 错误处理
      return ;
     }
     BYTE bIDCmd = 0;
     SENDCMDINPARAMS scip;
     bIDCmd = (VersionParams.bIDEDeviceMap >> 0 & 0x10) ?
    IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
     memset (&scip, 0, sizeof(scip));
     memset (IdOutCmd, 0, sizeof(IdOutCmd));
     scip.cBufferSize=IDENTIFY_BUFFER_SIZE;
     scip.irDriveRegs.bFeaturesReg=0;
     scip.irDriveRegs.bSectorCountReg=1;
     scip.irDriveRegs.bSectorNumberReg=1;
     scip.irDriveRegs.bCylLowReg=0;
     scip.irDriveRegs.bCylHighReg=0;
     scip.irDriveRegs.bDriveHeadReg=0xA0 | (((BYTE) drive & 1) << 4);
     scip.irDriveRegs.bCommandReg=bIDCmd;
     scip.bDriveNumber=(BYTE) drive;
     scip.cBufferSize=IDENTIFY_BUFFER_SIZE;
     if (!DeviceIoControl(drive, DFP_RECEIVE_DRIVE_DATA, &scip, sizeof
    (SENDCMDINPARAMS) - 1,
           (LPVOID)&IdOutCmd,
    sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
           &cbBytesReturned,
    NULL))
     {
      // 错误处理
      return ;
     }
     USHORT *pIdSector = (USHORT *)((PSENDCMDOUTPARAMS) IdOutCmd) ->
    bBuffer;
     int nIndex=0, nPosition=0;
     for (nIndex=13; nIndex<20; nIndex++)
     {
      pchDiskPhysicalSN[nPosition++]=(unsigned char)(pIdSector
    [nIndex]/256);
      pchDiskPhysicalSN[nPosition++]=(unsigned char)(pIdSector
    [nIndex]%256);
     }
    }
     
    需要自定义的常量和结构为:
    // IOCTL 指令常数
    #define DFP_GET_VERSION   0x00074080
    #define DFP_RECEIVE_DRIVE_DATA 0x0007c088
    // 用于 IDEREGS 结构 bCommandReg 项的有效值
    #define IDE_ATAPI_IDENTIFY  0xA1
    #define IDE_ATA_IDENTIFY  0xEC
    #define IDENTIFY_BUFFER_SIZE 512

    // 结构体定义
    // 保存磁盘驱动器的信息
    typedef struct _GETVERSIONOUTPARAMS
    {
     BYTE bVersion;
     BYTE bRevision;
     BYTE bReserved;
     BYTE bIDEDeviceMap;
     DWORD fCapabilities;
     DWORD dwReserved[4];
    } GETVERSIONOUTPARAMS, *PGETVERSIONOUTPARAMS, *LPGETVERSIONOUTPARAMS;
    // IDE 寄存器
    typedef struct _IDEREGS
    {
     BYTE bFeaturesReg;
     BYTE bSectorCountReg;
     BYTE bSectorNumberReg;
     BYTE bCylLowReg;
     BYTE bCylHighReg;
     BYTE bDriveHeadReg;
     BYTE bCommandReg;
     BYTE bReserved;
    } IDEREGS, *PIDEREGS, *LPIDEREGS;
    // 发送磁盘指令的输入参数
    typedef struct _SENDCMDINPARAMS
    {
     DWORD cBufferSize;
     IDEREGS irDriveRegs;
     BYTE bDriveNumber;
     BYTE bReserved[3];
     DWORD dwReserved[4];
     BYTE bBuffer[1];
    } SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;
    // 磁盘状态
    typedef struct _DRIVERSTATUS
    {
     BYTE bDriverError;
     BYTE bIDEStatus;
     BYTE bReserved[2];
     DWORD dwReserved[2];
    } DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS;
    // 发送磁盘指令的输出参数
    typedef struct _SENDCMDOUTPARAMS
    {
     DWORD cBufferSize;
     DRIVERSTATUS DriverStatus;
     BYTE bBuffer[1];
    } SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;
     
    同时,还需要提醒的是,这个程序需要用到头文件 Iphlpapi.h,并需要将 Iphlpapi.lib 包含在连接器的库文件参数下。
     
    其中很多的细节我还搞得不是特别清楚,该死的微软,那么多的好东西都不公开......


     

  • 相关阅读:
    mysql access denied for user root Mysql用户无权限
    远程链接调用sql脚本
    CuteEditor使用详解
    如何设置release模式
    ShardingJDBC不分库,只分表例子
    SpringCloud Stream整合RocketMQ实现消息发送与接收
    Spring Cloud Gateway的PrefixPath及StripPrefix功能
    使用MongoDB的Spring Boot和MongoTemplate教程
    ShardingJDBC读写分离案例
    SpringBoot那些好用的连接池HikariCP
  • 原文地址:https://www.cnblogs.com/ganmk/p/1597902.html
Copyright © 2020-2023  润新知