[IMM32_WINETEST]
[reactos.git] / rostests / winetests / inetmib1 / main.c
1 /*
2 * Copyright 2008 Juan Lang
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18 #include <stdio.h>
19 #include <stdarg.h>
20 #include <windef.h>
21 #include <winbase.h>
22 #include <snmp.h>
23
24 #include "wine/test.h"
25
26 static HMODULE inetmib1;
27
28 static void testInit(void)
29 {
30 BOOL (WINAPI *pInit)(DWORD, HANDLE *, AsnObjectIdentifier *);
31 BOOL ret;
32 HANDLE event;
33 AsnObjectIdentifier oid;
34
35 pInit = (void *)GetProcAddress(inetmib1, "SnmpExtensionInit");
36 if (!pInit)
37 {
38 win_skip("no SnmpExtensionInit\n");
39 return;
40 }
41 /* Crash
42 ret = pInit(0, NULL, NULL);
43 ret = pInit(0, NULL, &oid);
44 ret = pInit(0, &event, NULL);
45 */
46 ret = pInit(0, &event, &oid);
47 ok(ret, "SnmpExtensionInit failed: %d\n", GetLastError());
48 ok(!strcmp("1.3.6.1.2.1.1", SnmpUtilOidToA(&oid)),
49 "Expected 1.3.6.1.2.1.1, got %s\n", SnmpUtilOidToA(&oid));
50
51 SnmpUtilOidFree(&oid);
52 }
53
54 static void testQuery(void)
55 {
56 BOOL (WINAPI *pQuery)(BYTE, SnmpVarBindList *, AsnInteger32 *,
57 AsnInteger32 *);
58 BOOL ret, moreData, noChange;
59 SnmpVarBindList list;
60 AsnInteger32 error, index;
61 UINT bogus[] = { 1,2,3,4 };
62 UINT mib2System[] = { 1,3,6,1,2,1,1 };
63 UINT mib2If[] = { 1,3,6,1,2,1,2 };
64 UINT mib2IfTable[] = { 1,3,6,1,2,1,2,2 };
65 UINT mib2IfDescr[] = { 1,3,6,1,2,1,2,2,1,2 };
66 UINT mib2IfAdminStatus[] = { 1,3,6,1,2,1,2,2,1,7 };
67 UINT mib2IfOperStatus[] = { 1,3,6,1,2,1,2,2,1,8 };
68 UINT mib2IpAddr[] = { 1,3,6,1,2,1,4,20,1,1 };
69 UINT mib2IpRouteTable[] = { 1,3,6,1,2,1,4,21,1,1 };
70 UINT mib2UdpTable[] = { 1,3,6,1,2,1,7,5,1,1 };
71 SnmpVarBind vars[3], vars2[3], vars3[3];
72 UINT entry;
73
74 pQuery = (void *)GetProcAddress(inetmib1, "SnmpExtensionQuery");
75 if (!pQuery)
76 {
77 win_skip("couldn't find SnmpExtensionQuery\n");
78 return;
79 }
80 /* Crash
81 ret = pQuery(0, NULL, NULL, NULL);
82 ret = pQuery(0, NULL, &error, NULL);
83 ret = pQuery(0, NULL, NULL, &index);
84 ret = pQuery(0, &list, NULL, NULL);
85 ret = pQuery(0, &list, &error, NULL);
86 */
87
88 /* An empty list succeeds */
89 list.len = 0;
90 error = 0xdeadbeef;
91 index = 0xdeadbeef;
92 ret = pQuery(SNMP_PDU_GET, &list, &error, &index);
93 ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index);
94 ok(error == SNMP_ERRORSTATUS_NOERROR,
95 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error);
96 ok(index == 0, "expected index 0, got %d\n", index);
97
98 /* Oddly enough, this "succeeds," even though the OID is clearly
99 * unsupported.
100 */
101 vars[0].name.idLength = sizeof(bogus) / sizeof(bogus[0]);
102 vars[0].name.ids = bogus;
103 vars[0].value.asnType = 0;
104 list.len = 1;
105 list.list = vars;
106 SetLastError(0xdeadbeef);
107 error = 0xdeadbeef;
108 index = 0xdeadbeef;
109 ret = pQuery(SNMP_PDU_GET, &list, &error, &index);
110 ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index);
111 ok(error == SNMP_ERRORSTATUS_NOERROR ||
112 broken(error == ERROR_FILE_NOT_FOUND) /* NT4 */,
113 "expected SNMP_ERRORSTATUS_NOERROR or ERROR_FILE_NOT_FOUND, got %d\n",
114 error);
115 if (error == SNMP_ERRORSTATUS_NOERROR)
116 ok(index == 0, "expected index 0, got %d\n", index);
117 else if (error == ERROR_FILE_NOT_FOUND)
118 ok(index == 1, "expected index 1, got %d\n", index);
119 /* The OID isn't changed either: */
120 ok(!strcmp("1.2.3.4", SnmpUtilOidToA(&vars[0].name)),
121 "expected 1.2.3.4, got %s\n", SnmpUtilOidToA(&vars[0].name));
122
123 /* The table is not an accessible variable, so it fails */
124 vars[0].name.idLength = sizeof(mib2IfTable) / sizeof(mib2IfTable[0]);
125 vars[0].name.ids = mib2IfTable;
126 SetLastError(0xdeadbeef);
127 error = 0xdeadbeef;
128 index = 0xdeadbeef;
129 ret = pQuery(SNMP_PDU_GET, &list, &error, &index);
130 ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index);
131 ok(error == SNMP_ERRORSTATUS_NOSUCHNAME,
132 "expected SNMP_ERRORSTATUS_NOSUCHNAME, got %d\n", error);
133 /* The index is 1-based rather than 0-based */
134 ok(index == 1, "expected index 1, got %d\n", index);
135
136 /* A Get fails on something that specifies a table (but not a particular
137 * entry in it)...
138 */
139 vars[0].name.idLength = sizeof(mib2IfDescr) / sizeof(mib2IfDescr[0]);
140 vars[0].name.ids = mib2IfDescr;
141 vars[1].name.idLength =
142 sizeof(mib2IfAdminStatus) / sizeof(mib2IfAdminStatus[0]);
143 vars[1].name.ids = mib2IfAdminStatus;
144 vars[2].name.idLength =
145 sizeof(mib2IfOperStatus) / sizeof(mib2IfOperStatus[0]);
146 vars[2].name.ids = mib2IfOperStatus;
147 list.len = 3;
148 SetLastError(0xdeadbeef);
149 error = 0xdeadbeef;
150 index = 0xdeadbeef;
151 ret = pQuery(SNMP_PDU_GET, &list, &error, &index);
152 ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index);
153 ok(error == SNMP_ERRORSTATUS_NOSUCHNAME,
154 "expected SNMP_ERRORSTATUS_NOSUCHNAME, got %d\n", error);
155 ok(index == 1, "expected index 1, got %d\n", index);
156 /* but a GetNext succeeds with the same values, because GetNext gets the
157 * entry after the specified OID, not the entry specified by it. The
158 * successor to the table is the first entry in the table.
159 * The OIDs need to be allocated, because GetNext modifies them to indicate
160 * the end of data.
161 */
162 SnmpUtilOidCpy(&vars2[0].name, &vars[0].name);
163 SnmpUtilOidCpy(&vars2[1].name, &vars[1].name);
164 SnmpUtilOidCpy(&vars2[2].name, &vars[2].name);
165 list.list = vars2;
166 moreData = TRUE;
167 noChange = FALSE;
168 entry = 0;
169 do {
170 SetLastError(0xdeadbeef);
171 error = 0xdeadbeef;
172 index = 0xdeadbeef;
173 ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index);
174 ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index);
175 ok(error == SNMP_ERRORSTATUS_NOERROR,
176 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error);
177 ok(index == 0, "expected index 0, got %d\n", index);
178 if (!ret)
179 moreData = FALSE;
180 else if (error)
181 moreData = FALSE;
182 else if (SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name,
183 vars[0].name.idLength))
184 moreData = FALSE;
185 else if (SnmpUtilOidNCmp(&vars2[1].name, &vars[1].name,
186 vars[1].name.idLength))
187 moreData = FALSE;
188 else if (SnmpUtilOidNCmp(&vars2[2].name, &vars[2].name,
189 vars[2].name.idLength))
190 moreData = FALSE;
191 else if (!SnmpUtilOidCmp(&vars[0].name, &vars2[0].name) ||
192 !SnmpUtilOidCmp(&vars[1].name, &vars2[1].name) ||
193 !SnmpUtilOidCmp(&vars[2].name, &vars2[2].name))
194 {
195 /* If the OID isn't modified, the function isn't implemented on this
196 * platform, skip the remaining tests.
197 */
198 noChange = TRUE;
199 }
200 if (moreData)
201 {
202 UINT lastID;
203
204 /* Check the OIDs. For these types of values (display strings and
205 * integers) they should increase by 1 for each element of the table
206 * according to RFC 1158. Windows sometimes has a weird value in the
207 * table, so allow any value as long as it's greater than the previous
208 * value on Windows.
209 */
210 ok(vars2[0].name.idLength == vars[0].name.idLength + 1,
211 "expected length %d, got %d\n", vars[0].name.idLength + 1,
212 vars2[0].name.idLength);
213 lastID = vars2[0].name.ids[vars2[0].name.idLength - 1];
214 ok(lastID == entry + 1 || broken(lastID > entry),
215 "expected %d, got %d\n", entry + 1, lastID);
216 ok(vars2[1].name.idLength == vars[1].name.idLength + 1,
217 "expected length %d, got %d\n", vars[1].name.idLength + 1,
218 vars2[1].name.idLength);
219 lastID = vars2[1].name.ids[vars2[1].name.idLength - 1];
220 ok(lastID == entry + 1 || broken(lastID > entry),
221 "expected %d, got %d\n", entry + 1, lastID);
222 ok(vars2[2].name.idLength == vars[2].name.idLength + 1,
223 "expected length %d, got %d\n", vars[2].name.idLength + 1,
224 vars2[2].name.idLength);
225 lastID = vars2[2].name.ids[vars2[2].name.idLength - 1];
226 ok(lastID == entry + 1 || broken(lastID > entry),
227 "expected %d, got %d\n", entry + 1, lastID);
228 entry = lastID;
229 /* Check the types while we're at it */
230 ok(vars2[0].value.asnType == ASN_OCTETSTRING,
231 "expected ASN_OCTETSTRING, got %02x\n", vars2[0].value.asnType);
232 ok(vars2[1].value.asnType == ASN_INTEGER,
233 "expected ASN_INTEGER, got %02x\n", vars2[1].value.asnType);
234 ok(vars2[2].value.asnType == ASN_INTEGER,
235 "expected ASN_INTEGER, got %02x\n", vars2[2].value.asnType);
236 }
237 else if (noChange)
238 skip("no change in OID, no MIB2 IF table implementation\n");
239 } while (moreData && !noChange);
240 SnmpUtilVarBindFree(&vars2[0]);
241 SnmpUtilVarBindFree(&vars2[1]);
242 SnmpUtilVarBindFree(&vars2[2]);
243
244 /* Even though SnmpExtensionInit says this DLL supports the MIB2 system
245 * variables, on recent systems (at least Win2k) the first variable it
246 * returns a value for is the first interface.
247 */
248 vars[0].name.idLength = sizeof(mib2System) / sizeof(mib2System[0]);
249 vars[0].name.ids = mib2System;
250 SnmpUtilOidCpy(&vars2[0].name, &vars[0].name);
251 vars2[0].value.asnType = 0;
252 list.len = 1;
253 list.list = vars2;
254 noChange = FALSE;
255 ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index);
256 ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index);
257 ok(error == SNMP_ERRORSTATUS_NOERROR,
258 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error);
259 ok(index == 0, "expected index 0, got %d\n", index);
260 vars3[0].name.idLength = sizeof(mib2If) / sizeof(mib2If[0]);
261 vars3[0].name.ids = mib2If;
262 ok(!SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name, vars[0].name.idLength) ||
263 !SnmpUtilOidNCmp(&vars2[0].name, &vars3[0].name, vars3[0].name.idLength),
264 "expected 1.3.6.1.2.1.1 or 1.3.6.1.2.1.2, got %s\n",
265 SnmpUtilOidToA(&vars2[0].name));
266 SnmpUtilVarBindFree(&vars2[0]);
267
268 /* Check the type and OIDs of the IP address table */
269 vars[0].name.idLength = sizeof(mib2IpAddr) / sizeof(mib2IpAddr[0]);
270 vars[0].name.ids = mib2IpAddr;
271 SnmpUtilOidCpy(&vars2[0].name, &vars[0].name);
272 vars2[0].value.asnType = 0;
273 list.len = 1;
274 list.list = vars2;
275 moreData = TRUE;
276 do {
277 ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index);
278 ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index);
279 ok(error == SNMP_ERRORSTATUS_NOERROR,
280 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error);
281 ok(index == 0, "expected index 0, got %d\n", index);
282 if (!ret)
283 moreData = FALSE;
284 else if (error)
285 moreData = FALSE;
286 else if (SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name,
287 vars[0].name.idLength))
288 moreData = FALSE;
289 else if (!SnmpUtilOidCmp(&vars2[0].name, &vars[0].name))
290 {
291 /* If the OID isn't modified, the function isn't implemented on this
292 * platform, skip the remaining tests.
293 */
294 noChange = TRUE;
295 }
296 if (moreData)
297 {
298 /* Make sure the size of the OID is right.
299 * FIXME: don't know if IPv6 addrs are shared with this table.
300 * Don't think so, but I'm not certain.
301 */
302 ok(vars2[0].name.idLength == vars[0].name.idLength + 4,
303 "expected length %d, got %d\n", vars[0].name.idLength + 4,
304 vars2[0].name.idLength);
305 /* Make sure the type is right */
306 ok(vars2[0].value.asnType == ASN_IPADDRESS,
307 "expected type ASN_IPADDRESS, got %02x\n",
308 vars2[0].value.asnType);
309 if (vars2[0].value.asnType == ASN_IPADDRESS)
310 {
311 UINT i;
312
313 /* This looks uglier than it is: the base OID for the IP
314 * address, 1.3.6.1.2.1.4.20.1.1, is appended with the IP
315 * address of the entry. So e.g. the loopback address is
316 * identified in MIB2 as 1.3.6.1.2.1.4.20.1.1.127.0.0.1
317 */
318 for (i = 0; i < vars2[0].value.asnValue.address.length; i++)
319 {
320 ok(vars2[0].value.asnValue.address.stream[i] ==
321 vars2[0].name.ids[vars2[0].name.idLength - 4 + i],
322 "expected ident byte %d to be %d, got %d\n", i,
323 vars2[0].value.asnValue.address.stream[i],
324 vars2[0].name.ids[vars2[0].name.idLength - 4 + i]);
325 }
326 }
327 }
328 else if (noChange)
329 skip("no change in OID, no MIB2 IP address table implementation\n");
330 } while (moreData && !noChange);
331 SnmpUtilVarBindFree(&vars2[0]);
332
333 /* Check the type and OIDs of the IP route table */
334 vars[0].name.idLength = DEFINE_SIZEOF(mib2IpRouteTable);
335 vars[0].name.ids = mib2IpRouteTable;
336 SnmpUtilOidCpy(&vars2[0].name, &vars[0].name);
337 vars2[0].value.asnType = 0;
338 list.len = 1;
339 list.list = vars2;
340 moreData = TRUE;
341 noChange = FALSE;
342 do {
343 ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index);
344 ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index);
345 ok(error == SNMP_ERRORSTATUS_NOERROR,
346 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error);
347 ok(index == 0, "expected index 0, got %d\n", index);
348 if (!ret)
349 moreData = FALSE;
350 else if (error)
351 moreData = FALSE;
352 else if (SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name,
353 vars[0].name.idLength))
354 moreData = FALSE;
355 else if (!SnmpUtilOidCmp(&vars2[0].name, &vars[0].name))
356 {
357 /* If the OID isn't modified, the function isn't implemented on this
358 * platform, skip the remaining tests.
359 */
360 noChange = TRUE;
361 }
362 if (moreData)
363 {
364 /* Make sure the size of the OID is right.
365 * FIXME: don't know if IPv6 addrs are shared with this table.
366 * Don't think so, but I'm not certain.
367 */
368 ok(vars2[0].name.idLength == vars[0].name.idLength + 4,
369 "expected length %d, got %d\n", vars[0].name.idLength + 4,
370 vars2[0].name.idLength);
371 /* Make sure the type is right */
372 ok(vars2[0].value.asnType == ASN_IPADDRESS,
373 "expected type ASN_IPADDRESS, got %02x\n",
374 vars2[0].value.asnType);
375 if (vars2[0].value.asnType == ASN_IPADDRESS)
376 {
377 UINT i;
378
379 /* The base OID for the route table, 1.3.6.1.2.1.4.21.1.1, is
380 * appended with the dest IP address of the entry. So e.g. a
381 * route entry for 224.0.0.0 is identified in MIB2 as
382 * 1.3.6.1.2.1.4.21.1.1.224.0.0.0
383 */
384 for (i = 0; i < vars2[0].value.asnValue.address.length; i++)
385 {
386 ok(vars2[0].value.asnValue.address.stream[i] ==
387 vars2[0].name.ids[vars2[0].name.idLength - 4 + i],
388 "expected ident byte %d to be %d, got %d\n", i,
389 vars2[0].value.asnValue.address.stream[i],
390 vars2[0].name.ids[vars2[0].name.idLength - 4 + i]);
391 }
392 }
393 }
394 else if (noChange)
395 skip("no change in OID, no MIB2 IP route table implementation\n");
396 } while (moreData && !noChange);
397 SnmpUtilVarBindFree(&vars2[0]);
398
399 /* Check the type and OIDs of the UDP table */
400 vars[0].name.idLength = DEFINE_SIZEOF(mib2UdpTable);
401 vars[0].name.ids = mib2UdpTable;
402 SnmpUtilOidCpy(&vars2[0].name, &vars[0].name);
403 vars2[0].value.asnType = 0;
404 list.len = 1;
405 list.list = vars2;
406 moreData = TRUE;
407 noChange = FALSE;
408 do {
409 ret = pQuery(SNMP_PDU_GETNEXT, &list, &error, &index);
410 ok(ret, "SnmpExtensionQuery failed: %d, %d\n", error, index);
411 /* FIXME: error and index aren't checked here because the UDP table is
412 * the last OID currently supported by Wine, so the last GetNext fails.
413 * todo_wine is also not effective because it will succeed for all but
414 * the last GetNext. Remove the if (0) if any later OID is supported
415 * by Wine.
416 */
417 if (0) {
418 ok(error == SNMP_ERRORSTATUS_NOERROR,
419 "expected SNMP_ERRORSTATUS_NOERROR, got %d\n", error);
420 ok(index == 0, "expected index 0, got %d\n", index);
421 }
422 if (!ret)
423 moreData = FALSE;
424 else if (error)
425 moreData = FALSE;
426 else if (SnmpUtilOidNCmp(&vars2[0].name, &vars[0].name,
427 vars[0].name.idLength))
428 moreData = FALSE;
429 else if (!SnmpUtilOidCmp(&vars2[0].name, &vars[0].name))
430 {
431 /* If the OID isn't modified, the function isn't implemented on this
432 * platform, skip the remaining tests.
433 */
434 noChange = TRUE;
435 }
436 if (moreData)
437 {
438 /* Make sure the size of the OID is right. */
439 ok(vars2[0].name.idLength == vars[0].name.idLength + 5,
440 "expected length %d, got %d\n", vars[0].name.idLength + 5,
441 vars2[0].name.idLength);
442 /* Make sure the type is right */
443 ok(vars2[0].value.asnType == ASN_IPADDRESS,
444 "expected type ASN_IPADDRESS, got %02x\n",
445 vars2[0].value.asnType);
446 if (vars2[0].value.asnType == ASN_IPADDRESS)
447 {
448 UINT i;
449
450 /* Again with the ugly: the base OID for the UDP table,
451 * 1.3.6.1.2.1.7.5.1, is appended with the local IP address and
452 * port number of the entry. So e.g. an entry for
453 * 192.168.1.1:4000 is identified in MIB2 as
454 * 1.3.6.1.2.1.7.5.1.192.168.1.1.4000
455 */
456 for (i = 0; i < vars2[0].value.asnValue.address.length; i++)
457 {
458 ok(vars2[0].value.asnValue.address.stream[i] ==
459 vars2[0].name.ids[vars2[0].name.idLength - 5 + i],
460 "expected ident byte %d to be %d, got %d\n", i,
461 vars2[0].value.asnValue.address.stream[i],
462 vars2[0].name.ids[vars2[0].name.idLength - 5 + i]);
463 }
464 }
465 }
466 else if (noChange)
467 skip("no change in OID, no MIB2 UDP table implementation\n");
468 } while (moreData && !noChange);
469 SnmpUtilVarBindFree(&vars2[0]);
470 }
471
472 START_TEST(main)
473 {
474 inetmib1 = LoadLibraryA("inetmib1");
475 testInit();
476 testQuery();
477 FreeLibrary(inetmib1);
478 }