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