1. 获取机器的MAC地址真的有很多种方法。可以通过windows api,可以通过wmi服务等。MSDN上面的例子是使用IP helper函数GetAdaptersInfo。其实还有一个api,是GetAdaptersAddresses。NetBios和DDK的方法不推荐使用,低于api层次的调用不保证微软会淘汰掉。建立一个支持MFC的控制台程序:
stdafx.h
- #include <vector>
- #include <string>
- typedef std::vector< std::string > MACAddresses;
- typedef MACAddresses::iterator vsIt;
GetNetBiosMacAddresses.cpp
- #include "stdafx.h"
- #include <windows.h>
- #include <wincon.h>
- #include <stdio.h>
- #include <nb30.h>
- // Netbios is not supported on Windows Vista, Windows Server 2008, and subsequent versions of the operating system]l
- // For using NetAPI to get MAC, should include nb30.h
- #define MACSESION 6
- #pragma warning( disable : 4996 )
- #pragma comment(lib,"Netapi32.lib")
- typedef struct _ASTAT_
- {
- ADAPTER_STATUS adapt;
- NAME_BUFFER NameBuff [30];
- }ASTAT, * PASTAT;
-
- ASTAT Adapter; // to store MAC information
- // input parameter: lana_num start from 0, but in windows, not continuously allocated, so not reliable.
- std::string getmac_one( int lana_num )
- {
- NCB ncb;
- UCHAR uRetCode;
-
- memset( &ncb, 0, sizeof( ncb ) );
- ncb.ncb_command = NCBRESET;
- ncb.ncb_lana_num = lana_num;
-
- uRetCode = Netbios( &ncb );
- //printf( "The NCBRESET return code is:0x%x \n", uRetCode );
-
- memset( &ncb, 0, sizeof( ncb ) );
- ncb.ncb_command = NCBASTAT;
- ncb.ncb_lana_num = lana_num;
-
- strcpy( (char *)ncb.ncb_callname, "* " );
- ncb.ncb_buffer = ( unsigned char * ) &Adapter;
-
- ncb.ncb_length = sizeof( Adapter );
- uRetCode = Netbios( &ncb );
- // printf( "The NCBASTAT return code is: 0x%x \n", uRetCode );
- std::string s;
- if ( uRetCode == 0 )
- {
- int bAddressInt [ MACSESION ];
- char CommarSeperatedAddress[ MACSESION * 3 ]={0};
- for( int i = 0; i < MACSESION; ++i )
- {
- bAddressInt[ i ] = Adapter.adapt.adapter_address[ i ];
- bAddressInt[ i ] &= 0x000000ff; // avoid "ff" leading bytes when "char" is lager then 0x7f
- }
- sprintf( CommarSeperatedAddress, "%02x:%02x:%02x:%02x:%02x:%02x",
- bAddressInt[ 0 ],
- bAddressInt[ 1 ],
- bAddressInt[ 2 ],
- bAddressInt[ 3 ],
- bAddressInt[ 4 ],
- bAddressInt[ 5 ]); // Should use scl::FormatString inside
- s = CommarSeperatedAddress;
- }
- return s;
- }
-
- MACAddresses GetNetBiosMacAddresses()
- {
- NCB ncb;
- UCHAR uRetCode;
- LANA_ENUM lana_enum;
- memset( &ncb, 0, sizeof( ncb ) );
- ncb.ncb_command = NCBENUM;
-
- ncb.ncb_buffer = (unsigned char *) &lana_enum;
- ncb.ncb_length = sizeof( lana_enum );
-
- uRetCode = Netbios( &ncb );
- //printf( "The NCBENUM return code is:0x%x \n", uRetCode );
- MACAddresses vAdd;
- if ( uRetCode == 0 )
- {
- //printf( "Ethernet Count is : %d\n\n", lana_enum.length);
- for ( int i=0; i < lana_enum.length; ++i )
- {
- std::string s = getmac_one( lana_enum.lana[i] );
- if( ! s.empty() )
- {
- vAdd.push_back( s );
- }
- }
- }
- return vAdd;
- }
GetMacAddresses.cpp
- #include "stdafx.h"
- #include <Winsock2.h>
- #include <Iphlpapi.h>
- #pragma comment(lib,"Iphlpapi")
- #pragma warning( disable : 4996 )
- #define MACSESION 6
- MACAddresses GetINETMacAddresses()
- {
- PIP_ADAPTER_ADDRESSES pAddresses = NULL;
- ULONG family = AF_INET;
- ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
- ULONG outBufLen = sizeof( IP_ADAPTER_ADDRESSES );
-
- // Make an initial call to GetAdaptersAddresses to get the
- // size needed into the outBufLen variable
- if ( GetAdaptersAddresses( family, flags, NULL, pAddresses, &outBufLen ) == ERROR_BUFFER_OVERFLOW )
- {
- pAddresses = static_cast<PIP_ADAPTER_ADDRESSES>( HeapAlloc( GetProcessHeap(), 0, outBufLen ) );
- }
-
- _ASSERT( pAddresses );
- // Make a second call to GetAdapters Addresses to get the
- // actual data we want
- DWORD dwRetVal = GetAdaptersAddresses( family, flags, NULL, pAddresses, &outBufLen );
-
- MACAddresses vAddress;
- if ( dwRetVal != ERROR_SUCCESS )
- {
- return vAddress;
- }
- PIP_ADAPTER_ADDRESSES pFirst = pAddresses;
- while( pAddresses )
- {
- BYTE* pa = pAddresses->PhysicalAddress;
- if ( ! pa || ! pa[ 0 ] )
- {
- break;
- }
- char bAddressBytes[ MACSESION ];
- int bAddressInt [ MACSESION ];
- memset( bAddressBytes, 0, MACSESION );
- size_t nAddressSize = pAddresses->PhysicalAddressLength;
- memcpy( bAddressBytes, pa, ( nAddressSize < MACSESION ? nAddressSize : MACSESION ));
- char CommarSeperatedAddress[ MACSESION * 3 ]={0};
- for( int i = 0; i < MACSESION; ++i )
- {
- bAddressInt[ i ] = bAddressBytes[ i ];
- bAddressInt[ i ] &= 0x000000ff; // avoid "ff" leading bytes when "char" is lager then 0x7f
- }
- sprintf( CommarSeperatedAddress, "%02x:%02x:%02x:%02x:%02x:%02x",
- bAddressInt[ 0 ],
- bAddressInt[ 1 ],
- bAddressInt[ 2 ],
- bAddressInt[ 3 ],
- bAddressInt[ 4 ],
- bAddressInt[ 5 ]); // Should use scl::FormatString inside
- pAddresses = pAddresses->Next ? pAddresses->Next : NULL;
- vAddress.push_back( std::string( CommarSeperatedAddress ) );
- }
- HeapFree( GetProcessHeap(), 0, pFirst );
- return vAddress;
- }
2. 获取硬盘的id, api函数得到的都是和windows安装相关的id,也就是windows硬件管理器分配的id,而不是真正的硬件生产厂商的id. 所以,为了得到真正的和硬盘序列号相关的信息,最好是使用WMI服务查询。
GetPartitionVolumeSerialNumber.cpp
- #include "stdafx.h"
- DWORD GetPartitionVolumeSerialNumber() // Get Disk partition volumn id, not hard disk id
- {
- TCHAR lpRootPathName[]= _T( "\\\\.\\PhysicalDrive0\\" ); // Use physical drive, not C:disk
- TCHAR lpVolumeNameBuffer[ 12 ]; //disk volumn
- DWORD nVolumeNameSize =12;
- DWORD VolumeSerialNumber; // Serial number
- DWORD MaximumComponentLength;
- TCHAR lpFileSystemNameBuffer[ 10 ];
- DWORD nFileSystemNameSize = 10;
- DWORD FileSystemFlags;
- BOOL ret = GetVolumeInformation( lpRootPathName,
- lpVolumeNameBuffer,
- nVolumeNameSize,
- &VolumeSerialNumber,
- &MaximumComponentLength,
- &FileSystemFlags,
- lpFileSystemNameBuffer,
- nFileSystemNameSize);
-
- printf( "Partition serial number is %0xd\n", VolumeSerialNumber );
- if( ret )
- {
- return VolumeSerialNumber;
- }
- else
- {
- return FALSE;
- }
- }
GetPhysicalSerialNumber.cpp
- #include "stdafx.h"
- #include <Iphlpapi.h>
- #pragma comment(lib,"Iphlpapi")
- //#pragma warning( disable : 4996 )
- // IOCTL command constants
- #define DFP_GET_VERSION 0x00074080
- #define DFP_RECEIVE_DRIVE_DATA 0x0007c088
- // values for IDEREGS.bCommandReg
- #define IDE_ATAPI_IDENTIFY 0xA1
- #define IDE_ATA_IDENTIFY 0xEC
- #define IDENTIFY_BUFFER_SIZE 512
-
- //save disk information
- typedef struct _GETVERSIONOUTPARAMS
- {
- BYTE bVersion;
- BYTE bRevision;
- BYTE bReserved;
- BYTE bIDEDeviceMap;
- DWORD fCapabilities;
- DWORD dwReserved[4];
- } GETVERSIONOUTPARAMS, *PGETVERSIONOUTPARAMS, *LPGETVERSIONOUTPARAMS;
- // IDE register information
- typedef struct _IDEREGS
- {
- BYTE bFeaturesReg;
- BYTE bSectorCountReg;
- BYTE bSectorNumberReg;
- BYTE bCylLowReg;
- BYTE bCylHighReg;
- BYTE bDriveHeadReg;
- BYTE bCommandReg;
- BYTE bReserved;
- } IDEREGS, *PIDEREGS, *LPIDEREGS;
- // disk command input parameter
- typedef struct _SENDCMDINPARAMS
- {
- DWORD cBufferSize;
- IDEREGS irDriveRegs;
- BYTE bDriveNumber;
- BYTE bReserved[3];
- DWORD dwReserved[4];
- BYTE bBuffer[1];
- } SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;
- // disk status
- typedef struct _DRIVERSTATUS
- {
- BYTE bDriverError;
- BYTE bIDEStatus;
- BYTE bReserved[2];
- DWORD dwReserved[2];
- } DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS;
- // sent param for disk commands
- typedef struct _SENDCMDOUTPARAMS
- {
- DWORD cBufferSize;
- DRIVERSTATUS DriverStatus;
- BYTE bBuffer[1];
- } SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;
- void GetDiskPhysicalSN(char pchDiskPhysicalSN[14])
- {
- BYTE IdOutCmd[530];
- HANDLE drive=CreateFile(L"\\\\.\\PhysicalDrive0", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
- if ( drive == INVALID_HANDLE_VALUE )
- {
- pchDiskPhysicalSN[ 0 ] = 0;
- return ;
- }
- GETVERSIONOUTPARAMS VersionParams;
- DWORD cbBytesReturned = 0;
- memset( ( void* ) &VersionParams, 0, sizeof( VersionParams ) );
- if ( ! DeviceIoControl( drive, DFP_GET_VERSION, NULL, 0, &VersionParams, sizeof( VersionParams ), &cbBytesReturned, NULL ) )
- {
- pchDiskPhysicalSN[ 0 ] = 0;
- return ;
- }
- if (VersionParams.bIDEDeviceMap<=0)
- {
- pchDiskPhysicalSN[ 0 ] = 0;
- return ;
- }
- BYTE bIDCmd = 0;
- SENDCMDINPARAMS scip;
- bIDCmd = ( VersionParams.bIDEDeviceMap >> 0 & 0x10 ) ? IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
- memset( &scip, 0, sizeof( scip) );
- memset( IdOutCmd, 0, sizeof( IdOutCmd ) );
- scip.cBufferSize = IDENTIFY_BUFFER_SIZE;
- scip.irDriveRegs.bFeaturesReg = 0;
- scip.irDriveRegs.bSectorCountReg = 1;
- scip.irDriveRegs.bSectorNumberReg = 1;
- scip.irDriveRegs.bCylLowReg = 0;
- scip.irDriveRegs.bCylHighReg = 0;
- scip.irDriveRegs.bDriveHeadReg= 0xA0 | ( ( ( BYTE ) drive & 1 ) << 4 );
- scip.irDriveRegs.bCommandReg = bIDCmd;
- scip.bDriveNumber = ( BYTE ) drive;
- scip.cBufferSize = IDENTIFY_BUFFER_SIZE;
- if ( ! DeviceIoControl( drive, DFP_RECEIVE_DRIVE_DATA, &scip, sizeof( SENDCMDINPARAMS)- 1, ( LPVOID )&IdOutCmd, sizeof( SENDCMDOUTPARAMS ) + IDENTIFY_BUFFER_SIZE - 1, &cbBytesReturned, NULL ) )
- {
- pchDiskPhysicalSN[ 0 ] = 0;
- return ;
- }
- USHORT *pIdSector = ( USHORT * )( ( PSENDCMDOUTPARAMS )IdOutCmd )->bBuffer;
- int nPosition = 0;
- for( int nIndex = 13; nIndex < 20; nIndex++ )
- {
- pchDiskPhysicalSN[ nPosition++ ]=( unsigned char )( pIdSector[ nIndex ] / 256 );
- pchDiskPhysicalSN[ nPosition++ ]=( unsigned char )( pIdSector[ nIndex ] % 256 );
- }
- }
-
- void GetDiskPhysicalSerialNumber( char* pchSerialNumber )
- {
- char pchDiskPhysicalSN[ 14 ];
- GetDiskPhysicalSN( pchDiskPhysicalSN );
- int nSerial[ 14 ];
- for( int i = 0 ; i < 14; ++ i )
- {
- nSerial[ i ] = pchDiskPhysicalSN[ i ];
- nSerial[ i ] &= 0x000000ff;
- }
- sprintf( pchSerialNumber, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
- nSerial[ 0 ],
- nSerial[ 1 ],
- nSerial[ 2 ],
- nSerial[ 3 ],
- nSerial[ 4 ],
- nSerial[ 5 ],
- nSerial[ 6 ],
- nSerial[ 7 ],
- nSerial[ 8 ],
- nSerial[ 9 ],
- nSerial[ 10 ],
- nSerial[ 11 ],
- nSerial[ 12 ],
- nSerial[ 13 ]); // Should use scl::FormatString inside
- }
main.cpp
- #include "stdafx.h"
- MACAddresses GetINETMacAddresses();
- MACAddresses GetNetBiosMacAddresses();
- DWORD GetPartitionVolumeSerialNumber();
- void GetDiskPhysicalSerialNumber( char* pchDiskPhysicalSN );
- int main(int argc, char* argv[])
- {
- DWORD VolumeSerialNumber = 0;
- if( ! GetPartitionVolumeSerialNumber() )
- {
- TRACE( "(Get Disk Partition ID met error : %d)\n", GetLastError() );
- }
- else
- {
- printf( "Disk Partition ID = %0xd\n", VolumeSerialNumber );
- }
- char pchSerialNumber[ 50 ];
- GetDiskPhysicalSerialNumber( pchSerialNumber );
- printf("PhysicalSerialNumber is %s\n", pchSerialNumber );
- printf("--------\n");
-
- MACAddresses& vAddresses = GetINETMacAddresses();
- for( vsIt it = vAddresses.begin(); it != vAddresses.end(); ++ it )
- {
- printf( "INET MAC addresses = %s\n", it->c_str() );
- }
- MACAddresses& vAddresses2 = GetNetBiosMacAddresses();
- for( vsIt it = vAddresses2.begin(); it != vAddresses2.end(); ++ it )
- {
- printf( "NetBios MAC addresses = %s\n", it->c_str() );
- }
- return 0;
- }