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

Alexandre Julliard julliard at winehq.org
Fri Jul 9 16:45:33 CDT 2021


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

Author: Huw Davies <huw at codeweavers.com>
Date:   Fri Jul  9 09:09:25 2021 +0100

iphlpapi: Implement GetIfTable() 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  | 131 ++++++++++++++++++++++-------------------
 dlls/iphlpapi/tests/iphlpapi.c |  16 +++++
 2 files changed, 87 insertions(+), 60 deletions(-)

diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c
index ff534afa0f9..e5b6e72bde1 100644
--- a/dlls/iphlpapi/iphlpapi_main.c
+++ b/dlls/iphlpapi/iphlpapi_main.c
@@ -1775,6 +1775,38 @@ DWORD WINAPI GetFriendlyIfIndex(DWORD IfIndex)
   return IfIndex;
 }
 
+static void if_counted_string_copy( WCHAR *dst, unsigned int len, IF_COUNTED_STRING *src );
+
+static void if_row_fill( MIB_IFROW *row, struct nsi_ndis_ifinfo_rw *rw, struct nsi_ndis_ifinfo_dynamic *dyn,
+                         struct nsi_ndis_ifinfo_static *stat )
+{
+    if_counted_string_copy( row->wszName, ARRAY_SIZE(row->wszName), &rw->alias );
+    row->dwIndex = stat->if_index;
+    row->dwType = stat->type;
+    row->dwMtu = dyn->mtu;
+    row->dwSpeed = dyn->rcv_speed;
+    row->dwPhysAddrLen = rw->phys_addr.Length;
+    if (row->dwPhysAddrLen > sizeof(row->bPhysAddr)) row->dwPhysAddrLen = 0;
+    memcpy( row->bPhysAddr, rw->phys_addr.Address, row->dwPhysAddrLen );
+    row->dwAdminStatus = rw->admin_status;
+    row->dwOperStatus = (dyn->oper_status == IfOperStatusUp) ? MIB_IF_OPER_STATUS_OPERATIONAL : MIB_IF_OPER_STATUS_NON_OPERATIONAL;
+    row->dwLastChange = 0;
+    row->dwInOctets = dyn->in_octets;
+    row->dwInUcastPkts = dyn->in_ucast_pkts;
+    row->dwInNUcastPkts = dyn->in_bcast_pkts + dyn->in_mcast_pkts;
+    row->dwInDiscards = dyn->in_discards;
+    row->dwInErrors = dyn->in_errors;
+    row->dwInUnknownProtos = 0;
+    row->dwOutOctets = dyn->out_octets;
+    row->dwOutUcastPkts = dyn->out_ucast_pkts;
+    row->dwOutNUcastPkts = dyn->out_bcast_pkts + dyn->out_mcast_pkts;
+    row->dwOutDiscards = dyn->out_discards;
+    row->dwOutErrors = dyn->out_errors;
+    row->dwOutQLen = 0;
+    row->dwDescrLen = WideCharToMultiByte( CP_ACP, 0, stat->descr.String, stat->descr.Length / sizeof(WCHAR),
+                                           (char *)row->bDescr, sizeof(row->bDescr) - 1, NULL, NULL );
+    row->bDescr[row->dwDescrLen] = '\0';
+}
 
 /******************************************************************
  *    GetIfEntry (IPHLPAPI.@)
@@ -1811,91 +1843,70 @@ DWORD WINAPI GetIfEntry(PMIB_IFROW pIfRow)
   return ret;
 }
 
-static int IfTableSorter(const void *a, const void *b)
+static int ifrow_cmp( const void *a, const void *b )
 {
-  int ret;
-
-  if (a && b)
-    ret = ((const MIB_IFROW*)a)->dwIndex - ((const MIB_IFROW*)b)->dwIndex;
-  else
-    ret = 0;
-  return ret;
+    return ((const MIB_IFROW*)a)->dwIndex - ((const MIB_IFROW*)b)->dwIndex;
 }
 
-
 /******************************************************************
  *    GetIfTable (IPHLPAPI.@)
  *
  * Get a table of local interfaces.
  *
  * PARAMS
- *  pIfTable [Out]    buffer for local interfaces table
- *  pdwSize  [In/Out] length of output buffer
- *  bOrder   [In]     whether to sort the table
+ *  table [Out]    buffer for local interfaces 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
+ *  If size 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 interface index.
+ *  If sort is true, the returned table will be sorted by interface index.
  */
-DWORD WINAPI GetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder)
+DWORD WINAPI GetIfTable( MIB_IFTABLE *table, ULONG *size, BOOL sort )
 {
-  DWORD ret;
+    DWORD i, count, needed, err;
+    NET_LUID *keys;
+    struct nsi_ndis_ifinfo_rw *rw;
+    struct nsi_ndis_ifinfo_dynamic *dyn;
+    struct nsi_ndis_ifinfo_static *stat;
 
-  TRACE("pIfTable %p, pdwSize %p, bOrder %d\n", pIfTable, pdwSize, bOrder);
+    if (!size) return ERROR_INVALID_PARAMETER;
 
-  if (!pdwSize)
-    ret = ERROR_INVALID_PARAMETER;
-  else {
-    DWORD numInterfaces = get_interface_indices( FALSE, NULL );
-    ULONG size = sizeof(MIB_IFTABLE);
+    /* While this could be implemented on top of GetIfTable2(), it would require
+       an additional copy of the data */
+    err = NsiAllocateAndGetTable( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, (void **)&keys, sizeof(*keys),
+                                  (void **)&rw, sizeof(*rw), (void **)&dyn, sizeof(*dyn),
+                                  (void **)&stat, sizeof(*stat), &count, 0 );
+    if (err) return err;
+
+    needed = FIELD_OFFSET( MIB_IFTABLE, table[count] );
 
-    if (numInterfaces > 1)
-      size += (numInterfaces - 1) * sizeof(MIB_IFROW);
-    if (!pIfTable || *pdwSize < size) {
-      *pdwSize = size;
-      ret = ERROR_INSUFFICIENT_BUFFER;
+    if (!table || *size < needed)
+    {
+        *size = needed;
+        err = ERROR_INSUFFICIENT_BUFFER;
+        goto err;
     }
-    else {
-      InterfaceIndexTable *table;
-      get_interface_indices( FALSE, &table );
-
-      if (table) {
-        size = sizeof(MIB_IFTABLE);
-        if (table->numIndexes > 1)
-          size += (table->numIndexes - 1) * sizeof(MIB_IFROW);
-        if (*pdwSize < size) {
-          *pdwSize = size;
-          ret = ERROR_INSUFFICIENT_BUFFER;
-        }
-        else {
-          DWORD ndx;
 
-          *pdwSize = size;
-          pIfTable->dwNumEntries = 0;
-          for (ndx = 0; ndx < table->numIndexes; ndx++) {
-            pIfTable->table[ndx].dwIndex = table->indexes[ndx];
-            GetIfEntry(&pIfTable->table[ndx]);
-            pIfTable->dwNumEntries++;
-          }
-          if (bOrder)
-            qsort(pIfTable->table, pIfTable->dwNumEntries, sizeof(MIB_IFROW),
-             IfTableSorter);
-          ret = NO_ERROR;
-        }
-        HeapFree(GetProcessHeap(), 0, table);
-      }
-      else
-        ret = ERROR_OUTOFMEMORY;
+    table->dwNumEntries = count;
+    for (i = 0; i < count; i++)
+    {
+        MIB_IFROW *row = table->table + i;
+
+        if_row_fill( row, rw + i, dyn + i, stat + i );
     }
-  }
-  TRACE("returning %d\n", ret);
-  return ret;
+
+    if (sort) qsort( table->table, count, sizeof(MIB_IFROW), ifrow_cmp );
+
+err:
+    NsiFreeTable( keys, rw, dyn, stat );
+    return err;
 }
 
 static void if_counted_string_copy( WCHAR *dst, unsigned int len, IF_COUNTED_STRING *src )
diff --git a/dlls/iphlpapi/tests/iphlpapi.c b/dlls/iphlpapi/tests/iphlpapi.c
index 784eafbd1ef..1e8950f3482 100644
--- a/dlls/iphlpapi/tests/iphlpapi.c
+++ b/dlls/iphlpapi/tests/iphlpapi.c
@@ -238,12 +238,16 @@ static void testGetIfTable(void)
 
         if (apiReturn == NO_ERROR)
         {
+            char descr[MAX_INTERFACE_NAME_LEN];
+            WCHAR name[MAX_INTERFACE_NAME_LEN];
             DWORD i, index;
 
             if (winetest_debug > 1) trace( "interface table: %u entries\n", buf->dwNumEntries );
             for (i = 0; i < buf->dwNumEntries; i++)
             {
                 MIB_IFROW *row = &buf->table[i];
+                MIB_IF_ROW2 row2;
+                GUID *guid;
 
                 if (winetest_debug > 1)
                 {
@@ -261,6 +265,18 @@ static void testGetIfTable(void)
                 ok( index == row->dwIndex ||
                     broken( index != row->dwIndex && index ), /* Win8 can have identical guids for two different ifaces */
                     "got %d vs %d\n", index, row->dwIndex );
+                memset( &row2, 0, sizeof(row2) );
+                row2.InterfaceIndex = row->dwIndex;
+                GetIfEntry2( &row2 );
+                WideCharToMultiByte( CP_ACP, 0, row2.Description, -1, descr, sizeof(descr), NULL, NULL );
+                ok( !strcmp( (char *)row->bDescr, descr ), "got %s vs %s\n", row->bDescr, descr );
+                guid = &row2.InterfaceGuid;
+                swprintf( name, ARRAY_SIZE(name), L"\\DEVICE\\TCPIP_{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+                          guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1],
+                          guid->Data4[2], guid->Data4[3], guid->Data4[4], guid->Data4[5],
+                          guid->Data4[6], guid->Data4[7]);
+todo_wine
+                ok( !wcscmp( row->wszName, name ), "got %s vs %s\n", debugstr_w( row->wszName ), debugstr_w( name ) );
             }
         }
         HeapFree(GetProcessHeap(), 0, buf);




More information about the wine-cvs mailing list