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