用硬盘物理编号(序列号)、mac地址、文件版本、当前时间来生成机器序列号
2014 年 6 月 27 日 用硬盘物理编号(序列号)、mac地址、文件版本、当前时间来生成机器序列号无评论
在制作程序注册机的时候需要获取到机器的唯一编号,本文从硬盘、网卡硬件地址及文件版本生成一个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()
#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 ;
}
{
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);
}
{
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;
}
{
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('.'));
}
{
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;
}
{
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()即可生成序列号。
Tags: mac地址 MFC 序列号 文件版本号 注册机 注册机制 硬盘物理地址
发表评论