Содержание
- GetAdaptersAddresses function (iphlpapi.h)
- Syntax
- Parameters
- Return value
- Remarks
- Examples
- Ошибка конфигурации call to getadaptersaddresses failed with error
- Asked by:
- Question
GetAdaptersAddresses function (iphlpapi.h)
The GetAdaptersAddresses function retrieves the addresses associated with the adapters on the local computer.
Syntax
Parameters
The address family of the addresses to retrieve. This parameter must be one of the following values.
Value | Meaning |
---|---|
AF_UNSPEC 0 | Return both IPv4 and IPv6 addresses associated with adapters with IPv4 or IPv6 enabled. |
AF_INET 2 | Return only IPv4 addresses associated with adapters with IPv4 enabled. |
AF_INET6 23 | Return only IPv6 addresses associated with adapters with IPv6 enabled. |
The type of addresses to retrieve. The possible values are defined in the Iptypes.h header file. Note that the Iptypes.h header file is automatically included in Iphlpapi.h, and should never be used directly.
This parameter is a combination of the following values. If this parameter is zero, then unicast, anycast, and multicast IP addresses will be returned.
Value | Meaning |
---|---|
GAA_FLAG_SKIP_UNICAST 0x0001 | Do not return unicast addresses. |
GAA_FLAG_SKIP_ANYCAST 0x0002 | Do not return IPv6 anycast addresses. |
GAA_FLAG_SKIP_MULTICAST 0x0004 | Do not return multicast addresses. |
GAA_FLAG_SKIP_DNS_SERVER 0x0008 | Do not return addresses of DNS servers. |
GAA_FLAG_INCLUDE_PREFIX 0x0010 | Return a list of IP address prefixes on this adapter. When this flag is set, IP address prefixes are returned for both IPv6 and IPv4 addresses.
This flag is supported on WindowsВ XP with SP1 and later. |
GAA_FLAG_SKIP_FRIENDLY_NAME 0x0020 | Do not return the adapter friendly name. |
GAA_FLAG_INCLUDE_WINS_INFO 0x0040 | Return addresses of Windows Internet Name Service (WINS) servers.
This flag is supported on WindowsВ Vista and later. |
GAA_FLAG_INCLUDE_GATEWAYS 0x0080 | Return the addresses of default gateways.
This flag is supported on WindowsВ Vista and later. |
GAA_FLAG_INCLUDE_ALL_INTERFACES 0x0100 | Return addresses for all NDIS interfaces.
This flag is supported on WindowsВ Vista and later. |
GAA_FLAG_INCLUDE_ALL_COMPARTMENTS 0x0200 | Return addresses in all routing compartments.
This flag is not currently supported and reserved for future use. |
GAA_FLAG_INCLUDE_TUNNEL_BINDINGORDER 0x0400 | Return the adapter addresses sorted in tunnel binding order. This flag is supported on WindowsВ Vista and later. |
This parameter is not currently used, but is reserved for future system use. The calling application should pass NULL for this parameter.
[in, out] AdapterAddresses
A pointer to a buffer that contains a linked list of IP_ADAPTER_ADDRESSES structures on successful return.
[in, out] SizePointer
A pointer to a variable that specifies the size of the buffer pointed to by AdapterAddresses.
Return value
If the function succeeds, the return value is ERROR_SUCCESS (defined to the same value as NO_ERROR).
If the function fails, the return value is one of the following error codes.
Return code | Description |
---|---|
ERROR_ADDRESS_NOT_ASSOCIATED | An address has not yet been associated with the network endpoint. DHCP lease information was available. |
ERROR_BUFFER_OVERFLOW | The buffer size indicated by the SizePointer parameter is too small to hold the adapter information or the AdapterAddresses parameter is NULL. The SizePointer parameter returned points to the required size of the buffer to hold the adapter information. |
ERROR_INVALID_PARAMETER | One of the parameters is invalid. This error is returned for any of the following conditions: the SizePointer parameter is NULL, the Address parameter is not AF_INET, AF_INET6, or AF_UNSPEC, or the address information for the parameters requested is greater than ULONG_MAX. |
ERROR_NOT_ENOUGH_MEMORY | Insufficient memory resources are available to complete the operation. |
ERROR_NO_DATA | No addresses were found for the requested parameters. |
Other | Use FormatMessage to obtain the message string for the returned error. |
The
GetAdaptersAddresses function can retrieve information for IPv4 and IPv6 addresses.
Addresses are returned as a linked list of IP_ADAPTER_ADDRESSES structures in the buffer pointed to by the AdapterAddresses parameter. The application that calls the GetAdaptersAddresses function must allocate the amount of memory needed to return the IP_ADAPTER_ADDRESSES structures pointed to by the AdapterAddresses parameter. When these returned structures are no longer required, the application should free the memory allocated. This can be accomplished by calling the HeapAlloc function to allocate memory and later calling the HeapFree function to free the allocated memory, as shown in the example code. Other memory allocation and free functions can be used as long as the same family of functions are used for both the allocation and the free function.
GetAdaptersAddresses is implemented only as a synchronous function call. The GetAdaptersAddresses function requires a significant amount of network resources and time to complete since all of the low-level network interface tables must be traversed.
One method that can be used to determine the memory needed to return the IP_ADAPTER_ADDRESSES structures pointed to by the AdapterAddresses parameter is to pass too small a buffer size as indicated in the SizePointer parameter in the first call to the GetAdaptersAddresses function, so the function will fail with ERROR_BUFFER_OVERFLOW. When the return value is ERROR_BUFFER_OVERFLOW, the SizePointer parameter returned points to the required size of the buffer to hold the adapter information. Note that it is possible for the buffer size required for the IP_ADAPTER_ADDRESSES structures pointed to by the AdapterAddresses parameter to change between subsequent calls to the GetAdaptersAddresses function if an adapter address is added or removed. However, this method of using the GetAdaptersAddresses function is strongly discouraged. This method requires calling the GetAdaptersAddresses function multiple times.
The recommended method of calling the GetAdaptersAddresses function is to pre-allocate a 15KB working buffer pointed to by the AdapterAddresses parameter. On typical computers, this dramatically reduces the chances that the GetAdaptersAddresses function returns ERROR_BUFFER_OVERFLOW, which would require calling GetAdaptersAddresses function multiple times. The example code illustrates this method of use.
In versions prior to WindowsВ 10, the order in which adapters appear in the list returned by this function can be controlled from the Network Connections folder: select the Advanced Settings menu item from the Advanced menu. Starting with WindowsВ 10, the order in which adapters appear in the list is determined by the IPv4 or IPv6 route metric.
If the GAA_FLAG_INCLUDE_ALL_INTERFACES is set, then all NDIS adapters will be retrieved even those addresses associated with adapters not bound to an address family specified in the Family parameter. When this flag is not set, then only the addresses that are bound to an adapter enabled for the address family specified in the Family parameter are returned.
The size of the IP_ADAPTER_ADDRESSES structure was changed on WindowsВ XP with Service PackВ 1 (SP1) and later. Several additional members were added to this structure. The size of the IP_ADAPTER_ADDRESSES structure was also changed on WindowsВ Vista and later. A number of additional members were added to this structure. The size of the IP_ADAPTER_ADDRESSES structure also changed on WindowsВ Vista with Service PackВ 1 (SP1)and later and onWindows ServerВ 2008 and later. One additional member was added to this structure. The Length member of the IP_ADAPTER_ADDRESSES structure returned in the linked list of structures in the buffer pointed to by the AdapterAddresses parameter should be used to determine which version of the IP_ADAPTER_ADDRESSES structure is being used.
The GetIpAddrTable function retrieves the interface–to–IPv4 address mapping table on a local computer and returns this information in an MIB_IPADDRTABLE structure.
On the Platform Software Development Kit (SDK) released for Windows ServerВ 2003 and earlier, the return value for the GetAdaptersAddresses function was defined as a DWORD, rather than a ULONG.
The SOCKET_ADDRESS structure is used in the IP_ADAPTER_ADDRESSES structure pointed to by the AdapterAddresses parameter. On the Microsoft Windows Software Development Kit (SDK) released for WindowsВ Vista and later, the organization of header files has changed and the SOCKET_ADDRESS structure is defined in the Ws2def.h header file which is automatically included by the Winsock2.h header file. On the Platform SDK released for Windows ServerВ 2003 and WindowsВ XP, the SOCKET_ADDRESS structure is declared in the Winsock2.h header file. In order to use the IP_ADAPTER_ADDRESSES structure, the Winsock2.h header file must be included before the Iphlpapi.h header file.
Examples
This example retrieves the IP_ADAPTER_ADDRESSES structure for the adapters associated with the system and prints some members for each adapter interface.
Источник
Ошибка конфигурации call to getadaptersaddresses failed with error
This forum has migrated to Microsoft Q&A. Visit Microsoft Q&A to post new questions.
Asked by:
Question
I use the API GetAdaptersAddresses() to get the network adapters information.
But I found it has a memory leak problem: when I finished calling this API, and use HeapFree() to free the memory, it look likes not really works in NT 5.x.
Anyone can help me? Thanks!
Here is the test code:
// Test_GetAdaptersAddresses_MemUsages.cpp |
#include |
#include |
#include |
#include |
#include |
#pragma comment(lib, «iphlpapi.lib») #pragma comment(lib, «psapi.lib» ) #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) #define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) void Try_GetAdaptersAddresses( void ); void PrintMemoryUsage(DWORD dwProcessID); int _tmain( int argc, _TCHAR* argv[]) < OSVERSIONINFO osvi; DWORD dwProcessID; ZeroMemory(&osvi, sizeof (OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); GetVersionEx(&osvi); _tprintf(_T( «nWindows version:t%u.%u, %sn» ), osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.szCSDVersion); dwProcessID = GetCurrentProcessId(); _tprintf(_T( «Current process ID: t%un» ), dwProcessID); _tprintf(_T( «n* Memory usage of current process before GetAdaptersAddresses()n» )); PrintMemoryUsage(dwProcessID); Try_GetAdaptersAddresses(); Sleep(1000); _tprintf(_T( «n* Memory usage of current process After GetAdaptersAddresses()n» )); PrintMemoryUsage(dwProcessID); return 0; > void Try_GetAdaptersAddresses( void ) < _tprintf(_T( «nTry to GetAdaptersAddresses.n» )); PIP_ADAPTER_ADDRESSES pAddresses = NULL; ULONG outBufLen = 0; ULONG family = AF_UNSPEC; ULONG flags = GAA_FLAG_INCLUDE_PREFIX; DWORD dwRetVal = 0; outBufLen = sizeof (IP_ADAPTER_ADDRESSES); pAddresses = (IP_ADAPTER_ADDRESSES *) MALLOC(outBufLen); if (pAddresses == NULL) < _tprintf(_T( «Memory allocation failed for IP_ADAPTER_ADDRESSES structn» )); return ; > // Make an initial call to GetAdaptersAddresses to get the // size needed into the outBufLen variable if (GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen) == ERROR_BUFFER_OVERFLOW) < FREE(pAddresses); pAddresses = (IP_ADAPTER_ADDRESSES *) MALLOC(outBufLen); > if (pAddresses == NULL) < _tprintf(_T( «Memory allocation failed for IP_ADAPTER_ADDRESSES structn» )); > // Make a second call to GetAdapters Addresses to get the // actual data we want _tprintf(_T( «Memory allocated for GetAdapterAddresses = %d bytesn» , outBufLen)); dwRetVal = GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen); if (dwRetVal == NO_ERROR) < _tprintf(_T( «GetAdapterAddresses successful.n» )); > else < _tprintf(_T( «Call to GetAdaptersAddresses failed with error: %dn» ), dwRetVal); > _tprintf(_T( «Frees memory by HeapFree() » )); BOOL bFreeResult = FREE(pAddresses); if (bFreeResult) _tprintf(_T( «success.n» ), dwRetVal); else _tprintf(_T( «failed.n» )); return ; > // Try_GetAdaptersAddresses() void PrintMemoryUsage(DWORD dwProcessID) < HANDLE hProcess; PROCESS_MEMORY_COUNTERS pmc; DWORD dwSize = sizeof (pmc); hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessID ); if (NULL == hProcess) return ; if (GetProcessMemoryInfo(hProcess, &pmc, dwSize)) < _tprintf(_T( » WorkingSet Size: t%u KBn» ), pmc.WorkingSetSize / 1024 ); > CloseHandle( hProcess ); > // PrintMemoryUsage()
Here is the result in Windows 2003:
Windows version: 5.2, Service Pack 2 |
Current process ID: 3896 |
* Memory usage of current process before GetAdaptersAddresses() |
WorkingSet Size: 1832 KB |
Try to GetAdaptersAddresses. |
Memory allocated for GetAdapterAddresses = 1916 bytes |
GetAdapterAddresses successful. |
Frees memory by HeapFree() success. |
* Memory usage of current process After GetAdaptersAddresses() |
WorkingSet Size: 5680 KB |
Here is the result in Windows 7:
Источник
I’m new to C++, and I want to test the example in this link:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa366058.aspx
When I build my project, I get many errors, and I don’t know WHY.
I copied the example code exactly, and include the necessary headers.
I’m using Eclipse as my IDE.
This is my code:
#include <windows.h>
#include <winsock2.h>
#include <iphlpapi.h>
#include <iptypes.h>
#include <stdio.h>
#include <iostream>
#pragma comment(lib, "IPHLPAPI.lib")
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
/* Note: could also use malloc() and free() */
int __cdecl main(int argc, char **argv)
{
/* Declare and initialize variables */
DWORD dwSize = 0;
DWORD dwRetVal = 0;
unsigned int i = 0;
// Set the flags to pass to GetAdaptersAddresses
ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
// default to unspecified address family (both)
ULONG family = AF_UNSPEC;
LPVOID lpMsgBuf = NULL;
PIP_ADAPTER_ADDRESSES pAddresses = NULL;
ULONG outBufLen = 0;
PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
PIP_ADAPTER_ANYCAST_ADDRESS pAnycast = NULL;
PIP_ADAPTER_MULTICAST_ADDRESS pMulticast = NULL;
IP_ADAPTER_DNS_SERVER_ADDRESS *pDnServer = NULL;
IP_ADAPTER_PREFIX *pPrefix = NULL;
if (argc != 2) {
printf(" Usage: getadapteraddresses familyn");
printf(" getadapteraddresses 4 (for IPv4)n");
printf(" getadapteraddresses 6 (for IPv6)n");
printf(" getadapteraddresses A (for both IPv4 and IPv6)n");
exit(1);
}
if (atoi(argv[1]) == 4)
family = AF_INET;
else if (atoi(argv[1]) == 6)
family = AF_INET6;
outBufLen = sizeof (IP_ADAPTER_ADDRESSES);
pAddresses = (IP_ADAPTER_ADDRESSES *) MALLOC(outBufLen);
// Make an initial call to GetAdaptersAddresses to get the
// size needed into the outBufLen variable
if (GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen)
== ERROR_BUFFER_OVERFLOW) {
FREE(pAddresses);
pAddresses = (IP_ADAPTER_ADDRESSES *) MALLOC(outBufLen);
}
if (pAddresses == NULL) {
printf("Memory allocation failed for IP_ADAPTER_ADDRESSES structn");
exit(1);
}
// Make a second call to GetAdapters Addresses to get the
// actual data we want
printf("Memory allocated for GetAdapterAddresses = %d bytesn", outBufLen);
printf("Calling GetAdaptersAddresses function with family = ");
if (family == AF_INET)
printf("AF_INETn");
if (family == AF_INET6)
printf("AF_INET6n");
if (family == AF_UNSPEC)
printf("AF_UNSPECnn");
dwRetVal =
GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);
if (dwRetVal == NO_ERROR) {
// If successful, output some information from the data we received
pCurrAddresses = pAddresses;
while (pCurrAddresses) {
printf("tLength of the IP_ADAPTER_ADDRESS struct: %ldn",
pCurrAddresses->Length);
printf("tIfIndex (IPv4 interface): %un", pCurrAddresses->IfIndex);
printf("tAdapter name: %sn", pCurrAddresses->AdapterName);
pUnicast = pCurrAddresses->FirstUnicastAddress;
if (pUnicast != NULL) {
for (i = 0; pUnicast != NULL; i++)
pUnicast = pUnicast->Next;
printf("tNumber of Unicast Addresses: %dn", i);
} else
printf("tNo Unicast Addressesn");
pAnycast = pCurrAddresses->FirstAnycastAddress;
if (pAnycast) {
for (i = 0; pAnycast != NULL; i++)
pAnycast = pAnycast->Next;
printf("tNumber of Anycast Addresses: %dn", i);
} else
printf("tNo Anycast Addressesn");
pMulticast = pCurrAddresses->FirstMulticastAddress;
if (pMulticast) {
for (i = 0; pMulticast != NULL; i++)
pMulticast = pMulticast->Next;
printf("tNumber of Multicast Addresses: %dn", i);
} else
printf("tNo Multicast Addressesn");
pDnServer = pCurrAddresses->FirstDnsServerAddress;
if (pDnServer) {
for (i = 0; pDnServer != NULL; i++)
pDnServer = pDnServer->Next;
printf("tNumber of DNS Server Addresses: %dn", i);
} else
printf("tNo DNS Server Addressesn");
printf("tDNS Suffix: %wSn", pCurrAddresses->DnsSuffix);
printf("tDescription: %wSn", pCurrAddresses->Description);
printf("tFriendly name: %wSn", pCurrAddresses->FriendlyName);
if (pCurrAddresses->PhysicalAddressLength != 0) {
printf("tPhysical address: ");
for (i = 0; i < pCurrAddresses->PhysicalAddressLength;
i++) {
if (i == (pCurrAddresses->PhysicalAddressLength - 1))
printf("%.2Xn",
(int) pCurrAddresses->PhysicalAddress[i]);
else
printf("%.2X-",
(int) pCurrAddresses->PhysicalAddress[i]);
}
}
printf("tFlags: %ldn", pCurrAddresses->Flags);
printf("tMtu: %lun", pCurrAddresses->Mtu);
printf("tIfType: %ldn", pCurrAddresses->IfType);
printf("tOperStatus: %ldn", pCurrAddresses->OperStatus);
printf("tIpv6IfIndex (IPv6 interface): %un",
pCurrAddresses->Ipv6IfIndex);
printf("tZoneIndices (hex): ");
for (i = 0; i < 16; i++)
printf("%lx ", pCurrAddresses->ZoneIndices[i]);
printf("n");
pPrefix = pCurrAddresses->FirstPrefix;
if (pPrefix) {
for (i = 0; pPrefix != NULL; i++)
pPrefix = pPrefix->Next;
printf("tNumber of IP Adapter Prefix entries: %dn", i);
} else
printf("tNo IP Adapter Prefix entriesn");
printf("n");
pCurrAddresses = pCurrAddresses->Next;
}
} else {
printf("Call to GetAdaptersAddresses failed with error: %dn",
dwRetVal);
if (dwRetVal == ERROR_NO_DATA)
printf("tNo addresses were found for the requested parametersn");
else {
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) & lpMsgBuf, 0, NULL)) {
printf("tError: %s", lpMsgBuf);
LocalFree(lpMsgBuf);
FREE(pAddresses);
exit(1);
}
}
}
FREE(pAddresses);
return 0;
}
These is the errors:
Info: Internal Builder is used for build
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o "src\test3.o" "..\src\test3.cpp"
..srctest3.cpp:7:0: warning: ignoring #pragma comment [-Wunknown-pragmas]
#pragma comment(lib, "IPHLPAPI.lib")
..srctest3.cpp:8:0: warning: ignoring #pragma comment [-Wunknown-pragmas]
#pragma comment(lib, "Ws2_32.lib")
..srctest3.cpp: In function 'int main(int, char**)':
..srctest3.cpp:26:19: error: 'GAA_FLAG_INCLUDE_PREFIX' was not declared in this scope
ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
^~~~~~~~~~~~~~~~~~~~~~~
..srctest3.cpp:33:5: error: 'PIP_ADAPTER_ADDRESSES' was not declared in this scope
PIP_ADAPTER_ADDRESSES pAddresses = NULL; // @suppress("Type cannot be resolved")
^~~~~~~~~~~~~~~~~~~~~
..srctest3.cpp:36:27: error: expected ';' before 'pCurrAddresses'
PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
^~~~~~~~~~~~~~
..srctest3.cpp:37:5: error: 'PIP_ADAPTER_UNICAST_ADDRESS' was not declared in this scope
PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
^~~~~~~~~~~~~~~~~~~~~~~~~~~
..srctest3.cpp:38:5: error: 'PIP_ADAPTER_ANYCAST_ADDRESS' was not declared in this scope
PIP_ADAPTER_ANYCAST_ADDRESS pAnycast = NULL;
^~~~~~~~~~~~~~~~~~~~~~~~~~~
..srctest3.cpp:39:5: error: 'PIP_ADAPTER_MULTICAST_ADDRESS' was not declared in this scope
PIP_ADAPTER_MULTICAST_ADDRESS pMulticast = NULL;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
..srctest3.cpp:40:5: error: 'IP_ADAPTER_DNS_SERVER_ADDRESS' was not declared in this scope
IP_ADAPTER_DNS_SERVER_ADDRESS *pDnServer = NULL;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
..srctest3.cpp:40:36: error: 'pDnServer' was not declared in this scope
IP_ADAPTER_DNS_SERVER_ADDRESS *pDnServer = NULL;
^~~~~~~~~
..srctest3.cpp:41:5: error: 'IP_ADAPTER_PREFIX' was not declared in this scope
IP_ADAPTER_PREFIX *pPrefix = NULL;
^~~~~~~~~~~~~~~~~
..srctest3.cpp:41:24: error: 'pPrefix' was not declared in this scope
IP_ADAPTER_PREFIX *pPrefix = NULL;
^~~~~~~
..srctest3.cpp:56:25: error: 'IP_ADAPTER_ADDRESSES' was not declared in this scope
outBufLen = sizeof (IP_ADAPTER_ADDRESSES);
^~~~~~~~~~~~~~~~~~~~
..srctest3.cpp:57:5: error: 'pAddresses' was not declared in this scope
pAddresses = (IP_ADAPTER_ADDRESSES *) MALLOC(outBufLen);
^~~~~~~~~~
..srctest3.cpp:57:41: error: expected primary-expression before ')' token
pAddresses = (IP_ADAPTER_ADDRESSES *) MALLOC(outBufLen);
^
..srctest3.cpp:61:73: error: 'GetAdaptersAddresses' was not declared in this scope
if (GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen)
^
..srctest3.cpp:64:45: error: expected primary-expression before ')' token
pAddresses = (IP_ADAPTER_ADDRESSES *) MALLOC(outBufLen);
^
..srctest3.cpp:73:78: warning: format '%d' expects argument of type 'int', but argument 2 has type 'ULONG {aka long unsigned int}' [-Wformat=]
printf("Memory allocated for GetAdapterAddresses = %d bytesn", outBufLen);
^
..srctest3.cpp:83:73: error: 'GetAdaptersAddresses' was not declared in this scope
GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);
^
..srctest3.cpp:87:9: error: 'pCurrAddresses' was not declared in this scope
pCurrAddresses = pAddresses;
^~~~~~~~~~~~~~
..srctest3.cpp:94:13: error: 'pUnicast' was not declared in this scope
pUnicast = pCurrAddresses->FirstUnicastAddress;
^~~~~~~~
..srctest3.cpp:102:13: error: 'pAnycast' was not declared in this scope
pAnycast = pCurrAddresses->FirstAnycastAddress;
^~~~~~~~
..srctest3.cpp:110:13: error: 'pMulticast' was not declared in this scope
pMulticast = pCurrAddresses->FirstMulticastAddress;
^~~~~~~~~~
..srctest3.cpp:167:24: warning: format '%d' expects argument of type 'int', but argument 2 has type 'DWORD {aka long unsigned int}' [-Wformat=]
dwRetVal);
^
..srctest3.cpp:174:47: warning: format '%s' expects argument of type 'char*', but argument 2 has type 'LPVOID {aka void*}' [-Wformat=]
printf("tError: %s", lpMsgBuf);
^
..srctest3.cpp:20:11: warning: unused variable 'dwSize' [-Wunused-variable]
DWORD dwSize = 0;
^~~~~~
Hi there,
I am developing an application which uses GetAdaptersAddresses. It works under XP service pack 2, but fails under vista home premium. I get code 13 whenever i call it(formated with FormatMessage i get «invalid data»), and the last parameter (related with length or the structure to be allocated) doesn’t change at all. I call this function twice, in this way:
{
PIP_ADAPTER_ADDRESSES adapterAddresses = NULL;
PIP_ADAPTER_ADDRESSES adapterAddress = NULL;
DWORD ret = 0;
ULONG len = 0;
len = sizeof (IP_ADAPTER_ADDRESSES);
adapterAddresses = (IP_ADAPTER_ADDRESSES*) malloc(len);
if (adapterAddresses == NULL) {
// Don’t care about return value
return INADDR_ANY;
}
// Try to get the size. It is not modified under vista…..
if ((ret=GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX , NULL, adapterAddresses, &len)) == ERROR_BUFFER_OVERFLOW){
// This should happen….
MessageBox(NULL,L»RESERVING»,L»LLL»,MB_OK);
free(adapterAddresses);
adapterAddresses = (IP_ADAPTER_ADDRESSES*) malloc(len);
if (adapterAddresses == NULL){
return INADDR_ANY;
}
}
// Check return value.
switch(ret){
case NO_ERROR :MessageBox(NULL,L»AdapterAddress OK!!», L»Enter Interfaces», MB_OK);break;
case ERROR_ADDRESS_NOT_ASSOCIATED :MessageBox(NULL,L»AdapterAddress FAILED!!-NO ADDRESS ASSOCIATED», L»Enter Interfaces», MB_OK);break;
case ERROR_BUFFER_OVERFLOW :MessageBox(NULL,L»AdapterAddress FAILED!!-OVERFLOW», L»Enter Interfaces», MB_OK);break;
case ERROR_INVALID_PARAMETER :MessageBox(NULL,L»AdapterAddress FAILED!!- PARAMETERS», L»Enter Interfaces», MB_OK);break;
case ERROR_NOT_ENOUGH_MEMORY :MessageBox(NULL,L»AdapterAddress FAILED!!- NO MEMORY», L»Enter Interfaces», MB_OK);break;
case ERROR_NO_DATA :
MessageBox(NULL,L»AdapterAddress FAILED!!- NO DATA», L»Enter Interfaces», MB_OK);break;
default :
{
LPVOID MsgBuf;
if (FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
ret,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &MsgBuf,
0,
NULL ))
MessageBox(NULL,(LPCWSTR)MsgBuf,L»ERROR ADAPTER 1″,MB_OK);
WCHAR aux[100];
wsprintf(aux,L»Len %d — ret %d»,len,ret);
MessageBox(NULL,aux,L»data»,MB_OK);
}
break;
}
ret = GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, NULL, adapterAddresses, &len);
// Check return value
switch(ret){
case NO_ERROR :MessageBox(NULL,L»AdapterAddress OK!!», L»Enter Interfaces», MB_OK);break;
case ERROR_ADDRESS_NOT_ASSOCIATED :MessageBox(NULL,L»AdapterAddress FAILED!!-NO ADDRESS ASSOCIATED», L»Enter Interfaces», MB_OK);break;
case ERROR_BUFFER_OVERFLOW :MessageBox(NULL,L»AdapterAddress FAILED!!-OVERFLOW», L»Enter Interfaces», MB_OK);break;
case ERROR_INVALID_PARAMETER :MessageBox(NULL,L»AdapterAddress FAILED!!- PARAMETERS», L»Enter Interfaces», MB_OK);break;
case ERROR_NOT_ENOUGH_MEMORY :MessageBox(NULL,L»AdapterAddress FAILED!!- NO MEMORY», L»Enter Interfaces», MB_OK);break;
case ERROR_NO_DATA :
MessageBox(NULL,L»AdapterAddress FAILED!!- NO DATA», L»Enter Interfaces», MB_OK);break;
default :
{
LPVOID MsgBuf;
// printf(«Call to GetAdaptersAddresses failed.n»);
if (FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
ret,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &MsgBuf,
0,
NULL ))
MessageBox(NULL,(LPCWSTR)MsgBuf,L»ERROR ADAPTER»,MB_OK);
WCHAR aux[100];
wsprintf(aux,L»Len %d — ret %d»,len,ret);
MessageBox(NULL,aux,L»data 2 «,MB_OK);
}
break;
}
// Function continues….
}
Being a newbi with AutoHotKey deveopment, I am trying to extract the network configuration details out of iphlpapi.dllGetAdaptersAddresses.
all needed information in IP_ADAPTER_ADDRESSES structure I manged reasonably. Just trying to get information which are exposed by Pointers I completely struggle.
Any hint or support is very much appreciated.
Code: Select all
#Persistent
#warn
OutPut := GetAdaptersAddresses()
PrintArr(OutPut)
GetAdaptersAddresses()
{
vAdapterAddresses := A_PtrSize ? "Ptr" : "UInt"
vSizePointer := A_PtrSize ? "Ptr" : "UInt"
vSizePointer := 0
; initial call to GetAdaptersAddresses to get the necessary size
vResult := DllCall("iphlpapi.dllGetAdaptersAddresses", "Int", 0, "Int", 0, "UPTR", 0, "UPTR", &vAdapterAddresses, "UPTR", &vSizePointer)
if ( vResult = 111) ; ERROR_BUFFER_OVERFLOW
{
;msgbox %vResult% . " / " . %vSizePointer%
if !(VarSetCapacity(vAdapterAddresses, vSizePointer, 0)) ; vSizePointer ==> 1x = 704 | 2x = 1408 | 3x = 2112
{
msgbox "Memory allocation failed for IP_ADAPTER_INFO struct"
return "Memory allocation failed for IP_ADAPTER_INFO struct"
}
}
; second call to GetAdapters Addresses to get the actual data we want
vResult := DllCall("iphlpapi.dllGetAdaptersAddresses", "UInt", 0, "UInt", 0, "UPTR", 0, "UPTR", &vAdapterAddresses, "UPTR", &vSizePointer)
if ( vResult != 0) ; NO_ERROR / ERROR_SUCCESS
{
msgbox "Call to GetAdaptersAddresses failed with error: " %vResult%
return "Call to GetAdaptersAddresses failed with error: " vResult
}
; get some information from the data we received
addr := &vAdapterAddresses+0, IP_ADAPTER_ADDRESSES := {}
y := &vSizePointer
msgbox "addr = " %addr% " / length " %y%
iaddr := addr
while (addr)
{
IP_ADAPTER_ADDRESSES [A_Index, "addr"] := addr
vLength := NumGet(addr+0, o := 0, "UINT") , o += A_PtrSize ; 0
IP_ADAPTER_ADDRESSES [A_Index, "vLength"] := vLength
vIfIndex := NumGet(addr+0, o , "UINT") , o += A_PtrSize ; 4
IP_ADAPTER_ADDRESSES [A_Index, "ifIndex"] := vIfIndex
vNext := NumGet(addr+0, o , "UINT") , o += A_PtrSize ; 8
; IP_ADAPTER_ADDRESSES [A_Index, "Next"] := vNext
pAdapterName := NumGet(addr+0, o, "UPTR"), o += A_PtrSize ; 12
vAdapterName := StrGet(pAdapterName, "CP0")
IP_ADAPTER_ADDRESSES [A_Index, "AdapterName"] := vAdapterName
pFirstUnicastAddress := NumGet(addr+0, o, "UPTR"), o += A_PtrSize ;16
vTest := NumGet(pFirstUnicastAddress, 12, "UINT")
IP_ADAPTER_ADDRESSES [A_Index, "FirstUnicastAddress"] := pFirstUnicastAddress
pFirstAnycastAddress := NumGet(addr+0, o, "UPTR") , o += A_PtrSize ;20
IP_ADAPTER_ADDRESSES [A_Index, "FirstAnycastAddress"] := pFirstAnycastAddress
pFirstMulticastAddress := NumGet(addr+0, o, "UPTR") , o += A_PtrSize ;24
IP_ADAPTER_ADDRESSES [A_Index, "FirstMulticastAddress"]:= pFirstMulticastAddress
IP_ADAPTER_ADDRESSES [A_Index, "a_pos"] := o
pFirstDnsServerAddress := NumGet(addr+0, o, "UPTR") , o += A_PtrSize ;28
; lpsaAddress := NumGet(pFirstDnsServerAddress, 12, "PTR") ;8 ;10.0.0.1
; dwAddressLength := NumGet(pFirstDnsServerAddress, 16, "INT") ;8 ;10.0.0.1
; vTest := DllCall("Ws2_32.libWSAAddressToString", "UPTR", lpsaAddress, "UPTR", dwAddressLength, "UPTR", 0, "UPTR", &lpszAddressString, "UPTR", &lpdwAddressStringLength)
IP_ADAPTER_ADDRESSES [A_Index, "DnsTest"] := vTest
IP_ADAPTER_ADDRESSES [A_Index, "FirstDnsServerAddress"]:= pFirstDnsServerAddress
; msgbox %A_Index% " / " %pFirstDnsServerAddress% ;" / " %vDnsLength% " / " %t%
pDnsSuffix := NumGet(addr+0, o, "UINT") , o += A_PtrSize ;32
vDnsSuffix := StrGet(pDnsSuffix)
IP_ADAPTER_ADDRESSES [A_Index, "DnsSuffix"] := vDnsSuffix
pDescription := NumGet(addr+0, o, "UINT"), o += A_PtrSize ;36
vDescription := StrGet(pDescription)
IP_ADAPTER_ADDRESSES [A_Index, "Description"] := vDescription
pFriendlyName := NumGet(addr+0, o, "UINT"), o += A_PtrSize ;40
vFriendlyName := StrGet(pFriendlyName )
IP_ADAPTER_ADDRESSES [A_Index, "FriendlyName"] := vFriendlyName
pPhysicalAddressLength := NumGet(addr+0, o + 8, "UCHAR") ;52
IP_ADAPTER_ADDRESSES [A_Index, "PhysicalAddressLength"]:= pPhysicalAddressLength
mac :=""
loop % pPhysicalAddressLength
mac .= Format("{:02X}", NumGet(addr+0, o + A_Index - 1, "UChar")) "-"
IP_ADAPTER_ADDRESSES[A_Index, "Address"] := SubStr(mac, 1, -1), mac := "", o += 12 ;44
pFlags := NumGet(addr+0, o, "UINT"), o += 4 ;56
IP_ADAPTER_ADDRESSES [A_Index, "Flags"] := pFlags
pMtu := NumGet(addr+0, o, "UINT"), o += 4 ;60
IP_ADAPTER_ADDRESSES [A_Index, "Mtu"] := pMtu
pIfType := NumGet(addr+0, o, "UINT"), o += 4 ;64
IP_ADAPTER_ADDRESSES [A_Index, "ifType"] := pIfType
pIfOperStatus := NumGet(addr+0, o, "UINT"), o += 4 ;68
IP_ADAPTER_ADDRESSES [A_Index, "ifOperStatus"] := pIfOperStatus
;msgbox "test : " . %addr%+0
addr := vNext
}
;msgbox "test : " . NumGet(addr+0, o := A_PtrSize, "UInt")
; output the data we received and free the buffer
return IP_ADAPTER_ADDRESSES, VarSetCapacity(vAdapterAddresses, 0), VarSetCapacity(addr, 0)
}
PrintArr(Arr, Option := "w1200 h200", GuiNum := 90)
{
cnt:=0
for index, obj in Arr {
if (A_Index = 1) {
for k, v in obj {
Columns .= k "|"
cnt++
}
Gui, %GuiNum%: Margin, 5, 5
Gui, %GuiNum%: Add, ListView, %Option%, % Columns
}
RowNum := A_Index
Gui, %GuiNum%: default
LV_Add("")
for k, v in obj {
LV_GetText(Header, 0, A_Index)
if (k <> Header) {
FoundHeader := False
loop % LV_GetCount("Column") {
LV_GetText(Header, 0, A_Index)
if (k <> Header)
continue
else {
FoundHeader := A_Index
break
}
}
if !(FoundHeader) {
LV_InsertCol(cnt + 1, "", k)
cnt++
ColNum := "Col" cnt
} else
ColNum := "Col" FoundHeader
} else
ColNum := "Col" A_Index
LV_Modify(RowNum, ColNum, (IsObject(v) ? "Object()" : v))
}
}
loop % LV_GetCount("Column")
LV_ModifyCol(A_Index, "AutoHdr")
Gui, %GuiNum%: Show,, Array
}
- Download source — 2.6 KB
Introduction
I’m working on a commercial software related to an industrial field that happens to require specific network settings.
For reliability, we aim our software to work only with an ethernet adapter on a harsh environment but we don’t really control the kind of computer our customers are using.
Nowadays, computers come with a variety of connection devices besides an ethernet card, such as bluetooth or wi-fi adapters. To make things worse, some programs like WMWare create virtual adapters for their own use. We need to automatically find a physical ethernet card and enforce a given set of parameters for our program to work properly.
The industrial field runs at a very different pace than software development and change happens slowly. That makes it necessary to support older OS like Windows XP as they are seldom updated, since most of the times the computers are not even connected to the internet.
As the code changes system settings, administrator privileges are required.
Background
The code below is a compilation of the examples shown on MSDN for GetAdaptersAddresses
, WlanOpenHandle
and WlanEnumInterfaces
plus several ideas taken from different blogs.
Using the Code
The code is self explanatory. All dependencies are explicitly included in the cpp file. Additionally, this project relies on MFC for simple string
manipulation with CString
and convenient data handling with CMap
.
For a non-MFC project, it should be simple to get rid of MFC classes by using C or C++ standard string
manipulation routines. It should be necessary to get rid of CRegKey
class and replace it with standard APIs too.
The first step is to retrieve all network adapters with IPv4 compatibility using GetAdaptersAddresses
, as shown in the MSDN.
CMapStringToString mapAdapters; ULONG nFlags = GAA_FLAG_INCLUDE_PREFIX; ULONG nFamily = AF_INET; PIP_ADAPTER_ADDRESSES pAddresses = NULL; PIP_ADAPTER_ADDRESSES pCurrAddress = NULL; ULONG nBufLen = 16324, nTries = 0, nMaxTries = 3; DWORD dwResult; do { pAddresses = (IP_ADAPTER_ADDRESSES*) MALLOC(nBufLen); if (pAddresses == NULL) { _tprintf(_T("Memory allocation failed for IP_ADAPTER_ADDRESSES structn")); return SNA_ERROR_MALLOC; } dwResult = GetAdaptersAddresses(nFamily, nFlags, NULL, pAddresses, &nBufLen); if (dwResult == ERROR_BUFFER_OVERFLOW) { FREE(pAddresses); pAddresses = NULL; } else break; nTries++; } while (dwResult == ERROR_BUFFER_OVERFLOW && nTries < nMaxTries); if (dwResult != NO_ERROR) { _tprintf(_T("Call to GetAdaptersAddresses failed with error: %dn"), dwResult); FREE(pAddresses); return SNA_ERROR_GETADAPTERSADDRESS; } pCurrAddress = pAddresses; while (pCurrAddress) { if (pCurrAddress->IfType == IF_TYPE_ETHERNET_CSMACD) { USES_CONVERSION; CString cKey = A2T(pCurrAddress->AdapterName); mapAdapters[cKey] = pCurrAddress-&FriendlyName; } pCurrAddress = pCurrAddress-&Next; } FREE(pAddresses); if (mapAdapters.GetCount() == 0) { _tprintf(_T("No ethernet adapter foundn")); return SNA_ERROR_NOADAPTERFOUND; }
On older OSes like Windows XP, wireless network cards are reported as IF_TYPE_ETHERNET_CSMACD
.
Gather identifiers of wireless adapters and remove them for the list generated in the step above.
OSVERSIONINFO osvi; ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osvi); if (osvi.dwMajorVersion < 6) { _tprintf(_T("Compatibility moden")); HANDLE hClient = NULL; DWORD dwMaxClient = 2; DWORD dwCurVersion = 0; PWLAN_INTERFACE_INFO_LIST pIfList = NULL; PWLAN_INTERFACE_INFO pIfInfo = NULL; dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &hClient); if (dwResult == ERROR_SUCCESS) { dwResult = WlanEnumInterfaces(hClient, NULL, &pIfList); if (dwResult == ERROR_SUCCESS) { WCHAR szWlanGuid[256] = { 0 }; int nMaxLen = 256; for (int i = 0; i < (int) pIfList->dwNumberOfItems; i++) { pIfInfo = (WLAN_INTERFACE_INFO *) &pIfList->InterfaceInfo[i]; if (StringFromGUID2(pIfInfo->InterfaceGuid, (LPOLESTR) szWlanGuid, nMaxLen) > 0) { CString cKey = szWlanGuid; CString cValue; if (mapAdapters.Lookup(cKey, cValue)) mapAdapters.RemoveKey(szWlanGuid); } } } else _tprintf(_T("WlanEnumInterfaces failed with error: %un"), dwResult); WlanCloseHandle(hClient, NULL); } else _tprintf(_T("WlanOpenHandle failed with error: %un"), dwResult); }
Use registry entries in order to distinguish between physical and virtual adapters.
CString sFriendlyName; CRegKey oRegKey; TCHAR szSubkey[1024]; DWORD dwNameLength; CString sBaseKey = _T("SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards"); if (ERROR_SUCCESS == oRegKey.Open(HKEY_LOCAL_MACHINE, sBaseKey, KEY_READ | KEY_ENUMERATE_SUB_KEYS)) { DWORD dwIndex = 0; while (TRUE) { dwNameLength = 1024; if (ERROR_NO_MORE_ITEMS == oRegKey.EnumKey (dwIndex++, szSubkey, &dwNameLength, NULL)) break; CRegKey oRegKeyCard; if (ERROR_SUCCESS == oRegKeyCard.Open (HKEY_LOCAL_MACHINE, sBaseKey + _T("\") + szSubkey, KEY_READ)) { TCHAR szGuid[256]; DWORD dwGuidLength = 256; CString cGuid; if (ERROR_SUCCESS == oRegKeyCard.QueryStringValue (_T("ServiceName"), szGuid, &dwGuidLength)) { CString cValue; cGuid = szGuid; cGuid.Trim(); if (mapAdapters.Lookup(cGuid, cValue)) sFriendlyName = cValue; } oRegKeyCard.Close(); if (!sFriendlyName.IsEmpty()) break; } } oRegKey.Close(); } if (sFriendlyName.IsEmpty()) { CString sKey; POSITION pos = mapAdapters.GetStartPosition(); if (pos != NULL) mapAdapters.GetNextAssoc(pos, sKey, sFriendlyName); } if (sFriendlyName.IsEmpty()) { _tprintf(_T("No ethernet adapter foundn")); return SNA_ERROR_NOADAPTERFOUND; }
We have already chosen an adapter, so the last step is pretty straightforward. Just set IP, mask and gateway using netsh
.
This last step requires administrator privileges:
CString sIp = _T("192.168.1.2"); CString sMask = _T("255.255.255.0"); CString sGateway = _T("192.168.1.1"); CString sNetshIp; sNetshIp.Format(_T("netsh interface ip set address name="%s" static %s %s %s"), sFriendlyName, sIp, sMask, sGateway); sNetshIp.Trim(); CString sDns = _T("8.8.8.8"); CString sNetshDns; sNetshDns.Format(_T("netsh interface ip set dns name="%s" static %s"), sFriendlyName, sDns); _tprintf(_T("Running: %sn"), sNetshIp); ::ShellExecute(NULL, NULL, _T("cmd.exe"), CString(_T("/C ")) + sNetshIp, NULL, SW_HIDE); _tprintf(_T("Running: %sn"), sNetshDns); ::ShellExecute(NULL, NULL, _T("cmd.exe"), CString(_T("/C ")) + sNetshDns, NULL, SW_HIDE); return 0;
References
- https://msdn.microsoft.com/en-us/library/windows/desktop/aa365915%28v=vs.85%29.aspx
- https://msdn.microsoft.com/en-us/library/windows/desktop/ms706716%28v=vs.85%29.aspx
- http://www.howtogeek.com/103190/change-your-ip-address-from-the-command-prompt/
History
- February 29th, 2016 — Initial version
UID | title | description | old-location | tech.root | ms.assetid | ms.date | ms.keywords | req.header | req.include-header | req.target-type | req.target-min-winverclnt | req.target-min-winversvr | req.kmdf-ver | req.umdf-ver | req.ddi-compliance | req.unicode-ansi | req.idl | req.max-support | req.namespace | req.assembly | req.type-library | req.lib | req.dll | req.irql | targetos | req.typenames | req.redist | ms.custom | f1_keywords | dev_langs | topic_type | api_type | api_location | api_name | ||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
NF:iphlpapi.GetAdaptersAddresses |
GetAdaptersAddresses function (iphlpapi.h) |
Retrieves the addresses associated with the adapters on the local computer. |
iphlpgetadaptersaddresses.htm |
IpHlp |
7b34138f-7263-4b73-95df-9e854fd81135 |
12/05/2018 |
AF_INET, AF_INET6, AF_UNSPEC, GAA_FLAG_INCLUDE_ALL_COMPARTMENTS, GAA_FLAG_INCLUDE_ALL_INTERFACES, GAA_FLAG_INCLUDE_GATEWAYS, GAA_FLAG_INCLUDE_PREFIX, GAA_FLAG_INCLUDE_TUNNEL_BINDINGORDER, GAA_FLAG_INCLUDE_WINS_INFO, GAA_FLAG_SKIP_ANYCAST, GAA_FLAG_SKIP_DNS_SERVER, GAA_FLAG_SKIP_FRIENDLY_NAME, GAA_FLAG_SKIP_MULTICAST, GAA_FLAG_SKIP_UNICAST, GetAdaptersAddresses, GetAdaptersAddresses function [IP Helper], _iphlp_getadaptersaddresses, iphlp.getadaptersaddresses, iphlpapi/GetAdaptersAddresses |
iphlpapi.h |
Windows |
Windows XP [desktop apps | UWP apps] |
Windows Server 2003 [desktop apps | UWP apps] |
Iphlpapi.lib |
Iphlpapi.dll |
Windows |
19H1 |
|
c++ |
|
DllExport |
Iphlpapi.dll |
GetAdaptersAddresses |
GetAdaptersAddresses function
-description
The
GetAdaptersAddresses function retrieves the addresses associated with the adapters on the local computer.
-parameters
-param Family [in]
The address family of the addresses to retrieve. This parameter must be one of the following values.
Value | Meaning |
---|---|
|
Return both IPv4 and IPv6 addresses associated with adapters with IPv4 or IPv6 enabled. |
|
Return only IPv4 addresses associated with adapters with IPv4 enabled. |
|
Return only IPv6 addresses associated with adapters with IPv6 enabled. |
-param Flags [in]
The type of addresses to retrieve. The possible values are defined in the Iptypes.h header file. Note that the Iptypes.h header file is automatically included in Iphlpapi.h, and should never be used directly.
This parameter is a combination of the following values. If this parameter is zero, then unicast, anycast, and multicast IP addresses will be returned.
Value | Meaning |
---|---|
|
Do not return unicast addresses. |
|
Do not return IPv6 anycast addresses. |
|
Do not return multicast addresses. |
|
Do not return addresses of DNS servers. |
|
Return a list of IP address prefixes on this adapter. When this flag is set, IP address prefixes are returned for both IPv6 and IPv4 addresses.
This flag is supported on Windows XP with SP1 and later. |
|
Do not return the adapter friendly name. |
|
Return addresses of Windows Internet Name Service (WINS) servers.
This flag is supported on Windows Vista and later. |
|
Return the addresses of default gateways.
This flag is supported on Windows Vista and later. |
|
Return addresses for all NDIS interfaces.
This flag is supported on Windows Vista and later. |
|
Return addresses in all routing compartments.
This flag is not currently supported and reserved for future use. |
|
Return the adapter addresses sorted in tunnel binding order. This flag is supported on Windows Vista and later. |
-param Reserved [in]
This parameter is not currently used, but is reserved for future system use. The calling application should pass NULL for this parameter.
-param AdapterAddresses [in, out]
A pointer to a buffer that contains a linked list of IP_ADAPTER_ADDRESSES structures on successful return.
-param SizePointer [in, out]
A pointer to a variable that specifies the size of the buffer pointed to by AdapterAddresses.
-returns
If the function succeeds, the return value is ERROR_SUCCESS (defined to the same value as NO_ERROR).
If the function fails, the return value is one of the following error codes.
Return code | Description |
---|---|
|
An address has not yet been associated with the network endpoint. DHCP lease information was available. |
|
The buffer size indicated by the SizePointer parameter is too small to hold the adapter information or the AdapterAddresses parameter is NULL. The SizePointer parameter returned points to the required size of the buffer to hold the adapter information. |
|
One of the parameters is invalid. This error is returned for any of the following conditions: the SizePointer parameter is NULL, the Address parameter is not AF_INET, AF_INET6, or AF_UNSPEC, or the address information for the parameters requested is greater than ULONG_MAX. |
|
Insufficient memory resources are available to complete the operation. |
|
No addresses were found for the requested parameters. |
|
Use FormatMessage to obtain the message string for the returned error. |
-remarks
The
GetAdaptersAddresses function can retrieve information for IPv4 and IPv6 addresses.
Addresses are returned as a linked list of IP_ADAPTER_ADDRESSES structures in the buffer pointed to by the AdapterAddresses parameter. The application that calls the GetAdaptersAddresses function must allocate the amount of memory needed to return the IP_ADAPTER_ADDRESSES structures pointed to by the AdapterAddresses parameter. When these returned structures are no longer required, the application should free the memory allocated. This can be accomplished by calling the HeapAlloc function to allocate memory and later calling the HeapFree function to free the allocated memory, as shown in the example code. Other memory allocation and free functions can be used as long as the same family of functions are used for both the allocation and the free function.
GetAdaptersAddresses is implemented only as a synchronous function call. The GetAdaptersAddresses function requires a significant amount of network resources and time to complete since all of the low-level network interface tables must be traversed.
One method that can be used to determine the memory needed to return the IP_ADAPTER_ADDRESSES structures pointed to by the AdapterAddresses parameter is to pass too small a buffer size as indicated in the SizePointer parameter in the first call to the GetAdaptersAddresses function, so the function will fail with ERROR_BUFFER_OVERFLOW. When the return value is ERROR_BUFFER_OVERFLOW, the SizePointer parameter returned points to the required size of the buffer to hold the adapter information. Note that it is possible for the buffer size required for the IP_ADAPTER_ADDRESSES structures pointed to by the AdapterAddresses parameter to change between subsequent calls to the GetAdaptersAddresses function if an adapter address is added or removed. However, this method of using the GetAdaptersAddresses function is strongly discouraged. This method requires calling the GetAdaptersAddresses function multiple times.
The recommended method of calling the GetAdaptersAddresses function is to pre-allocate a 15KB working buffer pointed to by the AdapterAddresses parameter. On typical computers, this dramatically reduces the chances that the GetAdaptersAddresses function returns ERROR_BUFFER_OVERFLOW, which would require calling GetAdaptersAddresses function multiple times. The example code illustrates this method of use.
In versions prior to Windows 10, the order in which adapters appear in the list returned by this function can be controlled from the Network Connections folder: select the Advanced Settings menu item from the Advanced menu. Starting with Windows 10, the order in which adapters appear in the list is determined by the IPv4 or IPv6 route metric.
If the GAA_FLAG_INCLUDE_ALL_INTERFACES is set, then all NDIS adapters will be retrieved even those addresses associated with adapters not bound to an address family specified in the Family parameter. When this flag is not set, then only the addresses that are bound to an adapter enabled for the address family specified in the Family parameter are returned.
The size of the IP_ADAPTER_ADDRESSES structure was changed on Windows XP with Service Pack 1 (SP1) and later. Several additional members were added to this structure. The size of the IP_ADAPTER_ADDRESSES structure was also changed on Windows Vista and later. A number of additional members were added to this structure. The size of the
IP_ADAPTER_ADDRESSES structure also changed on
Windows Vista with Service Pack 1 (SP1)and later and onWindows Server 2008 and later. One additional member was added to this structure. The Length member of the IP_ADAPTER_ADDRESSES structure returned in the linked list of structures in the buffer pointed to by the AdapterAddresses parameter should be used to determine which version of the IP_ADAPTER_ADDRESSES structure is being used.
The GetIpAddrTable function retrieves the interface–to–IPv4 address mapping table on a local computer and returns this information in an MIB_IPADDRTABLE structure.
On the Platform Software Development Kit (SDK) released for Windows Server 2003 and earlier, the return value for the GetAdaptersAddresses function was defined as a DWORD, rather than a ULONG.
The SOCKET_ADDRESS structure is used in the IP_ADAPTER_ADDRESSES structure pointed to by the AdapterAddresses parameter. On the Microsoft Windows Software Development Kit (SDK) released for Windows Vista and later, the organization of header files has changed and the SOCKET_ADDRESS structure is defined in the Ws2def.h header file which is automatically included by the Winsock2.h header file. On the Platform SDK released for Windows Server 2003 and Windows XP, the SOCKET_ADDRESS structure is declared in the Winsock2.h header file. In order to use the IP_ADAPTER_ADDRESSES structure, the Winsock2.h header file must be included before the Iphlpapi.h header file.
Examples
This example retrieves the IP_ADAPTER_ADDRESSES structure for the adapters associated with the system and prints some members for each adapter interface.
#include <winsock2.h> #include <iphlpapi.h> #include <stdio.h> #include <stdlib.h> // Link with Iphlpapi.lib #pragma comment(lib, "IPHLPAPI.lib") #define WORKING_BUFFER_SIZE 15000 #define MAX_TRIES 3 #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) #define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) /* Note: could also use malloc() and free() */ int __cdecl main(int argc, char **argv) { /* Declare and initialize variables */ DWORD dwSize = 0; DWORD dwRetVal = 0; unsigned int i = 0; // Set the flags to pass to GetAdaptersAddresses ULONG flags = GAA_FLAG_INCLUDE_PREFIX; // default to unspecified address family (both) ULONG family = AF_UNSPEC; LPVOID lpMsgBuf = NULL; PIP_ADAPTER_ADDRESSES pAddresses = NULL; ULONG outBufLen = 0; ULONG Iterations = 0; PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL; PIP_ADAPTER_ANYCAST_ADDRESS pAnycast = NULL; PIP_ADAPTER_MULTICAST_ADDRESS pMulticast = NULL; IP_ADAPTER_DNS_SERVER_ADDRESS *pDnServer = NULL; IP_ADAPTER_PREFIX *pPrefix = NULL; if (argc != 2) { printf(" Usage: getadapteraddresses familyn"); printf(" getadapteraddresses 4 (for IPv4)n"); printf(" getadapteraddresses 6 (for IPv6)n"); printf(" getadapteraddresses A (for both IPv4 and IPv6)n"); exit(1); } if (atoi(argv[1]) == 4) family = AF_INET; else if (atoi(argv[1]) == 6) family = AF_INET6; printf("Calling GetAdaptersAddresses function with family = "); if (family == AF_INET) printf("AF_INETn"); if (family == AF_INET6) printf("AF_INET6n"); if (family == AF_UNSPEC) printf("AF_UNSPECnn"); // Allocate a 15 KB buffer to start with. outBufLen = WORKING_BUFFER_SIZE; do { pAddresses = (IP_ADAPTER_ADDRESSES *) MALLOC(outBufLen); if (pAddresses == NULL) { printf ("Memory allocation failed for IP_ADAPTER_ADDRESSES structn"); exit(1); } dwRetVal = GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen); if (dwRetVal == ERROR_BUFFER_OVERFLOW) { FREE(pAddresses); pAddresses = NULL; } else { break; } Iterations++; } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (Iterations < MAX_TRIES)); if (dwRetVal == NO_ERROR) { // If successful, output some information from the data we received pCurrAddresses = pAddresses; while (pCurrAddresses) { printf("tLength of the IP_ADAPTER_ADDRESS struct: %ldn", pCurrAddresses->Length); printf("tIfIndex (IPv4 interface): %un", pCurrAddresses->IfIndex); printf("tAdapter name: %sn", pCurrAddresses->AdapterName); pUnicast = pCurrAddresses->FirstUnicastAddress; if (pUnicast != NULL) { for (i = 0; pUnicast != NULL; i++) pUnicast = pUnicast->Next; printf("tNumber of Unicast Addresses: %dn", i); } else printf("tNo Unicast Addressesn"); pAnycast = pCurrAddresses->FirstAnycastAddress; if (pAnycast) { for (i = 0; pAnycast != NULL; i++) pAnycast = pAnycast->Next; printf("tNumber of Anycast Addresses: %dn", i); } else printf("tNo Anycast Addressesn"); pMulticast = pCurrAddresses->FirstMulticastAddress; if (pMulticast) { for (i = 0; pMulticast != NULL; i++) pMulticast = pMulticast->Next; printf("tNumber of Multicast Addresses: %dn", i); } else printf("tNo Multicast Addressesn"); pDnServer = pCurrAddresses->FirstDnsServerAddress; if (pDnServer) { for (i = 0; pDnServer != NULL; i++) pDnServer = pDnServer->Next; printf("tNumber of DNS Server Addresses: %dn", i); } else printf("tNo DNS Server Addressesn"); printf("tDNS Suffix: %wSn", pCurrAddresses->DnsSuffix); printf("tDescription: %wSn", pCurrAddresses->Description); printf("tFriendly name: %wSn", pCurrAddresses->FriendlyName); if (pCurrAddresses->PhysicalAddressLength != 0) { printf("tPhysical address: "); for (i = 0; i < (int) pCurrAddresses->PhysicalAddressLength; i++) { if (i == (pCurrAddresses->PhysicalAddressLength - 1)) printf("%.2Xn", (int) pCurrAddresses->PhysicalAddress[i]); else printf("%.2X-", (int) pCurrAddresses->PhysicalAddress[i]); } } printf("tFlags: %ldn", pCurrAddresses->Flags); printf("tMtu: %lun", pCurrAddresses->Mtu); printf("tIfType: %ldn", pCurrAddresses->IfType); printf("tOperStatus: %ldn", pCurrAddresses->OperStatus); printf("tIpv6IfIndex (IPv6 interface): %un", pCurrAddresses->Ipv6IfIndex); printf("tZoneIndices (hex): "); for (i = 0; i < 16; i++) printf("%lx ", pCurrAddresses->ZoneIndices[i]); printf("n"); printf("tTransmit link speed: %I64un", pCurrAddresses->TransmitLinkSpeed); printf("tReceive link speed: %I64un", pCurrAddresses->ReceiveLinkSpeed); pPrefix = pCurrAddresses->FirstPrefix; if (pPrefix) { for (i = 0; pPrefix != NULL; i++) pPrefix = pPrefix->Next; printf("tNumber of IP Adapter Prefix entries: %dn", i); } else printf("tNumber of IP Adapter Prefix entries: 0n"); printf("n"); pCurrAddresses = pCurrAddresses->Next; } } else { printf("Call to GetAdaptersAddresses failed with error: %dn", dwRetVal); if (dwRetVal == ERROR_NO_DATA) printf("tNo addresses were found for the requested parametersn"); else { if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) & lpMsgBuf, 0, NULL)) { printf("tError: %s", lpMsgBuf); LocalFree(lpMsgBuf); if (pAddresses) FREE(pAddresses); exit(1); } } } if (pAddresses) { FREE(pAddresses); } return 0; }
-see-also
GetIpAddrTable
HeapAlloc
HeapFree
IP Helper Function Reference
IP Helper Start Page
IP_ADAPTER_ADDRESSES
MIB_IPADDRTABLE
SOCKET_ADDRESS
Windows Sockets
#include <winsock2.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>
#include <WS2tcpip.h>
using namespace std;
// Link with Iphlpapi.lib
#pragma comment(lib, "IPHLPAPI.lib")
#pragma comment(lib, "Ws2_32.lib")
#define WORKING_BUFFER_SIZE 15000
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
/* Note: could also use malloc() and free() */
static vector<string> getIPv4Addr()
{
/* IPv4 address vector */
vector<string> vStrIP;
/* Declare and initialize variables */
DWORD dwRetVal = 0;
// Set the flags to pass to GetAdaptersAddresses
ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
// IPv4 address family
ULONG family = AF_INET;
LPVOID lpMsgBuf = NULL;
PIP_ADAPTER_ADDRESSES pAddresses = NULL;
ULONG outBufLen = 0;
ULONG Iterations = 0;
PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
// Allocate a 15 KB buffer to start with.
outBufLen = WORKING_BUFFER_SIZE;
do {
pAddresses = (IP_ADAPTER_ADDRESSES *)MALLOC(outBufLen);
if (pAddresses == NULL) {
cout << "Memory allocation failed for IP_ADAPTER_ADDRESSES struct" << endl;
return vStrIP;
}
dwRetVal =
GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);
if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
FREE(pAddresses);
pAddresses = NULL;
}
else {
break;
}
} while (dwRetVal == ERROR_BUFFER_OVERFLOW);
if (dwRetVal == NO_ERROR) {
pCurrAddresses = pAddresses;
while (pCurrAddresses) {
if (pCurrAddresses->IfType == MIB_IF_TYPE_ETHERNET) //ethernet interface
{
CHAR IP[130] = { 0 };
pUnicast = pCurrAddresses->FirstUnicastAddress;
inet_ntop(PF_INET, &((sockaddr_in*)pUnicast->Address.lpSockaddr)->sin_addr, IP, sizeof(IP));
vStrIP.push_back(IP);
}
pCurrAddresses = pCurrAddresses->Next;
}
}
if (pAddresses) {
FREE(pAddresses);
}
return vStrIP;
}
int __cdecl main(int argc, char **argv)
{
/* Declare and initialize variables */
DWORD dwRetVal = 0;
// Set the flags to pass to GetAdaptersAddresses
ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
// IPv4 address family
ULONG family = AF_INET;
LPVOID lpMsgBuf = NULL;
PIP_ADAPTER_ADDRESSES pAddresses = NULL;
ULONG outBufLen = 0;
ULONG Iterations = 0;
PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
// Allocate a 15 KB buffer to start with.
outBufLen = WORKING_BUFFER_SIZE;
do {
pAddresses = (IP_ADAPTER_ADDRESSES *)MALLOC(outBufLen);
if (pAddresses == NULL) {
printf
("Memory allocation failed for IP_ADAPTER_ADDRESSES structn");
exit(1);
}
dwRetVal =
GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen);
if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
FREE(pAddresses);
pAddresses = NULL;
}
else {
break;
}
} while (dwRetVal == ERROR_BUFFER_OVERFLOW);
if (dwRetVal == NO_ERROR) {
// If successful, output some information from the data we received
pCurrAddresses = pAddresses;
while (pCurrAddresses) {
if (pCurrAddresses->PhysicalAddressLength != 0)
{
printf("tAdapter Mac: %02X%02X%02X%02X%02X%02Xn",
pCurrAddresses->PhysicalAddress[0], pCurrAddresses->PhysicalAddress[1],
pCurrAddresses->PhysicalAddress[2], pCurrAddresses->PhysicalAddress[3],
pCurrAddresses->PhysicalAddress[4], pCurrAddresses->PhysicalAddress[5]);
}
char type[64];
switch (pCurrAddresses->IfType)
{
case MIB_IF_TYPE_ETHERNET:
Sprintf_s (тип, интерфейс Ethernet);
break;
case MIB_IF_TYPE_PPP:
Sprintf_s (тип, интерфейс PPP);
break;
case MIB_IF_TYPE_LOOPBACK:
SPRINTF_S (тип, интерфейс журнала программного обеспечения »);
break;
case MIB_IF_TYPE_SLIP:
SPRINTF_S (тип, сетевой интерфейс ATM »);
break;
case IF_TYPE_IEEE80211:
SPRINTF_S (тип, беспроводной сетевой интерфейс »);
break;
default:
break;
}
Printf (типа " t Тип Nic:% s n", Тип);
pUnicast = pCurrAddresses->FirstUnicastAddress;
while (pUnicast)//IP
{
CHAR IP[130] = { 0 };
Если (af_inet == punicast-> address.lpsockaddr-> sa_family) // IPv4 Адрес, используйте преобразование IPv4
{
inet_ntop(PF_INET, &((sockaddr_in*)pUnicast->Address.lpSockaddr)->sin_addr, IP, sizeof(IP));
printf("tIPv4: %sn", IP);
}
Else is (af_inet6 == punicast-> address.lpsockaddr-> sa_family) // IPv6 Адрес, используйте преобразование IPv6
{
inet_ntop(PF_INET6, &((sockaddr_in6*)pUnicast->Address.lpSockaddr)->sin6_addr, IP, sizeof(IP));
printf("tIPv6: %sn", IP);
}
pUnicast = pUnicast->Next;
}
printf("tMtu: %lun", pCurrAddresses->Mtu);
printf("n");
pCurrAddresses = pCurrAddresses->Next;
}
}
else {
printf("Call to GetAdaptersAddresses failed with error: %dn",
dwRetVal);
if (dwRetVal == ERROR_NO_DATA)
printf("tNo addresses were found for the requested parametersn");
else {
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
// Default language
(LPTSTR)& lpMsgBuf, 0, NULL)) {
printf("tError: %s", lpMsgBuf);
LocalFree(lpMsgBuf);
if (pAddresses)
FREE(pAddresses);
exit(1);
}
}
}
if (pAddresses) {
FREE(pAddresses);
}
return 0;
}