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

本文主要是介绍用硬盘物理编号(序列号)、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()即可生成序列号。

这篇关于用硬盘物理编号(序列号)、mac地址、文件版本、当前时间来生成机器序列号的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1062096

相关文章

Linux卸载自带jdk并安装新jdk版本的图文教程

《Linux卸载自带jdk并安装新jdk版本的图文教程》在Linux系统中,有时需要卸载预装的OpenJDK并安装特定版本的JDK,例如JDK1.8,所以本文给大家详细介绍了Linux卸载自带jdk并... 目录Ⅰ、卸载自带jdkⅡ、安装新版jdkⅠ、卸载自带jdk1、输入命令查看旧jdkrpm -qa

Java实现时间与字符串互相转换详解

《Java实现时间与字符串互相转换详解》这篇文章主要为大家详细介绍了Java中实现时间与字符串互相转换的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、日期格式化为字符串(一)使用预定义格式(二)自定义格式二、字符串解析为日期(一)解析ISO格式字符串(二)解析自定义

Tomcat版本与Java版本的关系及说明

《Tomcat版本与Java版本的关系及说明》:本文主要介绍Tomcat版本与Java版本的关系及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Tomcat版本与Java版本的关系Tomcat历史版本对应的Java版本Tomcat支持哪些版本的pythonJ

java中使用POI生成Excel并导出过程

《java中使用POI生成Excel并导出过程》:本文主要介绍java中使用POI生成Excel并导出过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录需求说明及实现方式需求完成通用代码版本1版本2结果展示type参数为atype参数为b总结注:本文章中代码均为

在java中如何将inputStream对象转换为File对象(不生成本地文件)

《在java中如何将inputStream对象转换为File对象(不生成本地文件)》:本文主要介绍在java中如何将inputStream对象转换为File对象(不生成本地文件),具有很好的参考价... 目录需求说明问题解决总结需求说明在后端中通过POI生成Excel文件流,将输出流(outputStre

mysql如何查看当前连接数

《mysql如何查看当前连接数》:本文主要介绍mysql如何查看当前连接数问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录mysql查看当前连接数查看mysql数据库允许最大连接数总结mysql查看当前连接数查看当前连接数SHOW STATUS LIKE

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

IDEA中Git版本回退的两种实现方案

《IDEA中Git版本回退的两种实现方案》作为开发者,代码版本回退是日常高频操作,IntelliJIDEA集成了强大的Git工具链,但面对reset和revert两种核心回退方案,许多开发者仍存在选择... 目录一、版本回退前置知识二、Reset方案:整体改写历史1、IDEA图形化操作(推荐)1.1、查看提

JDK多版本共存并自由切换的操作指南(本文为JDK8和JDK17)

《JDK多版本共存并自由切换的操作指南(本文为JDK8和JDK17)》本文介绍了如何在Windows系统上配置多版本JDK(以JDK8和JDK17为例),并通过图文结合的方式给大家讲解了详细步骤,具有... 目录第一步 下载安装JDK第二步 配置环境变量第三步 切换JDK版本并验证可能遇到的问题前提:公司常

nvm如何切换与管理node版本

《nvm如何切换与管理node版本》:本文主要介绍nvm如何切换与管理node版本问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录nvm切换与管理node版本nvm安装nvm常用命令总结nvm切换与管理node版本nvm适用于多项目同时开发,然后项目适配no