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