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