• windows平台c++获取硬盘序列号(msys环境)


    windows平台c++获取硬盘序列号(msys环境)

    vmware虚拟机环境有时候获取不到硬盘序列号,设置后可以,参见:https://jingyan.baidu.com/article/cbcede07d345db43f40b4d88.html

    本文参考:https://blog.csdn.net/yanchenyu365/article/details/85061879

    1.makefile文件

    app : HardDrive.cpp HardDriveSerialNumer.cpp
        g++ -w -o $@ $^

    2.main函数文件:HardDrive.cpp

    #include "HardDriveSerialNumer.hpp"
    #include <iostream>
    #include <string.h>
    
    int main()
    {
        char SerialNumber[1024] = {""};
        memset(&SerialNumber, 0, sizeof(SerialNumber));
    
        MasterHardDiskSerial a;
        int ret = a.GetSerialNo(SerialNumber);
    
        if (ret == 0)
        {
            std::cout << "SN " << SerialNumber << std::endl;
        }
        else
        {
            std::cout << "can't get sn" << std::endl;
        }
    }

    3.头文件:HardDriveSerialNumer.hpp

    #ifndef _HDD_SERIAL_INFO_H_
    #define _HDD_SERIAL_INFO_H_
    
    #include <stdio.h>
    #include <string.h>
    #include <tchar.h>
    #include <vector>
    #include <windows.h>
    #include <winioctl.h>
    
    #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 GetSerialNo(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_

    4.实现文件:HardDriveSerialNumer.hpp

    //#include "pch.h" //vs控制台项目自动生成
    #include "HardDriveSerialNumer.hpp"
    #include <iostream>
    
    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() %ld, DFP_GET_VERSION) returned 0, error is %d
    ", __LINE__, (long long)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
    ",
          //            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, "
    %d ReadPhysicalDriveInNTUsingSmart ERROR DeviceIoControl(%ld, SMART_GET_VERSION) returned 0, error is %d", __LINE__, (long long)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] = '';
       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] == ''); ++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] != '') && !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] != ''); ++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] = '';
    
       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] != ''); ++iK)
       {
          if (!isspace(pcszBuf[iK]))
          {
             if (iI < 0)
                iI = iK;
             iJ = iK;
          }
       }
    
       if ((iI >= 0) && (iJ >= 0))
       {
          for (iK = iI; (iK <= iJ) && (pcszBuf[iK] != ''); ++iK)
             pcszBuf[iK - iI] = pcszBuf[iK];
          pcszBuf[iK - iI] = '';
       }
    
       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
    ", 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)
    int MasterHardDiskSerial::GetSerialNo(char *SerialNumber)
    {
       getHardDriveComputerID();
       size_t numberLength = strlen(m_cszHardDriveSerialNumber);
       if (numberLength == 0)
          return -1;
       //serialNumber.resize(numberLength);
       //std::cout << "size " << serialNumber.size() << std::endl;
       //memcpy(&serialNumber.front(), m_cszHardDriveSerialNumber, serialNumber.size()); //m_cszHardDriveSerialNumber;
       memcpy(SerialNumber, m_cszHardDriveSerialNumber, numberLength);
       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] = '';
    
       //  cut off the trailing blanks
       for (iIndex = iPosition - 1; iIndex > 0 && isspace(pcszBuf[iIndex]); iIndex--)
          pcszBuf[iIndex] = '';
    
       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()
    {
    }
  • 相关阅读:
    手写PE文件(不借助编译器,用十六进制数进行编写)
    浅谈代码段加密原理(防止静态分析)
    PE文件动态加载执行过程
    静态数据连接库(.lib)和动态连接库(.dll)
    关于普通断点/内存断点/硬件断点
    x64dbg零基础使用教程
    HOOK相关原理与例子
    socket,实现服务器和客户端对话
    解析PE文件
    python正则表达式---基于re模块
  • 原文地址:https://www.cnblogs.com/Netsharp/p/14077129.html
Copyright © 2020-2023  润新知