Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
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);
--
2.23.0