[PATCH 5/5] nsi/tests: Add tests for the NDIS ifinfo table.

Huw Davies huw at codeweavers.com
Thu Jun 24 07:41:56 CDT 2021


Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 dlls/nsi/tests/Makefile.in |   5 ++
 dlls/nsi/tests/nsi.c       | 146 +++++++++++++++++++++++++++++++++++++
 include/ifmib.h            |  72 ++++++++++++++++++
 3 files changed, 223 insertions(+)
 create mode 100644 dlls/nsi/tests/Makefile.in
 create mode 100644 dlls/nsi/tests/nsi.c

diff --git a/dlls/nsi/tests/Makefile.in b/dlls/nsi/tests/Makefile.in
new file mode 100644
index 00000000000..98129935198
--- /dev/null
+++ b/dlls/nsi/tests/Makefile.in
@@ -0,0 +1,5 @@
+TESTDLL = nsi.dll
+IMPORTS = nsi uuid iphlpapi
+
+C_SRCS = \
+	nsi.c
diff --git a/dlls/nsi/tests/nsi.c b/dlls/nsi/tests/nsi.c
new file mode 100644
index 00000000000..96806e444de
--- /dev/null
+++ b/dlls/nsi/tests/nsi.c
@@ -0,0 +1,146 @@
+/*
+ * Network Store Interface tests
+ *
+ * Copyright 2021 Huw Davies
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "winsock2.h"
+#include "winternl.h"
+#include "ws2ipdef.h"
+#include "iphlpapi.h"
+#include "netioapi.h"
+#include "iptypes.h"
+#include "netiodef.h"
+
+#include "wine/test.h"
+
+static int bounded( ULONG64 val, ULONG64 lo, ULONG64 hi )
+{
+    return lo <= val && val <= hi;
+}
+
+static void test_ndis_ifinfo( void )
+{
+    DWORD rw_sizes[] = { FIELD_OFFSET(struct nsi_ndis_ifinfo_rw, name2), FIELD_OFFSET(struct nsi_ndis_ifinfo_rw, unk),
+                         sizeof(struct nsi_ndis_ifinfo_rw) };
+    struct nsi_ndis_ifinfo_rw *rw_tbl;
+    struct nsi_ndis_ifinfo_dynamic *dyn_tbl, *dyn_tbl_2;
+    struct nsi_ndis_ifinfo_static *stat_tbl;
+    DWORD err, count, i, rw_size;
+    NET_LUID *luid_tbl, *luid_tbl_2;
+    MIB_IF_TABLE2 *table;
+
+    /* Contents of GetIfTable2() keyed by luids */
+
+    for (i = 0; i < ARRAY_SIZE(rw_sizes); i++)
+    {
+        err = NsiAllocateAndGetTable( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, (void **)&luid_tbl, sizeof(*luid_tbl),
+                                      (void **)&rw_tbl, rw_sizes[i], (void **)&dyn_tbl, sizeof(*dyn_tbl),
+                                      (void **)&stat_tbl, sizeof(*stat_tbl), &count, 0 );
+        if (!err) break;
+    }
+todo_wine
+    ok( !err, "got %d\n", err );
+    if (err) return;
+    rw_size = rw_sizes[i];
+
+    err = GetIfTable2( &table );
+    ok( !err, "got %d\n", err );
+    ok( table->NumEntries == count, "table entries %d count %d\n", table->NumEntries, count );
+
+    /* Grab the dyn table again to provide an upper bound for the stats returned from GetIfTable2().
+       (The luids must be retrieved again otherwise NsiAllocateAndGetTable() fails). */
+    err = NsiAllocateAndGetTable( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, (void **)&luid_tbl_2, sizeof(*luid_tbl_2),
+                                  NULL, 0, (void **)&dyn_tbl_2, sizeof(*dyn_tbl_2),
+                                  NULL, 0, &count, 0 );
+    ok( !err, "got %d\n", err );
+    ok( table->NumEntries == count, "table entries %d count %d\n", table->NumEntries, count );
+
+    for (i = 0; i < count; i++)
+    {
+        MIB_IF_ROW2 *row = table->Table + i;
+        NET_LUID *luid = luid_tbl + i;
+        struct nsi_ndis_ifinfo_rw *rw = (struct nsi_ndis_ifinfo_rw *)((BYTE *)rw_tbl + i * rw_size);
+        struct nsi_ndis_ifinfo_dynamic *dyn = dyn_tbl + i, *dyn_2 = dyn_tbl_2 + i;
+        struct nsi_ndis_ifinfo_static *stat = stat_tbl + i;
+
+        ok( row->InterfaceLuid.Value == luid->Value, "%d: mismatch\n", i );
+        ok( row->InterfaceIndex == stat->if_index, "%d: mismatch\n", i );
+        ok( IsEqualGUID( &row->InterfaceGuid, &stat->if_guid ), "%d: mismatch\n", i );
+        ok( !memcmp( row->Alias, rw->alias.String, rw->alias.Length ), "%d: mismatch\n", i );
+        ok( lstrlenW( row->Alias ) * 2 == rw->alias.Length, "%d: mismatch\n", i );
+        ok( !memcmp( row->Description, stat->descr.String, sizeof(row->Description) ), "%d: mismatch\n", i );
+        ok( lstrlenW( row->Description ) * 2 == stat->descr.Length, "%d: mismatch\n", i );
+        ok( row->PhysicalAddressLength == rw->phys_addr.Length, "%d: mismatch\n", i );
+        ok( !memcmp( row->PhysicalAddress, rw->phys_addr.Address, IF_MAX_PHYS_ADDRESS_LENGTH ), "%d: mismatch\n", i );
+        ok( row->PhysicalAddressLength == stat->perm_phys_addr.Length, "%d: mismatch\n", i );
+        ok( !memcmp( row->PermanentPhysicalAddress, stat->perm_phys_addr.Address, IF_MAX_PHYS_ADDRESS_LENGTH ), "%d: mismatch\n", i );
+        ok( row->Mtu == dyn->mtu, "%d: mismatch\n", i );
+        ok( row->Type == stat->type, "%d: mismatch\n", i );
+        /* TunnelType */
+        ok( row->MediaType == stat->media_type, "%d: mismatch\n", i );
+        ok( row->PhysicalMediumType == stat->phys_medium_type, "%d: mismatch\n", i );
+        ok( row->AccessType == stat->access_type, "%d: mismatch\n", i );
+        /* DirectionType */
+        ok( row->InterfaceAndOperStatusFlags.HardwareInterface == stat->flags.hw, "%d: mismatch\n", i );
+        ok( row->InterfaceAndOperStatusFlags.FilterInterface == stat->flags.filter, "%d: mismatch\n", i );
+        ok( row->InterfaceAndOperStatusFlags.ConnectorPresent == stat->conn_present, "%d: mismatch\n", i );
+        /* NotAuthenticated */
+        ok( row->InterfaceAndOperStatusFlags.NotMediaConnected == dyn->flags.not_media_conn, "%d: mismatch\n", i );
+        /* Paused */
+        /* LowPower */
+        /* EndPointInterface */
+        ok( row->OperStatus == dyn->oper_status, "%d: mismatch\n", i );
+        ok( row->AdminStatus == rw->admin_status, "%d: mismatch\n", i );
+        ok( row->MediaConnectState == dyn->media_conn_state, "%d: status mismatch\n", i );
+        ok( IsEqualGUID( &row->NetworkGuid, &rw->network_guid ), "%d: mismatch\n", i );
+        ok( row->ConnectionType == stat->conn_type, "%d: mismatch\n", i );
+        if (dyn->xmit_speed == ~0ULL) dyn->xmit_speed = 0;
+        ok( row->TransmitLinkSpeed == dyn->xmit_speed, "%d: mismatch\n", i );
+        if (dyn->rcv_speed == ~0ULL) dyn->rcv_speed = 0;
+        ok( row->ReceiveLinkSpeed == dyn->rcv_speed, "%d: mismatch\n", i );
+        ok( bounded( row->InOctets, dyn->in_octets, dyn_2->in_octets ), "%d: mismatch\n", i );
+        ok( bounded( row->InUcastPkts, dyn->in_ucast_pkts, dyn_2->in_ucast_pkts ), "%d: mismatch\n", i );
+        ok( bounded( row->InNUcastPkts, dyn->in_mcast_pkts + dyn->in_bcast_pkts,
+                     dyn_2->in_mcast_pkts + dyn_2->in_bcast_pkts ), "%d: mismatch\n", i );
+        ok( bounded( row->InDiscards, dyn->in_discards, dyn_2->in_discards ), "%d: mismatch\n", i );
+        ok( bounded( row->InErrors, dyn->in_errors, dyn_2->in_errors ), "%d: mismatch\n", i );
+        /* InUnknownProtos */
+        ok( bounded( row->InUcastOctets, dyn->in_ucast_octs, dyn_2->in_ucast_octs ), "%d: mismatch\n", i );
+        ok( bounded( row->InMulticastOctets, dyn->in_mcast_octs, dyn_2->in_mcast_octs ), "%d: mismatch\n", i );
+        ok( bounded( row->InBroadcastOctets, dyn->in_bcast_octs, dyn_2->in_bcast_octs ), "%d: mismatch\n", i );
+        ok( bounded( row->OutOctets, dyn->out_octets, dyn_2->out_octets ), "%d: mismatch\n", i );
+        ok( bounded( row->OutUcastPkts, dyn->out_ucast_pkts, dyn_2->out_ucast_pkts ), "%d: mismatch\n", i );
+        ok( bounded( row->OutNUcastPkts, dyn->out_mcast_pkts + dyn->out_bcast_pkts,
+                     dyn_2->out_mcast_pkts + dyn_2->out_bcast_pkts ), "%d: mismatch\n", i );
+        ok( bounded( row->OutDiscards, dyn->out_discards, dyn_2->out_discards ), "%d: mismatch\n", i );
+        ok( bounded( row->OutErrors, dyn->out_errors, dyn_2->out_errors ), "%d: mismatch\n", i );
+        ok( bounded( row->OutUcastOctets, dyn->out_ucast_octs, dyn_2->out_ucast_octs ), "%d: mismatch\n", i );
+        ok( bounded( row->OutMulticastOctets, dyn->out_mcast_octs, dyn_2->out_mcast_octs ), "%d: mismatch\n", i );
+        ok( bounded( row->OutBroadcastOctets, dyn->out_bcast_octs, dyn_2->out_bcast_octs ), "%d: mismatch\n", i );
+        /* OutQLen */
+    }
+
+    FreeMibTable( table );
+    NsiFreeTable( luid_tbl_2, NULL, dyn_tbl_2, NULL );
+    NsiFreeTable( luid_tbl, rw_tbl, dyn_tbl, stat_tbl );
+}
+
+START_TEST( nsi )
+{
+    test_ndis_ifinfo();
+}
diff --git a/include/ifmib.h b/include/ifmib.h
index 440ed144037..83f2c090945 100644
--- a/include/ifmib.h
+++ b/include/ifmib.h
@@ -66,5 +66,77 @@ typedef struct _MIB_IFTABLE
     MIB_IFROW table[1];
 } MIB_IFTABLE, *PMIB_IFTABLE;
 
+/* Undocumented NSI NDIS tables */
+#define NSI_NDIS_IFINFO_TABLE              0
+#define NSI_NDIS_INDEX_LUID_TABLE          2
+
+struct nsi_ndis_ifinfo_rw
+{
+    GUID network_guid;
+    DWORD admin_status;
+    IF_COUNTED_STRING alias; /* .Length in bytes not including '\0' */
+    IF_PHYSICAL_ADDRESS phys_addr;
+    USHORT pad;
+    IF_COUNTED_STRING name2;
+    DWORD unk;
+};
+
+struct nsi_ndis_ifinfo_dynamic
+{
+    DWORD oper_status;
+    struct
+    {
+        DWORD unk : 1;
+        DWORD not_media_conn : 1;
+        DWORD unk2 : 30;
+    } flags;
+    DWORD media_conn_state;
+    DWORD unk;
+    DWORD mtu;
+    ULONG64 xmit_speed;
+    ULONG64 rcv_speed;
+    ULONG64 in_errors;
+    ULONG64 in_discards;
+    ULONG64 out_errors;
+    ULONG64 out_discards;
+    ULONG64 unk2;
+    ULONG64 in_octets;
+    ULONG64 in_ucast_pkts;
+    ULONG64 in_mcast_pkts;
+    ULONG64 in_bcast_pkts;
+    ULONG64 out_octets;
+    ULONG64 out_ucast_pkts;
+    ULONG64 out_mcast_pkts;
+    ULONG64 out_bcast_pkts;
+    ULONG64 unk3[2];
+    ULONG64 in_ucast_octs;
+    ULONG64 in_mcast_octs;
+    ULONG64 in_bcast_octs;
+    ULONG64 out_ucast_octs;
+    ULONG64 out_mcast_octs;
+    ULONG64 out_bcast_octs;
+    ULONG64 unk4;
+};
+
+struct nsi_ndis_ifinfo_static
+{
+    DWORD if_index;
+    IF_COUNTED_STRING descr;
+    DWORD type;
+    DWORD access_type;
+    DWORD unk;
+    DWORD conn_type;
+    GUID if_guid;
+    USHORT conn_present;
+    IF_PHYSICAL_ADDRESS perm_phys_addr;
+    struct
+    {
+        DWORD hw : 1;
+        DWORD filter : 1;
+        DWORD unk : 30;
+    } flags;
+    DWORD media_type;
+    DWORD phys_medium_type;
+};
 
 #endif /* __WINE_IFMIB_H */
-- 
2.23.0




More information about the wine-devel mailing list