From: André Hentschel Subject: iphlpapi: Implement GetUnicastIpAddressTable Message-Id: Date: Sat, 25 Mar 2017 19:31:52 +0100 Signed-off-by: André Hentschel --- https://bugs.winehq.org/show_bug.cgi?id=42684 dlls/iphlpapi/iphlpapi.spec | 2 +- dlls/iphlpapi/iphlpapi_main.c | 73 ++++++++++++++++++++++++++++++++++++++++++ dlls/iphlpapi/tests/iphlpapi.c | 52 ++++++++++++++++++++++++++++++ include/netioapi.h | 6 ++++ 4 files changed, 132 insertions(+), 1 deletion(-) diff --git a/dlls/iphlpapi/iphlpapi.spec b/dlls/iphlpapi/iphlpapi.spec index d69b80e..4e01926 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 6f16807..dca87b0 100644 --- a/dlls/iphlpapi/iphlpapi_main.c +++ b/dlls/iphlpapi/iphlpapi_main.c @@ -2534,6 +2534,79 @@ 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 *t; + DWORD ret, u = 0; + ULONG size; + + TRACE("%u, %p\n", family, table); + + if (!table || (family != WS_AF_INET && family != WS_AF_INET6 && family != WS_AF_UNSPEC)) + return ERROR_INVALID_PARAMETER; + + ret = GetAdaptersAddresses(family, 0, NULL, NULL, &size); + if (ret != ERROR_BUFFER_OVERFLOW) + return ret; + if (!(ptr = HeapAlloc(GetProcessHeap(), 0, size))) + return ERROR_OUTOFMEMORY; + if ((ret = GetAdaptersAddresses(family, 0, 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) + { + u++; + ua = ua->Next; + } + } + + if (!(t = HeapAlloc(GetProcessHeap(), 0, sizeof(*t) + (u - 1) * sizeof(t->Table[0])))) + { + HeapFree(GetProcessHeap(), 0, ptr); + return ERROR_OUTOFMEMORY; + } + + t->NumEntries = 0; + for (aa = ptr; aa; aa = aa->Next) + { + IP_ADAPTER_UNICAST_ADDRESS *ua = aa->FirstUnicastAddress; + while (ua) + { + MIB_UNICASTIPADDRESS_ROW *row = &t->Table[t->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); + + t->NumEntries++; + ua = ua->Next; + } + } + + HeapFree(GetProcessHeap(), 0, ptr); + + *table = t; + return ret; +} + /****************************************************************** * GetUniDirectionalAdapterInfo (IPHLPAPI.@) * diff --git a/dlls/iphlpapi/tests/iphlpapi.c b/dlls/iphlpapi/tests/iphlpapi.c index bc99660..6050865 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,55 @@ 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); + + ret = pGetUnicastIpAddressTable(AF_INET6, &table); + ok( ret == NO_ERROR, "got %u\n", ret ); + trace("GetUnicastIpAddressTable(AF_INET6): NumEntries %u\n", table->NumEntries); + + 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("%u:\n", i); + trace("Address.si_family:\t%d\n", table->Table[i].Address.si_family); + trace("InterfaceLuid.Info.Reserved:\t%d\n", table->Table[i].InterfaceLuid.Info.Reserved); + trace("InterfaceLuid.Info.NetLuidIndex:\t%d\n", table->Table[i].InterfaceLuid.Info.NetLuidIndex); + trace("InterfaceLuid.Info.IfType:\t%d\n", table->Table[i].InterfaceLuid.Info.IfType); + trace("InterfaceIndex:\t%d\n", table->Table[i].InterfaceIndex); + trace("PrefixOrigin:\t%d\n", table->Table[i].PrefixOrigin); + trace("SuffixOrigin:\t%d\n", table->Table[i].SuffixOrigin); + trace("ValidLifetime:\t%d\n", table->Table[i].ValidLifetime); + trace("PreferredLifetime:\t%d\n", table->Table[i].PreferredLifetime); + trace("OnLinkPrefixLength:\t%d\n", table->Table[i].OnLinkPrefixLength); + trace("SkipAsSource:\t%d\n", table->Table[i].SkipAsSource); + trace("DadState:\t%d\n", table->Table[i].DadState); + trace("ScopeId.Value:\t%d\n", table->Table[i].ScopeId.Value); + trace("CreationTimeStamp:\t%08x%08x\n", table->Table[i].CreationTimeStamp.HighPart, table->Table[i].CreationTimeStamp.LowPart); + } +} + START_TEST(iphlpapi) { @@ -2120,6 +2171,7 @@ START_TEST(iphlpapi) test_GetIfEntry2(); test_GetIfTable2(); test_GetUnicastIpAddressEntry(); + test_GetUnicastIpAddressTable(); freeIPHlpApi(); } } diff --git a/include/netioapi.h b/include/netioapi.h index b34d019..cabfe9e 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, -- 2.7.4