mac address

User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

Alex,

Check the source code of Harbour's Directory() function. It shows how to create, fill and return a multidimensional array.
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
AlexSchaft
Posts: 172
Joined: Fri Oct 07, 2005 1:29 pm
Location: Edenvale, Gauteng, South Africa

Post by AlexSchaft »

Found that code thanks. All working now. I couldn't format the hex numbers nicely in c using sprintf, so thats why I've got the extra code, and returning each byte separately

Code: Select all

Function Dec2x(pnNo, pnBase)

  Local cRetVal              := ""
  Local nCount               := 0
  Local acDigits             := {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}
  Local nNo                  := 0

  For nCount := 65 to 65 + pnBase - 11
    aadd(acDigits, chr(nCount))
  Next

  For nCount := 7 to 0 step - 1
    nNo                      := int(pnNo / (pnBase**nCount))
    If nNo > 0 .or. !empty(cRetVal)
      cRetVal                += acDigits[nNo + 1]

      pnNo                   -= nNo * pnBase**nCount
    Endif
  Next

Return cRetval


Function GetMacAddresses()

  local aaTemp := {}
  local axTemp
  local aaRetval
  local cMac := ""
  aaTemp := _GETMACADDRESSES()

  aaRetval := {}

  For each axTemp in aaTemp
    cMac := ""

    cMac += padl(Dec2x(axTemp[3], 16), 2, "0") + "-"
    cMac += padl(Dec2x(axTemp[4], 16), 2, "0") + "-"
    cMac += padl(Dec2x(axTemp[5], 16), 2, "0") + "-"
    cMac += padl(Dec2x(axTemp[6], 16), 2, "0") + "-"
    cMac += padl(Dec2x(axTemp[7], 16), 2, "0") + "-"
    cMac += padl(Dec2x(axTemp[8], 16), 2, "0")

    aadd(aaRetval, {axTemp[2], cMac})
  Next

return aaRetval
//---------------------------------------------------------------------------------------------//
#pragma begindump

#include <WinTen.h>
#include <Windows.h>
#include <ClipApi.h>

#ifdef __FLAT__
   #include <ShellApi.h>
#endif

#ifdef __HARBOUR__
   #include <hbapiitm.h>
   #include <hbdate.h>
   #include <hbset.h>
#endif

#include <iphlpapi.h>

// Fetches the MAC address and prints it
HB_FUNC( _GETMACADDRESSES )

{

  PHB_ITEM paAddress = hb_itemArrayNew( 0 );

  IP_ADAPTER_INFO AdapterInfo[16];       // Allocate information
                                         // for up to 16 NICs
  DWORD dwBufLen = sizeof(AdapterInfo);  // Save memory size of buffer

  DWORD dwStatus = GetAdaptersInfo(      // Call GetAdapterInfo
    AdapterInfo,                 // [out] buffer to receive data
    &dwBufLen);                  // [in] size of receive data buffer
//  assert(dwStatus == ERROR_SUCCESS);  // Verify return value is
                                      // valid, no buffer overflow

  PIP_ADAPTER_INFO pAdapterInfo = AdapterInfo; // Contains pointer to
                                               // current adapter info
  PHB_ITEM pName = hb_itemNew(NULL);
  PHB_ITEM pDesc = hb_itemNew(NULL);
  PHB_ITEM pAddress = hb_itemNew(NULL);

  char cMacAddress[17];

  do {
//    PrintMACaddress(pAdapterInfo->Address); // Print MAC address

    PHB_ITEM pSubArray = hb_itemArrayNew(8);

    hb_arraySet(pSubArray, 1, hb_itemPutC(pName, pAdapterInfo->AdapterName));
    hb_arraySet(pSubArray, 2, hb_itemPutC(pDesc, pAdapterInfo->Description));

//    sprintf( cMacAddress, "%x-%x-%x-%x-%x-%x", pAdapterInfo->Address[0], pAdapterInfo->Address[1], pAdapterInfo->Address[2]
    hb_arraySet(pSubArray, 3, hb_itemPutNL(pDesc, pAdapterInfo->Address[0]));
    hb_arraySet(pSubArray, 4, hb_itemPutNL(pDesc, pAdapterInfo->Address[1]));
    hb_arraySet(pSubArray, 5, hb_itemPutNL(pDesc, pAdapterInfo->Address[2]));
    hb_arraySet(pSubArray, 6, hb_itemPutNL(pDesc, pAdapterInfo->Address[3]));
    hb_arraySet(pSubArray, 7, hb_itemPutNL(pDesc, pAdapterInfo->Address[4]));
    hb_arraySet(pSubArray, 8, hb_itemPutNL(pDesc, pAdapterInfo->Address[5]));


    hb_arrayAdd(paAddress, pSubArray);

    hb_itemRelease(pSubArray);
    pAdapterInfo = pAdapterInfo->Next;    // Progress through
                                          // linked list
  }
  while(pAdapterInfo);                    // Terminate if last adapter

  hb_itemRelease(pName);
  hb_itemRelease(pDesc);
  hb_itemRelease(pAddress);

  hb_itemRelease(hb_itemReturn(paAddress));
}


#pragma enddump

User avatar
vailtom
Posts: 47
Joined: Thu Jan 05, 2006 6:56 pm
Contact:

Post by vailtom »

I made some changes in the function above to getting more information about the NIC. This is the code:

Code: Select all

#include "fivewin.ch"
/*
 * Retrieves adapter information for the local computer.
 * Original code by AlexSchaft
 * http://fivetechsoft.com/forums/viewtopic.php?t=77&postdays=0&postorder=asc&start=15
 *
 * Changed by Vailton Renato @ 07/06/2007 - 09:24:03
 */ 
function main()
   local NICs := GetMacAddresses()
   local crlf,i,s
   
   crlf := chr(13)+chr(10)
   
   FOR i := 1 TO len( NICs )
     
     * An ANSI character string of the description for the adapter.  
       s := "Description: "   + NICs[i,1] + crlf
     * MAC Address  
       s += "MAC Address: "   + NICs[i,2] + crlf
     * An ANSI character string of the name of the adapter.  
       s += "Adapter Name: "  + NICs[i,3] + crlf
       s += crlf

     * IP info  
       s += "IP: " + NICs[i,4] + crlf
       s += "Mask: " + NICs[i,5] + " / " 
       s += "Gateway: " + NICs[i,6] + crlf 
       s += crlf

     * DHCP Sever IP or empty string ""
       if !Empty( NICs[i,7] )  
          s += "DHCP: " + NICs[i,7] + " / "
        * The time when the current DHCP lease was obtained.  
          s += "Lease Obtained: " + alltrim( str( NICs[i,8] ))+ crlf 
       else
          s += 'DHCP disabled'
       end

     * Primary WINS server  
       if !Empty( NICs[i,9] )  
          s += "Pimary WINS: " + NICs[i,9] + crlf
       end
     * Secondary WINS server    
       if !Empty( NICs[i,9] )  
          s += "Secondary WINS: " + NICs[i,10] + crlf 
       end
       
      ? s         
   End
   
   return nil
   
//---------------------------------------------------------------------------------------------//
#pragma begindump

#include <WinTen.h>
#include <Windows.h>
#include <ClipApi.h>

#ifdef __FLAT__
   #include <ShellApi.h>
#endif

#ifdef __HARBOUR__
   #include <hbapiitm.h>
   #include <hbdate.h>
   #include <hbset.h>
#endif

#include <iphlpapi.h>

// Fetches the MAC address and prints it
HB_FUNC( GETMACADDRESSES )

{
 IP_ADAPTER_INFO AdapterInfo[16];       // Allocate information
                                         // for up to 16 NICs
                                         // http://msdn2.microsoft.com/En-US/library/aa366062.aspx
                                         
  DWORD dwBufLen = sizeof(AdapterInfo);  // Save memory size of buffer

  DWORD dwStatus = GetAdaptersInfo(      // Call GetAdapterInfo
            AdapterInfo,                 // [out] buffer to receive data
            &dwBufLen);                  // [in] size of receive data buffer

  PIP_ADAPTER_INFO pAdapterInfo = AdapterInfo; // Contains pointer to
                                               // current adapter info
  char cMacAddress[17];

  PHB_ITEM pItem;
  PHB_ITEM paAddress = hb_itemArrayNew( 0 );
  
  // Verify return value is valid, no buffer overflow... 
  if (dwStatus != ERROR_SUCCESS)
  {
      hb_itemRelease(hb_itemReturn(paAddress));
      return;
  }
  
  pItem = hb_itemNew(NULL);

  do {
    PHB_ITEM pSubArray = hb_itemArrayNew(10);

  // Description of NIC  
    hb_arraySet(pSubArray, 1, hb_itemPutC(pItem, pAdapterInfo->Description));

  // MAC address
    sprintf( cMacAddress, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", pAdapterInfo->Address[0], pAdapterInfo->Address[1], pAdapterInfo->Address[2],
                                                pAdapterInfo->Address[3], pAdapterInfo->Address[4], pAdapterInfo->Address[5] );
                                                
    hb_strUpper( cMacAddress, strlen(cMacAddress));
    hb_arraySet(pSubArray, 2, hb_itemPutC(pItem, cMacAddress ));
  // GUID of NIC
    hb_arraySet(pSubArray, 3, hb_itemPutC(pItem, pAdapterInfo->AdapterName));
    
  // IP Address
    hb_arraySet(pSubArray, 4, hb_itemPutC(pItem, pAdapterInfo->IpAddressList.IpAddress.String ));

  // IP Mask 
    hb_arraySet(pSubArray, 5, hb_itemPutC(pItem, pAdapterInfo->IpAddressList.IpMask.String ));

  // IP Gateway
    hb_arraySet(pSubArray, 6, hb_itemPutC(pItem, pAdapterInfo->GatewayList.IpAddress.String ));

  // DHCP server IP & Lease Obtained     
    if (pAdapterInfo->DhcpEnabled)
    {
       hb_arraySet(pSubArray, 7, hb_itemPutC( pItem, pAdapterInfo->DhcpServer.IpAddress.String ));
       hb_arraySet(pSubArray, 8, hb_itemPutNL(pItem, pAdapterInfo->LeaseObtained ));
    } else {
       hb_arraySet(pSubArray, 7, hb_itemPutC( pItem, "" ));
       hb_arraySet(pSubArray, 8, hb_itemPutNI(pItem, 0 ));
    }
    
 // WINS server info - Primary & Secondary ip address
    if (pAdapterInfo->HaveWins)
    {
       hb_arraySet(pSubArray,  9, hb_itemPutC( pItem, pAdapterInfo->PrimaryWinsServer.IpAddress.String ));
       hb_arraySet(pSubArray, 10, hb_itemPutC( pItem, pAdapterInfo->SecondaryWinsServer.IpAddress.String ));
    } else {
       hb_arraySet(pSubArray,  9, hb_itemPutC( pItem, "" ));
       hb_arraySet(pSubArray, 10, hb_itemPutC( pItem, "" ));
    }
  
    hb_arrayAdd(paAddress, pSubArray);
    
    hb_itemRelease(pSubArray);
    pAdapterInfo = pAdapterInfo->Next;    // Progress through
                                          // linked list
  }
  while(pAdapterInfo);                    // Terminate if last adapter

  hb_itemRelease(pItem);
  hb_itemRelease(hb_itemReturn(paAddress));
}

#pragma enddump
Sorry, my english is very bad.
:wink:
Vailton Renato
User avatar
AlexSchaft
Posts: 172
Joined: Fri Oct 07, 2005 1:29 pm
Location: Edenvale, Gauteng, South Africa

Post by AlexSchaft »

Thanks for that.

The %.2x syntax seems to crash under commercial xhb.

Alex
User avatar
AlexSchaft
Posts: 172
Joined: Fri Oct 07, 2005 1:29 pm
Location: Edenvale, Gauteng, South Africa

Post by AlexSchaft »

I found my problem :oops: A mac address is 17 characters, so in xbase a 17 character string is enough, but you need another character for \0 in C.

So initializing cMacAddress as

Code: Select all

char cMacAddress[18]


and using

Code: Select all

    sprintf( cMacAddress, "%02X-%02X-%02X-%02X-%02X-%02X", pAdapterInfo->Address[0], pAdapterInfo->Address[1], pAdapterInfo->Address[2],
      pAdapterInfo->Address[3], pAdapterInfo->Address[4], pAdapterInfo->Address[5]);
solves my problem :)
StefanHaupt
Posts: 824
Joined: Thu Oct 13, 2005 7:39 am
Location: Germany

Post by StefanHaupt »

Alex,

your function is not working with Vista / Vista64. It returns an empty array.

Do you have a version that runs with vista ?
kind regards
Stefan
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

Stefan,

You can use FWH GetNetCardID()

It returns an array if there are more than one network adapters:

Code: Select all

   if ValType( GetNetCardID() ) == "C"
      MsgInfo( GetNetCardID() )
   else
      aAdapters = GetNetCardID()
      for n = 1 to Len( aAdapters )
         MsgInfo( aAdapters[ n ] )
      next
   endif      
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
AlexSchaft
Posts: 172
Joined: Fri Oct 07, 2005 1:29 pm
Location: Edenvale, Gauteng, South Africa

Vista

Post by AlexSchaft »

Haven't bothered with a version for Vista yet. I see a new API is recommended for XP/Vista, which I haven't investigated yet.
StefanHaupt
Posts: 824
Joined: Thu Oct 13, 2005 7:39 am
Location: Germany

Post by StefanHaupt »

Antonio,

I made some tests and I get some curios results.

Alex function is working with XPx64, not with XPx32 Sp3 and not with Vistax32/x64.

XPx32: detects 1 NIC, returns wrong MAC (1 NIC present)
Vista32: detects 0 NIC, returns wrong MAC (2 NIC present)

GetNetcardID ():

XPx32: detects 1 NIC, returns wrong MAC (1 NIC present)
Vista32: detects 1 NIC, returns wrong MAC (2 NIC present)
kind regards
Stefan
StefanHaupt
Posts: 824
Joined: Thu Oct 13, 2005 7:39 am
Location: Germany

Post by StefanHaupt »

MS suggests a new api function to be used with XP and later, GetAdaptersAdresses().

This function does not seem to be available with bcc55, or I´m linking the wrong libs.

This is my try to convert Alex function to this new api-function.
I´m getting an unresolved external "GetAdaptersAdresses".
There may be some other errors in the code, so I would be happy, if anyone could look over the code.

Code: Select all

HB_FUNC( GETMAC )

{
 IP_ADAPTER_ADDRESSES AdapterInfo[16];       // Allocate information
                                         // for up to 16 NICs
                                         
  DWORD dwBufLen = sizeof(AdapterInfo);  // Save memory size of buffer

  DWORD dwStatus = GetAdaptersAdresses(      // Call GetAdapterInfo
            AF_INET,0,0,
            AdapterInfo,                 // [out] buffer to receive data
            &dwBufLen);                  // [in] size of receive data buffer

  PIP_ADAPTER_ADDRESSES pAdapterInfo = AdapterInfo; // Contains pointer to
                                               // current adapter info
  char cMacAddress[18];

  PHB_ITEM pItem;
  PHB_ITEM paAddress = hb_itemArrayNew( 0 );

  // Verify return value is valid, no buffer overflow...
  if (dwStatus != ERROR_SUCCESS)
  {
      hb_itemRelease(hb_itemReturn(paAddress));
      return;
  }

  pItem = hb_itemNew(NULL);

  do {
    PHB_ITEM pSubArray = hb_itemArrayNew(3);

  // Description of NIC
    hb_arraySet(pSubArray, 1, hb_itemPutC(pItem, pAdapterInfo->Description));

  // MAC address
    sprintf( cMacAddress, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", pAdapterInfo->PhysicalAddress[0],
                                                           pAdapterInfo->PhysicalAddress[1],
                                                           pAdapterInfo->PhysicalAddress[2],
                                                           pAdapterInfo->PhysicalAddress[3],
                                                           pAdapterInfo->PhysicalAddress[4],
                                                           pAdapterInfo->PhysicalAddress[5] );

    hb_strUpper( cMacAddress, strlen(cMacAddress));
    hb_arraySet(pSubArray, 2, hb_itemPutC(pItem, cMacAddress ));
  // GUID of NIC
    hb_arraySet(pSubArray, 3, hb_itemPutC(pItem, pAdapterInfo->AdapterName));

    pAdapterInfo = pAdapterInfo->Next;    // Progress through
                                          // linked list
  }
  while(pAdapterInfo);                    // Terminate if last adapter

  hb_itemRelease(pItem);
  hb_itemRelease(hb_itemReturn(paAddress));
}

kind regards
Stefan
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

Stefan,

It seems as there is a typo in the function name. It should be:

GetAdaptersAddresses()

Notice the "dd"

http://msdn.microsoft.com/en-us/library/aa365915.aspx

You have to create an import library from Windows Iphlpapi.dll
regards, saludos

Antonio Linares
www.fivetechsoft.com
StefanHaupt
Posts: 824
Joined: Thu Oct 13, 2005 7:39 am
Location: Germany

Post by StefanHaupt »

Antonio,

yes, thanks, a small typo I hadn´t seen :(

I got it working so far, I have only 2 warnings I don´t undestand. Maybe you have an idea what to do

Warning: Suspicious pointer converversion
hb_arraySet(pSubArray, 1, hb_itemPutC(pItem, pAdapterInfo->Description));
hb_arraySet(pSubArray, 3, hb_itemPutC(pItem, pAdapterInfo->FriendlyName));

Code: Select all

HB_FUNC( GETMAC )

{
 IP_ADAPTER_ADDRESSES AdapterInfo[16];   // Allocate information 

  DWORD dwBufLen = sizeof(AdapterInfo);   // Save memory size of buffer
  ULONG flags = GAA_FLAG_SKIP_UNICAST;  // Set the flags 
  ULONG family = AF_INET;                 // only IP4

  DWORD dwStatus = GetAdaptersAddresses(  // Call GetAdapterInfo
                   family,flags,NULL,
                   AdapterInfo,                 // [out] buffer to receive data
                   &dwBufLen);                  // [in] size of receive data buffer

  PIP_ADAPTER_ADDRESSES pAdapterInfo = AdapterInfo; // Contains pointer to
                                               // current adapter info
  char cMacAddress[18];

  PHB_ITEM pItem;
  PHB_ITEM paAddress = hb_itemArrayNew( 0 );

  // Verify return value is valid, no buffer overflow...
  if (dwStatus != ERROR_SUCCESS)
  {
      hb_itemRelease(hb_itemReturn(paAddress));
      return;
  }

  pItem = hb_itemNew(NULL);

  do {
    PHB_ITEM pSubArray = hb_itemArrayNew(4);

  // Description of NIC
    hb_arraySet(pSubArray, 1, hb_itemPutC(pItem, pAdapterInfo->Description)); ]  // *** Suspicious pointer conversion ***

  // MAC address
    sprintf( cMacAddress, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", 
pAdapterInfo->PhysicalAddress[0],                                                          pAdapterInfo->PhysicalAddress[1],                                                           pAdapterInfo->PhysicalAddress[2],                                                           pAdapterInfo->PhysicalAddress[3],                                                           pAdapterInfo->PhysicalAddress[4],                                                           pAdapterInfo->PhysicalAddress[5] );

    hb_strUpper( cMacAddress, strlen(cMacAddress));
    hb_arraySet(pSubArray, 2, hb_itemPutC(pItem, cMacAddress ));
  // GUID of NIC
    hb_arraySet(pSubArray, 3, hb_itemPutC(pItem, pAdapterInfo->FriendlyName)); // *** Suspicious pointer conversion ***

    // Type
    hb_arraySet(pSubArray, 4, hb_itemPutNI (pItem, pAdapterInfo->IfType));

    hb_arrayAdd(paAddress, pSubArray);

    hb_itemRelease(pSubArray);

    pAdapterInfo = pAdapterInfo->Next;    // Progress through
                                          // linked list
  }
  while(pAdapterInfo);                    // Terminate if last adapter

  hb_itemRelease(pItem);
  hb_itemRelease(hb_itemReturn(paAddress));
}
kind regards
Stefan
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

Stefan,

hb_arraySet(pSubArray, 1, hb_itemPutC(pItem, ( char * ) pAdapterInfo->Description));

and

hb_arraySet(pSubArray, 3, hb_itemPutC(pItem, ( char * ) pAdapterInfo->FriendlyName));
regards, saludos

Antonio Linares
www.fivetechsoft.com
Post Reply