[PATCH 3/4] iphlpapi: Implement GetIpNetTable() on top of nsi.

Huw Davies huw at codeweavers.com
Tue Aug 10 03:20:49 CDT 2021


Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 dlls/iphlpapi/iphlpapi_main.c | 93 +++++++++++++++++++++++++----------
 1 file changed, 67 insertions(+), 26 deletions(-)

diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c
index 6a9fb3d0914..24cfedd2b02 100644
--- a/dlls/iphlpapi/iphlpapi_main.c
+++ b/dlls/iphlpapi/iphlpapi_main.c
@@ -2230,50 +2230,91 @@ err:
     return err;
 }
 
+static int ipnetrow_cmp( const void *a, const void *b )
+{
+    const MIB_IPNETROW *row_a = a;
+    const MIB_IPNETROW *row_b = b;
+
+    return RtlUlongByteSwap( row_a->dwAddr ) - RtlUlongByteSwap( row_b->dwAddr );
+}
+
 /******************************************************************
  *    GetIpNetTable (IPHLPAPI.@)
  *
  * Get the IP-to-physical address mapping table.
  *
  * PARAMS
- *  pIpNetTable [Out]    buffer for mapping table
- *  pdwSize     [In/Out] length of output buffer
- *  bOrder      [In]     whether to sort the table
+ *  table       [Out]    buffer for mapping table
+ *  size        [In/Out] length of output buffer
+ *  sort        [In]     whether to sort the table
  *
  * RETURNS
  *  Success: NO_ERROR
  *  Failure: error code from winerror.h
  *
- * NOTES
- *  If pdwSize is less than required, the function will return
- *  ERROR_INSUFFICIENT_BUFFER, and *pdwSize will be set to the required byte
- *  size.
- *  If bOrder is true, the returned table will be sorted by IP address.
  */
-DWORD WINAPI GetIpNetTable(PMIB_IPNETTABLE pIpNetTable, PULONG pdwSize, BOOL bOrder)
+DWORD WINAPI GetIpNetTable( MIB_IPNETTABLE *table, ULONG *size, BOOL sort )
 {
-    DWORD ret;
-    PMIB_IPNETTABLE table;
+    DWORD err, count, needed, i;
+    struct nsi_ipv4_neighbour_key *keys;
+    struct nsi_ip_neighbour_rw *rw;
+    struct nsi_ip_neighbour_dynamic *dyn;
 
-    TRACE("pIpNetTable %p, pdwSize %p, bOrder %d\n", pIpNetTable, pdwSize, bOrder);
+    TRACE( "table %p, size %p, sort %d\n", table, size, sort );
 
-    if (!pdwSize) return ERROR_INVALID_PARAMETER;
+    if (!size) return ERROR_INVALID_PARAMETER;
 
-    ret = AllocateAndGetIpNetTableFromStack( &table, bOrder, GetProcessHeap(), 0 );
-    if (!ret) {
-        DWORD size = FIELD_OFFSET( MIB_IPNETTABLE, table[table->dwNumEntries] );
-        if (!pIpNetTable || *pdwSize < size) {
-          *pdwSize = size;
-          ret = ERROR_INSUFFICIENT_BUFFER;
-        }
-        else {
-          *pdwSize = size;
-          memcpy(pIpNetTable, table, size);
+    err = NsiAllocateAndGetTable( 1, &NPI_MS_IPV4_MODULEID, NSI_IP_NEIGHBOUR_TABLE, (void **)&keys, sizeof(*keys),
+                                  (void **)&rw, sizeof(*rw), (void **)&dyn, sizeof(*dyn),
+                                  NULL, 0, &count, 0 );
+    if (err) return err;
+
+    needed = FIELD_OFFSET( MIB_IPNETTABLE, table[count] );
+
+    if (!table || *size < needed)
+    {
+        *size = needed;
+        err = ERROR_INSUFFICIENT_BUFFER;
+        goto err;
+    }
+
+    table->dwNumEntries = count;
+    for (i = 0; i < count; i++)
+    {
+        MIB_IPNETROW *row = table->table + i;
+
+        ConvertInterfaceLuidToIndex( &keys[i].luid, &row->dwIndex );
+        row->dwPhysAddrLen = dyn[i].phys_addr_len;
+        if (row->dwPhysAddrLen > sizeof(row->bPhysAddr)) row->dwPhysAddrLen = 0;
+        memcpy( row->bPhysAddr, rw[i].phys_addr, row->dwPhysAddrLen );
+        memset( row->bPhysAddr + row->dwPhysAddrLen, 0,
+                sizeof(row->bPhysAddr) - row->dwPhysAddrLen );
+        row->dwAddr = keys[i].addr.WS_s_addr;
+        switch (dyn->state)
+        {
+        case NlnsUnreachable:
+        case NlnsIncomplete:
+            row->u.Type = MIB_IPNET_TYPE_INVALID;
+            break;
+        case NlnsProbe:
+        case NlnsDelay:
+        case NlnsStale:
+        case NlnsReachable:
+            row->u.Type = MIB_IPNET_TYPE_DYNAMIC;
+            break;
+        case NlnsPermanent:
+            row->u.Type = MIB_IPNET_TYPE_STATIC;
+            break;
+        default:
+            row->u.Type = MIB_IPNET_TYPE_OTHER;
         }
-        HeapFree(GetProcessHeap(), 0, table);
     }
-    TRACE("returning %d\n", ret);
-    return ret;
+
+    if (sort) qsort( table->table, table->dwNumEntries, sizeof(*table->table), ipnetrow_cmp );
+
+err:
+    NsiFreeTable( keys, rw, dyn, NULL );
+    return err;
 }
 
 static void ipnet_row2_fill( MIB_IPNET_ROW2 *row, USHORT fam, void *key, struct nsi_ip_neighbour_rw *rw,
-- 
2.23.0




More information about the wine-devel mailing list