Signed-off-by: Huw Davies huw@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);