msi: Only insert entries into listbox if property value matches.
[wine] / dlls / snmpapi / main.c
1 /*
2  * Implementation of SNMPAPI.DLL
3  *
4  * Copyright 2002 Patrik Stridvall
5  * Copyright 2007 Hans Leidekker
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "config.h"
23
24 #include <stdio.h>
25 #include <stdarg.h>
26
27 #include "windef.h"
28 #include "winbase.h"
29 #include "snmp.h"
30
31 #include "wine/debug.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(snmpapi);
34
35 static INT asn_any_copy(AsnAny *dst, AsnAny *src)
36 {
37     memset(dst, 0, sizeof(AsnAny));
38     switch (src->asnType)
39     {
40     case ASN_INTEGER32:  dst->asnValue.number = src->asnValue.number; break;
41     case ASN_UNSIGNED32: dst->asnValue.unsigned32 = src->asnValue.unsigned32; break;
42     case ASN_COUNTER64:  dst->asnValue.counter64 = src->asnValue.counter64; break;
43     case ASN_COUNTER32:  dst->asnValue.counter = src->asnValue.counter; break;
44     case ASN_GAUGE32:    dst->asnValue.gauge = src->asnValue.gauge; break;
45     case ASN_TIMETICKS:  dst->asnValue.ticks = src->asnValue.ticks; break;
46
47     case ASN_OCTETSTRING:
48     case ASN_BITS:
49     case ASN_SEQUENCE:
50     case ASN_IPADDRESS:
51     case ASN_OPAQUE:
52     {
53         BYTE *stream;
54         UINT length = src->asnValue.string.length;
55
56         if (!(stream = HeapAlloc(GetProcessHeap(), 0, length))) return SNMPAPI_ERROR;
57
58         dst->asnValue.string.stream = stream;
59         dst->asnValue.string.length = length;
60         dst->asnValue.string.dynamic = TRUE;
61         break;
62     }
63     case ASN_OBJECTIDENTIFIER:
64     {
65         UINT *ids, i, size = src->asnValue.object.idLength * sizeof(UINT);
66
67         if (!(ids = HeapAlloc(GetProcessHeap(), 0, size))) return SNMPAPI_ERROR;
68
69         dst->asnValue.object.ids = ids;
70         dst->asnValue.object.idLength = src->asnValue.object.idLength;
71
72         for (i = 0; i < dst->asnValue.object.idLength; i++)
73             dst->asnValue.object.ids[i] = src->asnValue.object.ids[i];
74         break;
75     }
76     default:
77     {
78         WARN("unknown ASN type: %d\n", src->asnType);
79         return SNMPAPI_ERROR;
80     }
81     }
82     dst->asnType = src->asnType;
83     return SNMPAPI_NOERROR;
84 }
85
86 static void asn_any_free(AsnAny *any)
87 {
88     switch (any->asnType)
89     {
90     case ASN_OCTETSTRING:
91     case ASN_BITS:
92     case ASN_SEQUENCE:
93     case ASN_IPADDRESS:
94     case ASN_OPAQUE:
95     {
96         if (any->asnValue.string.dynamic)
97         {
98             HeapFree(GetProcessHeap(), 0, any->asnValue.string.stream);
99             any->asnValue.string.stream = NULL;
100         }
101         break;
102     }
103     case ASN_OBJECTIDENTIFIER:
104     {
105         HeapFree(GetProcessHeap(), 0, any->asnValue.object.ids);
106         any->asnValue.object.ids = NULL;
107         break;
108     }
109     default: break;
110     }
111     any->asnType = ASN_NULL;
112 }
113
114 /***********************************************************************
115  *              DllMain for SNMPAPI
116  */
117 BOOL WINAPI DllMain(
118         HINSTANCE hInstDLL,
119         DWORD fdwReason,
120         LPVOID lpvReserved)
121 {
122     TRACE("(%p,%d,%p)\n", hInstDLL, fdwReason, lpvReserved);
123
124     switch(fdwReason) {
125     case DLL_WINE_PREATTACH:
126         return FALSE;  /* prefer native version */
127     case DLL_PROCESS_ATTACH:
128         DisableThreadLibraryCalls(hInstDLL);
129         break;
130     case DLL_PROCESS_DETACH:
131         break;
132     }
133
134     return TRUE;
135 }
136
137 /***********************************************************************
138  *      SnmpUtilDbgPrint        (SNMPAPI.@)
139  *
140  * NOTES
141  *  The Microsoft headers claim this function uses the stdcall calling
142  *  convention. But stdcall functions cannot take a variable number of
143  *  arguments so this does not make sense. The stdcall specification is
144  *  probably ignored by Microsoft's compiler in this case. So declare it
145  *  correctly in Wine so it works with all compilers.
146  */
147 VOID WINAPIV SnmpUtilDbgPrint(INT loglevel, LPSTR format, ...)
148 {
149     FIXME("(%d, %s)\n", loglevel, debugstr_a(format));
150 }
151
152 /***********************************************************************
153  *      SnmpUtilMemAlloc        (SNMPAPI.@)
154  */
155 LPVOID WINAPI SnmpUtilMemAlloc(UINT nbytes)
156 {
157     TRACE("(%d)\n", nbytes);
158     return HeapAlloc(GetProcessHeap(), 0, nbytes);
159 }
160
161 /***********************************************************************
162  *      SnmpUtilMemReAlloc      (SNMPAPI.@)
163  */
164 LPVOID WINAPI SnmpUtilMemReAlloc(LPVOID mem, UINT nbytes)
165 {
166     TRACE("(%p, %d)\n", mem, nbytes);
167     return HeapReAlloc(GetProcessHeap(), 0, mem, nbytes);
168 }
169
170 /***********************************************************************
171  *      SnmpUtilMemFree         (SNMPAPI.@)
172  */
173 VOID WINAPI SnmpUtilMemFree(LPVOID mem)
174 {
175     TRACE("(%p)\n", mem);
176     HeapFree(GetProcessHeap(), 0, mem);
177 }
178
179 /***********************************************************************
180  *      SnmpUtilAsnAnyCpy       (SNMPAPI.@)
181  */
182 INT WINAPI SnmpUtilAsnAnyCpy(AsnAny *dst, AsnAny *src)
183 {
184     TRACE("(%p, %p)\n", dst, src);
185     return asn_any_copy(dst, src);
186 }
187
188 /***********************************************************************
189  *      SnmpUtilAsnAnyFree      (SNMPAPI.@)
190  */
191 VOID WINAPI SnmpUtilAsnAnyFree(AsnAny *any)
192 {
193     TRACE("(%p)\n", any);
194     asn_any_free(any);
195 }
196
197 /***********************************************************************
198  *      SnmpUtilOctetsCpy       (SNMPAPI.@)
199  */
200 INT WINAPI SnmpUtilOctetsCpy(AsnOctetString *dst, AsnOctetString *src)
201 {
202     TRACE("(%p, %p)\n", dst, src);
203
204     if (!dst) return SNMPAPI_ERROR;
205     if (!src)
206     {
207         dst->dynamic = FALSE;
208         dst->length = 0;
209         dst->stream = NULL;
210         return SNMPAPI_NOERROR;
211     }
212     if ((dst->stream = HeapAlloc(GetProcessHeap(), 0, src->length)))
213     {
214         unsigned int i;
215
216         dst->dynamic = TRUE;
217         dst->length = src->length;
218         for (i = 0; i < dst->length; i++) dst->stream[i] = src->stream[i];
219         return SNMPAPI_NOERROR;
220     }
221     return SNMPAPI_ERROR;
222 }
223
224 /***********************************************************************
225  *      SnmpUtilOctetsFree      (SNMPAPI.@)
226  */
227 VOID WINAPI SnmpUtilOctetsFree(AsnOctetString *octets)
228 {
229     TRACE("(%p)\n", octets);
230
231     if (octets)
232     {
233         octets->length = 0;
234         if (octets->dynamic) HeapFree(GetProcessHeap(), 0, octets->stream);
235         octets->stream = NULL;
236         octets->dynamic = FALSE;
237     }
238 }
239
240 /***********************************************************************
241  *      SnmpUtilOctetsNCmp      (SNMPAPI.@)
242  */
243 INT WINAPI SnmpUtilOctetsNCmp(AsnOctetString *octets1, AsnOctetString *octets2, UINT count)
244 {
245     INT ret;
246     unsigned int i;
247
248     TRACE("(%p, %p, %d)\n", octets1, octets2, count);
249
250     if (!octets1 || !octets2) return 0;
251
252     for (i = 0; i < count; i++)
253         if ((ret = octets1->stream[i] - octets2->stream[i])) return ret;
254
255     return 0;
256 }
257
258 /***********************************************************************
259  *      SnmpUtilOctetsCmp       (SNMPAPI.@)
260  */
261 INT WINAPI SnmpUtilOctetsCmp(AsnOctetString *octets1, AsnOctetString *octets2)
262 {
263     TRACE("(%p, %p)\n", octets1, octets2);
264
265     if (octets1->length < octets2->length) return -1;
266     if (octets1->length > octets2->length) return 1;
267
268     return SnmpUtilOctetsNCmp(octets1, octets2, octets1->length);
269 }
270
271 /***********************************************************************
272  *      SnmpUtilOidAppend       (SNMPAPI.@)
273  */
274 INT WINAPI SnmpUtilOidAppend(AsnObjectIdentifier *dst, AsnObjectIdentifier *src)
275 {
276     UINT *ids, i, size;
277
278     TRACE("(%p, %p)\n", dst, src);
279
280     if (!dst) return SNMPAPI_ERROR;
281     if (!src) return SNMPAPI_NOERROR;
282
283     size = (src->idLength + dst->idLength) * sizeof(UINT);
284     if (!(ids = HeapReAlloc(GetProcessHeap(), 0, dst->ids, size)))
285     {
286         if (!(ids = HeapAlloc(GetProcessHeap(), 0, size)))
287         {
288             SetLastError(SNMP_MEM_ALLOC_ERROR);
289             return SNMPAPI_ERROR;
290         }
291         else memcpy(ids, dst->ids, dst->idLength * sizeof(UINT));
292     }
293
294     for (i = 0; i < src->idLength; i++) ids[i + dst->idLength] = src->ids[i];
295     dst->idLength = dst->idLength + src->idLength;
296     dst->ids = ids;
297
298     return SNMPAPI_NOERROR;
299 }
300
301 /***********************************************************************
302  *      SnmpUtilOidCpy          (SNMPAPI.@)
303  */
304 INT WINAPI SnmpUtilOidCpy(AsnObjectIdentifier *dst, AsnObjectIdentifier *src)
305 {
306     TRACE("(%p, %p)\n", dst, src);
307
308     if (!dst) return SNMPAPI_ERROR;
309     if (!src)
310     {
311         dst->idLength = 0;
312         dst->ids = NULL;
313         return SNMPAPI_NOERROR;
314     }
315     if ((dst->ids = HeapAlloc(GetProcessHeap(), 0, src->idLength * sizeof(UINT))))
316     {
317         unsigned int i;
318
319         dst->idLength = src->idLength;
320         for (i = 0; i < dst->idLength; i++) dst->ids[i] = src->ids[i];
321         return SNMPAPI_NOERROR;
322     }
323     return SNMPAPI_ERROR;
324 }
325
326 /***********************************************************************
327  *      SnmpUtilOidFree         (SNMPAPI.@)
328  */
329 VOID WINAPI SnmpUtilOidFree(AsnObjectIdentifier *oid)
330 {
331     TRACE("(%p)\n", oid);
332
333     if (!oid) return;
334
335     oid->idLength = 0;
336     HeapFree(GetProcessHeap(), 0, oid->ids);
337     oid->ids = NULL;
338 }
339
340 /***********************************************************************
341  *      SnmpUtilOidNCmp         (SNMPAPI.@)
342  */
343 INT WINAPI SnmpUtilOidNCmp(AsnObjectIdentifier *oid1, AsnObjectIdentifier *oid2, UINT count)
344 {
345     unsigned int i;
346
347     TRACE("(%p, %p, %d)\n", oid1, oid2, count);
348
349     if (!oid1 || !oid2) return 0;
350
351     for (i = 0; i < count; i++)
352     {
353         if (oid1->ids[i] > oid2->ids[i]) return 1;
354         if (oid1->ids[i] < oid2->ids[i]) return -1;
355     }
356     return 0;
357 }
358
359 /***********************************************************************
360  *      SnmpUtilOidCmp          (SNMPAPI.@)
361  */
362 INT WINAPI SnmpUtilOidCmp(AsnObjectIdentifier *oid1, AsnObjectIdentifier *oid2)
363 {
364     TRACE("(%p, %p)\n", oid1, oid2);
365
366     if (oid1->idLength < oid2->idLength) return -1;
367     if (oid1->idLength > oid2->idLength) return 1;
368
369     return SnmpUtilOidNCmp(oid1, oid2, oid1->idLength);
370 }
371
372 /***********************************************************************
373  *      SnmpUtilVarBindCpy      (SNMPAPI.@)
374  */
375 INT WINAPI SnmpUtilVarBindCpy(SnmpVarBind *dst, SnmpVarBind *src)
376 {
377     unsigned int i, size;
378
379     TRACE("(%p, %p)\n", dst, src);
380
381     if (!dst) return SNMPAPI_ERROR;
382     if (!src)
383     {
384         dst->value.asnType = ASN_NULL;
385         return SNMPAPI_NOERROR;
386     }
387
388     size = src->name.idLength * sizeof(UINT);
389     if (!(dst->name.ids = HeapAlloc(GetProcessHeap(), 0, size))) return SNMPAPI_ERROR;
390
391     for (i = 0; i < src->name.idLength; i++) dst->name.ids[i] = src->name.ids[i];
392     dst->name.idLength = src->name.idLength;
393
394     if (!asn_any_copy(&dst->value, &src->value))
395     {
396         HeapFree(GetProcessHeap(), 0, dst->name.ids);
397         return SNMPAPI_ERROR;
398     }
399     return SNMPAPI_NOERROR;
400 }
401
402 /***********************************************************************
403  *      SnmpUtilVarBindFree     (SNMPAPI.@)
404  */
405 VOID WINAPI SnmpUtilVarBindFree(SnmpVarBind *vb)
406 {
407     TRACE("(%p)\n", vb);
408
409     if (!vb) return;
410
411     asn_any_free(&vb->value);
412     HeapFree(GetProcessHeap(), 0, vb->name.ids);
413     vb->name.idLength = 0;
414     vb->name.ids = NULL;
415 }
416
417 /***********************************************************************
418  *      SnmpUtilVarBindListCpy  (SNMPAPI.@)
419  */
420 INT WINAPI SnmpUtilVarBindListCpy(SnmpVarBindList *dst, SnmpVarBindList *src)
421 {
422     unsigned int i, size;
423     SnmpVarBind *src_entry, *dst_entry;
424
425     TRACE("(%p, %p)\n", dst, src);
426
427     if (!src)
428     {
429         dst->list = NULL;
430         dst->len = 0;
431         return SNMPAPI_NOERROR;
432     }
433     size = src->len * sizeof(SnmpVarBind *);
434     if (!(dst->list = HeapAlloc(GetProcessHeap(), 0, size)))
435     {
436         HeapFree(GetProcessHeap(), 0, dst);
437         return SNMPAPI_ERROR;
438     }
439     src_entry = src->list;
440     dst_entry = dst->list;
441     for (i = 0; i < src->len; i++)
442     {
443         if (SnmpUtilVarBindCpy(dst_entry, src_entry))
444         {
445             src_entry++;
446             dst_entry++;
447         }
448         else
449         {
450             for (--i; i > 0; i--) SnmpUtilVarBindFree(--dst_entry);
451             HeapFree(GetProcessHeap(), 0, dst->list);
452             return SNMPAPI_ERROR;
453         }
454     }
455     dst->len = src->len;
456     return SNMPAPI_NOERROR;
457 }
458
459 /***********************************************************************
460  *      SnmpUtilVarBindListFree (SNMPAPI.@)
461  */
462 VOID WINAPI SnmpUtilVarBindListFree(SnmpVarBindList *vb)
463 {
464     unsigned int i;
465     SnmpVarBind *entry;
466
467     TRACE("(%p)\n", vb);
468
469     entry = vb->list;
470     for (i = 0; i < vb->len; i++) SnmpUtilVarBindFree(entry++);
471     HeapFree(GetProcessHeap(), 0, vb->list);
472     vb->list = NULL;
473     vb->len = 0;
474 }
475
476 /***********************************************************************
477  *      SnmpUtilIdsToA          (SNMPAPI.@)
478  */
479 LPSTR WINAPI SnmpUtilIdsToA(UINT *ids, UINT length)
480 {
481     static char one[10], oid[514], null_oid[] = "<null oid>";
482     unsigned int i, len, left = sizeof(oid) - 1;
483
484     TRACE("(%p, %d)\n", ids, length);
485
486     if (!ids || !length) return null_oid;
487
488     *oid = 0;
489     for (i = 0; i < length; i++)
490     {
491         sprintf(one, "%d", ids[i]);
492         len = strlen(one);
493         if (left >= len)
494         {
495             strcat(oid, one);
496             left -= len;
497         }
498         else return oid;
499
500         if (i < length - 1)
501         {
502             if (left > 0)
503             {
504                 strcat(oid, ".");
505                 left--;
506             }
507             else return oid;
508         }
509     }
510     return oid;
511 }
512
513 /***********************************************************************
514  *      SnmpUtilOidToA          (SNMPAPI.@)
515  */
516 LPSTR WINAPI SnmpUtilOidToA(AsnObjectIdentifier *oid)
517 {
518     static char null_oid[] = "<null oid>";
519
520     TRACE("(%p)\n", oid);
521
522     if (oid)
523         return SnmpUtilIdsToA(oid->ids, oid->idLength);
524     else
525         return null_oid;
526 }
527
528 /***********************************************************************
529  *      SnmpUtilPrintOid        (SNMPAPI.@)
530  */
531 VOID WINAPI SnmpUtilPrintOid(AsnObjectIdentifier *oid)
532 {
533     unsigned int i;
534
535     TRACE("(%p)\n", oid);
536
537     if (!oid) return;
538
539     for (i = 0; i < oid->idLength; i++)
540     {
541         TRACE("%u", oid->ids[i]);
542         if (i < oid->idLength - 1) TRACE(".");
543     }
544     TRACE("\n");
545 }
546
547 /***********************************************************************
548  *      SnmpUtilPrintAsnAny     (SNMPAPI.@)
549  */
550 VOID WINAPI SnmpUtilPrintAsnAny(AsnAny *any)
551 {
552     unsigned int i;
553
554     TRACE("(%p)\n", any);
555
556     switch (any->asnType)
557     {
558     case ASN_NULL:       TRACE("Null value\n"); return;
559     case ASN_INTEGER32:  TRACE("Integer32 %d\n", any->asnValue.number); return;
560     case ASN_UNSIGNED32: TRACE("Unsigned32 %u\n", any->asnValue.unsigned32); return;
561     case ASN_COUNTER32:  TRACE("Counter32 %u\n", any->asnValue.counter); return;
562     case ASN_GAUGE32:    TRACE("Gauge32 %u\n", any->asnValue.gauge); return;
563     case ASN_TIMETICKS:  TRACE("Timeticks %u\n", any->asnValue.ticks); return;
564     case ASN_COUNTER64:
565     {
566         TRACE("Counter64 %llu\n", any->asnValue.counter64.QuadPart);
567         return;
568     }
569     case ASN_OCTETSTRING:
570     {
571         TRACE("String ");
572         for (i = 0; i < any->asnValue.string.length; i++)
573             TRACE("%c", any->asnValue.string.stream[i]);
574         TRACE("\n");
575         return;
576     }
577     case ASN_IPADDRESS:
578     {
579         TRACE("IpAddress ");
580         if (any->asnValue.string.length < 4)
581         {
582             TRACE("Invalid\n");
583             return;
584         }
585         for (i = 0; i < 4; i++)
586         {
587             TRACE("%u", any->asnValue.string.stream[i]);
588             if (i < 3) TRACE(".");
589         }
590         TRACE("\n");
591         return;
592     }
593     case ASN_BITS:
594     {
595         TRACE("Bits ");
596         for (i = 0; i < any->asnValue.string.length; i++)
597         {
598             TRACE("0x%02x", any->asnValue.string.stream[i]);
599             if (i < any->asnValue.object.idLength - 1) TRACE(" ");
600         }
601         TRACE("\n");
602         return;
603     }
604     case ASN_OPAQUE:
605     {
606         TRACE("Opaque ");
607         for (i = 0; i < any->asnValue.string.length; i++)
608         {
609             TRACE("0x%02x", any->asnValue.string.stream[i]);
610             if (i < any->asnValue.object.idLength - 1) TRACE(" ");
611         }
612         TRACE("\n");
613         return;
614     }
615     case ASN_OBJECTIDENTIFIER:
616     {
617         TRACE("ObjectID ");
618         for (i = 0; i < any->asnValue.object.idLength; i++)
619         {
620             TRACE("%u", any->asnValue.object.ids[i]);
621             if (i < any->asnValue.object.idLength - 1) TRACE(".");
622         }
623         TRACE("\n");
624         return;
625     }
626     default:
627     {
628         TRACE("Invalid type %d\n", any->asnType);
629         return;
630     }
631     }
632 }