none
GetAdaptersInfo, localtime, time_t 32/64 bit differences

    Question

  • I use GetAdaptersInfo to retrieve the DHCP server address along with the lease obtained and expire times. The MSDN documentation Says: "On Windows XP and later:  Use the GetAdapterAddresses function instead of GetAdapterInfo"

     

    I believe this is incorrect due to GetAdapterAddresses lacks DHCP lease times. I can find no other function or structure besides IP_ADAPTER_INFO which returns this. Did I miss it?

     

    I am forced to use #define _USE_32BIT_TIME_T and am concerned my program will not work correctly on 64 bit versions of XP and Vista. Can anyone give me info if using 32  time_t will work on 64 bit systems?

     

    Code Snippet

     

    #define _USE_32BIT_TIME_T // Now the whole program is 32 bit time_t

     

    if (GetAdaptersInfo (pAdapterInfo, &ulOutBufLen) == ERROR_SUCCESS)

    {

      PIP_ADAPTER_INFO pAdapter = NULL;

      struct tm newtime;

      time_t ltime; // Now 32 bits

      errno_t err;

      ...

      ...

      pAdapter = pAdapterInfo;

      ltime = pAdapter->LeaseObtained;

      err = localtime_s( &newtime, &ltime );

      if(!err(

      {

        ..

        ..

      }

      ...

      ...

    }

     

     

    Can the _USE_32BIT_TIME_T  define be used as a switch on and off within the program if 64 bit time_t is required in other locations? Or are we stuck on 32 bit program wide?

     

    Thanks...

    Mark..

    Wednesday, January 23, 2008 10:52 PM

Answers

  • If I were you, I wouldn't #define _USE_32BIT_TIME_T, that seems like too much of a hassle. Instead, I would duplicate the IP_ADAPTER_INFO struct with __time32_t in place of time_t for the LeaseObtained and LeaseExpires members:

    typedef struct _IP_ADAPTER_INFO_32 {
    	struct _IP_ADAPTER_INFO_32* Next;
    	DWORD ComboIndex;
    	char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4];
    	char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4];
    	UINT AddressLength;
    	BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH];
    	DWORD Index;
    	UINT Type;
    	UINT DhcpEnabled;
    	PIP_ADDR_STRING CurrentIpAddress;
    	IP_ADDR_STRING IpAddressList;
    	IP_ADDR_STRING GatewayList;
    	IP_ADDR_STRING DhcpServer;
    	BOOL HaveWins;
    	IP_ADDR_STRING PrimaryWinsServer;
    	IP_ADDR_STRING SecondaryWinsServer;
    	__time32_t LeaseObtained;
    	__time32_t LeaseExpires;
    } IP_ADAPTER_INFO_32, *PIP_ADAPTER_INFO_32;

    This way you'll just need to reinterpret_cast your IP_ADAPTER_INFO_32 buffer to a PIP_ADAPTER_INFO when you call GetAdapterInfo:

    ULONG adapter_count = 0;
    GetAdaptersInfo(0, &adapter_count);
    std::vector<char> adapters(adapter_count);
    GetAdaptersInfo(reinterpret_cast<PIP_ADAPTER_INFO>(&adapters[0]), &adapter_count);
    PIP_ADAPTER_INFO_32 adapter = reinterpret_cast<PIP_ADAPTER_INFO_32>(&adapters[0]);
    while (adapter)
    {
    	// ...
    	adapter = adapter->Next;
    }
    • Edited by ildjarn Friday, August 05, 2011 9:24 PM
    Thursday, January 24, 2008 11:18 PM

All replies

  • If I were you, I wouldn't #define _USE_32BIT_TIME_T, that seems like too much of a hassle. Instead, I would duplicate the IP_ADAPTER_INFO struct with __time32_t in place of time_t for the LeaseObtained and LeaseExpires members:

    typedef struct _IP_ADAPTER_INFO_32 {
    	struct _IP_ADAPTER_INFO_32* Next;
    	DWORD ComboIndex;
    	char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4];
    	char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4];
    	UINT AddressLength;
    	BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH];
    	DWORD Index;
    	UINT Type;
    	UINT DhcpEnabled;
    	PIP_ADDR_STRING CurrentIpAddress;
    	IP_ADDR_STRING IpAddressList;
    	IP_ADDR_STRING GatewayList;
    	IP_ADDR_STRING DhcpServer;
    	BOOL HaveWins;
    	IP_ADDR_STRING PrimaryWinsServer;
    	IP_ADDR_STRING SecondaryWinsServer;
    	__time32_t LeaseObtained;
    	__time32_t LeaseExpires;
    } IP_ADAPTER_INFO_32, *PIP_ADAPTER_INFO_32;

    This way you'll just need to reinterpret_cast your IP_ADAPTER_INFO_32 buffer to a PIP_ADAPTER_INFO when you call GetAdapterInfo:

    ULONG adapter_count = 0;
    GetAdaptersInfo(0, &adapter_count);
    std::vector<char> adapters(adapter_count);
    GetAdaptersInfo(reinterpret_cast<PIP_ADAPTER_INFO>(&adapters[0]), &adapter_count);
    PIP_ADAPTER_INFO_32 adapter = reinterpret_cast<PIP_ADAPTER_INFO_32>(&adapters[0]);
    while (adapter)
    {
    	// ...
    	adapter = adapter->Next;
    }
    • Edited by ildjarn Friday, August 05, 2011 9:24 PM
    Thursday, January 24, 2008 11:18 PM
  • Thak you ildjarn,

     

    That works perfectly, building a new structure. I did not have to reinterpret the cast, but just a simple (PIP_ADAPTER_INFO) cast works.

     

    The supplied PIP_ADAPTER_INFO structure with the win32 libs are broken as they are since the compilers default to 64 bits. In contrast, they should have been built as you suggested and instructed the programmers to use _localtime32_s to fill the tm structure.

     

    Code Snippet

     

    PIP_ADAPTER_INFO_32 pAdapterInfo = NULL;

    PIP_ADAPTER_INFO_32 pAdapter = NULL;

     

    GetAdaptersInfo ((PIP_ADAPTER_INFO) pAdapterInfo, &ulOutBufLen);

     

    pAdapter = pAdapterInfo;

     

    Again, thanks for the info.

    Mark...

    Friday, January 25, 2008 2:29 AM
  • Hello All,

     

    regarding this GetAdaptersInfo API, I have question that need your expertist..

    i found that GetAdaptersInfo i call returned a pointer to IP_ADAPTER_INFO data of which the size is 280 byte,

    while the sizeof(IP_ADAPTER_INFO) is 288 byte..

    after checking the memory content, i found that the data returned from GetAdaptersInfo seems has a 32 byte time of time_t.. Then it make sense that size difference (2x4byte)

    How can the return of this AP still contain a 32 bit time_t (is it machine dependent or SDK dependent or what?)?  and if supposed that i prefer not to define a 32 bit time_t , how can i handle it?  

    Im using SDK 6001

    Below is excerpt of my code,

     

    thanks for your help

    Dana

     

    Code Snippet

    PIP_ADAPTER_INFO pALL_AI  = NULL;

    //-----

    dwRtn = GetAdaptersInfo(pALL_AI, &uSizeAll);
     if(dwRtn != ERROR_BUFFER_OVERFLOW){
      pALL_AI  = NULL;
      uSizeAll = NULL;
      return dwRtn;
     }

     pALL_AI = (PIP_ADAPTER_INFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, uSizeAll);
     if(!pALL_AI){
      uSizeAll = NULL;
      return GetLastError();
     }

     dwRtn = GetAdaptersInfo(pALL_AI, &uSizeAll);
     if(dwRtn != ERROR_SUCCESS){
      HeapFree(GetProcessHeap(), NULL, pALL_AI);
      pALL_AI  = NULL;
      uSizeAll = NULL;
      return dwRtn;
     }

    //-------------
    // here i try to get information of one adapter 
    // ....

     

     

     

    Tuesday, May 13, 2008 4:39 AM
  • danny

     

    This was answeed above with two solutions. The compiler defaults to 64 bit time while the GetAdaptersInfo function call only has a 32 bit time structure. Unless you use the compiler directive _USE_32BIT_TIME_T, it returns false time info. But using this directive forces the exe to default all time functions to 32 bit making it possibly fail in 64 bit XP and VISTA systems. The better solution is to redefine the IP_ADAPTER_INFO structure as used above.

     

    Mark

    Wednesday, May 14, 2008 1:43 AM