在制作程序注册机的时候需要获取到机器的唯一编号,本文从硬盘、网卡硬件地址及文件版本生成一个4*7的序列号,形如 3CEA-82E6-1396-9C78-45C4-06C9-9564
1.获取硬盘物理地址(非逻辑分区序列号)
逻辑分区序列号获取很简单,但是这个编号不唯一,且可以轻易修改。如果ghost系统的话恐怕id也一样,所以获取硬盘的物理地址更合理一些。
需要的结构体及头文件
#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 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 serialId = GetHardDiskSerialNumber ( ) ;
serialId. Remove ( '-' ) ;
return serialId. Right ( 8 ) ;
}
2.获取以太网网卡地址
{
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
{
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 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()即可生成序列号。