用硬盘物理编号(序列号)、mac地址、文件版本、当前时间来生成机器序列号

来源:互联网 发布:30岁没结婚的女人 知乎 编辑:程序博客网 时间:2024/06/06 06:53
转载与http://www.xdty.org/1692

在制作程序注册机的时候需要获取到机器的唯一编号,本文从硬盘、网卡硬件地址及文件版本生成一个4*7的序列号,形如 3CEA-82E6-1396-9C78-45C4-06C9-9564

1.获取硬盘物理地址(非逻辑分区序列号)
逻辑分区序列号获取很简单,但是这个编号不唯一,且可以轻易修改。如果ghost系统的话恐怕id也一样,所以获取硬盘的物理地址更合理一些。
需要的结构体及头文件

#include <winioctl.h>

#include <pshpack1.h>
#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()

实现函数

CString GetHardDiskSerialNumber()
{
    CString strHardDiskSerialNumber ;

    HANDLE hDrive = 0;

    CString szDriveName = _T("\\\\.\\PhysicalDrive0");

    hDrive = CreateFile (szDriveName, GENERIC_READ| GENERIC_WRITE, FILE_SHARE_DELETE | FILE_SHARE_READ| FILE_SHARE_WRITE, NULL, OPEN_EXISTING,0, NULL);
    if (hDrive != INVALID_HANDLE_VALUE)
    {
        DWORD cbBytesReturned = 0;

        GETVERSIONINPARAMS objVersionParams ;
        memset (&objVersionParams,0, sizeof(objVersionParams));
        if (  DeviceIoControl (hDrive, SMART_GET_VERSION, NULL, 0, &objVersionParams, sizeof(GETVERSIONINPARAMS), &cbBytesReturned, NULL) )
        {        
            ULONG nCommandSize = sizeof(SENDCMDINPARAMS)+ IDENTIFY_BUFFER_SIZE;
            PSENDCMDINPARAMS pSendCommands = (PSENDCMDINPARAMS) malloc(nCommandSize) ;

            pSendCommands->irDriveRegs.bCommandReg= ID_CMD ;
            DWORD BytesReturned = 0;
            if (DeviceIoControl(hDrive, SMART_RCV_DRIVE_DATA, pSendCommands, sizeof(SENDCMDINPARAMS), pSendCommands, nCommandSize,&BytesReturned, NULL))
            {
                WORD* pIdSector =(WORD *)(PIDENTIFY_DATA) ((PSENDCMDOUTPARAMS) pSendCommands)->bBuffer;

                char szSerialNumber[100]= "" ;
                for (int index= 10, position=0; index<= 19; index++)
                {
                    szSerialNumber[position]= (char)(pIdSector[index]/ 256);
                    position++ ;

                    szSerialNumber[position]= (char)(pIdSector[index]% 256);
                    position++ ;
                }

                strHardDiskSerialNumber = szSerialNumber;
                strHardDiskSerialNumber.TrimLeft();
                strHardDiskSerialNumber.TrimRight();
            }

            CloseHandle (hDrive);
            free (pSendCommands);
            pSendCommands = NULL;
        }
    }

    return strHardDiskSerialNumber ;
}

最后获取到的字串类似为 WD-WMAYUS743480 ,只需要取后八位就可以了。

CString GetHardDiskSerialID()
{
    CString serialId = GetHardDiskSerialNumber();
    serialId.Remove('-');
    return serialId.Right(8);
}

2.获取以太网网卡地址

CString GetMacAddress(bool format/*=false*/)
{
    CString csMacAddress;
    ULONG BufferLength = 0;
    BYTE* pBuffer = 0;
    if( ERROR_BUFFER_OVERFLOW == GetAdaptersInfo( 0, &BufferLength ))
    {
        pBuffer = new BYTE[ BufferLength];
    }

    PIP_ADAPTER_INFO pAdapterInfo =
        reinterpret_cast<PIP_ADAPTER_INFO>(pBuffer);
    GetAdaptersInfo( pAdapterInfo, &BufferLength);

    while( pAdapterInfo )
    {
        if (pAdapterInfo->Type==MIB_IF_TYPE_ETHERNET)
        {
            CString szFormat;
            if (format)
            {
                szFormat = _T("%02x:%02x:%02x:%02x:%02x:%02x");
            }
            else
            {
                szFormat = _T("%02x%02x%02x%02x%02x%02x");
            }
            csMacAddress.Format(szFormat,
                pAdapterInfo->Address[0],
                pAdapterInfo->Address[1],
                pAdapterInfo->Address[2],
                pAdapterInfo->Address[3],
                pAdapterInfo->Address[4],
                pAdapterInfo->Address[5]);
        }
        pAdapterInfo = pAdapterInfo->Next;
    }
    delete[] pBuffer;

    return csMacAddress;
}

3.获取程序版本号
需要在项目属性连接里引入Version.lib

bool GetProductAndVersion(CString&strProductName, CString &strProductVersion)
{
    TCHAR szFilename[MAX_PATH +1] = {0};
    if (GetModuleFileName(NULL, szFilename, MAX_PATH)== 0)
    {
        return false;
    }

    DWORD dummy;
    DWORD dwSize = GetFileVersionInfoSize(szFilename,&dummy);
    if (dwSize == 0)
    {
        return false;
    }
    std::vector<BYTE> data(dwSize);

    if (!GetFileVersionInfo(szFilename,NULL, dwSize, &data[0]))
    {
        return false;
    }

    LPVOID pvProductName = NULL;
    unsigned int iProductNameLen= 0;
    LPVOID pvProductVersion = NULL;
    unsigned int iProductVersionLen= 0;

    if (!VerQueryValue(&data[0], _T("\\StringFileInfo\\080404b0\\ProductName"),&pvProductName, &iProductNameLen)||
        !VerQueryValue(&data[0], _T("\\StringFileInfo\\080404b0\\ProductVersion"),&pvProductVersion, &iProductVersionLen))
    {
        return false;
    }

    strProductName.SetString((LPCTSTR)pvProductName, iProductNameLen);
    strProductVersion.SetString((LPCTSTR)pvProductVersion, iProductVersionLen);

    return true;
}

CString GetFileVersion()
{
    CString strProductName, strProductVersion;
    GetProductAndVersion(strProductName, strProductVersion);

    return strProductVersion.Left(strProductVersion.ReverseFind('.'));
}

4.生成序列号

CString CKeyController::GenerateMachineID()
{
    CString serialID = GetHardDiskSerialID();
    CString timeID;
    timeID.Format(_T("%lx"),time(NULL));
    timeID.Delete(6,3);
    return serialID+timeID+GetMacAddress();
}

CString CKeyController::GenerateSerialNumber()
{
    CString serialNumber = GenerateMachineID();
    for (int i=0; i<6; i++)
    {
        serialNumber.Insert(i*5+4, _T("-"));
    }
    CString version = GetFileVersion();
    version.Delete(1,1);
    version.Delete(2,1);
    version.Format(_T("%2x"), _ttoi(version));
    serialNumber.Append(version);
    serialNumber.MakeUpper();
    return serialNumber;
}

最后调用GenerateSerialNumber()即可生成序列号。

0 0
原创粉丝点击