GetVolumeInformation获取磁盘信息与DeviceIoControl获取硬盘信息

       硬盘序列号: 英文名 Hard Disk Serial Number, 该号是出厂时生产厂家为区别产品而设置的, 是唯一的, 是只读的, 利用硬盘序列号的加密往往是利用其唯一和只读的特性, 大多是针对有序列号的 IDE HDD而言, 对于没有序列号或SCSI HDD硬盘则无能为力, 这也是利用它进行加密的局限性.
       卷的序列号: 英文名 Volume Serial Number, 该号既可指软磁盘要得, 如: A:盘和B:盘的, 又可以指硬盘的逻辑盘, 如: C:, D:...的, 是高级格式化时随机产生的, 是可以修改的, 所以利用其进行 加密, 其唯一性还可, 而其可修改性对于安全而言就大打折扣了. 

        如何得到磁盘序列号和卷标及其它信息主要就是要调用GetVolumeInformation这个API函数,函数声明如下
BOOL GetVolumeInformation(
  LPCTSTR lpRootPathName,        // address of root directory of the 
                                 // file system
  LPTSTR lpVolumeNameBuffer,     // address of name of the volume
  DWORD nVolumeNameSize,         // length of lpVolumeNameBuffer
  LPDWORD lpVolumeSerialNumber,  // address of volume serial number
  LPDWORD lpMaximumComponentLength,
                                 // address of system's maximum 
                                 // filename length
  LPDWORD lpFileSystemFlags,     // address of file system flags
  LPTSTR lpFileSystemNameBuffer, // address of name of file system
  DWORD nFileSystemNameSize      // length of lpFileSystemNameBuffer
);

[VB]
Public Declare Function GetVolumeInformation& Lib "kernel32" Alias "Ge
tVolumeInformationA" (ByVal lpRootPathName As String, ByVal pVolumeNam
eBuffer As String, ByVal nVolumeNameSize As Long, lpVolumeSerialNumber
As Long, lpMaximumComponentLength As Long, lpFileSystemFlags As Long,
ByVal lpFileSystemNameBuffer As String, ByVal nFileSystemNameSize As
Long)

用API 函数GetVolumeInformation得到的不是硬盘的序列号!!! 看看英文啊:VolumeSerialNumber!得到的只是卷区序列号!

硬盘的序列号应该是
Drive Model Number________________: WDC WD400EB-00CPF0
Drive Serial Number_______________: WD-WCAATF083586
Drive Controller Revision Number__: 06.04G06
Controller Buffer Size on Drive___: 2097152 bytes
Drive Type________________________: Fixed
Drive Size________________________: 40020664320 bytes
中:

Drive Serial Number_______________: WD-WCAATF083586 这才是硬盘Serial Number!!!!


这个号是不会因为你格式化硬盘而改动,也不是网上流传的修改工具能改的,(其实网上流传的修改工具的也不过是卷区号而已,真是哭笑不得!)

硬盘序列号与磁盘序列号不同,磁盘序列号是硬盘分区中某个卷(volumn)也就是我们说的磁盘的序列号。而硬盘序列号是整块硬盘的序列号,不能被修改。

 

 

 

-----------------------

DeviceIoControl可以获取硬盘序列号。其实现在CSDN上有下。摘录部分

  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 = CreateFile (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;

 

 

 

 

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) );
}


 

posted @ 2013-02-20 14:14  zhiweiyouzhishenghuo  阅读(1587)  评论(0编辑  收藏  举报