用windows api获取mac地址和硬盘id编号

1. 获取机器的MAC地址真的有很多种方法。可以通过windows api,可以通过wmi服务等。MSDN上面的例子是使用IP helper函数GetAdaptersInfo。其实还有一个api,是GetAdaptersAddresses。NetBios和DDK的方法不推荐使用,低于api层次的调用不保证微软会淘汰掉。建立一个支持MFC的控制台程序:
stdafx.h
  1. #include <vector>
  2. #include <string>
  3. typedef std::vector< std::string > MACAddresses;
  4. typedef MACAddresses::iterator vsIt;
GetNetBiosMacAddresses.cpp
  1. #include "stdafx.h" 
  2. #include <windows.h> 
  3. #include <wincon.h> 
  4. #include <stdio.h> 
  5. #include <nb30.h> 
  6. // Netbios is not supported on Windows Vista, Windows Server 2008, and subsequent versions of the operating system]l
  7. // For using NetAPI to get MAC, should include nb30.h
  8. #define MACSESION 6
  9. #pragma warning( disable : 4996 )
  10. #pragma comment(lib,"Netapi32.lib")
  11. typedef struct _ASTAT_ 
  12. { 
  13.     ADAPTER_STATUS adapt; 
  14.     NAME_BUFFER NameBuff [30]; 
  15. }ASTAT, * PASTAT; 
  16.   
  17. ASTAT Adapter; // to store MAC information 
  18. // input parameter: lana_num start from 0, but in windows, not continuously allocated, so not reliable.
  19. std::string getmac_one( int lana_num )
  20. { 
  21.     NCB ncb; 
  22.     UCHAR uRetCode; 
  23.   
  24.     memset( &ncb, 0, sizeof( ncb ) ); 
  25.     ncb.ncb_command = NCBRESET; 
  26.     ncb.ncb_lana_num = lana_num; 
  27.     
  28.     uRetCode = Netbios( &ncb ); 
  29.     //printf( "The NCBRESET return code is:0x%x \n", uRetCode ); 
  30.   
  31.     memset( &ncb, 0, sizeof( ncb ) ); 
  32.     ncb.ncb_command = NCBASTAT; 
  33.     ncb.ncb_lana_num = lana_num; 
  34.   
  35.     strcpy( (char *)ncb.ncb_callname, "* " ); 
  36.     ncb.ncb_buffer = ( unsigned char * ) &Adapter; 
  37.   
  38.     ncb.ncb_length = sizeof( Adapter ); 
  39.     uRetCode = Netbios( &ncb ); 
  40.     // printf( "The NCBASTAT return code is: 0x%x \n", uRetCode );
  41.     std::string s;
  42.     if ( uRetCode == 0 ) 
  43.     {
  44.         int bAddressInt [ MACSESION ];
  45.         char CommarSeperatedAddress[ MACSESION * 3 ]={0};
  46.         for( int i = 0; i < MACSESION; ++i )
  47.         {
  48.             bAddressInt[ i ] = Adapter.adapt.adapter_address[ i ];
  49.             bAddressInt[ i ] &= 0x000000ff; // avoid "ff" leading bytes when "char" is lager then 0x7f
  50.         }
  51.         sprintf( CommarSeperatedAddress, "%02x:%02x:%02x:%02x:%02x:%02x",
  52.                                bAddressInt[ 0 ],
  53.                                bAddressInt[ 1 ],
  54.                                bAddressInt[ 2 ],
  55.                                bAddressInt[ 3 ],
  56.                                bAddressInt[ 4 ],
  57.                                bAddressInt[ 5 ]); // Should use scl::FormatString inside 
  58.         s = CommarSeperatedAddress;
  59.     }
  60.     return s;
  61. }

  62. MACAddresses GetNetBiosMacAddresses()
  63. {
  64.     NCB ncb; 
  65.     UCHAR uRetCode; 
  66.     LANA_ENUM lana_enum; 
  67.     memset( &ncb, 0, sizeof( ncb ) ); 
  68.     ncb.ncb_command = NCBENUM; 
  69.   
  70.     ncb.ncb_buffer = (unsigned char *) &lana_enum; 
  71.     ncb.ncb_length = sizeof( lana_enum ); 
  72.   
  73.     uRetCode = Netbios( &ncb ); 
  74.     //printf( "The NCBENUM return code is:0x%x \n", uRetCode );
  75.     MACAddresses vAdd;
  76.     if ( uRetCode == 0 ) 
  77.     { 
  78.         //printf( "Ethernet Count is : %d\n\n", lana_enum.length); 
  79.         for ( int i=0; i < lana_enum.length; ++i )
  80.         {
  81.             std::string s = getmac_one( lana_enum.lana[i] ); 
  82.             if( ! s.empty() )
  83.             {
  84.                 vAdd.push_back( s );
  85.             }
  86.         }
  87.     }
  88.     return vAdd;
  89. }
GetMacAddresses.cpp
  1. #include "stdafx.h"
  2. #include <Winsock2.h>
  3. #include <Iphlpapi.h>
  4. #pragma comment(lib,"Iphlpapi")
  5. #pragma warning( disable : 4996 )
  6. #define MACSESION 6
  7. MACAddresses GetINETMacAddresses()
  8. {
  9.     PIP_ADAPTER_ADDRESSES pAddresses = NULL;
  10.     ULONG family = AF_INET;
  11.     ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
  12.     ULONG outBufLen = sizeof( IP_ADAPTER_ADDRESSES );

  13.     // Make an initial call to GetAdaptersAddresses to get the 
  14.     // size needed into the outBufLen variable
  15.     if ( GetAdaptersAddresses( family, flags, NULL, pAddresses, &outBufLen ) == ERROR_BUFFER_OVERFLOW )
  16.     {
  17.         pAddresses = static_cast<PIP_ADAPTER_ADDRESSES>( HeapAlloc( GetProcessHeap(), 0, outBufLen ) );
  18.     }

  19.     _ASSERT( pAddresses );
  20.     // Make a second call to GetAdapters Addresses to get the
  21.     // actual data we want
  22.     DWORD dwRetVal = GetAdaptersAddresses( family, flags, NULL, pAddresses, &outBufLen );

  23.     MACAddresses vAddress;
  24.     if ( dwRetVal != ERROR_SUCCESS )
  25.     {
  26.         return vAddress;
  27.     }
  28.     PIP_ADAPTER_ADDRESSES pFirst = pAddresses;
  29.     while( pAddresses )
  30.     {
  31.         BYTE* pa = pAddresses->PhysicalAddress;
  32.         if ( ! pa || ! pa[ 0 ] )
  33.         {
  34.             break;
  35.         }
  36.         char bAddressBytes[ MACSESION ];
  37.         int bAddressInt [ MACSESION ];
  38.         memset( bAddressBytes, 0, MACSESION );
  39.         size_t nAddressSize = pAddresses->PhysicalAddressLength;
  40.         memcpy( bAddressBytes, pa, ( nAddressSize < MACSESION ? nAddressSize : MACSESION ));
  41.         char CommarSeperatedAddress[ MACSESION * 3 ]={0};
  42.         for( int i = 0; i < MACSESION; ++i )
  43.         {
  44.             bAddressInt[ i ] = bAddressBytes[ i ];
  45.             bAddressInt[ i ] &= 0x000000ff; // avoid "ff" leading bytes when "char" is lager then 0x7f
  46.         }
  47.         sprintf( CommarSeperatedAddress, "%02x:%02x:%02x:%02x:%02x:%02x",
  48.                                bAddressInt[ 0 ],
  49.                                bAddressInt[ 1 ],
  50.                                bAddressInt[ 2 ],
  51.                                bAddressInt[ 3 ],
  52.                                bAddressInt[ 4 ],
  53.                                bAddressInt[ 5 ]); // Should use scl::FormatString inside 
  54.         pAddresses = pAddresses->Next ? pAddresses->Next : NULL;
  55.         vAddress.push_back( std::string( CommarSeperatedAddress ) );
  56.     }
  57.     HeapFree( GetProcessHeap(), 0, pFirst );
  58.     return vAddress;
  59. }
2. 获取硬盘的id, api函数得到的都是和windows安装相关的id,也就是windows硬件管理器分配的id,而不是真正的硬件生产厂商的id. 所以,为了得到真正的和硬盘序列号相关的信息,最好是使用WMI服务查询。
GetPartitionVolumeSerialNumber.cpp
  1. #include "stdafx.h"
  2. DWORD GetPartitionVolumeSerialNumber() // Get Disk partition volumn id, not hard disk id
  3. {
  4.     TCHAR lpRootPathName[]= _T( "\\\\.\\PhysicalDrive0\\" ); // Use physical drive, not C:disk
  5.     TCHAR lpVolumeNameBuffer[ 12 ]; //disk volumn
  6.     DWORD nVolumeNameSize =12; 
  7.     DWORD VolumeSerialNumber; // Serial number
  8.     DWORD MaximumComponentLength; 
  9.     TCHAR lpFileSystemNameBuffer[ 10 ]; 
  10.     DWORD nFileSystemNameSize = 10; 
  11.     DWORD FileSystemFlags; 
  12.     BOOL ret = GetVolumeInformation( lpRootPathName, 
  13.                                      lpVolumeNameBuffer,
  14.                                      nVolumeNameSize, 
  15.                                      &VolumeSerialNumber,
  16.                                      &MaximumComponentLength, 
  17.                                      &FileSystemFlags, 
  18.                                      lpFileSystemNameBuffer,
  19.                                      nFileSystemNameSize); 

  20.     printf( "Partition serial number is %0xd\n", VolumeSerialNumber );
  21.     if( ret )
  22.     {
  23.         return VolumeSerialNumber;
  24.     }
  25.     else
  26.     {
  27.         return FALSE;
  28.     }
  29. }
GetPhysicalSerialNumber.cpp
  1. #include "stdafx.h"
  2. #include <Iphlpapi.h>
  3. #pragma comment(lib,"Iphlpapi")
  4. //#pragma warning( disable : 4996 )
  5. // IOCTL command constants
  6. #define DFP_GET_VERSION 0x00074080
  7. #define DFP_RECEIVE_DRIVE_DATA 0x0007c088
  8. // values for IDEREGS.bCommandReg
  9. #define IDE_ATAPI_IDENTIFY 0xA1
  10. #define IDE_ATA_IDENTIFY 0xEC
  11. #define IDENTIFY_BUFFER_SIZE 512

  12. //save disk information
  13. typedef struct _GETVERSIONOUTPARAMS
  14. {
  15.     BYTE bVersion;
  16.     BYTE bRevision;
  17.     BYTE bReserved;
  18.     BYTE bIDEDeviceMap;
  19.     DWORD fCapabilities;
  20.     DWORD dwReserved[4];
  21. } GETVERSIONOUTPARAMS, *PGETVERSIONOUTPARAMS, *LPGETVERSIONOUTPARAMS;
  22. // IDE register information
  23. typedef struct _IDEREGS
  24. {
  25.     BYTE bFeaturesReg;
  26.     BYTE bSectorCountReg;
  27.     BYTE bSectorNumberReg;
  28.     BYTE bCylLowReg;
  29.     BYTE bCylHighReg;
  30.     BYTE bDriveHeadReg;
  31.     BYTE bCommandReg;
  32.     BYTE bReserved;
  33. } IDEREGS, *PIDEREGS, *LPIDEREGS;
  34. // disk command input parameter
  35. typedef struct _SENDCMDINPARAMS
  36. {
  37.     DWORD cBufferSize;
  38.     IDEREGS irDriveRegs;
  39.     BYTE bDriveNumber;
  40.     BYTE bReserved[3];
  41.     DWORD dwReserved[4];
  42.     BYTE bBuffer[1];
  43. } SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS;
  44. // disk status
  45. typedef struct _DRIVERSTATUS
  46. {
  47.     BYTE bDriverError;
  48.     BYTE bIDEStatus;
  49.     BYTE bReserved[2];
  50.     DWORD dwReserved[2];
  51. } DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS;
  52. // sent param for disk commands
  53. typedef struct _SENDCMDOUTPARAMS
  54. {
  55.     DWORD cBufferSize;
  56.     DRIVERSTATUS DriverStatus;
  57.     BYTE bBuffer[1];
  58. } SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS;
  59. void GetDiskPhysicalSN(char pchDiskPhysicalSN[14])
  60. {
  61.     BYTE IdOutCmd[530];
  62.     HANDLE drive=CreateFile(L"\\\\.\\PhysicalDrive0", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
  63.     if ( drive == INVALID_HANDLE_VALUE )
  64.     {
  65.         pchDiskPhysicalSN[ 0 ] = 0;
  66.         return ;
  67.     }
  68.     GETVERSIONOUTPARAMS VersionParams;
  69.     DWORD cbBytesReturned = 0;
  70.     memset( ( void* ) &VersionParams, 0, sizeof( VersionParams ) );
  71.     if ( ! DeviceIoControl( drive, DFP_GET_VERSION, NULL, 0, &VersionParams, sizeof( VersionParams ), &cbBytesReturned, NULL ) )
  72.     {
  73.         pchDiskPhysicalSN[ 0 ] = 0;
  74.         return ;
  75.     }
  76.     if (VersionParams.bIDEDeviceMap<=0)
  77.     {
  78.         pchDiskPhysicalSN[ 0 ] = 0;
  79.         return ;
  80.     }
  81.     BYTE bIDCmd = 0;
  82.     SENDCMDINPARAMS scip;
  83.     bIDCmd = ( VersionParams.bIDEDeviceMap >> 0 & 0x10 ) ? IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
  84.     memset( &scip, 0, sizeof( scip) );
  85.     memset( IdOutCmd, 0, sizeof( IdOutCmd ) );
  86.     scip.cBufferSize = IDENTIFY_BUFFER_SIZE;
  87.     scip.irDriveRegs.bFeaturesReg = 0;
  88.     scip.irDriveRegs.bSectorCountReg = 1;
  89.     scip.irDriveRegs.bSectorNumberReg = 1;
  90.     scip.irDriveRegs.bCylLowReg = 0;
  91.     scip.irDriveRegs.bCylHighReg = 0;
  92.     scip.irDriveRegs.bDriveHeadReg= 0xA0 | ( ( ( BYTE ) drive & 1 ) << 4 );
  93.     scip.irDriveRegs.bCommandReg = bIDCmd;
  94.     scip.bDriveNumber = ( BYTE ) drive;
  95.     scip.cBufferSize = IDENTIFY_BUFFER_SIZE;
  96.     if ( ! DeviceIoControl( drive, DFP_RECEIVE_DRIVE_DATA, &scip, sizeof( SENDCMDINPARAMS)- 1, ( LPVOID )&IdOutCmd, sizeof( SENDCMDOUTPARAMS ) + IDENTIFY_BUFFER_SIZE - 1, &cbBytesReturned, NULL ) )
  97.     {
  98.         pchDiskPhysicalSN[ 0 ] = 0;
  99.         return ;
  100.     }
  101.     USHORT *pIdSector = ( USHORT * )( ( PSENDCMDOUTPARAMS )IdOutCmd )->bBuffer;
  102.     int nPosition = 0;
  103.     for( int nIndex = 13; nIndex < 20; nIndex++ )
  104.     {
  105.         pchDiskPhysicalSN[ nPosition++ ]=( unsigned char )( pIdSector[ nIndex ] / 256 );
  106.         pchDiskPhysicalSN[ nPosition++ ]=( unsigned char )( pIdSector[ nIndex ] % 256 );
  107.     }
  108. }

  109. void GetDiskPhysicalSerialNumber( char* pchSerialNumber )
  110. {
  111.     char pchDiskPhysicalSN[ 14 ];
  112.     GetDiskPhysicalSN( pchDiskPhysicalSN );
  113.     int nSerial[ 14 ];
  114.     for( int i = 0 ; i < 14; ++ i )
  115.     {
  116.         nSerial[ i ] = pchDiskPhysicalSN[ i ];
  117.         nSerial[ i ] &= 0x000000ff;
  118.     }
  119.     sprintf( pchSerialNumber, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
  120.                                nSerial[ 0 ],
  121.                                nSerial[ 1 ],
  122.                                nSerial[ 2 ],
  123.                                nSerial[ 3 ],
  124.                                nSerial[ 4 ],
  125.                                nSerial[ 5 ],
  126.                                nSerial[ 6 ],
  127.                                nSerial[ 7 ],
  128.                                nSerial[ 8 ],
  129.                                nSerial[ 9 ],
  130.                                nSerial[ 10 ],
  131.                                nSerial[ 11 ],
  132.                                nSerial[ 12 ],
  133.                                nSerial[ 13 ]); // Should use scl::FormatString inside 
  134. }
main.cpp
  1. #include "stdafx.h" 
  2. MACAddresses GetINETMacAddresses();
  3. MACAddresses GetNetBiosMacAddresses();
  4. DWORD GetPartitionVolumeSerialNumber();
  5. void GetDiskPhysicalSerialNumber( char* pchDiskPhysicalSN );
  6. int main(int argc, char* argv[]) 
  7. {
  8.     DWORD VolumeSerialNumber = 0;
  9.     if( ! GetPartitionVolumeSerialNumber() )
  10.     {
  11.         TRACE( "(Get Disk Partition ID met error : %d)\n", GetLastError() );
  12.     }
  13.     else
  14.     {
  15.         printf( "Disk Partition ID = %0xd\n", VolumeSerialNumber );
  16.     }
  17.     char pchSerialNumber[ 50 ];
  18.     GetDiskPhysicalSerialNumber( pchSerialNumber );
  19.     printf("PhysicalSerialNumber is %s\n", pchSerialNumber );
  20.     printf("--------\n");

  21.     MACAddresses& vAddresses = GetINETMacAddresses();
  22.     for( vsIt it = vAddresses.begin(); it != vAddresses.end(); ++ it )
  23.     {
  24.         printf( "INET MAC addresses = %s\n", it->c_str() );
  25.     }
  26.     MACAddresses& vAddresses2 = GetNetBiosMacAddresses();
  27.     for( vsIt it = vAddresses2.begin(); it != vAddresses2.end(); ++ it )
  28.     {
  29.         printf( "NetBios MAC addresses = %s\n", it->c_str() );
  30.     }
  31.     return 0; 
  32. }

你可能感兴趣的:(C++11)