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

转载与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()即可生成序列号。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值