[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