欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C/C++實(shí)現(xiàn)獲取硬盤序列號(hào)的示例代碼

 更新時(shí)間:2023年11月17日 08:59:27   作者:lyshark  
獲取硬盤的序列號(hào)、型號(hào)和固件版本號(hào),此類功能通常用于做硬盤綁定或硬件驗(yàn)證操作,下面我們就來(lái)學(xué)習(xí)一下如何使用C/C++實(shí)現(xiàn)獲取硬盤序列號(hào)吧

獲取硬盤的序列號(hào)、型號(hào)和固件版本號(hào),此類功能通常用于做硬盤綁定或硬件驗(yàn)證操作,通過(guò)使用Windows APIDeviceIoControl函數(shù)與物理硬盤驅(qū)動(dòng)程序進(jìn)行通信,發(fā)送ATA命令來(lái)獲取硬盤的信息。

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

定義常量 IDE_ATAPI_IDENTIFYIDE_ATA_IDENTIFY 分別表示讀取 ATAPI 設(shè)備和 ATA 設(shè)備信息的命令。

  • 實(shí)現(xiàn) Trim 函數(shù),用于去除字符串首尾的空格。
  • 實(shí)現(xiàn) ConvertToString 函數(shù),用于將 DWORD 數(shù)組轉(zhuǎn)換為字符串,并通過(guò) Trim 函數(shù)去除首尾空格。
  • 實(shí)現(xiàn) DoIdentify 函數(shù),該函數(shù)通過(guò) DeviceIoControl 發(fā)送 SMART 命令,獲取硬盤的詳細(xì)信息。
  • 實(shí)現(xiàn) GetDiskInfo 函數(shù),該函數(shù)打開物理硬盤設(shè)備,并調(diào)用 DoIdentify 獲取硬盤序列號(hào)、型號(hào)和固件版本號(hào)。

main 函數(shù)中,通過(guò)調(diào)用 GetDiskInfo 獲取硬盤信息,并輸出到控制臺(tái)。

#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <iostream>
#include <winioctl.h>
#include <string>

const WORD IDE_ATAPI_IDENTIFY = 0xA1;   // 讀取ATAPI設(shè)備的命令
const WORD IDE_ATA_IDENTIFY = 0xEC;     // 讀取ATA設(shè)備的命令

// 去除字符串首尾的空格
BOOL Trim(char* szStr)
{
  int i = 0, j = 0, iFirst = -1, iLast = -1;
  int iLen = strlen(szStr);
  char szTemp[256] = { 0 };
  
  // 從前往后遍歷,獲取第一個(gè)不為 空格 的下標(biāo)
  for (i = 0; i < iLen; i++)
  {
    if (' ' != szStr[i])
    {
      iFirst = i;
      break;
    }
  }
  
  // 從后往前遍歷,獲取第一個(gè)不為 空格 的下標(biāo)
  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;
}

// 數(shù)據(jù)轉(zhuǎn)換
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 character
    szResBuf[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);

  // 打開設(shè)備
  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;
  }

  // 發(fā)送控制代碼到指定設(shè)備驅(qū)動(dòng)程序
  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 cmd
  unsigned int uiIDCmd = 0;
  SENDCMDINPARAMS InParams;
  unsigned int uiDrive = 0;
  uiIDCmd = (gvopVersionParam.bIDEDeviceMap >> uiDrive & 0x10) ? IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;

  // 輸出參數(shù)
  BYTE btOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
  if (FALSE == DoIdentify(hFile,&InParams,(SENDCMDOUTPARAMS*)btOutCmd,(BYTE)uiIDCmd,(BYTE)uiDrive,&dwBytesReturned))
  {
    return -3;
  }

  // 關(guān)閉設(shè)備
  CloseHandle(hFile);

  DWORD dwDiskData[256];
  USHORT* pIDSector = NULL;
  
  // 對(duì)應(yīng)結(jié)構(gòu)IDSECTOR 見頭文件
  pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btOutCmd)->bBuffer;
  for (int i = 0; i < 256; i++)
  {
    dwDiskData[i] = pIDSector[i];
  }

  // 獲取序列號(hào)
  strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));

  // 獲取型號(hào)
  strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));

  // 獲取固件版本號(hào)
  strcpy(szFirmwareNumber, ConvertToString(dwDiskData, 23, 26));

  return 0;
}

int main(int argc,char *argv[])
{
  char SerialNumber[64];          // 硬盤序列號(hào)
  char ModelNumber[64];           // 硬盤型號(hào)
  char FirmwareNumber[64];        // 硬盤固件版本號(hào)

  if (0 == GetDiskInfo(0, SerialNumber, ModelNumber, FirmwareNumber))
  {
    std::cout << "序列號(hào): " << SerialNumber << std::endl;
    std::cout << "硬盤型號(hào): " << ModelNumber << std::endl;
    std::cout << "固件版本:" << FirmwareNumber << std::endl;
  }

  system("pause");
  return 0;
}

輸出效果:

到此這篇關(guān)于C/C++實(shí)現(xiàn)獲取硬盤序列號(hào)的示例代碼的文章就介紹到這了,更多相關(guān)C++獲取硬盤序列號(hào)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++?std::thread?使用方法

    C++?std::thread?使用方法

    這篇文章主要介紹了C++?std::thread?如何使用,C++中的std::thread類提供了一種方便的多線程編程方式,在使用std::thread類時(shí),我們需要注意線程間的同步和通信問(wèn)題,以確保多個(gè)線程之間的正確協(xié)同工作需要的朋友可以參考下
    2023-03-03
  • QT開發(fā)應(yīng)用程序的歡迎界面實(shí)例

    QT開發(fā)應(yīng)用程序的歡迎界面實(shí)例

    下面小編就為大家?guī)?lái)一篇QT開發(fā)應(yīng)用程序的歡迎界面實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-08-08
  • C語(yǔ)言中判斷兩數(shù)組中是否有相同的元素

    C語(yǔ)言中判斷兩數(shù)組中是否有相同的元素

    下面是我在做IF語(yǔ)句練習(xí)時(shí)遇到的一個(gè)練習(xí)題,想要整理在博客上判斷兩個(gè)數(shù)組中是否有相同的元素,需要的朋友可以參考下
    2019-10-10
  • C++基于EasyX圖形庫(kù)實(shí)現(xiàn)2048小游戲

    C++基于EasyX圖形庫(kù)實(shí)現(xiàn)2048小游戲

    這篇文章主要為大家詳細(xì)介紹了C++基于EasyX圖形庫(kù)實(shí)現(xiàn)2048小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • C++實(shí)現(xiàn)LeetCode(139.拆分詞句)

    C++實(shí)現(xiàn)LeetCode(139.拆分詞句)

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(139.拆分詞句),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • OpenGL繪制貝塞爾曲線

    OpenGL繪制貝塞爾曲線

    這篇文章主要為大家詳細(xì)介紹了OpenGL繪制貝塞爾曲線,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • C語(yǔ)言實(shí)現(xiàn)文件讀寫操作

    C語(yǔ)言實(shí)現(xiàn)文件讀寫操作

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)文件讀寫操作,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • C語(yǔ)言基于單鏈表實(shí)現(xiàn)通訊錄功能

    C語(yǔ)言基于單鏈表實(shí)現(xiàn)通訊錄功能

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言基于單鏈表實(shí)現(xiàn)通訊錄功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • 深入分析Visual C++進(jìn)行串口通信編程的詳解

    深入分析Visual C++進(jìn)行串口通信編程的詳解

    本篇文章是對(duì)Visual C++進(jìn)行串口通信編程進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • 使用C++一步步實(shí)現(xiàn)俄羅斯方塊后續(xù)

    使用C++一步步實(shí)現(xiàn)俄羅斯方塊后續(xù)

    本文主要給大家分享的是作者在使用C++制作俄羅斯方塊小游戲的時(shí)候所需要的常用的函數(shù),有需要的小伙伴可以借鑒下,希望大家能夠喜歡。
    2017-12-12

最新評(píng)論