nsi: Add a stub implementation of NsiGetAllParametersEx().
[wine.git] / dlls / nsi / tests / nsi.c
blob7c2c57b95484b32a70807cf3b9674054ca4b23e7
1 /*
2 * Network Store Interface tests
4 * Copyright 2021 Huw Davies
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "winsock2.h"
22 #include "winternl.h"
23 #include "ws2ipdef.h"
24 #include "iphlpapi.h"
25 #include "netioapi.h"
26 #include "iptypes.h"
27 #include "netiodef.h"
28 #include "wine/nsi.h"
29 #include "wine/test.h"
31 static int bounded( ULONG64 val, ULONG64 lo, ULONG64 hi )
33 return lo <= val && val <= hi;
36 static void test_nsi_api( void )
38 DWORD rw_sizes[] = { FIELD_OFFSET(struct nsi_ndis_ifinfo_rw, name2), FIELD_OFFSET(struct nsi_ndis_ifinfo_rw, unk),
39 sizeof(struct nsi_ndis_ifinfo_rw) };
40 struct nsi_ndis_ifinfo_rw *rw_tbl, *rw, get_rw, *enum_rw_tbl, *enum_rw;
41 struct nsi_ndis_ifinfo_dynamic *dyn_tbl, *dyn, get_dyn, *enum_dyn_tbl, *enum_dyn;
42 struct nsi_ndis_ifinfo_static *stat_tbl, *stat, get_stat, *enum_stat_tbl, *enum_stat;
43 struct nsi_get_all_parameters_ex get_all_params;
44 struct nsi_enumerate_all_ex enum_params;
45 DWORD err, count, i, rw_size, enum_count;
46 NET_LUID *luid_tbl, *enum_luid_tbl;
48 /* Use the NDIS ifinfo table to test various api */
49 for (i = 0; i < ARRAY_SIZE(rw_sizes); i++)
51 err = NsiAllocateAndGetTable( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, (void **)&luid_tbl, sizeof(*luid_tbl),
52 (void **)&rw_tbl, rw_sizes[i], (void **)&dyn_tbl, sizeof(*dyn_tbl),
53 (void **)&stat_tbl, sizeof(*stat_tbl), &count, 0 );
54 if (!err) break;
56 todo_wine
57 ok( !err, "got %d\n", err );
58 if (err) return;
59 rw_size = rw_sizes[i];
61 for (i = 0; i < count; i++)
63 winetest_push_context( "%d", i );
64 rw = (struct nsi_ndis_ifinfo_rw *)((BYTE *)rw_tbl + i * rw_size);
65 dyn = dyn_tbl + i;
66 stat = stat_tbl + i;
68 err = NsiGetAllParameters( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, luid_tbl + i, sizeof(*luid_tbl),
69 &get_rw, rw_size, &get_dyn, sizeof(get_dyn), &get_stat, sizeof(get_stat) );
70 ok( !err, "got %d\n", err );
71 /* test a selection of members */
72 ok( IsEqualGUID( &get_rw.network_guid, &rw->network_guid ), "mismatch\n" );
73 ok( get_rw.alias.Length == rw->alias.Length, "mismatch\n" );
74 ok( !memcmp( get_rw.alias.String, rw->alias.String, rw->alias.Length ), "mismatch\n" );
75 ok( get_rw.phys_addr.Length == rw->phys_addr.Length, "mismatch\n" );
76 ok( !memcmp( get_rw.phys_addr.Address, rw->phys_addr.Address, IF_MAX_PHYS_ADDRESS_LENGTH ), "mismatch\n" );
77 ok( get_dyn.oper_status == dyn->oper_status, "mismatch\n" );
78 ok( get_stat.if_index == stat->if_index, "mismatch\n" );
79 ok( IsEqualGUID( &get_stat.if_guid, &stat->if_guid ), "mismatch\n" );
81 memset( &get_rw, 0xcc, sizeof(get_rw) );
82 memset( &get_dyn, 0xcc, sizeof(get_dyn) );
83 memset( &get_stat, 0xcc, sizeof(get_stat) );
85 memset( &get_all_params, 0, sizeof(get_all_params) );
86 get_all_params.first_arg = 1;
87 get_all_params.module = &NPI_MS_NDIS_MODULEID;
88 get_all_params.table = NSI_NDIS_IFINFO_TABLE;
89 get_all_params.key = luid_tbl + i;
90 get_all_params.key_size = sizeof(*luid_tbl);
91 get_all_params.rw_data = &get_rw;
92 get_all_params.rw_size = rw_size;
93 get_all_params.dynamic_data = &get_dyn;
94 get_all_params.dynamic_size = sizeof(get_dyn);
95 get_all_params.static_data = &get_stat;
96 get_all_params.static_size = sizeof(get_stat);
98 err = NsiGetAllParametersEx( &get_all_params );
99 ok( !err, "got %d\n", err );
100 /* test a selection of members */
101 ok( IsEqualGUID( &get_rw.network_guid, &rw->network_guid ), "mismatch\n" );
102 ok( get_rw.alias.Length == rw->alias.Length, "mismatch\n" );
103 ok( !memcmp( get_rw.alias.String, rw->alias.String, rw->alias.Length ), "mismatch\n" );
104 ok( get_rw.phys_addr.Length == rw->phys_addr.Length, "mismatch\n" );
105 ok( !memcmp( get_rw.phys_addr.Address, rw->phys_addr.Address, IF_MAX_PHYS_ADDRESS_LENGTH ), "mismatch\n" );
106 ok( get_dyn.oper_status == dyn->oper_status, "mismatch\n" );
107 ok( get_stat.if_index == stat->if_index, "mismatch\n" );
108 ok( IsEqualGUID( &get_stat.if_guid, &stat->if_guid ), "mismatch\n" );
110 memset( &get_rw, 0xcc, sizeof(get_rw) );
111 memset( &get_dyn, 0xcc, sizeof(get_dyn) );
112 memset( &get_stat, 0xcc, sizeof(get_stat) );
114 err = NsiGetParameter( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, luid_tbl + i, sizeof(*luid_tbl),
115 NSI_PARAM_TYPE_RW, &get_rw.alias, sizeof(get_rw.alias),
116 FIELD_OFFSET(struct nsi_ndis_ifinfo_rw, alias) );
117 ok( !err, "got %d\n", err );
118 ok( get_rw.alias.Length == rw->alias.Length, "mismatch\n" );
119 ok( !memcmp( get_rw.alias.String, rw->alias.String, rw->alias.Length ), "mismatch\n" );
121 err = NsiGetParameter( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, luid_tbl + i, sizeof(*luid_tbl),
122 NSI_PARAM_TYPE_STATIC, &get_stat.if_index, sizeof(get_stat.if_index),
123 FIELD_OFFSET(struct nsi_ndis_ifinfo_static, if_index) );
124 ok( !err, "got %d\n", err );
125 ok( get_stat.if_index == stat->if_index, "mismatch\n" );
127 err = NsiGetParameter( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, luid_tbl + i, sizeof(*luid_tbl),
128 NSI_PARAM_TYPE_STATIC, &get_stat.if_guid, sizeof(get_stat.if_guid),
129 FIELD_OFFSET(struct nsi_ndis_ifinfo_static, if_guid) );
130 ok( !err, "got %d\n", err );
131 ok( IsEqualGUID( &get_stat.if_guid, &stat->if_guid ), "mismatch\n" );
132 winetest_pop_context();
135 enum_count = 0;
136 err = NsiEnumerateObjectsAllParameters( 1, 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE,
137 NULL, 0, NULL, 0,
138 NULL, 0, NULL, 0, &enum_count );
139 ok( !err, "got %d\n", err );
140 ok( enum_count == count, "mismatch\n" );
142 enum_luid_tbl = malloc( count * sizeof(*enum_luid_tbl) );
143 enum_rw_tbl = malloc( count * rw_size );
144 enum_dyn_tbl = malloc( count * sizeof(*enum_dyn_tbl) );
145 enum_stat_tbl = malloc( count * sizeof(*enum_stat_tbl) );
147 err = NsiEnumerateObjectsAllParameters( 1, 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE,
148 enum_luid_tbl, sizeof(*enum_luid_tbl), enum_rw_tbl, rw_size,
149 enum_dyn_tbl, sizeof(*enum_dyn_tbl), enum_stat_tbl, sizeof(*enum_stat_tbl),
150 &enum_count );
151 ok( !err, "got %d\n", err );
152 ok( enum_count == count, "mismatch\n" );
154 for (i = 0; i < count; i++)
156 winetest_push_context( "%d", i );
157 rw = (struct nsi_ndis_ifinfo_rw *)((BYTE *)rw_tbl + i * rw_size);
158 enum_rw = (struct nsi_ndis_ifinfo_rw *)((BYTE *)enum_rw_tbl + i * rw_size);
159 dyn = dyn_tbl + i;
160 enum_dyn = enum_dyn_tbl + i;
161 stat = stat_tbl + i;
162 enum_stat = enum_stat_tbl + i;
164 /* test a selection of members */
165 ok( enum_luid_tbl[i].Value == luid_tbl[i].Value, "mismatch\n" );
166 ok( IsEqualGUID( &enum_rw->network_guid, &rw->network_guid ), "mismatch\n" );
167 ok( enum_rw->alias.Length == rw->alias.Length, "mismatch\n" );
168 ok( !memcmp( enum_rw->alias.String, rw->alias.String, rw->alias.Length ), "mismatch\n" );
169 ok( enum_rw->phys_addr.Length == rw->phys_addr.Length, "mismatch\n" );
170 ok( !memcmp( enum_rw->phys_addr.Address, rw->phys_addr.Address, IF_MAX_PHYS_ADDRESS_LENGTH ), "mismatch\n" );
171 ok( enum_dyn->oper_status == dyn->oper_status, "mismatch\n" );
172 ok( enum_stat->if_index == stat->if_index, "mismatch\n" );
173 ok( IsEqualGUID( &enum_stat->if_guid, &stat->if_guid ), "mismatch\n" );
174 winetest_pop_context();
177 if (count > 0)
179 enum_count--;
180 memset( enum_luid_tbl, 0xcc, count * sizeof(*enum_luid_tbl) );
182 err = NsiEnumerateObjectsAllParameters( 1, 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE,
183 enum_luid_tbl, sizeof(*enum_luid_tbl), enum_rw_tbl, rw_size,
184 enum_dyn_tbl, sizeof(*enum_dyn_tbl), enum_stat_tbl, sizeof(*enum_stat_tbl),
185 &enum_count );
186 ok( err == ERROR_MORE_DATA, "got %d\n", err );
187 ok( enum_count == count - 1, "mismatch\n" );
189 for (i = 0; i < enum_count; i++) /* for simplicity just check the luids */
190 ok( enum_luid_tbl[i].Value == luid_tbl[i].Value, "%d: mismatch\n", i );
193 memset( &enum_params, 0, sizeof(enum_params) );
194 enum_params.first_arg = 1;
195 enum_params.second_arg = 1;
196 enum_params.module = &NPI_MS_NDIS_MODULEID;
197 enum_params.table = NSI_NDIS_IFINFO_TABLE;
198 enum_params.key_data = enum_luid_tbl;
199 enum_params.key_size = sizeof(*enum_luid_tbl);
200 enum_params.rw_data = enum_rw_tbl;
201 enum_params.rw_size = rw_size;
202 enum_params.dynamic_data = enum_dyn_tbl;
203 enum_params.dynamic_size = sizeof(*enum_dyn_tbl);
204 enum_params.static_data = enum_stat_tbl;
205 enum_params.static_size = sizeof(*enum_stat_tbl);
206 enum_params.count = count;
208 err = NsiEnumerateObjectsAllParametersEx( &enum_params );
209 ok( !err, "got %d\n", err );
210 ok( enum_params.count == count, "mismatch\n" );
212 free( enum_luid_tbl );
213 free( enum_rw_tbl );
214 free( enum_dyn_tbl );
215 free( enum_stat_tbl );
216 NsiFreeTable( luid_tbl, rw_tbl, dyn_tbl, stat_tbl );
219 static void test_ndis_ifinfo( void )
221 DWORD rw_sizes[] = { FIELD_OFFSET(struct nsi_ndis_ifinfo_rw, name2), FIELD_OFFSET(struct nsi_ndis_ifinfo_rw, unk),
222 sizeof(struct nsi_ndis_ifinfo_rw) };
223 struct nsi_ndis_ifinfo_rw *rw_tbl;
224 struct nsi_ndis_ifinfo_dynamic *dyn_tbl, *dyn_tbl_2;
225 struct nsi_ndis_ifinfo_static *stat_tbl;
226 DWORD err, count, i, rw_size;
227 NET_LUID *luid_tbl, *luid_tbl_2;
228 MIB_IF_TABLE2 *table;
230 /* Contents of GetIfTable2() keyed by luids */
232 for (i = 0; i < ARRAY_SIZE(rw_sizes); i++)
234 err = NsiAllocateAndGetTable( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, (void **)&luid_tbl, sizeof(*luid_tbl),
235 (void **)&rw_tbl, rw_sizes[i], (void **)&dyn_tbl, sizeof(*dyn_tbl),
236 (void **)&stat_tbl, sizeof(*stat_tbl), &count, 0 );
237 if (!err) break;
239 todo_wine
240 ok( !err, "got %d\n", err );
241 if (err) return;
242 rw_size = rw_sizes[i];
244 err = GetIfTable2( &table );
245 ok( !err, "got %d\n", err );
246 ok( table->NumEntries == count, "table entries %d count %d\n", table->NumEntries, count );
248 /* Grab the dyn table again to provide an upper bound for the stats returned from GetIfTable2().
249 (The luids must be retrieved again otherwise NsiAllocateAndGetTable() fails). */
250 err = NsiAllocateAndGetTable( 1, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, (void **)&luid_tbl_2, sizeof(*luid_tbl_2),
251 NULL, 0, (void **)&dyn_tbl_2, sizeof(*dyn_tbl_2),
252 NULL, 0, &count, 0 );
253 ok( !err, "got %d\n", err );
254 ok( table->NumEntries == count, "table entries %d count %d\n", table->NumEntries, count );
256 for (i = 0; i < count; i++)
258 MIB_IF_ROW2 *row = table->Table + i;
259 NET_LUID *luid = luid_tbl + i;
260 struct nsi_ndis_ifinfo_rw *rw = (struct nsi_ndis_ifinfo_rw *)((BYTE *)rw_tbl + i * rw_size);
261 struct nsi_ndis_ifinfo_dynamic *dyn = dyn_tbl + i, *dyn_2 = dyn_tbl_2 + i;
262 struct nsi_ndis_ifinfo_static *stat = stat_tbl + i;
264 winetest_push_context( "%d", i );
265 ok( row->InterfaceLuid.Value == luid->Value, "mismatch\n" );
266 ok( row->InterfaceIndex == stat->if_index, "mismatch\n" );
267 ok( IsEqualGUID( &row->InterfaceGuid, &stat->if_guid ), "mismatch\n" );
268 ok( !memcmp( row->Alias, rw->alias.String, rw->alias.Length ), "mismatch\n" );
269 ok( lstrlenW( row->Alias ) * 2 == rw->alias.Length, "mismatch\n" );
270 ok( !memcmp( row->Description, stat->descr.String, sizeof(row->Description) ), "mismatch\n" );
271 ok( lstrlenW( row->Description ) * 2 == stat->descr.Length, "mismatch\n" );
272 ok( row->PhysicalAddressLength == rw->phys_addr.Length, "mismatch\n" );
273 ok( !memcmp( row->PhysicalAddress, rw->phys_addr.Address, IF_MAX_PHYS_ADDRESS_LENGTH ), "mismatch\n" );
274 ok( row->PhysicalAddressLength == stat->perm_phys_addr.Length, "mismatch\n" );
275 ok( !memcmp( row->PermanentPhysicalAddress, stat->perm_phys_addr.Address, IF_MAX_PHYS_ADDRESS_LENGTH ),
276 "mismatch\n" );
277 ok( row->Mtu == dyn->mtu, "mismatch\n" );
278 ok( row->Type == stat->type, "mismatch\n" );
279 /* TunnelType */
280 ok( row->MediaType == stat->media_type, "mismatch\n" );
281 ok( row->PhysicalMediumType == stat->phys_medium_type, "mismatch\n" );
282 ok( row->AccessType == stat->access_type, "mismatch\n" );
283 /* DirectionType */
284 ok( row->InterfaceAndOperStatusFlags.HardwareInterface == stat->flags.hw, "mismatch\n" );
285 ok( row->InterfaceAndOperStatusFlags.FilterInterface == stat->flags.filter, "mismatch\n" );
286 ok( row->InterfaceAndOperStatusFlags.ConnectorPresent == stat->conn_present, "mismatch\n" );
287 /* NotAuthenticated */
288 ok( row->InterfaceAndOperStatusFlags.NotMediaConnected == dyn->flags.not_media_conn, "mismatch\n" );
289 /* Paused */
290 /* LowPower */
291 /* EndPointInterface */
292 ok( row->OperStatus == dyn->oper_status, "mismatch\n" );
293 ok( row->AdminStatus == rw->admin_status, "mismatch\n" );
294 ok( row->MediaConnectState == dyn->media_conn_state, "mismatch\n" );
295 ok( IsEqualGUID( &row->NetworkGuid, &rw->network_guid ), "mismatch\n" );
296 ok( row->ConnectionType == stat->conn_type, "mismatch\n" );
297 if (dyn->xmit_speed == ~0ULL) dyn->xmit_speed = 0;
298 ok( row->TransmitLinkSpeed == dyn->xmit_speed, "mismatch\n" );
299 if (dyn->rcv_speed == ~0ULL) dyn->rcv_speed = 0;
300 ok( row->ReceiveLinkSpeed == dyn->rcv_speed, "mismatch\n" );
301 ok( bounded( row->InOctets, dyn->in_octets, dyn_2->in_octets ), "mismatch\n" );
302 ok( bounded( row->InUcastPkts, dyn->in_ucast_pkts, dyn_2->in_ucast_pkts ), "mismatch\n" );
303 ok( bounded( row->InNUcastPkts, dyn->in_mcast_pkts + dyn->in_bcast_pkts,
304 dyn_2->in_mcast_pkts + dyn_2->in_bcast_pkts ), "mismatch\n" );
305 ok( bounded( row->InDiscards, dyn->in_discards, dyn_2->in_discards ), "mismatch\n" );
306 ok( bounded( row->InErrors, dyn->in_errors, dyn_2->in_errors ), "mismatch\n" );
307 /* InUnknownProtos */
308 ok( bounded( row->InUcastOctets, dyn->in_ucast_octs, dyn_2->in_ucast_octs ), "mismatch\n" );
309 ok( bounded( row->InMulticastOctets, dyn->in_mcast_octs, dyn_2->in_mcast_octs ), "mismatch\n" );
310 ok( bounded( row->InBroadcastOctets, dyn->in_bcast_octs, dyn_2->in_bcast_octs ), "mismatch\n" );
311 ok( bounded( row->OutOctets, dyn->out_octets, dyn_2->out_octets ), "mismatch\n" );
312 ok( bounded( row->OutUcastPkts, dyn->out_ucast_pkts, dyn_2->out_ucast_pkts ), "mismatch\n" );
313 ok( bounded( row->OutNUcastPkts, dyn->out_mcast_pkts + dyn->out_bcast_pkts,
314 dyn_2->out_mcast_pkts + dyn_2->out_bcast_pkts ), "mismatch\n" );
315 ok( bounded( row->OutDiscards, dyn->out_discards, dyn_2->out_discards ), "mismatch\n" );
316 ok( bounded( row->OutErrors, dyn->out_errors, dyn_2->out_errors ), "mismatch\n" );
317 ok( bounded( row->OutUcastOctets, dyn->out_ucast_octs, dyn_2->out_ucast_octs ), "mismatch\n" );
318 ok( bounded( row->OutMulticastOctets, dyn->out_mcast_octs, dyn_2->out_mcast_octs ), "mismatch\n" );
319 ok( bounded( row->OutBroadcastOctets, dyn->out_bcast_octs, dyn_2->out_bcast_octs ), "mismatch\n" );
320 /* OutQLen */
321 winetest_pop_context();
324 FreeMibTable( table );
325 NsiFreeTable( luid_tbl_2, NULL, dyn_tbl_2, NULL );
326 NsiFreeTable( luid_tbl, rw_tbl, dyn_tbl, stat_tbl );
329 START_TEST( nsi )
331 test_nsi_api();
333 test_ndis_ifinfo();