Retrieving network adapter info using the IP Helper API

Here’s a code snippet that enumerates the currently enabled network adapters and shows some info for each adapter :-

ULONG OutBufLen = 0;

//Get the required size of the buffer
if( GetAdaptersInfo(NULL, &OutBufLen) == ERROR_BUFFER_OVERFLOW )
  int divisor = sizeof IP_ADAPTER_INFO;

  /*** Uncomment for VC++ 2005 Beta 2
  if( sizeof time_t == 8 )
    divisor -= 8;

  pAdapterInfo = new IP_ADAPTER_INFO[OutBufLen/divisor];

  //Get info for the adapters
  if( GetAdaptersInfo(pAdapterInfo, &OutBufLen) != ERROR_SUCCESS )
    //Call failed
    delete[] pAdapterInfo;
    pAdapterInfo = NULL;
    int index = 0;
      cout << pAdapterInfo->Description << endl;
      cout << pAdapterInfo->AdapterName << endl;

      cout << "MAC Address : ";
      for(int i=0; i < (int)pAdapterInfo->AddressLength; i++)
        cout << setfill('0') << setw(2) << uppercase <<  hex
          << (int)pAdapterInfo->Address[i] << ' ';
      cout << endl;

      cout << "Default Gateway : ";
      cout << pAdapterInfo->GatewayList.IpAddress.String << endl;

      cout << "IP Address list : ";
      PIP_ADDR_STRING pIpStr = &pAdapterInfo->IpAddressList;
        cout << pIpStr->IpAddress.String << endl;
        pIpStr = pIpStr->Next;

      pAdapterInfo = pAdapterInfo->Next;
      cout << endl << endl;


      delete[] pAdapterInfo;

I have only used some of the fields in the IP_ADAPTER_INFO structure, so make sure you look it up on MSDN.

BTW I used code similar to the above snippet in my MAC Address Changer for Windows XP/2003 application available as a free tool with source code from this Code Project article.


Accessing version information is so damn hard

I am unable to fathom why there is no straightforward API to access version information from the running process. To retrieve any kind of version information, you need to call 3 APIs – GetFileVersionInfoSize, GetFileVersionInfo and VerQueryValue. Actually make that 4 APIs, since you also need to call GetModuleFileName to get the full path of the running process. In fact a simple process like retrieving the LegalCopyright version string involves the following process :-

  • Call GetModuleFileName and retrieve the full executable path
  • Pass this path to GetFileVersionInfoSize to get the size of the version info buffer
  • Allocate this buffer (using malloc as it’s supposed to be a void*)
  • Call VerQueryValue with \\VarFileInfo\\Translation to get the list of language and code pages (though you can skip this one if you are sure of what lang/codepage you need)
  • Call VerQueryValue again specifying the \\StringFileInfo\\[LangCodeCode] you need along with the name of the version string you are after
  • Free the buffer allocated early on

Good heavens! How hard would it have been for the Win32 API team to have added some function like GetFileVersionString(LPCTSTR versionstring)? 😮

Three recent CP articles

I’ve been writing articles the last couple of weeks and for those who missed them, here are the URLs :-

All of them started off well getting some 5-votes, but quickly dipped into the lower 4s presumably due to some 1-votes. I am not affected by the ratings all that much nowadays, but I still wonder at the psychology of the 1-voters. Could it be that they have a personal issue with me? Or perhaps they were angered by a comment I made? There’s a lot of room for analysis and dissection in this area – but it’s probably better not to give it a second thought.

STL.NET in VC++ 2005 Beta 2

Anson Tsao says it was an accidental inclusion and Ronald Laeremans says it isn’t within an order of the magnitude of the performance that they wanted to ship it with. Anson said that the idea is to release STL/CLR (or STL.NET) as a beta (downloadable off the web) around the time VC++ 2005 is finally released, and to release the final version a little later (again off the web). This means, STL.NET will not be part of VC++ 2005 installer when it gets released, but will be a separate add-on like library. Possibly, by Orcas it’ll be mature enough to be distributed as part of the full VC++ suite. I do hope it doesn’t go the WTL way (WTL might have succeeded in many ways, but it’s still pretty much an orphan compared to MFC and ATL).

Possibly proving Anson’s idea that it was included by accident are comments in the code such as the one shown below :-

/* Copyright (c) 2004-2005 by Dinkumware, Ltd. */

Anyway, I personally was very thrilled at its inclusion and at being able to play with it – something I’ve been wanting to do ever since Stan Lippman started blogging about STL.NET (and later he wrote that MSDN article whose title I forget at the moment). Not being an STL guy (at least not until now), I am unable to compare it with native STL, but it looks good to my pretty newbie-ish STL awareness levels.

BTW, here’s three ways to iterate through a string (the comments say what each iteration is based on) :-

string s = "Hello world";

//Using the ICollection<> interface
for each(wchar_t c in s)

//Using the default indexed property
for(int i=0; i<s.Count; i++)

//Using iterators
for(string::iterator i = s.begin(); i != s.end(); i++)

Alright, I know I am sounding like a 7 year old who got his first bike, but that’s how I’ve been feeling like ever since I installed Beta 2 😀

A more .NETish main()

In VC++.NET 2005 Beta 2, if you create a new .NET console app project (now aptly called a CLR console app in the wizard), you’ll see that the generated main() function is prototyped thus :-

int main(array<System::String ^> ^args)

That’s rather neat – considering that we are using .NET, it makes sense to have a String array passed to us rather than an array of char*s or a char** (whichever way you like to look at it).

Test out the following code :-

int main(array<System::String ^> ^args)
    Console::WriteLine("Number of args {0}", args->Length);
    int count = 0;
    for each(String^ s in args)
        Console::WriteLine("Argument {0} = {1}",count++,s);
    return 0;

Run it following the output shown below :-

>B2_Properties.exe interesting
Number of args 1
Argument 0 = interesting

>B2_Properties.exe hello world
Number of args 2
Argument 0 = hello
Argument 1 = world

Number of args 0

Hmmm, a slight difference from the way our traditional main(int argc, char** argv) behaved. The filename is not counted as an argument, so an app run without parameters has zero arguments passed and the String array is empty. I suppose they had to do it this way to be compatible with C# (which I believe does it this way).