iphlpapi: Implement GetUnicastIpAddressTable (try 3)

André Hentschel nerv at dawncrow.de
Mon Mar 27 15:48:00 CDT 2017


Signed-off-by: André Hentschel <nerv at dawncrow.de>
---

try 2: Fix test leaks, space indent traces, use meaningful variable names
try 3: Use GAA_FLAG_SKIP* to reduce provided data

 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 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..1407bfb 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 bc99660..9deccc2 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 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