iphlpapi: Implement GetUnicastIpAddressTable
André Hentschel
nerv at dawncrow.de
Sat Mar 25 13:31:52 CDT 2017
Signed-off-by: André Hentschel <nerv at dawncrow.de>
---
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
More information about the wine-patches
mailing list