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