views:

39

answers:

3

I looked at the GetAdaptersInfo() sample in MSDN:

http://msdn.microsoft.com/en-us/library/aa365917%28VS.85%29.aspx

and noticed that while the sample attempts to iterate through ALL adapters, it only allocates memory for the first one.

Is this a bug?

If not, why not? Do all adapters have the same info size?

To further clarify my question: I understood the role of the double call to malloc in the sample. What I don't understand is why is it outside the loop. If there is only one adapter in the system, of course there is no problem. But what happens when there are multiple adapters? Is this a bug?

Thanks.

A: 

It looks like you're missing this part of the code sample.

if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) {
    FREE(pAdapterInfo);
    pAdapterInfo = (IP_ADAPTER_INFO *) MALLOC(ulOutBufLen);
    if (pAdapterInfo == NULL) {
        printf("Error allocating memory needed to call GetAdaptersinfo\n");
        return 1;
    }
}

This code is calling GetAdaptersInfo with a single allocated adapter. It's essentially optimizing for the case where there is only one adapter on the machine. In the case it receieves the ERROR_BUFFER_OVERFLOW return it changes it's allocation the the size specified in ulOutBufLen (updated by the function call).

This is the line which changes the amount of memory allocated in the case of more than one adapter.

pAdapterInfo = (IP_ADAPTER_INFO *) MALLOC(ulOutBufLen);

EDIT

After reading Steve's comment I looked a bit closer and it appears that the code is incorrectly calling the GetAdaptersInfo function twice. In the case of 1 adapter the first call can potentially result in success removing the need for the second call.

JaredPar
@Jared, that's what I thought, but the optimization is not used afai can see. 2 calls always happen.
Steve Townsend
@Steve yeah that is indeed odd. Looks like a bug in the sample IMHO
JaredPar
@JaredPar thanks -- I understood the role of the double call to malloc in the sample. What I don't understand is why is it **outside the loop**. If there is only one adapter in the system, of course there is no problem. But what happens when there are multiple adapters? Is this a bug?
Android Eve
A: 

It's not a bug - the first call is to find out how much data area is actually needed.

If this first call fails with ERROR_BUFFER_OVERFLOW, it also tells you how much dataspace you need to hold all the results. The example then goes on to reallocate, and call Win32 again to get the full list. That is this code here, before the iteration you noted:

if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) {
    FREE(pAdapterInfo);
    pAdapterInfo = (IP_ADAPTER_INFO *) MALLOC(ulOutBufLen);
    if (pAdapterInfo == NULL) {
        printf("Error allocating memory needed to call GetAdaptersinfo\n");
        return 1;
    }
}

if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) {

Seems to me that in the best case, this second call is not required - a reasonable approach from a time when there was only one network adapter in most machines. The sample does not seem to check for NO_ERROR on the first call, which would obviate the second, for some reason.

Steve Townsend
Steve, thanks. I understood the role of the double call to malloc in the sample before I posted my question. What I don't understand is why is it **outside the loop**. If there's only one adapter in the system, of course there's no problem. But what happens when there are multiple adapters? Is this a bug?
Android Eve
@Android - no, the second call returns info on all the adapters in one go, with each structure linked to the next even though they are in a single memory block.
Steve Townsend
@Steven, +1 for referring to my specific question. With your help, I have been able to finally spot the tiny reference in the documentation to the fact that pOutBufLen related to the info size of ALL adapters: It's actually in the description for pAdapterInfo: "Pointer to a buffer that receives a linked list of IP_ADAPTER_INFO structures".
Android Eve
@Android Eve - glad to hear it. These Win32 APIs and their structures defy intuition at times.
Steve Townsend
@Steve, indeed. After investing so much effort understanding the documentation and/or its intent, I now notice that "On Windows XP and later: Use the GetAdaptersAddresses() function instead of GetAdaptersInfo." LOL my program is not intended to run on a Windows version earlier than XP... I selected your answer as the accepted one.
Android Eve
+1  A: 

One thing to note with this sample code is that if the number of adaptors happens to increase between calls to GetAdaptersInfo, you'll over run your buffer. It's extremely unlikely, but the code should still check for that condition.

Brett
Excellent point. That's what makes the different between an "OK program" and a superior one.
Android Eve