Take three ways to obtain the network card MAC address in the system
Do a good job, as a person. I don't want to have a stone of the mountain to attack jade, but never be a slave. Cker Original: borland Translation: cker
Translated by cker
The first method uses Microsoft's NetBIOS API. This is a set of commands that provide underlying networks through Winsock. The biggest disadvantage using NetBIOS is that you must have a NetBIOS service in your system (if you enable file sharing in your Windows network, this is not a problem). In addition, this method is fast and accurate.
The NetBIOS API only includes a function, just called NetBIOS. This function uses the Network Control Block structure as a parameter, which tells the function to do. Definition structure follows: typedef struct _NCB {UCHAR ncb_command; UCHAR ncb_retcode; UCHAR ncb_lsn; UCHAR ncb_num; PUCHAR ncb_buffer; WORD ncb_length; UCHAR ncb_callname [NCBNAMSZ]; UCHAR ncb_name [NCBNAMSZ]; UCHAR ncb_rto; UCHAR ncb_sto; void (CALLBACK * ncb_post (struct _ncb *); uchar ncb_lana_num; uchar ncb_cmd_cplt; #ifdef _win64 uchar ncb_reserve [18]; #ELSE UCHAR NCB_RESERVE [10]; #ENDIF HANDLE NCB_EVENT;} NCB, * PNCB;
The focus is on NCB_COMMAND members. This member tells NetBIOS what should I do. We use three commands to detect the MAC address. They are defined in MSDN as follows: Command Description: NcBenum Windows NT / 2000: Enumerally listing the number of network cards in the system. After using this command, the NCB_BUFFER member points to the buffer filled by the LANA_ENUM structure. Ncbenum is not a standard NetBIOS 3.0 command.
Ncbreset reset the network card. The NIC must reset before accepting the new NCB command. NCBastat accepts the status of the local or remote interface card. After using this command, the NCB_Buffer member points to the buffer filled by the Adapter_status structure, followed by an array of Name_Buffer structures.
Here is to get the steps of your system MAC address: 1 "list all interface cards. 2 "Reset each card to obtain its correct information. 3 "Query the interface card, get the MAC address and generate a standard colonial separation format.
Here is an example source program. Netbios.cpp
#include
Using namespace std; #define Bzero (Thing, SZ) MEMSET (Thing, 0, SZ)
bool GetAdapterInfo (int adapter_num, string & mac_addr) {// resets the card, so that we can query NCB Ncb; memset (& Ncb, 0, sizeof (Ncb)); Ncb.ncb_command = NCBRESET; Ncb.ncb_lana_num = adapter_num; if (Netbios (& NCB)! = Nrc_goodret) {mac_addr = ""; mac_addr = string (ncb.ncb_retcode); Return False;} // Prepare the status block Bzero (& NCB, SIZEOF (NCB); Ncb.ncb_command = NCBASTAT; Ncb.ncb_lana_num = adapter_num; strcpy ((char *) Ncb.ncb_callname, "*"); struct ASTAT {ADAPTER_STATUS adapt; NAME_BUFFER NameBuff [30];} Adapter; bzero (& Adapter, sizeof (Adapter) ); Ncb.ncb_buffer = (unsigned char *) & adapter; ncb.ncb_length = sizeof (adapter);
// Get information on the network card, and if the network card is working properly, return to the standard colonial separation format. IF (NetBIOS (& NCB) == 0) {Char Acmac [18]; Sprintf (acmac, "% 02x:% 02x:% 02x:% 02x:% 02x:% 02x", int (adapter.adapt.adapter_address [0 ]), Int (adapter.adapt.adapter_address [1]), int (adapter.adapt.adapter_address [2]), int (adapter.adapt.adapter_address [3]), int (adapter.adapt.adapter_address [4]) , Int (adapter.adapt.adapter_address [5])); mac_addr = acmac; return true;} else {mac_addr = ") (ncbastat):"; mac_addr = string (ncb.ncb_retcode); returnaf false;}}}
int main () {// acquired card list LANA_ENUM AdapterList; NCB Ncb; memset (& Ncb, 0, sizeof (NCB)); Ncb.ncb_command = NCBENUM; Ncb.ncb_buffer = (unsigned char *) & AdapterList; Ncb.ncb_length = sizeof AdapterList); NetBIOS (& NCB);
/ / Take the address of the local Ethernet card string mac_addr; for (int i = 0; i File: // ---------------------------------------------- ----------------------------- The second method - uses the COM GUID API to create a GUID (globally unique identifier) and inherit the MAC address from there. GUID is usually used to identify COM components and other objects in the system. They are calculated from the MAC address (combined with other things), and the MAC address on the surface is included there. I said that the surface is because it doesn't contain it. I provide this approach to more than a brock. You may use this method to get the MAC address, but sometimes you only get a random hexadecimal value. The following example is very simple, there is no need to talk more. We use CocreateGuid to create a GUID and place the last six bytes in a string. They may be a MAC address, but it is not necessarily. UUID.cpp # include Using namespace std; INT main () {cout << "Mac Address IS:"; / / A UUID to COM. If there is an Ethernet card in the machine, // uuid's last six bytes (2-7 bytes of DATA4) should be the MAC address of the local Ethernet card. Guid uuid; cocreateguid; // 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 } Third Method - The third method I want to discuss using the SNMP extended API is to use Windows SNMP (Simple Network Management Protocol) to get the MAC address. In my experience, this agreement is simple. The code is also forwarded. Basic steps and NetBIOS: 1 "Net Card List 2" Query the Type of Each Card and MAC Address 3 "Save the current network card, I personally know much about SNMP, but I just said that the code is very clear. snmp.cpp # include typedef bool (WINAPI * pSnmpExtensionTrap) (OUT AsnObjectIdentifier * enterprise, OUT AsnInteger * genericTrap, OUT AsnInteger * specificTrap, OUT AsnTimeticks * timeStamp, OUT RFC1157VarBindList * variableBindings); Typeryf Bool (WinAPI * PsnmpextensionQuery) (in out RFC1157VARBINDLIST * VARIABIABINDINGS, OUT Asninteger * ErrorStatus, Out AsnIndeger * Errorindex); Typedef Bool (WinAPI * PsnmpextensionInitex) (Out AsnObjectIdentifier * SupportedView); void main () {HINSTANCE m_hInst; pSnmpExtensionInit m_Init; pSnmpExtensionInitEx m_InitEx; pSnmpExtensionQuery m_Query; pSnmpExtensionTrap m_Trap; HANDLE PollForTrapEvent; AsnObjectIdentifier SupportedView; UINT OID_ifEntryType [] = {1, 3, 6, 1, 2, 1, 2, 2, 1, 3}; uint oid_ifentrynum [] = {1, 3, 6, 1, 2, 1, 2, 1}; uint oid_ipmacentaddr [] = {1, 3, 6, 1, 2, 1, 2, 2, 1, 6}; AsnObjectIdentifier MIB_ifMACEntAddr = {sizeof (OID_ipMACEntAddr) sizeof (UINT), OID_ipMACEntAddr}; AsnObjectIdentifier MIB_ifEntryType = {sizeof (OID_ifEntryType) sizeof (UINT), OID_ifEntryType}; AsnObjectIdentifier MIB_ifEntryNum = {sizeof (OID_ifEntryNum) sizeof (UINT), OID_ifEntryNum} ; RFC1157VarBindList varBindList; RFC1157VarBind varBind [2]; AsnInteger errorStatus; AsnInteger errorIndex; AsnObjectIdentifier MIB_NULL = {0, 0}; int ret; int dtmp; int i = 0, j = 0; bool found = false; char TempEthernet [13] ; M_init = null; m_initex = null; m_query = null; m_trap = null; / * Load SNMP DLL and get Examples handle * / m_hInst = LoadLibrary ( "inetmib1.dll"); if (m_hInst <(HINSTANCE) HINSTANCE_ERROR) {m_hInst = NULL; return;} m_Init = (pSnmpExtensionInit) GetProcAddress (m_hInst, "SnmpExtensionInit"); m_InitEx = (pSnmpExtensionInitEx ) GetProcAddress (m_hInst, "SnmpExtensionInitEx"); m_Query = (pSnmpExtensionQuery) GetProcAddress (m_hInst, "SnmpExtensionQuery"); m_Trap = (pSnmpExtensionTrap) GetProcAddress (m_hInst, "SnmpExtensionTrap"); m_Init (GetTickCount (), & PollForTrapEvent, & SupportedView); / * Initialize the variable list * / varbindlist.list = varbind; varbindlist.list = varbind; varbindlist.list = varbind; varbindlist.list = varbind; varbindlist.list = varbind; varbindlist.list = varbind; varbind [0] .name = mib_name = mib_null; / * Copy and look up in OID number of inlets * / varBindList.len = 1; / * Only retrieving one item * / SNMP_oidcpy (& varBind [0] .name, & MIB_ifEntryNum); ret = m_Query (ASN_RFC1157_GETNEXTREQUEST, & varBindList, & errorStatus, & errorIndex); printf ( "# of adapters in THIS system:% in ", varbind [0] .value.asnvalue.number; varbindlist.len = 2; / * Copy OID IFTYPE-Interface Type * / SNMP_OIDCPY (& Varbind [0] .Name, & MIB_IFENTRYTYPE); / * Copy OID IFPHYSADDRESS- Physical Address * / SNMP_OIDCPY (& Varbind [1] .Name, & MIB_IFMACENTDR); Do { / * Submit the query, and the result will be loaded into VarbindList. It can be expected that the number of cyclic calls and the number of interface cards in the system are equal * / RET = M_Query (asn_rfc1157_getnextrequest, & varbindlist, & errorstatus, & errorindex); if (! RET) RET = 1; Else / * confirm the correct return type * / Ret = SNMP_OIDNCMP (& varbind [0] .name, & mib_ifenTrytype, MIB_IB_IFENTRYTYPE.IDLENGTH); if (! RET) {J ; DTMP = varbind [0] .value.asnvalue.Number; Printf ("interface #% i type:% in" , J, DTMP); / * TYPE 6 Describes EtherNet Interfaces * / if (DTMP == 6) { / * Confirm that we have obtained address * / return = snmp_oidncmp (& varbind [1] .name, & mib_ifmacentaddr, mib_ifmacentaddr.idlength; if ((! Ret) && (Varbind [1] .Value.asnvalue.address.Stream! = NULL) {IF ((varbind [1] .value.asnvalue.address.Stream [0] == 0x44) && (varbind [1] .value.asnvalue.address.stream [1] == 0x45) && Varbind [1] .Value.asnvalue.address.Stream [2] == 0x53) && (varbind [1] .value.asnvalue.address.Stream [3] == 0x54) && (varbind [1] .value.asnvalue .address.Stream [4] == 0x00)) {/ * ignore all dial-up network interface card * / printf ("Interface #% I is a dun adaptern", J); Continue;} IF ((Varbind [1] .value.asnvalue.address.Stream [0] == 0x00) && (varbind [1] .value.asnvalue.address.Stream [1] == 0x00) && (varbind [1] .view.asnvalue.address.Stream [2] == 0x00) && (varbind [1] .value.asnvalue.address.Stream [3] == 0x00) && (varbind [1] .value.asnvalue.address.stream [4] == 0x0 0) && (VARBIND [1] .Value.asnvalue.address.Stream [5] == 0x00)) {/ * ignores NULL address returned by other network interface cards * / printf ("Interface #% i is a null Addressn, J); Continue;} sprintf (TemPethernet, "% 02x% 02x% 02x% 02x% 02x% 02x" Varbind [1] .value.asnvalue.address.Stream [0], Varbind [1] .value.asnvalue.address.Stream [1], Varbind [1] .Value.asnvalue.address.Stream [2], varbind [1] .value.asnvalue.address.Stream [3], Varbind [1] .Value.asnvalue.address.Stream [4], Varbind [1] .Value.asnvalue.address.Stream [5]); Printf "Mac Address of Interface #% i:% SN", J, Tempethernet);}}}} while (! RET); / * Error termination occurs. * / Getch (); freelibrary (m_hinst); / * Release binding * / snmp_freevarbind (& varbind [0]); snmp_freevarbind (& varbind [1]);}