include: Change twain.h to use LONG/ULONG for Win64 compatibility.
[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, const 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, len;
347
348     TRACE("(%p, %p, %d)\n", oid1, oid2, count);
349
350     if (!oid1 || !oid2) return 0;
351
352     len = min(count, oid1->idLength);
353     len = min(len, oid2->idLength);
354     for (i = 0; i < len; i++)
355     {
356         if (oid1->ids[i] > oid2->ids[i]) return 1;
357         if (oid1->ids[i] < oid2->ids[i]) return -1;
358     }
359     if (i == count) return 0;
360     if (oid1->idLength < oid2->idLength) return -1;
361     if (oid1->idLength > oid2->idLength) return 1;
362     return 0;
363 }
364
365 /***********************************************************************
366  *      SnmpUtilOidCmp          (SNMPAPI.@)
367  */
368 INT WINAPI SnmpUtilOidCmp(AsnObjectIdentifier *oid1, AsnObjectIdentifier *oid2)
369 {
370     TRACE("(%p, %p)\n", oid1, oid2);
371
372     if (oid1->idLength < oid2->idLength) return -1;
373     if (oid1->idLength > oid2->idLength) return 1;
374
375     return SnmpUtilOidNCmp(oid1, oid2, oid1->idLength);
376 }
377
378 /***********************************************************************
379  *      SnmpUtilVarBindCpy      (SNMPAPI.@)
380  */
381 INT WINAPI SnmpUtilVarBindCpy(SnmpVarBind *dst, SnmpVarBind *src)
382 {
383     unsigned int i, size;
384
385     TRACE("(%p, %p)\n", dst, src);
386
387     if (!dst) return SNMPAPI_ERROR;
388     if (!src)
389     {
390         dst->value.asnType = ASN_NULL;
391         return SNMPAPI_NOERROR;
392     }
393
394     size = src->name.idLength * sizeof(UINT);
395     if (!(dst->name.ids = HeapAlloc(GetProcessHeap(), 0, size))) return SNMPAPI_ERROR;
396
397     for (i = 0; i < src->name.idLength; i++) dst->name.ids[i] = src->name.ids[i];
398     dst->name.idLength = src->name.idLength;
399
400     if (!asn_any_copy(&dst->value, &src->value))
401     {
402         HeapFree(GetProcessHeap(), 0, dst->name.ids);
403         return SNMPAPI_ERROR;
404     }
405     return SNMPAPI_NOERROR;
406 }
407
408 /***********************************************************************
409  *      SnmpUtilVarBindFree     (SNMPAPI.@)
410  */
411 VOID WINAPI SnmpUtilVarBindFree(SnmpVarBind *vb)
412 {
413     TRACE("(%p)\n", vb);
414
415     if (!vb) return;
416
417     asn_any_free(&vb->value);
418     HeapFree(GetProcessHeap(), 0, vb->name.ids);
419     vb->name.idLength = 0;
420     vb->name.ids = NULL;
421 }
422
423 /***********************************************************************
424  *      SnmpUtilVarBindListCpy  (SNMPAPI.@)
425  */
426 INT WINAPI SnmpUtilVarBindListCpy(SnmpVarBindList *dst, SnmpVarBindList *src)
427 {
428     unsigned int i, size;
429     SnmpVarBind *src_entry, *dst_entry;
430
431     TRACE("(%p, %p)\n", dst, src);
432
433     if (!src)
434     {
435         dst->list = NULL;
436         dst->len = 0;
437         return SNMPAPI_NOERROR;
438     }
439     size = src->len * sizeof(SnmpVarBind);
440     if (!(dst->list = HeapAlloc(GetProcessHeap(), 0, size)))
441         return SNMPAPI_ERROR;
442
443     src_entry = src->list;
444     dst_entry = dst->list;
445     for (i = 0; i < src->len; i++)
446     {
447         if (SnmpUtilVarBindCpy(dst_entry, src_entry))
448         {
449             src_entry++;
450             dst_entry++;
451         }
452         else
453         {
454             for (--i; i > 0; i--) SnmpUtilVarBindFree(--dst_entry);
455             HeapFree(GetProcessHeap(), 0, dst->list);
456             return SNMPAPI_ERROR;
457         }
458     }
459     dst->len = src->len;
460     return SNMPAPI_NOERROR;
461 }
462
463 /***********************************************************************
464  *      SnmpUtilVarBindListFree (SNMPAPI.@)
465  */
466 VOID WINAPI SnmpUtilVarBindListFree(SnmpVarBindList *vb)
467 {
468     unsigned int i;
469     SnmpVarBind *entry;
470
471     TRACE("(%p)\n", vb);
472
473     entry = vb->list;
474     for (i = 0; i < vb->len; i++) SnmpUtilVarBindFree(entry++);
475     HeapFree(GetProcessHeap(), 0, vb->list);
476     vb->list = NULL;
477     vb->len = 0;
478 }
479
480 /***********************************************************************
481  *      SnmpUtilIdsToA          (SNMPAPI.@)
482  */
483 LPSTR WINAPI SnmpUtilIdsToA(UINT *ids, UINT length)
484 {
485     static char one[10], oid[514], null_oid[] = "<null oid>";
486     unsigned int i, len, left = sizeof(oid) - 1;
487
488     TRACE("(%p, %d)\n", ids, length);
489
490     if (!ids || !length) return null_oid;
491
492     *oid = 0;
493     for (i = 0; i < length; i++)
494     {
495         sprintf(one, "%d", ids[i]);
496         len = strlen(one);
497         if (left >= len)
498         {
499             strcat(oid, one);
500             left -= len;
501         }
502         else return oid;
503
504         if (i < length - 1)
505         {
506             if (left > 0)
507             {
508                 strcat(oid, ".");
509                 left--;
510             }
511             else return oid;
512         }
513     }
514     return oid;
515 }
516
517 /***********************************************************************
518  *      SnmpUtilOidToA          (SNMPAPI.@)
519  */
520 LPSTR WINAPI SnmpUtilOidToA(AsnObjectIdentifier *oid)
521 {
522     static char null_oid[] = "<null oid>";
523
524     TRACE("(%p)\n", oid);
525
526     if (oid)
527         return SnmpUtilIdsToA(oid->ids, oid->idLength);
528     else
529         return null_oid;
530 }
531
532 /***********************************************************************
533  *      SnmpUtilPrintOid        (SNMPAPI.@)
534  */
535 VOID WINAPI SnmpUtilPrintOid(AsnObjectIdentifier *oid)
536 {
537     unsigned int i;
538
539     TRACE("(%p)\n", oid);
540
541     if (!oid) return;
542
543     for (i = 0; i < oid->idLength; i++)
544     {
545         TRACE("%u", oid->ids[i]);
546         if (i < oid->idLength - 1) TRACE(".");
547     }
548     TRACE("\n");
549 }
550
551 /***********************************************************************
552  *      SnmpUtilPrintAsnAny     (SNMPAPI.@)
553  */
554 VOID WINAPI SnmpUtilPrintAsnAny(AsnAny *any)
555 {
556     unsigned int i;
557
558     TRACE("(%p)\n", any);
559
560     switch (any->asnType)
561     {
562     case ASN_NULL:       TRACE("Null value\n"); return;
563     case ASN_INTEGER32:  TRACE("Integer32 %d\n", any->asnValue.number); return;
564     case ASN_UNSIGNED32: TRACE("Unsigned32 %u\n", any->asnValue.unsigned32); return;
565     case ASN_COUNTER32:  TRACE("Counter32 %u\n", any->asnValue.counter); return;
566     case ASN_GAUGE32:    TRACE("Gauge32 %u\n", any->asnValue.gauge); return;
567     case ASN_TIMETICKS:  TRACE("Timeticks %u\n", any->asnValue.ticks); return;
568     case ASN_COUNTER64:
569     {
570         TRACE("Counter64 %x%08x\n", (DWORD)(any->asnValue.counter64.QuadPart>>32),(DWORD)any->asnValue.counter64.QuadPart);
571         return;
572     }
573     case ASN_OCTETSTRING:
574     {
575         TRACE("String ");
576         for (i = 0; i < any->asnValue.string.length; i++)
577             TRACE("%c", any->asnValue.string.stream[i]);
578         TRACE("\n");
579         return;
580     }
581     case ASN_IPADDRESS:
582     {
583         TRACE("IpAddress ");
584         if (any->asnValue.string.length < 4)
585         {
586             TRACE("Invalid\n");
587             return;
588         }
589         for (i = 0; i < 4; i++)
590         {
591             TRACE("%u", any->asnValue.string.stream[i]);
592             if (i < 3) TRACE(".");
593         }
594         TRACE("\n");
595         return;
596     }
597     case ASN_BITS:
598     {
599         TRACE("Bits ");
600         for (i = 0; i < any->asnValue.string.length; i++)
601         {
602             TRACE("0x%02x", any->asnValue.string.stream[i]);
603             if (i < any->asnValue.object.idLength - 1) TRACE(" ");
604         }
605         TRACE("\n");
606         return;
607     }
608     case ASN_OPAQUE:
609     {
610         TRACE("Opaque ");
611         for (i = 0; i < any->asnValue.string.length; i++)
612         {
613             TRACE("0x%02x", any->asnValue.string.stream[i]);
614             if (i < any->asnValue.object.idLength - 1) TRACE(" ");
615         }
616         TRACE("\n");
617         return;
618     }
619     case ASN_OBJECTIDENTIFIER:
620     {
621         TRACE("ObjectID ");
622         for (i = 0; i < any->asnValue.object.idLength; i++)
623         {
624             TRACE("%u", any->asnValue.object.ids[i]);
625             if (i < any->asnValue.object.idLength - 1) TRACE(".");
626         }
627         TRACE("\n");
628         return;
629     }
630     default:
631     {
632         TRACE("Invalid type %d\n", any->asnType);
633         return;
634     }
635     }
636 }