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