VC++ 获取硬盘序列号源码(XP适用)

// 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, 0x1f7 
        in al, dx 
        cmp al, 0x80 
        jb Endwaiting 
        jmp Waiting 
    } 
Endwaiting: 
    _asm 
    { 
        mov byTemp, al 
    } 
    return byTemp;  
}  
  
//中断服务程序 
void  _declspec( naked )InterruptProcess(void) 
{ 
     int   byTemp; 
     int   i; 
     WORD temp; 
     //保存寄存器值 
     _asm 
     { 
         push eax 
         push ebx 
         push ecx 
         push edx 
         push esi 
     } 
        
     WaitHardDiskIdle();//等待硬盘空闲状态 
     _asm 
     { 
         mov dx, 0x1f6 
         mov al, 0xa0 
         out dx, al 
     } 
     byTemp = WaitHardDiskIdle(); //若直接在Ring3级执行等待命令,会进入死循环 
     if ((byTemp&0x50)!=0x50)  
     { 
        _asm  // 恢复中断现场并退出中断服务程序 
        { 
            pop esi 
            pop edx 
            pop ecx 
            pop ebx 
            pop eax 
            iretd 
        } 
     } 
          
     _asm 
     { 
         mov dx, 0x1f6 //命令端口1f6,选择驱动器0 
         mov al, 0xa0 
         out dx, al 
         inc dx 
         mov al, 0xec 
         out dx, al //发送读驱动器参数命令 
     }   
     byTemp = WaitHardDiskIdle();  
     if ((byTemp&0x58)!=0x58)  
     { 
        _asm  // 恢复中断现场并退出中断服务程序 
        { 
             pop esi 
             pop edx 
             pop ecx 
             pop ebx 
             pop eax 
             iretd 
        } 
     } 
     //读取硬盘控制器的全部信息 
     for (i=0;i<256;i++)  
     { 
         _asm 
         { 
             mov dx, 0x1f0 
             in ax, dx 
             mov temp, ax 
         } 
         m_serial[i] = temp;  
     }                                 
     _asm 
     { 
         pop esi 
         pop edx 
         pop ecx 
         pop ebx 
         pop eax 
         iretd 
     }   
} 
// 
// 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+04h 
        cli 
        //保存原先的中断入口地址 
        push ecx 
        mov ecx,dword ptr [eax] 
        mov cx,word ptr [eax-04h] 
        mov dword ptr m_OldInterruptAddress,ecx 
        pop ecx 
        //设置修改的中断入口地址为新的中断处理程序入口地址 
        push ebx 
        lea ebx,InterruptProcess     
        mov word ptr [eax-04h],bx 
        shr ebx,10h 
        mov word ptr [eax+02h],bx 
        pop ebx 
        //执行中断,转到Ring 0(类似CIH病毒原理) 
        int 3h 
        //恢复原先的中断入口地址 
        push ecx 
        mov ecx,dword ptr m_OldInterruptAddress 
        mov word ptr [eax-04h],cx 
        shr ecx,10h 
        mov word ptr [eax+02h],cx 
        pop ecx 
        sti 
        pop 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 = 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; 
} 
  
// 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 = CreateFile (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) ); 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值