c++ 獲取硬盤序列號serialnumber

硬盤序列號,英文名:Hard Disk Serial Number,該號是硬盤廠家爲區別產品而設置的,是唯一的。網上搜索一下,發現獲取硬盤序列號的代碼遍地都是,但很多是錯誤的。典型代表就是使用GetVolumeInformation函數獲取序列號。這種方法獲取的是卷的序列號,即Volume Serial Number。硬盤格式化後,這種序列號將發生變化。本文描述的是獲取硬盤唯一的物理序列號的方法。

1、cmd命令行獲取;

windows命令行獲取命令:wmic diskdrive get serialnumber

2、c++函數底層獲取

三個文件:HardDriveSerialNumer.h    HardDriveSerialNumer.cpp    main.cpp

//HardDriveSerialNumer.h

#ifndef _HDD_SERIAL_INFO_H_
#define _HDD_SERIAL_INFO_H_

#include <tchar.h>
#include <string.h>
#include <windows.h>
#include <winioctl.h>
#include <stdio.h>
#include <vector>

#pragma pack(1)

#define  IDENTIFY_BUFFER_SIZE  512

//  IOCTL commands
#define  DFP_GET_VERSION          0x00074080
#define  DFP_SEND_DRIVE_COMMAND   0x0007c084
#define  DFP_RECEIVE_DRIVE_DATA   0x0007c088

#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

#define SMART_GET_VERSION               CTL_CODE(IOCTL_DISK_BASE, 0x0020, METHOD_BUFFERED, FILE_READ_ACCESS)
#define SMART_SEND_DRIVE_COMMAND        CTL_CODE(IOCTL_DISK_BASE, 0x0021, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define SMART_RCV_DRIVE_DATA            CTL_CODE(IOCTL_DISK_BASE, 0x0022, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)

//  GETVERSIONOUTPARAMS contains the data returned from the 
//  Get Driver Version function.
typedef struct _GETVERSIONOUTPARAMS
{
    BYTE bVersion;      // Binary driver version.
    BYTE bRevision;     // Binary driver revision.
    BYTE bReserved;     // Not used.
    BYTE bIDEDeviceMap; // Bit map of IDE devices.
    DWORD fCapabilities; // Bit mask of driver capabilities.
    DWORD dwReserved[4]; // For future use.
} GETVERSIONOUTPARAMS, *PGETVERSIONOUTPARAMS, *LPGETVERSIONOUTPARAMS;


//  Bits returned in the fCapabilities member of GETVERSIONOUTPARAMS 
#define  CAP_IDE_ID_FUNCTION             1  // ATA ID command supported
#define  CAP_IDE_ATAPI_ID                2  // ATAPI ID command supported
#define  CAP_IDE_EXECUTE_SMART_FUNCTION  4  // SMART commannds supported

//  Valid values for the bCommandReg member of IDEREGS.
#define  IDE_ATAPI_IDENTIFY  0xA1  //  Returns ID sector for ATAPI.
#define  IDE_ATA_IDENTIFY    0xEC  //  Returns ID sector for ATA.

// The following struct defines the interesting part of the IDENTIFY
// buffer:
typedef struct _IDSECTOR
{
    USHORT  wGenConfig;
    USHORT  wNumCyls;
    USHORT  wReserved;
    USHORT  wNumHeads;
    USHORT  wBytesPerTrack;
    USHORT  wBytesPerSector;
    USHORT  wSectorsPerTrack;
    USHORT  wVendorUnique[3];
    CHAR    sSerialNumber[20];
    USHORT  wBufferType;
    USHORT  wBufferSize;
    USHORT  wECCSize;
    CHAR    sFirmwareRev[8];
    CHAR    sModelNumber[40];
    USHORT  wMoreVendorUnique;
    USHORT  wDoubleWordIO;
    USHORT  wCapabilities;
    USHORT  wReserved1;
    USHORT  wPIOTiming;
    USHORT  wDMATiming;
    USHORT  wBS;
    USHORT  wNumCurrentCyls;
    USHORT  wNumCurrentHeads;
    USHORT  wNumCurrentSectorsPerTrack;
    ULONG   ulCurrentSectorCapacity;
    USHORT  wMultSectorStuff;
    ULONG   ulTotalAddressableSectors;
    USHORT  wSingleWordDMA;
    USHORT  wMultiWordDMA;
    BYTE    bReserved[128];
} IDSECTOR, *PIDSECTOR;


typedef struct _SRB_IO_CONTROL
{
    ULONG HeaderLength;
    UCHAR Signature[8];
    ULONG Timeout;
    ULONG ControlCode;
    ULONG ReturnCode;
    ULONG Length;
} SRB_IO_CONTROL, *PSRB_IO_CONTROL;

//  Max number of drives assuming primary/secondary, master/slave topology
//	Modified to read only the master serial
#define  MAX_IDE_DRIVES  1

//
// IDENTIFY data (from ATAPI driver source)
//

#pragma pack(1)

typedef struct _IDENTIFY_DATA {
    USHORT GeneralConfiguration;            // 00 00
    USHORT NumberOfCylinders;               // 02  1
    USHORT Reserved1;                       // 04  2
    USHORT NumberOfHeads;                   // 06  3
    USHORT UnformattedBytesPerTrack;        // 08  4
    USHORT UnformattedBytesPerSector;       // 0A  5
    USHORT SectorsPerTrack;                 // 0C  6
    USHORT VendorUnique1[3];                // 0E  7-9
    USHORT SerialNumber[10];                // 14  10-19
    USHORT BufferType;                      // 28  20
    USHORT BufferSectorSize;                // 2A  21
    USHORT NumberOfEccBytes;                // 2C  22
    USHORT FirmwareRevision[4];             // 2E  23-26
    USHORT ModelNumber[20];                 // 36  27-46
    UCHAR  MaximumBlockTransfer;            // 5E  47
    UCHAR  VendorUnique2;                   // 5F
    USHORT DoubleWordIo;                    // 60  48
    USHORT Capabilities;                    // 62  49
    USHORT Reserved2;                       // 64  50
    UCHAR  VendorUnique3;                   // 66  51
    UCHAR  PioCycleTimingMode;              // 67
    UCHAR  VendorUnique4;                   // 68  52
    UCHAR  DmaCycleTimingMode;              // 69
    USHORT TranslationFieldsValid:1;        // 6A  53
    USHORT Reserved3:15;
    USHORT NumberOfCurrentCylinders;        // 6C  54
    USHORT NumberOfCurrentHeads;            // 6E  55
    USHORT CurrentSectorsPerTrack;          // 70  56
    ULONG  CurrentSectorCapacity;           // 72  57-58
    USHORT CurrentMultiSectorSetting;       //     59
    ULONG  UserAddressableSectors;          //     60-61
    USHORT SingleWordDMASupport : 8;        //     62
    USHORT SingleWordDMAActive : 8;
    USHORT MultiWordDMASupport : 8;         //     63
    USHORT MultiWordDMAActive : 8;
    USHORT AdvancedPIOModes : 8;            //     64
    USHORT Reserved4 : 8;
    USHORT MinimumMWXferCycleTime;          //     65
    USHORT RecommendedMWXferCycleTime;      //     66
    USHORT MinimumPIOCycleTime;             //     67
    USHORT MinimumPIOCycleTimeIORDY;        //     68
    USHORT Reserved5[2];                    //     69-70
    USHORT ReleaseTimeOverlapped;           //     71
    USHORT ReleaseTimeServiceCommand;       //     72
    USHORT MajorRevision;                   //     73
    USHORT MinorRevision;                   //     74
    USHORT Reserved6[50];                   //     75-126
    USHORT SpecialFunctionsEnabled;         //     127
    USHORT Reserved7[128];                  //     128-255
} IDENTIFY_DATA, *PIDENTIFY_DATA;

#pragma pack()

//  Required to ensure correct PhysicalDrive IOCTL structure setup
#pragma pack(4)


//
// IOCTL_STORAGE_QUERY_PROPERTY
//
// Input Buffer:
//      a STORAGE_PROPERTY_QUERY structure which describes what type of query
//      is being done, what property is being queried for, and any additional
//      parameters which a particular property query requires.
//
//  Output Buffer:
//      Contains a buffer to place the results of the query into.  Since all
//      property descriptors can be cast into a STORAGE_DESCRIPTOR_HEADER,
//      the IOCTL can be called once with a small buffer then again using
//      a buffer as large as the header reports is necessary.
//


//
// Types of queries
//


//
// define some initial property id's
//


//
// Query structure - additional parameters for specific queries can follow
// the header
//


#define IOCTL_STORAGE_QUERY_PROPERTY   CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS)


//
// Device property descriptor - this is really just a rehash of the inquiry
// data retrieved from a scsi device
//
// This may only be retrieved from a target device.  Sending this to the bus
// will result in an error
//

#pragma pack(4)


// (* Output Bbuffer for the VxD (rt_IdeDinfo record) *)
typedef struct _rt_IdeDInfo_
{
    BYTE IDEExists[4];
    BYTE DiskExists[8];
    WORD DisksRawInfo[8*256];
} rt_IdeDInfo, *pt_IdeDInfo;


// (* IdeDinfo "data fields" *)
typedef struct _rt_DiskInfo_
{
    BOOL DiskExists;
    BOOL ATAdevice;
    BOOL RemovableDevice;
    WORD TotLogCyl;
    WORD TotLogHeads;
    WORD TotLogSPT;
    char SerialNumber[20];
    char FirmwareRevision[8];
    char ModelNumber[40];
    WORD CurLogCyl;
    WORD CurLogHeads;
    WORD CurLogSPT;
} rt_DiskInfo;

#define  SENDIDLENGTH  sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE
#define IOCTL_DISK_GET_DRIVE_GEOMETRY_EX CTL_CODE(IOCTL_DISK_BASE, 0x0028, METHOD_BUFFERED, FILE_ANY_ACCESS)

class MasterHardDiskSerial
{
public:
    MasterHardDiskSerial();
    ~MasterHardDiskSerial();
    int GetSerialNo(std::vector<char> &serialNumber);
    int GetErrorMessage(TCHAR* _ptszErrorMessage= NULL);
private:
    char* ConvertToString ( DWORD dwDiskdata [256], int iFirstIndex, int iLastIndex, char* pcBuf = NULL );
    BOOL DoIDENTIFY (HANDLE, PSENDCMDINPARAMS, PSENDCMDOUTPARAMS, BYTE, BYTE, PDWORD);
    int ReadPhysicalDriveInNTWithAdminRights (void);
    int	ReadPhysicalDriveInNTUsingSmart (void);
    int	ReadPhysicalDriveInNTWithZeroRights (void);
    int	ReadIdeDriveAsScsiDriveInNT (void);
    char* flipAndCodeBytes ( int iPos, int iFlip,const char * pcStr = NULL, char * pcBuf= NULL);
    void PrintIdeInfo (int iDrive, DWORD dwDiskdata [256]);
    long getHardDriveComputerID();
private:
    char m_cszHardDriveSerialNumber [1024];
    char m_cszHardDriveModelNumber [1024];
    char m_cszErrorMessage[256];
    BYTE byIdOutCmd [sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
};


#endif // _HDD_SERIAL_INFO_H_

//HardDriveSerialNumer.cpp

//#include "pch.h" //vs控制檯項目自動生成
#include "HardDriveSerialNumer.h"

int MasterHardDiskSerial::ReadPhysicalDriveInNTWithAdminRights (void)
{
   int iDone = FALSE;
   int iDrive = 0;

   for (iDrive = 0; iDrive < MAX_IDE_DRIVES; iDrive++)
   {
      HANDLE hPhysicalDriveIOCTL = 0;

         //  Try to get a handle to PhysicalDrive IOCTL, report failure
         //  and exit if can't.
      char cszDriveName [256];

      sprintf_s(cszDriveName, 256, "\\\\.\\PhysicalDrive%d", iDrive);

         //  Windows NT, Windows 2000, must have admin rights
      hPhysicalDriveIOCTL = CreateFileA (cszDriveName,
                               GENERIC_READ | GENERIC_WRITE, 
                               FILE_SHARE_READ | FILE_SHARE_WRITE , NULL,
                               OPEN_EXISTING, 0, NULL);
      if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE)
      {
		  SecureZeroMemory(m_cszErrorMessage,sizeof(m_cszErrorMessage));
		  sprintf_s(m_cszErrorMessage,256,"%d ReadPhysicalDriveInNTWithAdminRights ERROR ,CreateFileA(%s) returned INVALID_HANDLE_VALUE",__LINE__, cszDriveName);

      }
      else
      {
         GETVERSIONOUTPARAMS VersionParams;
         DWORD               dwBytesReturned = 0;

            // Get the version, etc of PhysicalDrive IOCTL
         memset ((void*) &VersionParams, 0, sizeof(VersionParams));

         if ( ! DeviceIoControl (hPhysicalDriveIOCTL, DFP_GET_VERSION,
                   NULL, 
                   0,
                   &VersionParams,
                   sizeof(VersionParams),
                   &dwBytesReturned, NULL) )
         {         

	           DWORD dwErr = GetLastError ();
			   SecureZeroMemory(m_cszErrorMessage,sizeof(m_cszErrorMessage));
	           sprintf_s(m_cszErrorMessage,256,"%d ReadPhysicalDriveInNTWithAdminRights ERROR DeviceIoControl() %d, DFP_GET_VERSION) returned 0, error is %d\n",__LINE__, (int) hPhysicalDriveIOCTL, (int) dwErr);
         }

            // If there is a IDE device at number "iI" issue commands
            // to the device
         if (VersionParams.bIDEDeviceMap <= 0)
         {
			 SecureZeroMemory(m_cszErrorMessage,sizeof(m_cszErrorMessage));
	         sprintf_s(m_cszErrorMessage,256,"%d ReadPhysicalDriveInNTWithAdminRights ERROR No device found at iPosition %d (%d)",__LINE__, (int) iDrive, (int) VersionParams.bIDEDeviceMap);
         }
         else
         {
            BYTE             bIDCmd = 0;   // IDE or ATAPI IDENTIFY cmd
            SENDCMDINPARAMS  scip;
            //SENDCMDOUTPARAMS OutCmd;

			   // Now, get the ID sector for all IDE devices in the system.
               // If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
               // otherwise use the IDE_ATA_IDENTIFY command
            bIDCmd = (VersionParams.bIDEDeviceMap >> iDrive & 0x10) ? \
                      IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;

            memset (&scip, 0, sizeof(scip));
            memset (byIdOutCmd, 0, sizeof(byIdOutCmd));

            if ( DoIDENTIFY (hPhysicalDriveIOCTL, 
                       &scip, 
                       (PSENDCMDOUTPARAMS)&byIdOutCmd, 
                       (BYTE) bIDCmd,
                       (BYTE) iDrive,
                       &dwBytesReturned))
            {
               DWORD dwDiskData [256];
               int iIjk = 0;
               USHORT *punIdSector = (USHORT *)
                             ((PSENDCMDOUTPARAMS) byIdOutCmd) -> bBuffer;

               for (iIjk = 0; iIjk < 256; iIjk++)
                  dwDiskData [iIjk] = punIdSector [iIjk];

               PrintIdeInfo (iDrive, dwDiskData);

               iDone = TRUE;
            }
	    }

         CloseHandle (hPhysicalDriveIOCTL);
      }
   }

   return iDone;
}

int MasterHardDiskSerial::ReadPhysicalDriveInNTUsingSmart (void)
{
   int iDone = FALSE;
   int iDrive = 0;

   for (iDrive = 0; iDrive < MAX_IDE_DRIVES; iDrive++)
   {
      HANDLE hPhysicalDriveIOCTL = 0;

         //  Try to get a handle to PhysicalDrive IOCTL, report failure
         //  and exit if can't.
      char cszDriveName [256];

      sprintf_s(cszDriveName,256, "\\\\.\\PhysicalDrive%d", iDrive);

         //  Windows NT, Windows 2000, Windows Server 2003, Vista
      hPhysicalDriveIOCTL = CreateFileA (cszDriveName,
                               GENERIC_READ | GENERIC_WRITE, 
                               FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, 
							   NULL, OPEN_EXISTING, 0, NULL);
      // if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE)
      //    printf ("Unable to open physical iDrive %d, error code: 0x%lX\n",
      //            iDrive, GetLastError ());

      if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE)
      {
			 SecureZeroMemory(m_cszErrorMessage,sizeof(m_cszErrorMessage));
			 sprintf_s(m_cszErrorMessage,256,"%d ReadPhysicalDriveInNTUsingSmart ERROR, CreateFileA(%s) returned INVALID_HANDLE_VALUE Error Code %d",__LINE__, cszDriveName, GetLastError ());
      }
      else
      {
         GETVERSIONINPARAMS GetVersionParams;
         DWORD dwBytesReturned = 0;

            // Get the version, etc of PhysicalDrive IOCTL
         memset ((void*) & GetVersionParams, 0, sizeof(GetVersionParams));

         if ( ! DeviceIoControl (hPhysicalDriveIOCTL, SMART_GET_VERSION,
                   NULL, 
                   0,
     			   &GetVersionParams, sizeof (GETVERSIONINPARAMS),
				   &dwBytesReturned, NULL) )
         {         
	           DWORD dwErr = GetLastError ();
			   SecureZeroMemory(m_cszErrorMessage,sizeof(m_cszErrorMessage));
	           sprintf_s(m_cszErrorMessage,256,"\n%d ReadPhysicalDriveInNTUsingSmart ERROR DeviceIoControl(%d, SMART_GET_VERSION) returned 0, error is %d",__LINE__, (int) hPhysicalDriveIOCTL, (int) dwErr);
         }
         else
         {
			 	// Print the SMART version
           	// PrintVersion (& GetVersionParams);
	           // Allocate the command cszBuffer
			ULONG CommandSize = sizeof(SENDCMDINPARAMS) + IDENTIFY_BUFFER_SIZE;
        	PSENDCMDINPARAMS Command = (PSENDCMDINPARAMS) malloc (CommandSize);
	           // Retrieve the IDENTIFY data
	           // Prepare the command
#define ID_CMD          0xEC            // Returns ID sector for ATA
			Command -> irDriveRegs.bCommandReg = ID_CMD;
			DWORD BytesReturned = 0;
	        if ( ! DeviceIoControl (hPhysicalDriveIOCTL, 
				                    SMART_RCV_DRIVE_DATA, Command, sizeof(SENDCMDINPARAMS),
									Command, CommandSize,
									&BytesReturned, NULL) )
            {
			   SecureZeroMemory(m_cszErrorMessage,sizeof(m_cszErrorMessage));
	           sprintf_s(m_cszErrorMessage,256,"SMART_RCV_DRIVE_DATA IOCTL");
		      
				// Print the error
		        //PrintError ("SMART_RCV_DRIVE_DATA IOCTL", GetLastError());
	        } 
			else
			{
        	       // Print the IDENTIFY data
                DWORD dwDiskData [256];
                USHORT *punIdSector = (USHORT *)
                             (PIDENTIFY_DATA) ((PSENDCMDOUTPARAMS) Command) -> bBuffer;

                for (int iIjk = 0; iIjk < 256; iIjk++)
                   dwDiskData [iIjk] = punIdSector [iIjk];

                PrintIdeInfo (iDrive, dwDiskData);
                iDone = TRUE;
			}
	           // Done
            CloseHandle (hPhysicalDriveIOCTL);
			free (Command);
		 }
      }
   }

   return iDone;
}
																		
char * MasterHardDiskSerial::flipAndCodeBytes ( int iPos, int iFlip, const char * pcszStr, char * pcszBuf)
{
   int iI;
   int iJ = 0;
   int iK = 0;

   pcszBuf [0] = '\0';
   if (iPos <= 0)
      return pcszBuf;

   if ( ! iJ)
   {
      char cP = 0;
      // First try to gather all characters representing hex digits only.
      iJ = 1;
      iK = 0;
      pcszBuf[iK] = 0;
      for (iI = iPos; iJ && !(pcszStr[iI] == '\0'); ++iI)
      {
		char cC = tolower(pcszStr[iI]);
		if (isspace(cC))
			cC = '0';
		++cP;
		pcszBuf[iK] <<= 4;

		if (cC >= '0' && cC <= '9')
			pcszBuf[iK] |= (char) (cC - '0');
		else if (cC >= 'a' && cC <= 'f')
			pcszBuf[iK] |= (char) (cC - 'a' + 10);
		else
		{
			iJ = 0;
			break;
		}

		if (cP == 2)
		{
			if ((pcszBuf[iK] != '\0') && ! isprint(pcszBuf[iK]))
			{
				iJ = 0;
				break;
			}
			++iK;
			cP = 0;
			pcszBuf[iK] = 0;
		}

      }
   }

   if ( ! iJ)
   {
      // There are non-digit characters, gather them as is.
      iJ = 1;
      iK = 0;
      for (iI = iPos; iJ && (pcszStr[iI] != '\0'); ++iI)
      {
	     char cC = pcszStr[iI];

	     if ( ! isprint(cC))
	     {
	        iJ = 0;
	        break;
	     }

	     pcszBuf[iK++] = cC;
      }
   }

   if ( ! iJ)
   {
      // The characters are not there or are not printable.
      iK = 0;
   }

   pcszBuf[iK] = '\0';

   if (iFlip)
      // Flip adjacent characters
      for (iJ = 0; iJ < iK; iJ += 2)
      {
	     char t = pcszBuf[iJ];
	     pcszBuf[iJ] = pcszBuf[iJ + 1];
	     pcszBuf[iJ + 1] = t;
      }

   // Trim any beginning and end space
   iI = iJ = -1;
   for (iK = 0; (pcszBuf[iK] != '\0'); ++iK)
   {
      if (! isspace(pcszBuf[iK]))
      {
	     if (iI < 0)
	        iI = iK;
	     iJ = iK;
      }
   }

   if ((iI >= 0) && (iJ >= 0))
   {
      for (iK = iI; (iK <= iJ) && (pcszBuf[iK] != '\0'); ++iK)
         pcszBuf[iK - iI] = pcszBuf[iK];
      pcszBuf[iK - iI] = '\0';
   }

   return pcszBuf;
}

int MasterHardDiskSerial::ReadPhysicalDriveInNTWithZeroRights (void)
{
   int iDone = FALSE;
   int iDrive = 0;

   for (iDrive = 0; iDrive < MAX_IDE_DRIVES; iDrive++)
   {
      HANDLE hPhysicalDriveIOCTL = 0;

         //  Try to get a handle to PhysicalDrive IOCTL, report failure
         //  and exit if can't.
      char cszDriveName [256];

      sprintf_s(cszDriveName,256,"\\\\.\\PhysicalDrive%d", iDrive);

         //  Windows NT, Windows 2000, Windows XP - admin rights not required
      hPhysicalDriveIOCTL = CreateFileA (cszDriveName, 0,
                               FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
                               OPEN_EXISTING, 0, NULL);
      if (hPhysicalDriveIOCTL == INVALID_HANDLE_VALUE)
      {
			SecureZeroMemory(m_cszErrorMessage,sizeof(m_cszErrorMessage));
			sprintf_s(m_cszErrorMessage,256,"%d ReadPhysicalDriveInNTWithZeroRights ERROR CreateFileA(%s) returned INVALID_HANDLE_VALUE",__LINE__, cszDriveName);
      }
      else
      {
		 STORAGE_PROPERTY_QUERY query;
         DWORD dwBytesReturned = 0;
		 char cszBuffer [10000];

         memset ((void *) & query, 0, sizeof (query));
		 query.PropertyId = StorageDeviceProperty;
		 query.QueryType = PropertyStandardQuery;

		 memset (cszBuffer, 0, sizeof (cszBuffer));

         if ( DeviceIoControl (hPhysicalDriveIOCTL, IOCTL_STORAGE_QUERY_PROPERTY,
                   & query,
                   sizeof (query),
				   & cszBuffer,
				   sizeof (cszBuffer),
                   & dwBytesReturned, NULL) )
         {         
			 STORAGE_DEVICE_DESCRIPTOR * descrip = (STORAGE_DEVICE_DESCRIPTOR *) & cszBuffer;
			 char cszSerialNumber [1000];
			 char cszModelNumber [1000];
             char cszVendorId [1000];
	         char cszProductRevision [1000];

             flipAndCodeBytes ( descrip -> VendorIdOffset,
			                    0,cszBuffer, cszVendorId );
	         flipAndCodeBytes ( descrip -> ProductIdOffset,
			                    0,cszBuffer, cszModelNumber );
	         flipAndCodeBytes ( descrip -> ProductRevisionOffset,
			                    0,cszBuffer, cszProductRevision );
	         flipAndCodeBytes ( descrip -> SerialNumberOffset,
			                    0,cszBuffer, cszSerialNumber );

			 if (0 == m_cszHardDriveSerialNumber [0] &&
						//  serial number must be alphanumeric
			            //  (but there can be leading spaces on IBM drives)
				   (iswalnum (cszSerialNumber [0]) || iswalnum (cszSerialNumber [19])))
			 {
				strcpy_s(m_cszHardDriveSerialNumber,	1024, cszSerialNumber);
				strcpy_s(m_cszHardDriveModelNumber,		1024, cszModelNumber);
				iDone = TRUE;
			 }
	           // Get the disk iDrive geometry.
	         memset (cszBuffer, 0, sizeof(cszBuffer));
	         if ( ! DeviceIoControl (hPhysicalDriveIOCTL,
			          IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
			          NULL,
			          0,
			          &cszBuffer,
			          sizeof(cszBuffer),
			          &dwBytesReturned,
			          NULL))
	         {
				SecureZeroMemory(m_cszErrorMessage,sizeof(m_cszErrorMessage));
				sprintf_s(m_cszErrorMessage,"%s ReadPhysicalDriveInNTWithZeroRights ERROR DeviceIoControl(), IOCTL_DISK_GET_DRIVE_GEOMETRY_EX) returned 0", cszDriveName);
			}
	         else
	         {         
	            DISK_GEOMETRY_EX* geom = (DISK_GEOMETRY_EX*) &cszBuffer;
	            int iFixed = (geom->Geometry.MediaType == FixedMedia);
	            __int64 i64Size = geom->DiskSize.QuadPart;
				     
	        }
         }
		 else
		 {
			 DWORD dwErr = GetLastError ();
			 SecureZeroMemory(m_cszErrorMessage,sizeof(m_cszErrorMessage));
			 sprintf_s (m_cszErrorMessage,"DeviceIOControl IOCTL_STORAGE_QUERY_PROPERTY error = %d\n", dwErr);

		 }

         CloseHandle (hPhysicalDriveIOCTL);
      }
   }

   return iDone;
}

BOOL MasterHardDiskSerial::DoIDENTIFY (HANDLE hPhysicalDriveIOCTL, PSENDCMDINPARAMS pSCIP,
                 PSENDCMDOUTPARAMS pSCOP, BYTE bIDCmd, BYTE bDriveNum,
                 PDWORD lpcbBytesReturned)
{
      // Set up data structures for IDENTIFY command.
   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;

      // Compute the iDrive number.
   pSCIP -> irDriveRegs.bDriveHeadReg = 0xA0 | ((bDriveNum & 1) << 4);

      // The command can either be IDE identify or ATAPI identify.
   pSCIP -> irDriveRegs.bCommandReg = bIDCmd;
   pSCIP -> bDriveNumber = bDriveNum;
   pSCIP -> cBufferSize = IDENTIFY_BUFFER_SIZE;

   return ( DeviceIoControl (hPhysicalDriveIOCTL, DFP_RECEIVE_DRIVE_DATA,
               (LPVOID) pSCIP,
               sizeof(SENDCMDINPARAMS) - 1,
               (LPVOID) pSCOP,
               sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
               lpcbBytesReturned, NULL) );
}

int MasterHardDiskSerial::ReadIdeDriveAsScsiDriveInNT (void)
{
   int iDone = FALSE;
   int iController = 0;

   for (iController = 0; iController < 2; iController++)
   {
      HANDLE hScsiDriveIOCTL = 0;
      char   cszDriveName [256];

         //  Try to get a handle to PhysicalDrive IOCTL, report failure
         //  and exit if can't.
      sprintf_s (cszDriveName, "\\\\.\\Scsi%d:", iController);

         //  Windows NT, Windows 2000, any rights should do
      hScsiDriveIOCTL = CreateFileA (cszDriveName,
                               GENERIC_READ | GENERIC_WRITE, 
                               FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
                               OPEN_EXISTING, 0, NULL);
     

      if (hScsiDriveIOCTL != INVALID_HANDLE_VALUE)
      {
         int iDrive = 0;

         for (iDrive = 0; iDrive < 2; iDrive++)
         {
            char cszBuffer [sizeof (SRB_IO_CONTROL) + SENDIDLENGTH];
            SRB_IO_CONTROL *cP = (SRB_IO_CONTROL *) cszBuffer;
            SENDCMDINPARAMS *pin =
                   (SENDCMDINPARAMS *) (cszBuffer + sizeof (SRB_IO_CONTROL));
            DWORD dwDummy;
   
            memset (cszBuffer, 0, sizeof (cszBuffer));
            cP -> HeaderLength = sizeof (SRB_IO_CONTROL);
            cP -> Timeout = 10000;
            cP -> Length = SENDIDLENGTH;
            cP -> ControlCode = IOCTL_SCSI_MINIPORT_IDENTIFY;
            strncpy ((char *) cP -> Signature, "SCSIDISK", 8);
  
            pin -> irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY;
            pin -> bDriveNumber = iDrive;

            if (DeviceIoControl (hScsiDriveIOCTL, IOCTL_SCSI_MINIPORT, 
                                 cszBuffer,
                                 sizeof (SRB_IO_CONTROL) +
                                         sizeof (SENDCMDINPARAMS) - 1,
                                 cszBuffer,
                                 sizeof (SRB_IO_CONTROL) + SENDIDLENGTH,
                                 &dwDummy, NULL))
            {
               SENDCMDOUTPARAMS *pOut =
                    (SENDCMDOUTPARAMS *) (cszBuffer + sizeof (SRB_IO_CONTROL));
               IDSECTOR *pId = (IDSECTOR *) (pOut -> bBuffer);
               if (pId -> sModelNumber [0])
               {
                  DWORD dwDiskData [256];
                  int iIjk = 0;
                  USHORT *punIdSector = (USHORT *) pId;
          
                  for (iIjk = 0; iIjk < 256; iIjk++)
                     dwDiskData [iIjk] = punIdSector [iIjk];

                  PrintIdeInfo (iController * 2 + iDrive, dwDiskData);

                  iDone = TRUE;
               }
            }
         }
         CloseHandle (hScsiDriveIOCTL);
      }
   }

   return iDone;
}

void MasterHardDiskSerial::PrintIdeInfo (int iDrive, DWORD dwDiskData [256])
{
   char cszSerialNumber [1024];
   char cszModelNumber [1024];
   char cszRevisionNumber [1024];
   char bufferSize [32];

   __int64 i64Sectors = 0;
   __int64 i64Byte = 0;

      //  copy the hard iDrive serial number to the cszBuffer
   ConvertToString (dwDiskData, 10, 19, cszSerialNumber);
   ConvertToString (dwDiskData, 27, 46, cszModelNumber);
   ConvertToString (dwDiskData, 23, 26, cszRevisionNumber);
   sprintf_s(bufferSize,32, "%u", dwDiskData [21] * 512);

   if (0 == m_cszHardDriveSerialNumber [0] &&
       //  serial number must be alphanumeric
       //  (but there can be leading spaces on IBM drives)
       (isalnum (cszSerialNumber [0]) || isalnum (cszSerialNumber [19])))
   {
      strcpy_s(m_cszHardDriveSerialNumber,1024, cszSerialNumber);
      strcpy_s(m_cszHardDriveModelNumber,1024, cszModelNumber);
   }

}

long MasterHardDiskSerial::getHardDriveComputerID ()
{
   int iDone = FALSE;
   // char string [1024];
   __int64 i64Id = 0;
   OSVERSIONINFO version;

   strcpy_s(m_cszHardDriveSerialNumber,1024, "");

   memset (&version, 0, sizeof (version));
   version.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
   GetVersionEx (&version);
   if (version.dwPlatformId == VER_PLATFORM_WIN32_NT)
	{
		  //  this works under WinNT4 or Win2K if you have admin rights
		iDone = ReadPhysicalDriveInNTWithAdminRights ();

			//  this should work in WinNT or Win2K if previous did not work
			//  this is kind of a backdoor via the SCSI mini port driver into
			//     the IDE drives
		if ( ! iDone) 
			iDone = ReadIdeDriveAsScsiDriveInNT ();

		  //  this works under WinNT4 or Win2K or WinXP if you have any rights
		if ( ! iDone)
			iDone = ReadPhysicalDriveInNTWithZeroRights ();

		  //  this works under WinNT4 or Win2K or WinXP or Windows Server 2003 or Vista if you have any rights
		if ( ! iDone)
			iDone = ReadPhysicalDriveInNTUsingSmart ();
   }
   
   if (m_cszHardDriveSerialNumber [0] > 0)
   {
      char *cP = m_cszHardDriveSerialNumber;

         //  ignore first 5 characters from western digital hard drives if
         //  the first four characters are WD-W
      if ( ! strncmp (m_cszHardDriveSerialNumber, "WD-W", 4)) 
         cP += 5;
      for ( ; cP && *cP; cP++)
      {
         if ('-' == *cP) 
            continue;
         i64Id *= 10;
         switch (*cP)
         {
            case '0': i64Id += 0; break;
            case '1': i64Id += 1; break;
            case '2': i64Id += 2; break;
            case '3': i64Id += 3; break;
            case '4': i64Id += 4; break;
            case '5': i64Id += 5; break;
            case '6': i64Id += 6; break;
            case '7': i64Id += 7; break;
            case '8': i64Id += 8; break;
            case '9': i64Id += 9; break;
            case 'a': case 'A': i64Id += 10; break;
            case 'b': case 'B': i64Id += 11; break;
            case 'c': case 'C': i64Id += 12; break;
            case 'd': case 'D': i64Id += 13; break;
            case 'e': case 'E': i64Id += 14; break;
            case 'f': case 'F': i64Id += 15; break;
            case 'g': case 'G': i64Id += 16; break;
            case 'h': case 'H': i64Id += 17; break;
            case 'i': case 'I': i64Id += 18; break;
            case 'j': case 'J': i64Id += 19; break;
            case 'k': case 'K': i64Id += 20; break;
            case 'l': case 'L': i64Id += 21; break;
            case 'm': case 'M': i64Id += 22; break;
            case 'n': case 'N': i64Id += 23; break;
            case 'o': case 'O': i64Id += 24; break;
            case 'p': case 'P': i64Id += 25; break;
            case 'q': case 'Q': i64Id += 26; break;
            case 'r': case 'R': i64Id += 27; break;
            case 's': case 'S': i64Id += 28; break;
            case 't': case 'T': i64Id += 29; break;
            case 'u': case 'U': i64Id += 30; break;
            case 'v': case 'V': i64Id += 31; break;
            case 'w': case 'W': i64Id += 32; break;
            case 'x': case 'X': i64Id += 33; break;
            case 'y': case 'Y': i64Id += 34; break;
            case 'z': case 'Z': i64Id += 35; break;
         }                            
      }
   }

   i64Id %= 100000000;
   if (strstr (m_cszHardDriveModelNumber, "IBM-"))
      i64Id += 300000000;
   else if (strstr (m_cszHardDriveModelNumber, "MAXTOR") ||
            strstr (m_cszHardDriveModelNumber, "Maxtor"))
      i64Id += 400000000;
   else if (strstr (m_cszHardDriveModelNumber, "WDC "))
      i64Id += 500000000;
   else
      i64Id += 600000000;

   return (long) i64Id;
}

int MasterHardDiskSerial::GetSerialNo(std::vector<char> &serialNumber)
{
    getHardDriveComputerID();
	size_t numberLength = strlen(m_cszHardDriveSerialNumber);
    if (numberLength == 0)
        return -1;
    serialNumber.resize(numberLength);
    memcpy(&serialNumber.front(), m_cszHardDriveSerialNumber, serialNumber.size());
	return 0;
}

char *MasterHardDiskSerial::ConvertToString (DWORD dwDiskData [256],
		       int iFirstIndex,
		       int iLastIndex,
		       char* pcszBuf)
{
   int iIndex = 0;
   int iPosition = 0;

   //  each integer has two characters stored in it backwards

   // Removes the spaces from the serial no
   for ( iIndex = iFirstIndex; iIndex <= iLastIndex ; iIndex++ )
   {
		//  get high byte for 1st character	
	    char ctemp = (char) (dwDiskData [iIndex] / 256);
		char cszmyspace[] = " ";
		if ( !(ctemp == *cszmyspace))
		{
			pcszBuf [iPosition++] = ctemp ;
		}
		 //  get low byte for 2nd character
		char ctemp1 = (char) (dwDiskData [iIndex] % 256);
		if ( !(ctemp1 == *cszmyspace))
		{
			pcszBuf [iPosition++] = ctemp1 ;
		}
   }

      //  end the string 
   pcszBuf[iPosition] = '\0';

      //  cut off the trailing blanks
   for (iIndex = iPosition - 1; iIndex > 0 && isspace(pcszBuf [iIndex]); iIndex--)
      pcszBuf [iIndex] = '\0';

   return pcszBuf;
}

int MasterHardDiskSerial::GetErrorMessage(TCHAR* tszErrorMessage)
{
	if (strlen(m_cszErrorMessage)!=0)
	{
		mbstowcs((wchar_t *)tszErrorMessage,m_cszErrorMessage,sizeof(m_cszErrorMessage));
		return 0;
	}
	else 
		return -1;
}

MasterHardDiskSerial::MasterHardDiskSerial()
{
	SecureZeroMemory(m_cszErrorMessage,sizeof(m_cszErrorMessage));
	SecureZeroMemory(m_cszHardDriveModelNumber,sizeof(m_cszHardDriveModelNumber));
	SecureZeroMemory(m_cszHardDriveSerialNumber,sizeof(m_cszHardDriveSerialNumber));
}

MasterHardDiskSerial::~MasterHardDiskSerial()
{
}

//main.cpp

#include "pch.h"
#include "HardDriveSerialNumer.h"
#include <iostream>
int main()
{
	std::vector<char> serialNumber;
	int out = 0;
	MasterHardDiskSerial a;
	out=a.GetSerialNo(serialNumber);
	std::cout << serialNumber.data() << std::endl;
}

以上在vs控制檯項目可以直接編譯通過得到結果,如果報錯

解決方案,項目 =》屬性 =》c/c++  =》預處理器=》點擊預處理器定義,編輯,加入_CRT_SECURE_NO_WARNINGS,即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章