From eda35423f4f52a1e9a2cb93219a4dd6c280baedf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Hentschel?= Date: Mon, 27 Mar 2017 22:48:00 +0200 Subject: [PATCH] iphlpapi: Implement GetUnicastIpAddressTable. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: André Hentschel Signed-off-by: Bruno Jesus Signed-off-by: Alexandre Julliard --- dlls/iphlpapi/iphlpapi.spec | 2 +- dlls/iphlpapi/iphlpapi_main.c | 78 ++++++++++++++++++++++++++++++++++ dlls/iphlpapi/tests/iphlpapi.c | 56 ++++++++++++++++++++++++ include/netioapi.h | 6 +++ 4 files changed, 141 insertions(+), 1 deletion(-) diff --git a/dlls/iphlpapi/iphlpapi.spec b/dlls/iphlpapi/iphlpapi.spec index d69b80e069..4e01926617 100644 --- a/dlls/iphlpapi/iphlpapi.spec +++ b/dlls/iphlpapi/iphlpapi.spec @@ -148,7 +148,7 @@ @ stdcall GetUdpTable( ptr ptr long ) @ stub GetUdpTableFromStack @ stdcall GetUnicastIpAddressEntry( ptr ) -#@ stub GetUnicastIpAddressTable +@ stdcall GetUnicastIpAddressTable(long ptr) @ stdcall GetUniDirectionalAdapterInfo( ptr ptr ) @ stdcall Icmp6CreateFile() #@ stub Icmp6ParseReplies diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c index 6f168073a1..1407bfbcfe 100644 --- a/dlls/iphlpapi/iphlpapi_main.c +++ b/dlls/iphlpapi/iphlpapi_main.c @@ -2534,6 +2534,84 @@ DWORD WINAPI GetUnicastIpAddressEntry(MIB_UNICASTIPADDRESS_ROW *row) return ret; } +DWORD WINAPI GetUnicastIpAddressTable(ADDRESS_FAMILY family, MIB_UNICASTIPADDRESS_TABLE **table) +{ + IP_ADAPTER_ADDRESSES *aa, *ptr; + MIB_UNICASTIPADDRESS_TABLE *data; + DWORD ret, count = 0; + ULONG size, flags; + + TRACE("%u, %p\n", family, table); + + if (!table || (family != WS_AF_INET && family != WS_AF_INET6 && family != WS_AF_UNSPEC)) + return ERROR_INVALID_PARAMETER; + + flags = GAA_FLAG_SKIP_ANYCAST | + GAA_FLAG_SKIP_MULTICAST | + GAA_FLAG_SKIP_DNS_SERVER | + GAA_FLAG_SKIP_FRIENDLY_NAME; + + ret = GetAdaptersAddresses(family, flags, NULL, NULL, &size); + if (ret != ERROR_BUFFER_OVERFLOW) + return ret; + if (!(ptr = HeapAlloc(GetProcessHeap(), 0, size))) + return ERROR_OUTOFMEMORY; + if ((ret = GetAdaptersAddresses(family, flags, NULL, ptr, &size))) + { + HeapFree(GetProcessHeap(), 0, ptr); + return ret; + } + + for (aa = ptr; aa; aa = aa->Next) + { + IP_ADAPTER_UNICAST_ADDRESS *ua = aa->FirstUnicastAddress; + while (ua) + { + count++; + ua = ua->Next; + } + } + + if (!(data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data) + (count - 1) * sizeof(data->Table[0])))) + { + HeapFree(GetProcessHeap(), 0, ptr); + return ERROR_OUTOFMEMORY; + } + + data->NumEntries = 0; + for (aa = ptr; aa; aa = aa->Next) + { + IP_ADAPTER_UNICAST_ADDRESS *ua = aa->FirstUnicastAddress; + while (ua) + { + MIB_UNICASTIPADDRESS_ROW *row = &data->Table[data->NumEntries]; + memcpy(&row->Address, ua->Address.lpSockaddr, ua->Address.iSockaddrLength); + memcpy(&row->InterfaceLuid, &aa->Luid, sizeof(aa->Luid)); + row->InterfaceIndex = aa->u.s.IfIndex; + row->PrefixOrigin = ua->PrefixOrigin; + row->SuffixOrigin = ua->SuffixOrigin; + row->ValidLifetime = ua->ValidLifetime; + row->PreferredLifetime = ua->PreferredLifetime; + row->OnLinkPrefixLength = ua->OnLinkPrefixLength; + row->SkipAsSource = 0; + row->DadState = ua->DadState; + if (row->Address.si_family == WS_AF_INET6) + row->ScopeId.u.Value = row->Address.Ipv6.sin6_scope_id; + else + row->ScopeId.u.Value = 0; + NtQuerySystemTime(&row->CreationTimeStamp); + + data->NumEntries++; + ua = ua->Next; + } + } + + HeapFree(GetProcessHeap(), 0, ptr); + + *table = data; + return ret; +} + /****************************************************************** * GetUniDirectionalAdapterInfo (IPHLPAPI.@) * diff --git a/dlls/iphlpapi/tests/iphlpapi.c b/dlls/iphlpapi/tests/iphlpapi.c index bc99660edc..9deccc2f16 100644 --- a/dlls/iphlpapi/tests/iphlpapi.c +++ b/dlls/iphlpapi/tests/iphlpapi.c @@ -76,6 +76,7 @@ static DWORD (WINAPI *pGetUdpTable)(PMIB_UDPTABLE,PDWORD,BOOL); static DWORD (WINAPI *pGetPerAdapterInfo)(ULONG,PIP_PER_ADAPTER_INFO,PULONG); static DWORD (WINAPI *pGetAdaptersAddresses)(ULONG,ULONG,PVOID,PIP_ADAPTER_ADDRESSES,PULONG); static DWORD (WINAPI *pGetUnicastIpAddressEntry)(MIB_UNICASTIPADDRESS_ROW*); +static DWORD (WINAPI *pGetUnicastIpAddressTable)(ADDRESS_FAMILY,MIB_UNICASTIPADDRESS_TABLE**); static DWORD (WINAPI *pNotifyAddrChange)(PHANDLE,LPOVERLAPPED); static BOOL (WINAPI *pCancelIPChangeNotify)(LPOVERLAPPED); static DWORD (WINAPI *pGetExtendedTcpTable)(PVOID,PDWORD,BOOL,ULONG,TCP_TABLE_CLASS,ULONG); @@ -125,6 +126,7 @@ static void loadIPHlpApi(void) pGetPerAdapterInfo = (void *)GetProcAddress(hLibrary, "GetPerAdapterInfo"); pGetAdaptersAddresses = (void *)GetProcAddress(hLibrary, "GetAdaptersAddresses"); pGetUnicastIpAddressEntry = (void *)GetProcAddress(hLibrary, "GetUnicastIpAddressEntry"); + pGetUnicastIpAddressTable = (void *)GetProcAddress(hLibrary, "GetUnicastIpAddressTable"); pNotifyAddrChange = (void *)GetProcAddress(hLibrary, "NotifyAddrChange"); pCancelIPChangeNotify = (void *)GetProcAddress(hLibrary, "CancelIPChangeNotify"); pGetExtendedTcpTable = (void *)GetProcAddress(hLibrary, "GetExtendedTcpTable"); @@ -2095,6 +2097,59 @@ static void test_GetUnicastIpAddressEntry(void) HeapFree(GetProcessHeap(), 0, ptr); } +static void test_GetUnicastIpAddressTable(void) +{ + MIB_UNICASTIPADDRESS_TABLE *table; + DWORD ret; + ULONG i; + + if (!pGetUnicastIpAddressTable) + { + win_skip( "GetUnicastIpAddressTable not available\n" ); + return; + } + + ret = pGetUnicastIpAddressTable(AF_UNSPEC, NULL); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + + ret = pGetUnicastIpAddressTable(AF_BAN, &table); + ok( ret == ERROR_INVALID_PARAMETER, "got %u\n", ret ); + + ret = pGetUnicastIpAddressTable(AF_INET, &table); + ok( ret == NO_ERROR, "got %u\n", ret ); + trace("GetUnicastIpAddressTable(AF_INET): NumEntries %u\n", table->NumEntries); + pFreeMibTable(table); + + ret = pGetUnicastIpAddressTable(AF_INET6, &table); + ok( ret == NO_ERROR, "got %u\n", ret ); + trace("GetUnicastIpAddressTable(AF_INET6): NumEntries %u\n", table->NumEntries); + pFreeMibTable(table); + + ret = pGetUnicastIpAddressTable(AF_UNSPEC, &table); + ok( ret == NO_ERROR, "got %u\n", ret ); + trace("GetUnicastIpAddressTable(AF_UNSPEC): NumEntries %u\n", table->NumEntries); + for (i = 0; i < table->NumEntries && winetest_debug > 1; i++) + { + trace("Index %u:\n", i); + trace("Address.si_family: %u\n", table->Table[i].Address.si_family); + trace("InterfaceLuid.Info.Reserved: %u\n", table->Table[i].InterfaceLuid.Info.Reserved); + trace("InterfaceLuid.Info.NetLuidIndex: %u\n", table->Table[i].InterfaceLuid.Info.NetLuidIndex); + trace("InterfaceLuid.Info.IfType: %u\n", table->Table[i].InterfaceLuid.Info.IfType); + trace("InterfaceIndex: %u\n", table->Table[i].InterfaceIndex); + trace("PrefixOrigin: %u\n", table->Table[i].PrefixOrigin); + trace("SuffixOrigin: %u\n", table->Table[i].SuffixOrigin); + trace("ValidLifetime: %u seconds\n", table->Table[i].ValidLifetime); + trace("PreferredLifetime: %u seconds\n", table->Table[i].PreferredLifetime); + trace("OnLinkPrefixLength: %u\n", table->Table[i].OnLinkPrefixLength); + trace("SkipAsSource: %u\n", table->Table[i].SkipAsSource); + trace("DadState: %u\n", table->Table[i].DadState); + trace("ScopeId.Value: %u\n", table->Table[i].ScopeId.Value); + trace("CreationTimeStamp: %08x%08x\n", table->Table[i].CreationTimeStamp.HighPart, table->Table[i].CreationTimeStamp.LowPart); + } + + pFreeMibTable(table); +} + START_TEST(iphlpapi) { @@ -2120,6 +2175,7 @@ START_TEST(iphlpapi) test_GetIfEntry2(); test_GetIfTable2(); test_GetUnicastIpAddressEntry(); + test_GetUnicastIpAddressTable(); freeIPHlpApi(); } } diff --git a/include/netioapi.h b/include/netioapi.h index b34d019030..cabfe9e031 100644 --- a/include/netioapi.h +++ b/include/netioapi.h @@ -145,6 +145,12 @@ typedef struct _MIB_UNICASTIPADDRESS_ROW LARGE_INTEGER CreationTimeStamp; } MIB_UNICASTIPADDRESS_ROW, *PMIB_UNICASTIPADDRESS_ROW; +typedef struct _MIB_UNICASTIPADDRESS_TABLE +{ + ULONG NumEntries; + MIB_UNICASTIPADDRESS_ROW Table[1]; +} MIB_UNICASTIPADDRESS_TABLE, *PMIB_UNICASTIPADDRESS_TABLE; + typedef VOID (WINAPI *PIPINTERFACE_CHANGE_CALLBACK)(PVOID, PMIB_IPINTERFACE_ROW, MIB_NOTIFICATION_TYPE); typedef VOID (WINAPI *PUNICAST_IPADDRESS_CHANGE_CALLBACK)(PVOID, PMIB_UNICASTIPADDRESS_ROW,