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