在VC下获取原始MAC地址

来源:互联网 发布:java swap docker 编辑:程序博客网 时间:2024/05/16 06:27

    在VC下获取原始MAC地址


    许多Windows的操作系统都支持修改MAC地址的功能,因此当用户修改了MAC地址之后,在DOS窗口下使用ipconfig /all命令和getmac /v命令得到的网卡地址信息都是经用户修改过的。修改MAC地址的方法可以在网上查找,这里主要讲述如何通过对驱动程序的操作来获取原始的MAC地址。
    本文参考Splash的博文,链接为:http://blog.csdn.net/jhqin/article/details/5618667


基本实现思路如下:
1、通过网卡接口类GUID获取物理网卡的设备路径名。
2、通过设备路径名,用CreateFile获取设备句柄。
3、通过设备句柄,用DeviceIoControl与驱动程序进行通信,获取网卡的原始MAC地址和当前MAC地址。


具体代码:

#include <windows.h>#include <stdio.h>#include <setupapi.h>#pragma comment (lib,"Setupapi.lib")#define MACADDRESS_BYTELEN      6   // MAC地址字节长度  #define OID_802_3_PERMANENT_ADDRESS 0x01010101  //The address of the NIC encoded in the hardware.//#define OID_802_3_CURRENT_ADDRESS 0x01010102  //The address the NIC is currently using./* An application can use IOCTL_NDIS_QUERY_GLOBAL_STATS to obtain information from a network adapter. * The application passes IOCTL_NDIS_QUERY_GLOBAL_STATS, along with an Object Identifier(OID), * in the DeviceIoControl() function.*/#define IOCTL_NDIS_QUERY_GLOBAL_STATS 0x00170002// 初始化网卡原始MAC地址的GUID结构GUID GUID_DEVCLASS_QUERY={0xAD498944, 0x762F, 0x11D0, 0x8D, 0xCB, 0x00, 0xC0, 0x4F, 0xC3, 0x35, 0x8C};static BOOL GetMacAddress(){HDEVINFO hDevInfo;DWORD MemberIndex,RequiredSize;SP_DEVICE_INTERFACE_DATA            DeviceInterfaceData;    PSP_DEVICE_INTERFACE_DETAIL_DATA    DeviceInterfaceDetailData;BOOL isOK=FALSE;// 获取设备信息集hDevInfo = SetupDiGetClassDevs( &GUID_DEVCLASS_QUERY, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE );if( INVALID_HANDLE_VALUE == hDevInfo )      {          return FALSE;      }//  枚举设备信息集中所有设备DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); /*台式机一般只有以太网卡,的以用"MemberIndex < 1"条件循环一次得到的便是以太网卡的地址,  而对笔记本来说,使用条件"MemberIndex < 2"可以得到两条信息,第一条信息是以太网卡的地址,  第二条信息是无线网卡的地址,可以设置参数来实现打印相应的网卡地址*/    for( MemberIndex = 0; MemberIndex < 1; MemberIndex++ )      {   // 获取设备接口          if( !SetupDiEnumDeviceInterfaces( hDevInfo, NULL, &GUID_DEVCLASS_QUERY, MemberIndex, &DeviceInterfaceData ) )          {   // 所有设备枚举完毕则进入此条语句,可以自行设置相应操作              break;          }            // 获取接收缓冲区大小,函数返回值为FALSE,GetLastError()=ERROR_INSUFFICIENT_BUFFER          SetupDiGetDeviceInterfaceDetail( hDevInfo, &DeviceInterfaceData, NULL, 0, &RequiredSize, NULL );                   // 申请接收缓冲区          DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc( RequiredSize );          DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);            // 获取设备细节信息          if( SetupDiGetDeviceInterfaceDetail( hDevInfo, &DeviceInterfaceData,  DeviceInterfaceDetailData, RequiredSize, NULL, NULL ) )          {      HANDLE hDeviceFile;// 获取设备句柄  hDeviceFile = CreateFile( DeviceInterfaceDetailData->DevicePath,  0,  FILE_SHARE_READ | FILE_SHARE_WRITE,  NULL,  OPEN_EXISTING,  0,  NULL);    if( hDeviceFile != INVALID_HANDLE_VALUE )  {     ULONG   dwID;  BYTE    ucData[MACADDRESS_BYTELEN];  DWORD   dwByteRet; // 获取原生MAC地址  dwID = OID_802_3_PERMANENT_ADDRESS;  isOK = DeviceIoControl( hDeviceFile, IOCTL_NDIS_QUERY_GLOBAL_STATS, &dwID, sizeof(dwID), ucData, sizeof(ucData), &dwByteRet, NULL );  if( isOK ){printf("%02X-%02X-%02X-%02X-%02X-%02X\n",        ucData[0],ucData[1],ucData[2],        ucData[3],ucData[4],ucData[5]);} // if( isOK )} // if( hDeviceFile != INVALID_HANDLE_VALUE )        } // if( SetupDiGetDeviceInterfaceDetail() )  free( DeviceInterfaceDetailData );      } // for( )      SetupDiDestroyDeviceInfoList( hDevInfo );  return TRUE;} int main(){BOOL ret;ret=GetMacAddress();printf("%d\n",ret);return 0;}