【原文网址:http://blog.sina.com.cn/s/blog_612b382d0100eezf.html】
网卡的物理地址即mac地址全球唯一,占用六个字节。(正规厂家的网卡mac地址全球唯一,盖因有统一的委员会进行分配,一般前3个字节为生产厂商ID,后三个字节为产品子ID.mac地址一般烧写在网卡的prom中,上电后读入网络协议芯片的mac地址寄存器中。笔者曾开发了一个基于单片机的远程测控系统,采用C8051F120和RTL8019as实现,当然委员会不可能给笔者分配一个mac,哥们便将其定为01-02-03-04-05-06,不想通过sniffer进行调试时发现该mac属于3com公司,一不小心侵了3com的权。由于mac地址会存在地址寄存器中,这就为某些修改mac的软件提供了可乘之机,当然其修改也是暂时的,这是题外话,暂且不表)。一般情况下,获取mac地址生成序列号可以保护我们的软件版权,这也是一帆风颇费周章的目的。
获取mac地址,一可以使用NetBIOS函数,二可使用IP助手函数。一帆风推荐使用后者,因为:Netbios函数得到的MAC经常是不准确的。它依赖于机器上安装网络协议的顺序。比如先装IPX协议再装TCP协议,与先装TCP再装IPX所得到的MAC很有可能不一致。这是因为Netbios函数会得到很多的虚拟MAC地址而不是真正的网卡MAC。
IPCONFIG就是使用IP助手函数来做的。以下是我的做法请参考:
#include "iphlpapi.h"
#pragma comment(lib, "iphlpapi.lib ")
//----------------------------------------------
//功能:获得网卡物理地址
//参数:strMac 返回网卡物理地址
//返回:TRUE 成功
// FALSE 失败
//----------------------------------------------
BOOL CCApp::GetMacAddress(CString &strMac)
{
PIP_ADAPTER_INFO pAdapterInfo;
DWORD AdapterInfoSize;
TCHAR szMac[32] = {0};
DWORD Err;
AdapterInfoSize = 0;
Err = GetAdaptersInfo(NULL, &AdapterInfoSize);
if((Err != 0) && (Err != ERROR_BUFFER_OVERFLOW)){
TRACE("获得网卡信息失败!");
return FALSE;
}
// 分配网卡信息内存
pAdapterInfo = (PIP_ADAPTER_INFO) GlobalAlloc(GPTR, AdapterInfoSize);
if(pAdapterInfo == NULL){
TRACE("分配网卡信息内存失败");
return FALSE;
}
if(GetAdaptersInfo(pAdapterInfo, &AdapterInfoSize) != 0){
TRACE(_T("获得网卡信息失败!\n"));
GlobalFree(pAdapterInfo);
return FALSE;
}
strMac.Format(_T("%02X%02X%02X%02X%02X%02X"),
pAdapterInfo->Address[0],
pAdapterInfo->Address[1],
pAdapterInfo->Address[2],
pAdapterInfo->Address[3],
pAdapterInfo->Address[4],
pAdapterInfo->Address[5]);
GlobalFree(pAdapterInfo);
return TRUE;
}
应注意以下几点:
1。iphlpapi.h和iphlpapi.lib在VC中不包含,在sdk中有,应下载sdk,并在vc路径中包含sdk的include和lib目录;
2。应将include和lib放在vc包含路径中的第一个。
该函数在VC6+sdk平台下开发,在WinXP sp2 +联想T61平台下测试通过。