1.NDIS(DDK)通過驅動程式擷取MAC地址
ndis規範中說明,網路卡驅動程式支援ioctl_ndis_query_stats介面
參數如下:
OID_802_3_PERMANENT_ADDRESS :物理地址
OID_802_3_CURRENT_ADDRESS :mac地址
於是我們的方法就得到了。
首先,看看註冊表,找一找網卡有幾塊,分別是什麼裝置名稱。
具體位置和os有關,2000下在hlm/software/microsoft/windows nt/current version/networkcards。
然後createfile(devicename,...)注意,要用linkname,因此
還要加上"////.//device//".
接著
deviceiocontrol(hmac,IOCTL_NDIS_QUERY_STATS,
OID_802_3_PERMANENT_ADDRESS/OID_802_3_CURRENT_ADDRESS...)
具體的情況可以參看ddk下的
OID_802_3_CURRENT_ADDRESS條目
2.NetAPI-2得到MAC (MSDN推薦方法)
#include <windows.h>
//#include <wincon.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
typedef struct _ASTAT_
{
ADAPTER_STATUS adapt;
NAME_BUFFER NameBuff [30];
}ASTAT, * PASTAT;
ASTAT Adapter;
int main (void)
{
NCB Ncb;
UCHAR uRetCode;
char NetName[50];
LANA_ENUM lenum;
int i;
memset( &Ncb, 0, sizeof(Ncb) );
Ncb.ncb_command = NCBENUM;
Ncb.ncb_buffer = (UCHAR *)&lenum;
Ncb.ncb_length = sizeof(lenum);
uRetCode = Netbios( &Ncb );
printf( "The NCBENUM return code is: 0x%x /n", uRetCode );
for(i=0; i < lenum.length ;i++)
{
memset( &Ncb, 0, sizeof(Ncb) );
Ncb.ncb_command = NCBRESET;
Ncb.ncb_lana_num = lenum.lana;
uRetCode = Netbios( &Ncb );
printf( "The NCBRESET on LANA %d return code is: 0x%x /n",
lenum.lana, uRetCode );
memset( &Ncb, 0, sizeof (Ncb) );
Ncb.ncb_command = NCBASTAT;
Ncb.ncb_lana_num = lenum.lana;
strcpy( Ncb.ncb_callname, "* " );
Ncb.ncb_buffer = (char *) &Adapter;
Ncb.ncb_length = sizeof(Adapter);
uRetCode = Netbios( &Ncb );
printf( "The NCBASTAT on LANA %d return code is: 0x%x /n",
lenum.lana, uRetCode );
if ( uRetCode == 0 )
{
printf( "The Ethernet Number on LANA %d is:%02x%02x%02x%02x%02x%02x/n",
lenum.lana,
Adapter.adapt.adapter_address[0],
Adapter.adapt.adapter_address[1],
Adapter.adapt.adapter_address[2],
Adapter.adapt.adapter_address[3],
Adapter.adapt.adapter_address[4],
Adapter.adapt.adapter_address[5] );
}
}
}
3.用COM API擷取網卡MAC地址
這種方法使用COM API建立一個GUID(通用唯一識別碼)並從那裡繼承MAC地址。
GUID通常用來標識COM組件以及系統中的其他對象。它們是由MAC地址(結合其他東西)計算得來的,表面上MAC地址就包含在其中。
我說表面上是因為事實上並沒有包含。我提供這種方法更多的是為了作為反面教材。您也許用這種方法能夠得到MAC地址,但
有時候您只會得到隨機的十六進位數值。下面的例子十分簡單,無需多講。我們使用CoCreateGuid建立GUID,並將最後六個位元組
放入字串中。它們可能是MAC地址,但並不是必然的。
uuid.cpp
#include <windows.h>
#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
cout << "MAC address is: ";
// 向COM要求一個UUID。如果機器中有乙太網路卡,
// UUID最後的六個位元組(Data4的2-7位元組)應該是本地乙太網路卡的MAC地址。
GUID uuid;
CoCreateGuid(&uuid);
// Spit the address out
char mac_addr[18];
sprintf(mac_addr,"%02X:%02X:%02X:%02X:%02X:%02X",
uuid.Data4[2],uuid.Data4[3],uuid.Data4[4],
uuid.Data4[5],uuid.Data4[6],uuid.Data4[7]);
cout << mac_addr << endl;
getch();
return 0;
}
4.用NetAPI來擷取網卡MAC地址
首先在標頭檔定義中加入#include "nb30.h"
#pragma comment(lib,"netapi32.lib")
typedef struct _ASTAT_
{
ADAPTER_STATUS adapt;
NAME_BUFFER NameBuff[30];
} ASTAT, * PASTAT;
就可以這樣調用來擷取遠程網卡MAC地址了:
CString GetMacAddress(CString sNetBiosName)
{
ASTAT Adapter;
NCB ncb;
UCHAR uRetCode;
memset(&ncb, 0, sizeof(ncb));
ncb.ncb_command = NCBRESET;
ncb.ncb_lana_num = 0;
uRetCode = Netbios(&ncb);
memset(&ncb, 0, sizeof(ncb));
ncb.ncb_command = NCBASTAT;
ncb.ncb_lana_num = 0;
sNetBiosName.MakeUpper();
FillMemory(ncb.ncb_callname, NCBNAMSZ - 1, 0x20);
strcpy((char *)ncb.ncb_callname, (LPCTSTR) sNetBiosName);
ncb.ncb_callname[sNetBiosName.GetLength()] = 0x20;
ncb.ncb_callname[NCBNAMSZ] = 0x0;
ncb.ncb_buffer = (unsigned char *) &Adapter;
ncb.ncb_length = sizeof(Adapter);
uRetCode = Netbios(&ncb);
CString sMacAddress;
if (uRetCode == 0)
{
sMacAddress.Format(_T("%02x%02x%02x%02x%02x%02x"),
Adapter.adapt.adapter_address[0],
Adapter.adapt.adapter_address[1],
Adapter.adapt.adapter_address[2],
Adapter.adapt.adapter_address[3],
Adapter.adapt.adapter_address[4],
Adapter.adapt.adapter_address[5]);
}
return sMacAddress;
}