转载:在VC下获取原始MAC地址

转自:http://blog.csdn.net/uncledou/article/details/8693462

在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;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值