1 /* 2 * DNS support 3 * 4 * Copyright (C) 2006 Hans Leidekker 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "precomp.h" 22 23 #define NDEBUG 24 #include <debug.h> 25 26 const char *dns_type_to_str( unsigned short type ) 27 { 28 switch (type) 29 { 30 #define X(x) case (x): return #x; 31 X(DNS_TYPE_ZERO) 32 X(DNS_TYPE_A) 33 X(DNS_TYPE_NS) 34 X(DNS_TYPE_MD) 35 X(DNS_TYPE_MF) 36 X(DNS_TYPE_CNAME) 37 X(DNS_TYPE_SOA) 38 X(DNS_TYPE_MB) 39 X(DNS_TYPE_MG) 40 X(DNS_TYPE_MR) 41 X(DNS_TYPE_NULL) 42 X(DNS_TYPE_WKS) 43 X(DNS_TYPE_PTR) 44 X(DNS_TYPE_HINFO) 45 X(DNS_TYPE_MINFO) 46 X(DNS_TYPE_MX) 47 X(DNS_TYPE_TEXT) 48 X(DNS_TYPE_RP) 49 X(DNS_TYPE_AFSDB) 50 X(DNS_TYPE_X25) 51 X(DNS_TYPE_ISDN) 52 X(DNS_TYPE_RT) 53 X(DNS_TYPE_NSAP) 54 X(DNS_TYPE_NSAPPTR) 55 X(DNS_TYPE_SIG) 56 X(DNS_TYPE_KEY) 57 X(DNS_TYPE_PX) 58 X(DNS_TYPE_GPOS) 59 X(DNS_TYPE_AAAA) 60 X(DNS_TYPE_LOC) 61 X(DNS_TYPE_NXT) 62 X(DNS_TYPE_EID) 63 X(DNS_TYPE_NIMLOC) 64 X(DNS_TYPE_SRV) 65 X(DNS_TYPE_ATMA) 66 X(DNS_TYPE_NAPTR) 67 X(DNS_TYPE_KX) 68 X(DNS_TYPE_CERT) 69 X(DNS_TYPE_A6) 70 X(DNS_TYPE_DNAME) 71 X(DNS_TYPE_SINK) 72 X(DNS_TYPE_OPT) 73 X(DNS_TYPE_UINFO) 74 X(DNS_TYPE_UID) 75 X(DNS_TYPE_GID) 76 X(DNS_TYPE_UNSPEC) 77 X(DNS_TYPE_ADDRS) 78 X(DNS_TYPE_TKEY) 79 X(DNS_TYPE_TSIG) 80 X(DNS_TYPE_IXFR) 81 X(DNS_TYPE_AXFR) 82 X(DNS_TYPE_MAILB) 83 X(DNS_TYPE_MAILA) 84 X(DNS_TYPE_ANY) 85 X(DNS_TYPE_WINS) 86 X(DNS_TYPE_WINSR) 87 #undef X 88 default: { static char tmp[7]; sprintf( tmp, "0x%04x", type ); return tmp; } 89 } 90 } 91 92 static int dns_strcmpX( LPCVOID str1, LPCVOID str2, BOOL wide ) 93 { 94 if (wide) 95 return lstrcmpiW( str1, str2 ); 96 else 97 return lstrcmpiA( str1, str2 ); 98 } 99 100 /****************************************************************************** 101 * DnsRecordCompare [DNSAPI.@] 102 * 103 */ 104 BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 ) 105 { 106 BOOL wide; 107 unsigned int i; 108 109 DPRINT( "(%p,%p)\n", r1, r2 ); 110 111 if (r1->wType != r2->wType || 112 r1->wDataLength != r2->wDataLength || 113 r1->Flags.S.Section != r2->Flags.S.Section || 114 r1->Flags.S.Delete != r2->Flags.S.Delete || 115 r1->Flags.S.Unused != r2->Flags.S.Unused || 116 r1->Flags.S.Reserved != r2->Flags.S.Reserved || 117 r1->dwReserved != r2->dwReserved) return FALSE; 118 119 wide = (r1->Flags.S.CharSet == DnsCharSetUnicode || r1->Flags.S.CharSet == DnsCharSetUnknown); 120 if (dns_strcmpX( r1->pName, r2->pName, wide )) return FALSE; 121 122 switch (r1->wType) 123 { 124 case DNS_TYPE_A: 125 { 126 if (r1->Data.A.IpAddress != r2->Data.A.IpAddress) return FALSE; 127 break; 128 } 129 case DNS_TYPE_SOA: 130 { 131 if (r1->Data.SOA.dwSerialNo != r2->Data.SOA.dwSerialNo || 132 r1->Data.SOA.dwRefresh != r2->Data.SOA.dwRefresh || 133 r1->Data.SOA.dwRetry != r2->Data.SOA.dwRetry || 134 r1->Data.SOA.dwExpire != r2->Data.SOA.dwExpire || 135 r1->Data.SOA.dwDefaultTtl != r2->Data.SOA.dwDefaultTtl) 136 return FALSE; 137 if (dns_strcmpX( r1->Data.SOA.pNamePrimaryServer, 138 r2->Data.SOA.pNamePrimaryServer, wide ) || 139 dns_strcmpX( r1->Data.SOA.pNameAdministrator, 140 r2->Data.SOA.pNameAdministrator, wide )) 141 return FALSE; 142 break; 143 } 144 case DNS_TYPE_PTR: 145 case DNS_TYPE_NS: 146 case DNS_TYPE_CNAME: 147 case DNS_TYPE_MB: 148 case DNS_TYPE_MD: 149 case DNS_TYPE_MF: 150 case DNS_TYPE_MG: 151 case DNS_TYPE_MR: 152 { 153 if (dns_strcmpX( r1->Data.PTR.pNameHost, 154 r2->Data.PTR.pNameHost, wide )) return FALSE; 155 break; 156 } 157 case DNS_TYPE_MINFO: 158 case DNS_TYPE_RP: 159 { 160 if (dns_strcmpX( r1->Data.MINFO.pNameMailbox, 161 r2->Data.MINFO.pNameMailbox, wide ) || 162 dns_strcmpX( r1->Data.MINFO.pNameErrorsMailbox, 163 r2->Data.MINFO.pNameErrorsMailbox, wide )) 164 return FALSE; 165 break; 166 } 167 case DNS_TYPE_MX: 168 case DNS_TYPE_AFSDB: 169 case DNS_TYPE_RT: 170 { 171 if (r1->Data.MX.wPreference != r2->Data.MX.wPreference) 172 return FALSE; 173 if (dns_strcmpX( r1->Data.MX.pNameExchange, 174 r2->Data.MX.pNameExchange, wide )) 175 return FALSE; 176 break; 177 } 178 case DNS_TYPE_HINFO: 179 case DNS_TYPE_ISDN: 180 case DNS_TYPE_TEXT: 181 case DNS_TYPE_X25: 182 { 183 if (r1->Data.TXT.dwStringCount != r2->Data.TXT.dwStringCount) 184 return FALSE; 185 for (i = 0; i < r1->Data.TXT.dwStringCount; i++) 186 { 187 if (dns_strcmpX( r1->Data.TXT.pStringArray[i], 188 r2->Data.TXT.pStringArray[i], wide )) 189 return FALSE; 190 } 191 break; 192 } 193 case DNS_TYPE_NULL: 194 { 195 if (r1->Data.Null.dwByteCount != r2->Data.Null.dwByteCount) 196 return FALSE; 197 if (memcmp( r1->Data.Null.Data, 198 r2->Data.Null.Data, r1->Data.Null.dwByteCount )) 199 return FALSE; 200 break; 201 } 202 case DNS_TYPE_AAAA: 203 { 204 for (i = 0; i < sizeof(IP6_ADDRESS)/sizeof(DWORD); i++) 205 { 206 if (r1->Data.AAAA.Ip6Address.IP6Dword[i] != 207 r2->Data.AAAA.Ip6Address.IP6Dword[i]) return FALSE; 208 } 209 break; 210 } 211 case DNS_TYPE_KEY: 212 { 213 if (r1->Data.KEY.wFlags != r2->Data.KEY.wFlags || 214 r1->Data.KEY.chProtocol != r2->Data.KEY.chProtocol || 215 r1->Data.KEY.chAlgorithm != r2->Data.KEY.chAlgorithm) 216 return FALSE; 217 if (memcmp( r1->Data.KEY.Key, r2->Data.KEY.Key, 218 r1->wDataLength - sizeof(DNS_KEY_DATA) + 1 )) 219 return FALSE; 220 break; 221 } 222 case DNS_TYPE_SIG: 223 { 224 if (dns_strcmpX( r1->Data.SIG.pNameSigner, 225 r2->Data.SIG.pNameSigner, wide )) 226 return FALSE; 227 if (r1->Data.SIG.wTypeCovered != r2->Data.SIG.wTypeCovered || 228 r1->Data.SIG.chAlgorithm != r2->Data.SIG.chAlgorithm || 229 r1->Data.SIG.chLabelCount != r2->Data.SIG.chLabelCount || 230 r1->Data.SIG.dwOriginalTtl != r2->Data.SIG.dwOriginalTtl || 231 r1->Data.SIG.dwExpiration != r2->Data.SIG.dwExpiration || 232 r1->Data.SIG.dwTimeSigned != r2->Data.SIG.dwTimeSigned || 233 r1->Data.SIG.wKeyTag != r2->Data.SIG.wKeyTag) 234 return FALSE; 235 if (memcmp( r1->Data.SIG.Signature, r2->Data.SIG.Signature, 236 r1->wDataLength - sizeof(DNS_SIG_DATAA) + 1 )) 237 return FALSE; 238 break; 239 } 240 case DNS_TYPE_ATMA: 241 { 242 if (r1->Data.ATMA.AddressType != r2->Data.ATMA.AddressType) 243 return FALSE; 244 for (i = 0; i < DNS_ATMA_MAX_ADDR_LENGTH; i++) 245 { 246 if (r1->Data.ATMA.Address[i] != r2->Data.ATMA.Address[i]) 247 return FALSE; 248 } 249 break; 250 } 251 case DNS_TYPE_NXT: 252 { 253 if (dns_strcmpX( r1->Data.NXT.pNameNext, 254 r2->Data.NXT.pNameNext, wide )) return FALSE; 255 if (r1->Data.NXT.wNumTypes != r2->Data.NXT.wNumTypes) return FALSE; 256 if (memcmp( r1->Data.NXT.wTypes, r2->Data.NXT.wTypes, 257 r1->wDataLength - sizeof(DNS_NXT_DATAA) + sizeof(WORD) )) 258 return FALSE; 259 break; 260 } 261 case DNS_TYPE_SRV: 262 { 263 if (dns_strcmpX( r1->Data.SRV.pNameTarget, 264 r2->Data.SRV.pNameTarget, wide )) return FALSE; 265 if (r1->Data.SRV.wPriority != r2->Data.SRV.wPriority || 266 r1->Data.SRV.wWeight != r2->Data.SRV.wWeight || 267 r1->Data.SRV.wPort != r2->Data.SRV.wPort) 268 return FALSE; 269 break; 270 } 271 case DNS_TYPE_TKEY: 272 { 273 if (dns_strcmpX( r1->Data.TKEY.pNameAlgorithm, 274 r2->Data.TKEY.pNameAlgorithm, wide )) 275 return FALSE; 276 if (r1->Data.TKEY.dwCreateTime != r2->Data.TKEY.dwCreateTime || 277 r1->Data.TKEY.dwExpireTime != r2->Data.TKEY.dwExpireTime || 278 r1->Data.TKEY.wMode != r2->Data.TKEY.wMode || 279 r1->Data.TKEY.wError != r2->Data.TKEY.wError || 280 r1->Data.TKEY.wKeyLength != r2->Data.TKEY.wKeyLength || 281 r1->Data.TKEY.wOtherLength != r2->Data.TKEY.wOtherLength || 282 r1->Data.TKEY.cAlgNameLength != r2->Data.TKEY.cAlgNameLength || 283 r1->Data.TKEY.bPacketPointers != r2->Data.TKEY.bPacketPointers) 284 return FALSE; 285 286 /* FIXME: ignoring pAlgorithmPacket field */ 287 if (memcmp( r1->Data.TKEY.pKey, r2->Data.TKEY.pKey, 288 r1->Data.TKEY.wKeyLength ) || 289 memcmp( r1->Data.TKEY.pOtherData, r2->Data.TKEY.pOtherData, 290 r1->Data.TKEY.wOtherLength )) return FALSE; 291 break; 292 } 293 case DNS_TYPE_TSIG: 294 { 295 if (dns_strcmpX( r1->Data.TSIG.pNameAlgorithm, 296 r2->Data.TSIG.pNameAlgorithm, wide )) 297 return FALSE; 298 if (r1->Data.TSIG.i64CreateTime != r2->Data.TSIG.i64CreateTime || 299 r1->Data.TSIG.wFudgeTime != r2->Data.TSIG.wFudgeTime || 300 r1->Data.TSIG.wOriginalXid != r2->Data.TSIG.wOriginalXid || 301 r1->Data.TSIG.wError != r2->Data.TSIG.wError || 302 r1->Data.TSIG.wSigLength != r2->Data.TSIG.wSigLength || 303 r1->Data.TSIG.wOtherLength != r2->Data.TSIG.wOtherLength || 304 r1->Data.TSIG.cAlgNameLength != r2->Data.TSIG.cAlgNameLength || 305 r1->Data.TSIG.bPacketPointers != r2->Data.TSIG.bPacketPointers) 306 return FALSE; 307 308 /* FIXME: ignoring pAlgorithmPacket field */ 309 if (memcmp( r1->Data.TSIG.pSignature, r2->Data.TSIG.pSignature, 310 r1->Data.TSIG.wSigLength ) || 311 memcmp( r1->Data.TSIG.pOtherData, r2->Data.TSIG.pOtherData, 312 r1->Data.TSIG.wOtherLength )) return FALSE; 313 break; 314 } 315 case DNS_TYPE_WINS: 316 { 317 if (r1->Data.WINS.dwMappingFlag != r2->Data.WINS.dwMappingFlag || 318 r1->Data.WINS.dwLookupTimeout != r2->Data.WINS.dwLookupTimeout || 319 r1->Data.WINS.dwCacheTimeout != r2->Data.WINS.dwCacheTimeout || 320 r1->Data.WINS.cWinsServerCount != r2->Data.WINS.cWinsServerCount) 321 return FALSE; 322 if (memcmp( r1->Data.WINS.WinsServers, r2->Data.WINS.WinsServers, 323 r1->wDataLength - sizeof(DNS_WINS_DATA) + sizeof(IP4_ADDRESS) )) 324 return FALSE; 325 break; 326 } 327 case DNS_TYPE_WINSR: 328 { 329 if (r1->Data.WINSR.dwMappingFlag != r2->Data.WINSR.dwMappingFlag || 330 r1->Data.WINSR.dwLookupTimeout != r2->Data.WINSR.dwLookupTimeout || 331 r1->Data.WINSR.dwCacheTimeout != r2->Data.WINSR.dwCacheTimeout) 332 return FALSE; 333 if (dns_strcmpX( r1->Data.WINSR.pNameResultDomain, 334 r2->Data.WINSR.pNameResultDomain, wide )) 335 return FALSE; 336 break; 337 } 338 default: 339 DPRINT1( "unknown type: %s\n", dns_type_to_str( r1->wType ) ); 340 return FALSE; 341 } 342 return TRUE; 343 } 344 345 static LPVOID dns_strcpyX( LPCVOID src, DNS_CHARSET in, DNS_CHARSET out ) 346 { 347 switch (in) 348 { 349 case DnsCharSetUnicode: 350 { 351 switch (out) 352 { 353 case DnsCharSetUnicode: return dns_strdup_w( src ); 354 case DnsCharSetUtf8: return dns_strdup_wu( src ); 355 case DnsCharSetAnsi: return dns_strdup_wa( src ); 356 default: 357 DPRINT1( "unhandled target charset: %d\n", out ); 358 break; 359 } 360 break; 361 } 362 case DnsCharSetUtf8: 363 switch (out) 364 { 365 case DnsCharSetUnicode: return dns_strdup_uw( src ); 366 case DnsCharSetUtf8: return dns_strdup_u( src ); 367 case DnsCharSetAnsi: return dns_strdup_ua( src ); 368 default: 369 DPRINT1( "unhandled target charset: %d\n", out ); 370 break; 371 } 372 break; 373 case DnsCharSetAnsi: 374 switch (out) 375 { 376 case DnsCharSetUnicode: return dns_strdup_aw( src ); 377 case DnsCharSetUtf8: return dns_strdup_au( src ); 378 case DnsCharSetAnsi: return dns_strdup_a( src ); 379 default: 380 DPRINT1( "unhandled target charset: %d\n", out ); 381 break; 382 } 383 break; 384 default: 385 DPRINT1( "unhandled source charset: %d\n", in ); 386 break; 387 } 388 return NULL; 389 } 390 391 /****************************************************************************** 392 * DnsRecordCopyEx [DNSAPI.@] 393 * 394 */ 395 PDNS_RECORD WINAPI DnsRecordCopyEx( PDNS_RECORD src, DNS_CHARSET in, DNS_CHARSET out ) 396 { 397 DNS_RECORD *dst; 398 unsigned int i, size; 399 400 DPRINT( "(%p,%d,%d)\n", src, in, out ); 401 402 size = FIELD_OFFSET(DNS_RECORD, Data) + src->wDataLength; 403 dst = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size ); 404 if (!dst) return NULL; 405 406 memcpy( dst, src, size ); 407 408 if (src->Flags.S.CharSet == DnsCharSetUtf8 || 409 src->Flags.S.CharSet == DnsCharSetAnsi || 410 src->Flags.S.CharSet == DnsCharSetUnicode) in = src->Flags.S.CharSet; 411 412 dst->Flags.S.CharSet = out; 413 dst->pName = dns_strcpyX( src->pName, in, out ); 414 if (!dst->pName) goto error; 415 416 switch (src->wType) 417 { 418 case DNS_TYPE_HINFO: 419 case DNS_TYPE_ISDN: 420 case DNS_TYPE_TEXT: 421 case DNS_TYPE_X25: 422 { 423 for (i = 0; i < src->Data.TXT.dwStringCount; i++) 424 { 425 dst->Data.TXT.pStringArray[i] = 426 dns_strcpyX( src->Data.TXT.pStringArray[i], in, out ); 427 428 if (!dst->Data.TXT.pStringArray[i]) 429 { 430 while (i > 0) HeapFree( GetProcessHeap(), 0, dst->Data.TXT.pStringArray[--i] ); 431 goto error; 432 } 433 } 434 break; 435 } 436 case DNS_TYPE_MINFO: 437 case DNS_TYPE_RP: 438 { 439 dst->Data.MINFO.pNameMailbox = 440 dns_strcpyX( src->Data.MINFO.pNameMailbox, in, out ); 441 if (!dst->Data.MINFO.pNameMailbox) goto error; 442 443 dst->Data.MINFO.pNameErrorsMailbox = 444 dns_strcpyX( src->Data.MINFO.pNameErrorsMailbox, in, out ); 445 if (!dst->Data.MINFO.pNameErrorsMailbox) 446 { 447 HeapFree( GetProcessHeap(), 0, dst->Data.MINFO.pNameMailbox ); 448 goto error; 449 } 450 break; 451 } 452 case DNS_TYPE_AFSDB: 453 case DNS_TYPE_RT: 454 case DNS_TYPE_MX: 455 { 456 dst->Data.MX.pNameExchange = 457 dns_strcpyX( src->Data.MX.pNameExchange, in, out ); 458 if (!dst->Data.MX.pNameExchange) goto error; 459 break; 460 } 461 case DNS_TYPE_NXT: 462 { 463 dst->Data.NXT.pNameNext = 464 dns_strcpyX( src->Data.NXT.pNameNext, in, out ); 465 if (!dst->Data.NXT.pNameNext) goto error; 466 break; 467 } 468 case DNS_TYPE_CNAME: 469 case DNS_TYPE_MB: 470 case DNS_TYPE_MD: 471 case DNS_TYPE_MF: 472 case DNS_TYPE_MG: 473 case DNS_TYPE_MR: 474 case DNS_TYPE_NS: 475 case DNS_TYPE_PTR: 476 { 477 dst->Data.PTR.pNameHost = 478 dns_strcpyX( src->Data.PTR.pNameHost, in, out ); 479 if (!dst->Data.PTR.pNameHost) goto error; 480 break; 481 } 482 case DNS_TYPE_SIG: 483 { 484 dst->Data.SIG.pNameSigner = 485 dns_strcpyX( src->Data.SIG.pNameSigner, in, out ); 486 if (!dst->Data.SIG.pNameSigner) goto error; 487 break; 488 } 489 case DNS_TYPE_SOA: 490 { 491 dst->Data.SOA.pNamePrimaryServer = 492 dns_strcpyX( src->Data.SOA.pNamePrimaryServer, in, out ); 493 if (!dst->Data.SOA.pNamePrimaryServer) goto error; 494 495 dst->Data.SOA.pNameAdministrator = 496 dns_strcpyX( src->Data.SOA.pNameAdministrator, in, out ); 497 if (!dst->Data.SOA.pNameAdministrator) 498 { 499 HeapFree( GetProcessHeap(), 0, dst->Data.SOA.pNamePrimaryServer ); 500 goto error; 501 } 502 break; 503 } 504 case DNS_TYPE_SRV: 505 { 506 dst->Data.SRV.pNameTarget = 507 dns_strcpyX( src->Data.SRV.pNameTarget, in, out ); 508 if (!dst->Data.SRV.pNameTarget) goto error; 509 break; 510 } 511 default: 512 break; 513 } 514 return dst; 515 516 error: 517 HeapFree( GetProcessHeap(), 0, dst->pName ); 518 HeapFree( GetProcessHeap(), 0, dst ); 519 return NULL; 520 } 521 522 /****************************************************************************** 523 * DnsRecordListFree [DNSAPI.@] 524 * 525 */ 526 VOID WINAPI DnsRecordListFree( PDNS_RECORD list, DNS_FREE_TYPE type ) 527 { 528 DNS_RECORD *r, *next; 529 unsigned int i; 530 531 DPRINT( "(%p,%d)\n", list, type ); 532 533 if (!list) return; 534 535 switch (type) 536 { 537 case DnsFreeRecordList: 538 { 539 for (r = list; (list = r); r = next) 540 { 541 HeapFree( GetProcessHeap(), 0, r->pName ); 542 543 switch (r->wType) 544 { 545 case DNS_TYPE_HINFO: 546 case DNS_TYPE_ISDN: 547 case DNS_TYPE_TEXT: 548 case DNS_TYPE_X25: 549 { 550 for (i = 0; i < r->Data.TXT.dwStringCount; i++) 551 HeapFree( GetProcessHeap(), 0, r->Data.TXT.pStringArray[i] ); 552 553 break; 554 } 555 case DNS_TYPE_MINFO: 556 case DNS_TYPE_RP: 557 { 558 HeapFree( GetProcessHeap(), 0, r->Data.MINFO.pNameMailbox ); 559 HeapFree( GetProcessHeap(), 0, r->Data.MINFO.pNameErrorsMailbox ); 560 break; 561 } 562 case DNS_TYPE_AFSDB: 563 case DNS_TYPE_RT: 564 case DNS_TYPE_MX: 565 { 566 HeapFree( GetProcessHeap(), 0, r->Data.MX.pNameExchange ); 567 break; 568 } 569 case DNS_TYPE_NXT: 570 { 571 HeapFree( GetProcessHeap(), 0, r->Data.NXT.pNameNext ); 572 break; 573 } 574 case DNS_TYPE_CNAME: 575 case DNS_TYPE_MB: 576 case DNS_TYPE_MD: 577 case DNS_TYPE_MF: 578 case DNS_TYPE_MG: 579 case DNS_TYPE_MR: 580 case DNS_TYPE_NS: 581 case DNS_TYPE_PTR: 582 { 583 HeapFree( GetProcessHeap(), 0, r->Data.PTR.pNameHost ); 584 break; 585 } 586 case DNS_TYPE_SIG: 587 { 588 HeapFree( GetProcessHeap(), 0, r->Data.SIG.pNameSigner ); 589 break; 590 } 591 case DNS_TYPE_SOA: 592 { 593 HeapFree( GetProcessHeap(), 0, r->Data.SOA.pNamePrimaryServer ); 594 HeapFree( GetProcessHeap(), 0, r->Data.SOA.pNameAdministrator ); 595 break; 596 } 597 case DNS_TYPE_SRV: 598 { 599 HeapFree( GetProcessHeap(), 0, r->Data.SRV.pNameTarget ); 600 break; 601 } 602 default: 603 break; 604 } 605 606 next = r->pNext; 607 HeapFree( GetProcessHeap(), 0, r ); 608 } 609 break; 610 } 611 case DnsFreeFlat: 612 case DnsFreeParsedMessageFields: 613 { 614 DPRINT1( "unhandled free type: %d\n", type ); 615 break; 616 } 617 default: 618 DPRINT1( "unknown free type: %d\n", type ); 619 break; 620 } 621 } 622 623 /****************************************************************************** 624 * DnsRecordSetCompare [DNSAPI.@] 625 * 626 */ 627 BOOL WINAPI DnsRecordSetCompare( PDNS_RECORD set1, PDNS_RECORD set2, 628 PDNS_RECORD *diff1, PDNS_RECORD *diff2 ) 629 { 630 BOOL ret = TRUE; 631 DNS_RECORD *r, *t, *u; 632 DNS_RRSET rr1, rr2; 633 634 DPRINT( "(%p,%p,%p,%p)\n", set1, set2, diff1, diff2 ); 635 636 if (!set1 && !set2) return FALSE; 637 638 if (diff1) *diff1 = NULL; 639 if (diff2) *diff2 = NULL; 640 641 if (set1 && !set2) 642 { 643 if (diff1) *diff1 = DnsRecordSetCopyEx( set1, 0, set1->Flags.S.CharSet ); 644 return FALSE; 645 } 646 if (!set1 && set2) 647 { 648 if (diff2) *diff2 = DnsRecordSetCopyEx( set2, 0, set2->Flags.S.CharSet ); 649 return FALSE; 650 } 651 652 DNS_RRSET_INIT( rr1 ); 653 DNS_RRSET_INIT( rr2 ); 654 655 for (r = set1; r; r = r->pNext) 656 { 657 for (t = set2; t; t = t->pNext) 658 { 659 u = DnsRecordCopyEx( r, r->Flags.S.CharSet, t->Flags.S.CharSet ); 660 if (!u) goto error; 661 662 if (!DnsRecordCompare( t, u )) 663 { 664 DNS_RRSET_ADD( rr1, u ); 665 ret = FALSE; 666 } 667 else DnsRecordListFree( u, DnsFreeRecordList ); 668 } 669 } 670 671 for (t = set2; t; t = t->pNext) 672 { 673 for (r = set1; r; r = r->pNext) 674 { 675 u = DnsRecordCopyEx( t, t->Flags.S.CharSet, r->Flags.S.CharSet ); 676 if (!u) goto error; 677 678 if (!DnsRecordCompare( r, u )) 679 { 680 DNS_RRSET_ADD( rr2, u ); 681 ret = FALSE; 682 } 683 else DnsRecordListFree( u, DnsFreeRecordList ); 684 } 685 } 686 687 DNS_RRSET_TERMINATE( rr1 ); 688 DNS_RRSET_TERMINATE( rr2 ); 689 690 if (diff1) *diff1 = rr1.pFirstRR; 691 else DnsRecordListFree( rr1.pFirstRR, DnsFreeRecordList ); 692 693 if (diff2) *diff2 = rr2.pFirstRR; 694 else DnsRecordListFree( rr2.pFirstRR, DnsFreeRecordList ); 695 696 return ret; 697 698 error: 699 DNS_RRSET_TERMINATE( rr1 ); 700 DNS_RRSET_TERMINATE( rr2 ); 701 702 DnsRecordListFree( rr1.pFirstRR, DnsFreeRecordList ); 703 DnsRecordListFree( rr2.pFirstRR, DnsFreeRecordList ); 704 705 return FALSE; 706 } 707 708 /****************************************************************************** 709 * DnsRecordSetCopyEx [DNSAPI.@] 710 * 711 */ 712 PDNS_RECORD WINAPI DnsRecordSetCopyEx( PDNS_RECORD src_set, DNS_CHARSET in, DNS_CHARSET out ) 713 { 714 DNS_RRSET dst_set; 715 DNS_RECORD *src, *dst; 716 717 DPRINT( "(%p,%d,%d)\n", src_set, in, out ); 718 719 DNS_RRSET_INIT( dst_set ); 720 721 for (src = src_set; (src_set = src); src = src_set->pNext) 722 { 723 dst = DnsRecordCopyEx( src, in, out ); 724 if (!dst) 725 { 726 DNS_RRSET_TERMINATE( dst_set ); 727 DnsRecordListFree( dst_set.pFirstRR, DnsFreeRecordList ); 728 return NULL; 729 } 730 DNS_RRSET_ADD( dst_set, dst ); 731 } 732 733 DNS_RRSET_TERMINATE( dst_set ); 734 return dst_set.pFirstRR; 735 } 736 737 /****************************************************************************** 738 * DnsRecordSetDetach [DNSAPI.@] 739 * 740 */ 741 PDNS_RECORD WINAPI DnsRecordSetDetach( PDNS_RECORD set ) 742 { 743 DNS_RECORD *r, *s; 744 745 DPRINT( "(%p)\n", set ); 746 747 for (r = set; (set = r); r = set->pNext) 748 { 749 if (r->pNext && !r->pNext->pNext) 750 { 751 s = r->pNext; 752 r->pNext = NULL; 753 return s; 754 } 755 } 756 return NULL; 757 } 758