Huw Davies : iphlpapi: Implement GetUnicastIpAddressTable() on top of nsi.

Alexandre Julliard julliard at winehq.org
Tue Jul 20 15:11:04 CDT 2021


Module: wine
Branch: master
Commit: 2f3ab0b242321a044ca68794f811165a8f748a74
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=2f3ab0b242321a044ca68794f811165a8f748a74

Author: Huw Davies <huw at codeweavers.com>
Date:   Tue Jul 20 08:43:26 2021 +0100

iphlpapi: Implement GetUnicastIpAddressTable() on top of nsi.

Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/iphlpapi/iphlpapi_main.c | 132 ++++++++++++++++++++++++------------------
 dlls/nsi/tests/nsi.c          |   1 -
 2 files changed, 76 insertions(+), 57 deletions(-)

diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c
index 4ff9feb57f2..f4e6ea1a504 100644
--- a/dlls/iphlpapi/iphlpapi_main.c
+++ b/dlls/iphlpapi/iphlpapi_main.c
@@ -77,6 +77,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi);
 
 DWORD WINAPI AllocateAndGetIfTableFromStack( MIB_IFTABLE **table, BOOL sort, HANDLE heap, DWORD flags );
 
+static const NPI_MODULEID *ip_module_id( USHORT family )
+{
+    if (family == WS_AF_INET) return &NPI_MS_IPV4_MODULEID;
+    if (family == WS_AF_INET6) return &NPI_MS_IPV6_MODULEID;
+    return NULL;
+}
+
 DWORD WINAPI ConvertGuidToStringA( const GUID *guid, char *str, DWORD len )
 {
     if (len < CHARS_IN_GUID) return ERROR_INSUFFICIENT_BUFFER;
@@ -2651,6 +2658,42 @@ DWORD WINAPI GetExtendedUdpTable(PVOID pUdpTable, PDWORD pdwSize, BOOL bOrder,
     return ret;
 }
 
+static void unicast_row_fill( MIB_UNICASTIPADDRESS_ROW *row, USHORT fam, void *key, struct nsi_ip_unicast_rw *rw,
+                              struct nsi_ip_unicast_dynamic *dyn, struct nsi_ip_unicast_static *stat )
+{
+    struct nsi_ipv4_unicast_key *key4 = (struct nsi_ipv4_unicast_key *)key;
+    struct nsi_ipv6_unicast_key *key6 = (struct nsi_ipv6_unicast_key *)key;
+
+    if (fam == WS_AF_INET)
+    {
+        row->Address.Ipv4.sin_family = fam;
+        row->Address.Ipv4.sin_port = 0;
+        row->Address.Ipv4.sin_addr = key4->addr;
+        memset( row->Address.Ipv4.sin_zero, 0, sizeof(row->Address.Ipv4.sin_zero) );
+        row->InterfaceLuid.Value = key4->luid.Value;
+    }
+    else
+    {
+        row->Address.Ipv6.sin6_family = fam;
+        row->Address.Ipv6.sin6_port = 0;
+        row->Address.Ipv6.sin6_flowinfo = 0;
+        row->Address.Ipv6.sin6_addr = key6->addr;
+        row->Address.Ipv6.sin6_scope_id = dyn->scope_id;
+        row->InterfaceLuid.Value = key6->luid.Value;
+    }
+
+    ConvertInterfaceLuidToIndex( &row->InterfaceLuid, &row->InterfaceIndex );
+    row->PrefixOrigin = rw->prefix_origin;
+    row->SuffixOrigin = rw->suffix_origin;
+    row->ValidLifetime = rw->valid_lifetime;
+    row->PreferredLifetime = rw->preferred_lifetime;
+    row->OnLinkPrefixLength = rw->on_link_prefix;
+    row->SkipAsSource = 0;
+    row->DadState = dyn->dad_state;
+    row->ScopeId.u.Value = dyn->scope_id;
+    row->CreationTimeStamp.QuadPart = stat->creation_time;
+}
+
 DWORD WINAPI GetUnicastIpAddressEntry(MIB_UNICASTIPADDRESS_ROW *row)
 {
     IP_ADAPTER_ADDRESSES *aa, *ptr;
@@ -2720,80 +2763,57 @@ DWORD WINAPI GetUnicastIpAddressEntry(MIB_UNICASTIPADDRESS_ROW *row)
 
 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;
+    void *key[2] = { NULL, NULL };
+    struct nsi_ip_unicast_rw *rw[2] = { NULL, NULL };
+    struct nsi_ip_unicast_dynamic *dyn[2] = { NULL, NULL };
+    struct nsi_ip_unicast_static *stat[2] = { NULL, NULL };
+    static const USHORT fam[2] = { WS_AF_INET, WS_AF_INET6 };
+    static const DWORD key_size[2] = { sizeof(struct nsi_ipv4_unicast_key), sizeof(struct nsi_ipv6_unicast_key) };
+    DWORD err, i, size, count[2] = { 0, 0 };
 
-    TRACE("%u, %p\n", family, table);
+    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)))
+    for (i = 0; i < 2; i++)
     {
-        HeapFree(GetProcessHeap(), 0, ptr);
-        return ret;
+        if (family != WS_AF_UNSPEC && family != fam[i]) continue;
+
+        err = NsiAllocateAndGetTable( 1, ip_module_id( fam[i] ), NSI_IP_UNICAST_TABLE, key + i, key_size[i],
+                                      (void **)rw + i, sizeof(**rw), (void **)dyn + i, sizeof(**dyn),
+                                      (void **)stat + i, sizeof(**stat), count + i, 0 );
+        if (err) goto err;
     }
 
-    for (aa = ptr; aa; aa = aa->Next)
+    size = FIELD_OFFSET(MIB_UNICASTIPADDRESS_TABLE, Table[ count[0] + count[1] ]);
+    *table = heap_alloc( size );
+    if (!*table)
     {
-        IP_ADAPTER_UNICAST_ADDRESS *ua = aa->FirstUnicastAddress;
-        while (ua)
-        {
-            count++;
-            ua = ua->Next;
-        }
+        err = ERROR_NOT_ENOUGH_MEMORY;
+        goto err;
     }
 
-    if (!(data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data) + (count - 1) * sizeof(data->Table[0]))))
+    (*table)->NumEntries = count[0] + count[1];
+    for (i = 0; i < count[0]; i++)
     {
-        HeapFree(GetProcessHeap(), 0, ptr);
-        return ERROR_OUTOFMEMORY;
+        MIB_UNICASTIPADDRESS_ROW *row = (*table)->Table + i;
+        struct nsi_ipv4_unicast_key *key4 = (struct nsi_ipv4_unicast_key *)key[0];
+
+        unicast_row_fill( row, fam[0], (void *)(key4 + i), rw[0] + i, dyn[0] + i, stat[0] + i );
     }
 
-    data->NumEntries = 0;
-    for (aa = ptr; aa; aa = aa->Next)
+    for (i = 0; i < count[1]; i++)
     {
-        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);
+        MIB_UNICASTIPADDRESS_ROW *row = (*table)->Table + count[0] + i;
+        struct nsi_ipv6_unicast_key *key6 = (struct nsi_ipv6_unicast_key *)key[1];
 
-            data->NumEntries++;
-            ua = ua->Next;
-        }
+        unicast_row_fill( row, fam[1], (void *)(key6 + i), rw[1] + i, dyn[1] + i, stat[1] + i );
     }
 
-    HeapFree(GetProcessHeap(), 0, ptr);
-
-    *table = data;
-    return ret;
+err:
+    for (i = 0; i < 2; i++) NsiFreeTable( key[i], rw[i], dyn[i], stat[i] );
+    return err;
 }
 
 /******************************************************************
diff --git a/dlls/nsi/tests/nsi.c b/dlls/nsi/tests/nsi.c
index c07653c2ede..869fa255bb2 100644
--- a/dlls/nsi/tests/nsi.c
+++ b/dlls/nsi/tests/nsi.c
@@ -470,7 +470,6 @@ static void test_ip_unicast( int family )
         /* SkipAsSource */
         ok( row->DadState == dyn->dad_state, "mismatch\n" );
         ok( row->ScopeId.Value == dyn->scope_id, "mismatch\n" );
-todo_wine
         ok( row->CreationTimeStamp.QuadPart == stat->creation_time, "mismatch\n" );
         winetest_pop_context();
     }




More information about the wine-cvs mailing list