Getting Mac address using GetAdaptersAddresses

nouman yosuf 1 Reputation point
2021-03-25T15:09:23.087+00:00

I am using "GetAdaptersAddresses" function (using C++) to get the MAC address of the computer.
GetAdaptersAddresses returns a link list of PIP_ADAPTER_ADDRESSES for all the adapters connected to the system. I want to fetch the physical address of the Ethernet card specifically. Currently it comes at the first node of the list returned by the GetAdaptersAddresses and the MSDN document (https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getadaptersaddresses) does not specifically mentioned about the order of the adapters in the list, and could be changed based on the connected adapters. The order is not reliable. Moreover, the order is different on different machine.

Ethernet card is assured to be always connected to the device and the mac address is never changed. How to traverse the list to fetch the physical address of Ethernet card?
(I understand that the'Description' and 'Friendly name' can not be used as they can be changed)

Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,455 questions
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,571 questions
0 comments No comments
{count} votes

3 answers

Sort by: Most helpful
  1. Petrus 【KIM】 456 Reputation points
    2021-03-29T07:33:11.033+00:00

    REF.
    My Old Code...

    https://stpetrus27.wordpress.com/2011/03/16/cc-local-network-mac-address/

    #define WIN32_LEAN_AND_MEAN
    
    #include <Windows.h>
    #include <winsock2.h>
    #include <iphlpapi.h>
    #include <stdio.h>
    #pragma comment(lib, "IPHLPAPI.lib")
    
     int main(int argc, char** argv)
    {
            unsigned char* pszBuff = NULL;
            int nCount = 0;
            int idx = 0;
            int chPos = 0;
            nCount = RetriveLocalMacAddress(GAA_FLAG_INCLUDE_ALL_COMPARTMENTS, AF_UNSPEC, &pszBuff);
    
            for (idx = 0; idx < nCount; ++idx)
            {
                   chPos = MAX_ADAPTER_ADDRESS_LENGTH * idx;
                   printf("%02X-%02X-%02X-%02X-%02X-%02X\n",
                           pszBuff[chPos], pszBuff[1+chPos], pszBuff[2+chPos], pszBuff[3+chPos],
                           pszBuff[4+chPos], pszBuff[5+chPos]);
            }
            HeapFree(GetProcessHeap(), 0x00, pszBuff);
            pszBuff = NULL;
    
            return 0;
    }
    
    int RetriveLocalMacAddress(ULONG ulFlags, ULONG ulFamily, unsigned char** pszAddress)
    {
            PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
            PIP_ADAPTER_ADDRESSES pAddresses = NULL;
    
            int nAddressCount = 0;
            DWORD dwRetVal = 0;
            ULONG ulBufLen = sizeof(IP_ADAPTER_ADDRESSES);
            HANDLE hHeap = NULL;
    
            hHeap = GetProcessHeap();
            pAddresses = (PIP_ADAPTER_ADDRESSES)HeapAlloc(hHeap, 0x00, ulBufLen);
            if (pAddresses == NULL) {
                   return 0;
            }      
    
            dwRetVal = GetAdaptersAddresses(ulFamily, ulFlags, NULL, pAddresses, &ulBufLen);
            if (dwRetVal == ERROR_BUFFER_OVERFLOW)
            {
                   HeapFree(hHeap, 0x00, pAddresses);
                   pAddresses = (PIP_ADAPTER_ADDRESSES)HeapAlloc(hHeap, 0x00, ulBufLen);
            }
    
            if (pAddresses == NULL) {
                   return 0;
            }      
    
            dwRetVal = GetAdaptersAddresses(ulFamily, ulFlags, NULL, pAddresses, &ulBufLen);
            if (dwRetVal == NO_ERROR)
            {
                   pCurrAddresses = pAddresses;
                   while (pCurrAddresses)
                   {
                           pCurrAddresses = pCurrAddresses->Next;
                           ++nAddressCount;
                   }
    
                   *pszAddress = (unsigned char*)HeapAlloc(hHeap, 0x00, MAX_ADAPTER_ADDRESS_LENGTH * nAddressCount);
                   pCurrAddresses = pAddresses;
                   nAddressCount = 0;
                   while (pCurrAddresses)
                   {
                           RtlCopyMemory(*pszAddress + (MAX_ADAPTER_ADDRESS_LENGTH * nAddressCount++),
                              pCurrAddresses->PhysicalAddress,
                                                   MAX_ADAPTER_ADDRESS_LENGTH);
                           pCurrAddresses = pCurrAddresses->Next;
                   }
            }
    
             if (pAddresses) {
                   HeapFree(hHeap, 0x00, pAddresses);
                   pAddresses = NULL;
            }
            return nAddressCount;
    }
    
    1 person found this answer helpful.
    0 comments No comments

  2. Castorix31 82,206 Reputation points
    2021-03-25T16:28:25.4+00:00

    I have this old code in my archives, using GetIpAddrTable (same as GetAdaptersAddresses for IPv4) :

    #include <windows.h>  
    #include <stdio.h>  
      
    #pragma comment(lib, "WS2_32")  
    #include <iphlpapi.h>  
    #pragma comment(lib, "iphlpapi")  
      
    #define IP_LOCALHOST    0x0100007F  
    void print_ip(DWORD nAddr)  
    {  
      printf("%d.%d.%d.%d\n", nAddr & 0x000000FF, (nAddr & 0x0000FF00) >> 8, (nAddr & 0x00FF0000) >> 16, (nAddr & 0xFF000000) >> 24);  
    }  
      
    int main()  
    {  
      ULONG nSize = 0;  
      MIB_IPADDRTABLE * ip_table = NULL;  
      if (GetIpAddrTable(ip_table, &nSize, 0) == ERROR_INSUFFICIENT_BUFFER)  
      {  
          ip_table = (MIB_IPADDRTABLE *) malloc(nSize);  
          if (GetIpAddrTable(ip_table, &nSize, 0) == NO_ERROR)  
          {  
              for (int i = 0; i < ip_table->dwNumEntries; ++i)  
              {  
                  print_ip(ip_table->table[i].dwAddr);  
                  if (IP_LOCALHOST != ip_table->table[i].dwAddr)  
                  {  
                      MIB_IFROW iInfo;  
                      BYTE byMAC[6] = { 0, 0, 0, 0, 0, 0 };  
                      memset(&iInfo, 0, sizeof(MIB_IFROW));  
                      iInfo.dwIndex = ip_table->table[i].dwIndex;  
                      GetIfEntry(&iInfo);  
                      if (MIB_IF_TYPE_ETHERNET == iInfo.dwType)  
                      {  
                           memcpy(&byMAC, iInfo.bPhysAddr, iInfo.dwPhysAddrLen);  
                          printf("MAC Address = %02x-%02x-%02x-%02x-%02x-%02x\n", byMAC[0],byMAC[1],byMAC[2], byMAC[3],byMAC[4],byMAC[5]);  
                      }  
                  }  
              }  
          }  
          else  
              printf("unable to read IP table from system\n");  
          free(ip_table);  
      }  
      else  
          printf("unable to determine number of entries in IP table\n");  
      return 0;  
    }  
    

  3. nouman yosuf 1 Reputation point
    2021-03-26T08:13:13.953+00:00

    @Castorix31 Thank for the answer. but unfortunately I does not give correct MAC of the device.