Commit e93053c3 authored by Huw Davies's avatar Huw Davies Committed by Alexandre Julliard

iphlpapi: Implement GetIfTable() on top of nsi.

parent bdc48738
......@@ -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;
if (numInterfaces > 1)
size += (numInterfaces - 1) * sizeof(MIB_IFROW);
if (!pIfTable || *pdwSize < size) {
*pdwSize = size;
ret = ERROR_INSUFFICIENT_BUFFER;
}
else {
InterfaceIndexTable *table;
get_interface_indices( FALSE, &table );
needed = FIELD_OFFSET( MIB_IFTABLE, table[count] );
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;
if (!table || *size < needed)
{
*size = needed;
err = ERROR_INSUFFICIENT_BUFFER;
goto err;
}
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 )
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment