Search code examples
cnetwork-programmingadapteraccess-violation

Access violation when getting network adapters with GetAdaptersAddresses in C


I don't know if the code from https://learn.microsoft.com/en-us/windows/desktop/api/iphlpapi/nf-iphlpapi-getadaptersaddresses is wrong but when I try to use it in my C project I keep getting the infamous

Access violation reading location 0xFFFFFFFFFFFFFFFF

I have tried increasing the buffer size but nothing seems to fix it. I think this happens after the first adapter is passed through the loop.

#include <stdio.h>
#include <string.h>
#include <locale.h>
#include <winsock2.h>
#include <iptypes.h>
#include <iphlpapi.h>
#include <windows.h>

#pragma comment(lib, "IPHLPAPI.lib")

#define MALLOC(x)       HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x)         HeapFree(GetProcessHeap(), 0, (x))

FILE* fLog = NULL;

void netinfo() {
    PIP_ADAPTER_ADDRESSES pAddresses = NULL;
    PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;

    DWORD dwRetVal = 0;
    ULONG outBufLen = 15000;
    ULONG iter = 0;
    do {
        pAddresses = (IP_ADAPTER_ADDRESSES*)MALLOC(outBufLen);
        if (pAddresses == NULL) {
            fwprintf(fLog, L"MALLOC error");
            break;

            dwRetVal = GetAdaptersAddresses(
                AF_UNSPEC,
                GAA_FLAG_INCLUDE_PREFIX,
                NULL,
                pAddresses,
                &outBufLen
            );

            if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
                FREE(pAddresses);
                pAddresses = NULL;
                fwprintf(fLog, L"GetAdaptersAddresses() error");
            } else {
                break;
            }

            iter++;
        }
    } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (iter < 3));

    wchar_t netAddressLog[256];
    if (dwRetVal == NO_ERROR && pAddresses != NULL) {
        pCurrAddresses = pAddresses;
        while (pCurrAddresses) {
            // this is where the debugger stops !!!
            swprintf(netAddressLog, 256, L"Index: %u", pCurrAddresses->IfIndex);
            fwprintf(fLog, netAddressLog);
            pCurrAddresses = pCurrAddresses->Next;
        }
    } else {
        fwprintf(fLog, L"GetAdaptersAddresses() error");
    }

    if (pAddresses) {
        FREE(pAddresses);
    }
}

int main(int argc, char **argv) {
    errno_t error = _wfopen_s(&fLog, L"log.txt", L"a+");

    netinfo();

    fclose(fLog);
}

So, when trying to access pCurrAddresses->IfIndex it's where the program fails, after the first loop (in which it logs some weird large number for index). I am trying to compare mi slightly modified code to the one from MSDN but I can't figure it out.

I know my code needs better organization but for now this is a blocker


Solution

  • There is some problem in the while loop block:

    do {
        pAddresses = (IP_ADAPTER_ADDRESSES*)MALLOC(outBufLen);
        if (pAddresses == NULL) {
            fwprintf(fLog, L"MALLOC error");
            break;
            /* a } is missing here*/
    
            dwRetVal = GetAdaptersAddresses(
                AF_UNSPEC,
                GAA_FLAG_INCLUDE_PREFIX,
                NULL,
                pAddresses,
                &outBufLen
            );
    
            if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
                FREE(pAddresses);
                pAddresses = NULL;
                fwprintf(fLog, L"GetAdaptersAddresses() error");
            } else {
                break;
            }
    
            iter++;
        }
    } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (iter < 3));
    

    The good corrected code could be:

    do {
        pAddresses = (IP_ADAPTER_ADDRESSES*)MALLOC(outBufLen);
        if (pAddresses == NULL) {
            fwprintf(fLog, L"MALLOC error");
            break;
        }
        dwRetVal = GetAdaptersAddresses(
            AF_UNSPEC,
            GAA_FLAG_INCLUDE_PREFIX,
            NULL,
            pAddresses,
            &outBufLen
        );
    
        if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
            FREE(pAddresses);
            pAddresses = NULL;
            fwprintf(fLog, L"GetAdaptersAddresses() error");
        } else {
            break;
        }
    
        iter++;        
    } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (iter < 3));