amstream: Return E_POINTER on NULL stream in IMediaStreamFilter::GetMediaStream().
[wine/zf.git] / dlls / dnsapi / record.c
blobdc6a1137d95b2a77e9b130262fb26d64a5e56b6f
1 /*
2 * DNS support
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.
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.
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
21 #include "config.h"
22 #include "wine/port.h"
23 #include "wine/debug.h"
24 #include "wine/unicode.h"
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <sys/types.h>
31 #ifdef HAVE_NETINET_IN_H
32 # include <netinet/in.h>
33 #endif
34 #ifdef HAVE_ARPA_NAMESER_H
35 # include <arpa/nameser.h>
36 #endif
37 #ifdef HAVE_RESOLV_H
38 # include <resolv.h>
39 #endif
41 #include "windef.h"
42 #include "winbase.h"
43 #include "winnls.h"
44 #include "windns.h"
46 #include "dnsapi.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(dnsapi);
50 const char *dns_type_to_str( unsigned short type )
52 switch (type)
54 #define X(x) case (x): return #x;
55 X(DNS_TYPE_ZERO)
56 X(DNS_TYPE_A)
57 X(DNS_TYPE_NS)
58 X(DNS_TYPE_MD)
59 X(DNS_TYPE_MF)
60 X(DNS_TYPE_CNAME)
61 X(DNS_TYPE_SOA)
62 X(DNS_TYPE_MB)
63 X(DNS_TYPE_MG)
64 X(DNS_TYPE_MR)
65 X(DNS_TYPE_NULL)
66 X(DNS_TYPE_WKS)
67 X(DNS_TYPE_PTR)
68 X(DNS_TYPE_HINFO)
69 X(DNS_TYPE_MINFO)
70 X(DNS_TYPE_MX)
71 X(DNS_TYPE_TEXT)
72 X(DNS_TYPE_RP)
73 X(DNS_TYPE_AFSDB)
74 X(DNS_TYPE_X25)
75 X(DNS_TYPE_ISDN)
76 X(DNS_TYPE_RT)
77 X(DNS_TYPE_NSAP)
78 X(DNS_TYPE_NSAPPTR)
79 X(DNS_TYPE_SIG)
80 X(DNS_TYPE_KEY)
81 X(DNS_TYPE_PX)
82 X(DNS_TYPE_GPOS)
83 X(DNS_TYPE_AAAA)
84 X(DNS_TYPE_LOC)
85 X(DNS_TYPE_NXT)
86 X(DNS_TYPE_EID)
87 X(DNS_TYPE_NIMLOC)
88 X(DNS_TYPE_SRV)
89 X(DNS_TYPE_ATMA)
90 X(DNS_TYPE_NAPTR)
91 X(DNS_TYPE_KX)
92 X(DNS_TYPE_CERT)
93 X(DNS_TYPE_A6)
94 X(DNS_TYPE_DNAME)
95 X(DNS_TYPE_SINK)
96 X(DNS_TYPE_OPT)
97 X(DNS_TYPE_UINFO)
98 X(DNS_TYPE_UID)
99 X(DNS_TYPE_GID)
100 X(DNS_TYPE_UNSPEC)
101 X(DNS_TYPE_ADDRS)
102 X(DNS_TYPE_TKEY)
103 X(DNS_TYPE_TSIG)
104 X(DNS_TYPE_IXFR)
105 X(DNS_TYPE_AXFR)
106 X(DNS_TYPE_MAILB)
107 X(DNS_TYPE_MAILA)
108 X(DNS_TYPE_ANY)
109 X(DNS_TYPE_WINS)
110 X(DNS_TYPE_WINSR)
111 #undef X
112 default: { static char tmp[7]; sprintf( tmp, "0x%04x", type ); return tmp; }
116 static int dns_strcmpX( LPCVOID str1, LPCVOID str2, BOOL wide )
118 if (wide)
119 return lstrcmpiW( str1, str2 );
120 else
121 return lstrcmpiA( str1, str2 );
124 /******************************************************************************
125 * DnsRecordCompare [DNSAPI.@]
128 BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 )
130 BOOL wide;
131 unsigned int i;
133 TRACE( "(%p,%p)\n", r1, r2 );
135 if (r1->wType != r2->wType ||
136 r1->wDataLength != r2->wDataLength ||
137 r1->Flags.S.Section != r2->Flags.S.Section ||
138 r1->Flags.S.Delete != r2->Flags.S.Delete ||
139 r1->Flags.S.Unused != r2->Flags.S.Unused ||
140 r1->Flags.S.Reserved != r2->Flags.S.Reserved ||
141 r1->dwReserved != r2->dwReserved) return FALSE;
143 wide = (r1->Flags.S.CharSet == DnsCharSetUnicode || r1->Flags.S.CharSet == DnsCharSetUnknown);
144 if (dns_strcmpX( r1->pName, r2->pName, wide )) return FALSE;
146 switch (r1->wType)
148 case DNS_TYPE_A:
150 if (r1->Data.A.IpAddress != r2->Data.A.IpAddress) return FALSE;
151 break;
153 case DNS_TYPE_SOA:
155 if (r1->Data.SOA.dwSerialNo != r2->Data.SOA.dwSerialNo ||
156 r1->Data.SOA.dwRefresh != r2->Data.SOA.dwRefresh ||
157 r1->Data.SOA.dwRetry != r2->Data.SOA.dwRetry ||
158 r1->Data.SOA.dwExpire != r2->Data.SOA.dwExpire ||
159 r1->Data.SOA.dwDefaultTtl != r2->Data.SOA.dwDefaultTtl)
160 return FALSE;
161 if (dns_strcmpX( r1->Data.SOA.pNamePrimaryServer,
162 r2->Data.SOA.pNamePrimaryServer, wide ) ||
163 dns_strcmpX( r1->Data.SOA.pNameAdministrator,
164 r2->Data.SOA.pNameAdministrator, wide ))
165 return FALSE;
166 break;
168 case DNS_TYPE_PTR:
169 case DNS_TYPE_NS:
170 case DNS_TYPE_CNAME:
171 case DNS_TYPE_MB:
172 case DNS_TYPE_MD:
173 case DNS_TYPE_MF:
174 case DNS_TYPE_MG:
175 case DNS_TYPE_MR:
177 if (dns_strcmpX( r1->Data.PTR.pNameHost,
178 r2->Data.PTR.pNameHost, wide )) return FALSE;
179 break;
181 case DNS_TYPE_MINFO:
182 case DNS_TYPE_RP:
184 if (dns_strcmpX( r1->Data.MINFO.pNameMailbox,
185 r2->Data.MINFO.pNameMailbox, wide ) ||
186 dns_strcmpX( r1->Data.MINFO.pNameErrorsMailbox,
187 r2->Data.MINFO.pNameErrorsMailbox, wide ))
188 return FALSE;
189 break;
191 case DNS_TYPE_MX:
192 case DNS_TYPE_AFSDB:
193 case DNS_TYPE_RT:
195 if (r1->Data.MX.wPreference != r2->Data.MX.wPreference)
196 return FALSE;
197 if (dns_strcmpX( r1->Data.MX.pNameExchange,
198 r2->Data.MX.pNameExchange, wide ))
199 return FALSE;
200 break;
202 case DNS_TYPE_HINFO:
203 case DNS_TYPE_ISDN:
204 case DNS_TYPE_TEXT:
205 case DNS_TYPE_X25:
207 if (r1->Data.TXT.dwStringCount != r2->Data.TXT.dwStringCount)
208 return FALSE;
209 for (i = 0; i < r1->Data.TXT.dwStringCount; i++)
211 if (dns_strcmpX( r1->Data.TXT.pStringArray[i],
212 r2->Data.TXT.pStringArray[i], wide ))
213 return FALSE;
215 break;
217 case DNS_TYPE_NULL:
219 if (r1->Data.Null.dwByteCount != r2->Data.Null.dwByteCount)
220 return FALSE;
221 if (memcmp( r1->Data.Null.Data,
222 r2->Data.Null.Data, r1->Data.Null.dwByteCount ))
223 return FALSE;
224 break;
226 case DNS_TYPE_OPT:
228 if (r1->Data.Opt.wDataLength != r2->Data.Opt.wDataLength)
229 return FALSE;
230 /* ignore wPad */
231 if (memcmp( r1->Data.Opt.Data,
232 r2->Data.Opt.Data, r1->Data.Opt.wDataLength ))
233 return FALSE;
234 break;
236 case DNS_TYPE_AAAA:
238 for (i = 0; i < sizeof(IP6_ADDRESS)/sizeof(DWORD); i++)
240 if (r1->Data.AAAA.Ip6Address.IP6Dword[i] !=
241 r2->Data.AAAA.Ip6Address.IP6Dword[i]) return FALSE;
243 break;
245 case DNS_TYPE_KEY:
247 if (r1->Data.KEY.wFlags != r2->Data.KEY.wFlags ||
248 r1->Data.KEY.chProtocol != r2->Data.KEY.chProtocol ||
249 r1->Data.KEY.chAlgorithm != r2->Data.KEY.chAlgorithm)
250 return FALSE;
251 if (memcmp( r1->Data.KEY.Key, r2->Data.KEY.Key,
252 r1->wDataLength - sizeof(DNS_KEY_DATA) + 1 ))
253 return FALSE;
254 break;
256 case DNS_TYPE_SIG:
258 if (dns_strcmpX( r1->Data.SIG.pNameSigner,
259 r2->Data.SIG.pNameSigner, wide ))
260 return FALSE;
261 if (r1->Data.SIG.wTypeCovered != r2->Data.SIG.wTypeCovered ||
262 r1->Data.SIG.chAlgorithm != r2->Data.SIG.chAlgorithm ||
263 r1->Data.SIG.chLabelCount != r2->Data.SIG.chLabelCount ||
264 r1->Data.SIG.dwOriginalTtl != r2->Data.SIG.dwOriginalTtl ||
265 r1->Data.SIG.dwExpiration != r2->Data.SIG.dwExpiration ||
266 r1->Data.SIG.dwTimeSigned != r2->Data.SIG.dwTimeSigned ||
267 r1->Data.SIG.wKeyTag != r2->Data.SIG.wKeyTag)
268 return FALSE;
269 if (memcmp( r1->Data.SIG.Signature, r2->Data.SIG.Signature,
270 r1->wDataLength - sizeof(DNS_SIG_DATAA) + 1 ))
271 return FALSE;
272 break;
274 case DNS_TYPE_ATMA:
276 if (r1->Data.ATMA.AddressType != r2->Data.ATMA.AddressType)
277 return FALSE;
278 for (i = 0; i < DNS_ATMA_MAX_ADDR_LENGTH; i++)
280 if (r1->Data.ATMA.Address[i] != r2->Data.ATMA.Address[i])
281 return FALSE;
283 break;
285 case DNS_TYPE_NXT:
287 if (dns_strcmpX( r1->Data.NXT.pNameNext,
288 r2->Data.NXT.pNameNext, wide )) return FALSE;
289 if (r1->Data.NXT.wNumTypes != r2->Data.NXT.wNumTypes) return FALSE;
290 if (memcmp( r1->Data.NXT.wTypes, r2->Data.NXT.wTypes,
291 r1->wDataLength - sizeof(DNS_NXT_DATAA) + sizeof(WORD) ))
292 return FALSE;
293 break;
295 case DNS_TYPE_SRV:
297 if (dns_strcmpX( r1->Data.SRV.pNameTarget,
298 r2->Data.SRV.pNameTarget, wide )) return FALSE;
299 if (r1->Data.SRV.wPriority != r2->Data.SRV.wPriority ||
300 r1->Data.SRV.wWeight != r2->Data.SRV.wWeight ||
301 r1->Data.SRV.wPort != r2->Data.SRV.wPort)
302 return FALSE;
303 break;
305 case DNS_TYPE_TKEY:
307 if (dns_strcmpX( r1->Data.TKEY.pNameAlgorithm,
308 r2->Data.TKEY.pNameAlgorithm, wide ))
309 return FALSE;
310 if (r1->Data.TKEY.dwCreateTime != r2->Data.TKEY.dwCreateTime ||
311 r1->Data.TKEY.dwExpireTime != r2->Data.TKEY.dwExpireTime ||
312 r1->Data.TKEY.wMode != r2->Data.TKEY.wMode ||
313 r1->Data.TKEY.wError != r2->Data.TKEY.wError ||
314 r1->Data.TKEY.wKeyLength != r2->Data.TKEY.wKeyLength ||
315 r1->Data.TKEY.wOtherLength != r2->Data.TKEY.wOtherLength ||
316 r1->Data.TKEY.cAlgNameLength != r2->Data.TKEY.cAlgNameLength ||
317 r1->Data.TKEY.bPacketPointers != r2->Data.TKEY.bPacketPointers)
318 return FALSE;
320 /* FIXME: ignoring pAlgorithmPacket field */
321 if (memcmp( r1->Data.TKEY.pKey, r2->Data.TKEY.pKey,
322 r1->Data.TKEY.wKeyLength ) ||
323 memcmp( r1->Data.TKEY.pOtherData, r2->Data.TKEY.pOtherData,
324 r1->Data.TKEY.wOtherLength )) return FALSE;
325 break;
327 case DNS_TYPE_TSIG:
329 if (dns_strcmpX( r1->Data.TSIG.pNameAlgorithm,
330 r2->Data.TSIG.pNameAlgorithm, wide ))
331 return FALSE;
332 if (r1->Data.TSIG.i64CreateTime != r2->Data.TSIG.i64CreateTime ||
333 r1->Data.TSIG.wFudgeTime != r2->Data.TSIG.wFudgeTime ||
334 r1->Data.TSIG.wOriginalXid != r2->Data.TSIG.wOriginalXid ||
335 r1->Data.TSIG.wError != r2->Data.TSIG.wError ||
336 r1->Data.TSIG.wSigLength != r2->Data.TSIG.wSigLength ||
337 r1->Data.TSIG.wOtherLength != r2->Data.TSIG.wOtherLength ||
338 r1->Data.TSIG.cAlgNameLength != r2->Data.TSIG.cAlgNameLength ||
339 r1->Data.TSIG.bPacketPointers != r2->Data.TSIG.bPacketPointers)
340 return FALSE;
342 /* FIXME: ignoring pAlgorithmPacket field */
343 if (memcmp( r1->Data.TSIG.pSignature, r2->Data.TSIG.pSignature,
344 r1->Data.TSIG.wSigLength ) ||
345 memcmp( r1->Data.TSIG.pOtherData, r2->Data.TSIG.pOtherData,
346 r1->Data.TSIG.wOtherLength )) return FALSE;
347 break;
349 case DNS_TYPE_WINS:
351 if (r1->Data.WINS.dwMappingFlag != r2->Data.WINS.dwMappingFlag ||
352 r1->Data.WINS.dwLookupTimeout != r2->Data.WINS.dwLookupTimeout ||
353 r1->Data.WINS.dwCacheTimeout != r2->Data.WINS.dwCacheTimeout ||
354 r1->Data.WINS.cWinsServerCount != r2->Data.WINS.cWinsServerCount)
355 return FALSE;
356 if (memcmp( r1->Data.WINS.WinsServers, r2->Data.WINS.WinsServers,
357 r1->wDataLength - sizeof(DNS_WINS_DATA) + sizeof(IP4_ADDRESS) ))
358 return FALSE;
359 break;
361 case DNS_TYPE_WINSR:
363 if (r1->Data.WINSR.dwMappingFlag != r2->Data.WINSR.dwMappingFlag ||
364 r1->Data.WINSR.dwLookupTimeout != r2->Data.WINSR.dwLookupTimeout ||
365 r1->Data.WINSR.dwCacheTimeout != r2->Data.WINSR.dwCacheTimeout)
366 return FALSE;
367 if (dns_strcmpX( r1->Data.WINSR.pNameResultDomain,
368 r2->Data.WINSR.pNameResultDomain, wide ))
369 return FALSE;
370 break;
372 default:
373 FIXME( "unknown type: %s\n", dns_type_to_str( r1->wType ) );
374 return FALSE;
376 return TRUE;
379 static LPVOID dns_strcpyX( LPCVOID src, DNS_CHARSET in, DNS_CHARSET out )
381 switch (in)
383 case DnsCharSetUnicode:
385 switch (out)
387 case DnsCharSetUnicode: return dns_strdup_w( src );
388 case DnsCharSetUtf8: return dns_strdup_wu( src );
389 case DnsCharSetAnsi: return dns_strdup_wa( src );
390 default:
391 WARN( "unhandled target charset: %d\n", out );
392 break;
394 break;
396 case DnsCharSetUtf8:
397 switch (out)
399 case DnsCharSetUnicode: return dns_strdup_uw( src );
400 case DnsCharSetUtf8: return dns_strdup_u( src );
401 case DnsCharSetAnsi: return dns_strdup_ua( src );
402 default:
403 WARN( "unhandled target charset: %d\n", out );
404 break;
406 break;
407 case DnsCharSetAnsi:
408 switch (out)
410 case DnsCharSetUnicode: return dns_strdup_aw( src );
411 case DnsCharSetUtf8: return dns_strdup_au( src );
412 case DnsCharSetAnsi: return dns_strdup_a( src );
413 default:
414 WARN( "unhandled target charset: %d\n", out );
415 break;
417 break;
418 default:
419 WARN( "unhandled source charset: %d\n", in );
420 break;
422 return NULL;
425 /******************************************************************************
426 * DnsRecordCopyEx [DNSAPI.@]
429 PDNS_RECORD WINAPI DnsRecordCopyEx( PDNS_RECORD src, DNS_CHARSET in, DNS_CHARSET out )
431 DNS_RECORD *dst;
432 unsigned int i, size;
434 TRACE( "(%p,%d,%d)\n", src, in, out );
436 size = FIELD_OFFSET(DNS_RECORD, Data) + src->wDataLength;
437 dst = heap_alloc_zero( size );
438 if (!dst) return NULL;
440 memcpy( dst, src, size );
442 if (src->Flags.S.CharSet == DnsCharSetUtf8 ||
443 src->Flags.S.CharSet == DnsCharSetAnsi ||
444 src->Flags.S.CharSet == DnsCharSetUnicode) in = src->Flags.S.CharSet;
446 dst->Flags.S.CharSet = out;
447 dst->pName = dns_strcpyX( src->pName, in, out );
448 if (!dst->pName) goto error;
450 switch (src->wType)
452 case DNS_TYPE_HINFO:
453 case DNS_TYPE_ISDN:
454 case DNS_TYPE_TEXT:
455 case DNS_TYPE_X25:
457 for (i = 0; i < src->Data.TXT.dwStringCount; i++)
459 dst->Data.TXT.pStringArray[i] =
460 dns_strcpyX( src->Data.TXT.pStringArray[i], in, out );
462 if (!dst->Data.TXT.pStringArray[i])
464 while (i > 0) heap_free( dst->Data.TXT.pStringArray[--i] );
465 goto error;
468 break;
470 case DNS_TYPE_MINFO:
471 case DNS_TYPE_RP:
473 dst->Data.MINFO.pNameMailbox =
474 dns_strcpyX( src->Data.MINFO.pNameMailbox, in, out );
475 if (!dst->Data.MINFO.pNameMailbox) goto error;
477 dst->Data.MINFO.pNameErrorsMailbox =
478 dns_strcpyX( src->Data.MINFO.pNameErrorsMailbox, in, out );
479 if (!dst->Data.MINFO.pNameErrorsMailbox)
481 heap_free( dst->Data.MINFO.pNameMailbox );
482 goto error;
485 dst->wDataLength = sizeof(dst->Data.MINFO);
486 if (out == DnsCharSetUnicode) dst->wDataLength +=
487 (strlenW( dst->Data.MINFO.pNameMailbox ) + 1) * sizeof(WCHAR) +
488 (strlenW( dst->Data.MINFO.pNameErrorsMailbox ) + 1) * sizeof(WCHAR);
489 break;
491 case DNS_TYPE_AFSDB:
492 case DNS_TYPE_RT:
493 case DNS_TYPE_MX:
495 dst->Data.MX.pNameExchange =
496 dns_strcpyX( src->Data.MX.pNameExchange, in, out );
497 if (!dst->Data.MX.pNameExchange) goto error;
499 dst->wDataLength = sizeof(dst->Data.MX);
500 if (out == DnsCharSetUnicode) dst->wDataLength +=
501 (strlenW( dst->Data.MX.pNameExchange ) + 1) * sizeof(WCHAR);
502 break;
504 case DNS_TYPE_NXT:
506 dst->Data.NXT.pNameNext =
507 dns_strcpyX( src->Data.NXT.pNameNext, in, out );
508 if (!dst->Data.NXT.pNameNext) goto error;
510 dst->wDataLength = sizeof(dst->Data.NXT);
511 if (out == DnsCharSetUnicode) dst->wDataLength +=
512 (strlenW( dst->Data.NXT.pNameNext ) + 1) * sizeof(WCHAR);
513 break;
515 case DNS_TYPE_CNAME:
516 case DNS_TYPE_MB:
517 case DNS_TYPE_MD:
518 case DNS_TYPE_MF:
519 case DNS_TYPE_MG:
520 case DNS_TYPE_MR:
521 case DNS_TYPE_NS:
522 case DNS_TYPE_PTR:
524 dst->Data.PTR.pNameHost =
525 dns_strcpyX( src->Data.PTR.pNameHost, in, out );
526 if (!dst->Data.PTR.pNameHost) goto error;
528 dst->wDataLength = sizeof(dst->Data.PTR);
529 if (out == DnsCharSetUnicode) dst->wDataLength +=
530 (strlenW( dst->Data.PTR.pNameHost ) + 1) * sizeof(WCHAR);
531 break;
533 case DNS_TYPE_SIG:
535 dst->Data.SIG.pNameSigner =
536 dns_strcpyX( src->Data.SIG.pNameSigner, in, out );
537 if (!dst->Data.SIG.pNameSigner) goto error;
539 dst->wDataLength = sizeof(dst->Data.SIG);
540 if (out == DnsCharSetUnicode) dst->wDataLength +=
541 (strlenW( dst->Data.SIG.pNameSigner ) + 1) * sizeof(WCHAR);
542 break;
544 case DNS_TYPE_SOA:
546 dst->Data.SOA.pNamePrimaryServer =
547 dns_strcpyX( src->Data.SOA.pNamePrimaryServer, in, out );
548 if (!dst->Data.SOA.pNamePrimaryServer) goto error;
550 dst->Data.SOA.pNameAdministrator =
551 dns_strcpyX( src->Data.SOA.pNameAdministrator, in, out );
552 if (!dst->Data.SOA.pNameAdministrator)
554 heap_free( dst->Data.SOA.pNamePrimaryServer );
555 goto error;
558 dst->wDataLength = sizeof(dst->Data.SOA);
559 if (out == DnsCharSetUnicode) dst->wDataLength +=
560 (strlenW( dst->Data.SOA.pNamePrimaryServer ) + 1) * sizeof(WCHAR) +
561 (strlenW( dst->Data.SOA.pNameAdministrator ) + 1) * sizeof(WCHAR);
562 break;
564 case DNS_TYPE_SRV:
566 dst->Data.SRV.pNameTarget =
567 dns_strcpyX( src->Data.SRV.pNameTarget, in, out );
568 if (!dst->Data.SRV.pNameTarget) goto error;
570 dst->wDataLength = sizeof(dst->Data.SRV);
571 if (out == DnsCharSetUnicode) dst->wDataLength +=
572 (strlenW( dst->Data.SRV.pNameTarget ) + 1) * sizeof(WCHAR);
573 break;
575 default:
576 break;
578 return dst;
580 error:
581 heap_free( dst->pName );
582 heap_free( dst );
583 return NULL;
586 /******************************************************************************
587 * DnsRecordListFree [DNSAPI.@]
590 VOID WINAPI DnsRecordListFree( PDNS_RECORD list, DNS_FREE_TYPE type )
592 DNS_RECORD *r, *next;
593 unsigned int i;
595 TRACE( "(%p,%d)\n", list, type );
597 if (!list) return;
599 switch (type)
601 case DnsFreeRecordList:
603 for (r = list; (list = r); r = next)
605 heap_free( r->pName );
607 switch (r->wType)
609 case DNS_TYPE_HINFO:
610 case DNS_TYPE_ISDN:
611 case DNS_TYPE_TEXT:
612 case DNS_TYPE_X25:
614 for (i = 0; i < r->Data.TXT.dwStringCount; i++)
615 heap_free( r->Data.TXT.pStringArray[i] );
617 break;
619 case DNS_TYPE_MINFO:
620 case DNS_TYPE_RP:
622 heap_free( r->Data.MINFO.pNameMailbox );
623 heap_free( r->Data.MINFO.pNameErrorsMailbox );
624 break;
626 case DNS_TYPE_AFSDB:
627 case DNS_TYPE_RT:
628 case DNS_TYPE_MX:
630 heap_free( r->Data.MX.pNameExchange );
631 break;
633 case DNS_TYPE_NXT:
635 heap_free( r->Data.NXT.pNameNext );
636 break;
638 case DNS_TYPE_CNAME:
639 case DNS_TYPE_MB:
640 case DNS_TYPE_MD:
641 case DNS_TYPE_MF:
642 case DNS_TYPE_MG:
643 case DNS_TYPE_MR:
644 case DNS_TYPE_NS:
645 case DNS_TYPE_PTR:
647 heap_free( r->Data.PTR.pNameHost );
648 break;
650 case DNS_TYPE_SIG:
652 heap_free( r->Data.SIG.pNameSigner );
653 break;
655 case DNS_TYPE_SOA:
657 heap_free( r->Data.SOA.pNamePrimaryServer );
658 heap_free( r->Data.SOA.pNameAdministrator );
659 break;
661 case DNS_TYPE_SRV:
663 heap_free( r->Data.SRV.pNameTarget );
664 break;
666 default:
667 break;
670 next = r->pNext;
671 heap_free( r );
673 break;
675 case DnsFreeFlat:
676 case DnsFreeParsedMessageFields:
678 FIXME( "unhandled free type: %d\n", type );
679 break;
681 default:
682 WARN( "unknown free type: %d\n", type );
683 break;
687 /******************************************************************************
688 * DnsFree [DNSAPI.@]
691 void WINAPI DnsFree( PVOID data, DNS_FREE_TYPE type )
693 DnsRecordListFree( data, type );
696 /******************************************************************************
697 * DnsRecordSetCompare [DNSAPI.@]
700 BOOL WINAPI DnsRecordSetCompare( PDNS_RECORD set1, PDNS_RECORD set2,
701 PDNS_RECORD *diff1, PDNS_RECORD *diff2 )
703 BOOL ret = TRUE;
704 DNS_RECORD *r, *t, *u;
705 DNS_RRSET rr1, rr2;
707 TRACE( "(%p,%p,%p,%p)\n", set1, set2, diff1, diff2 );
709 if (!set1 && !set2) return FALSE;
711 if (diff1) *diff1 = NULL;
712 if (diff2) *diff2 = NULL;
714 if (set1 && !set2)
716 if (diff1) *diff1 = DnsRecordSetCopyEx( set1, 0, set1->Flags.S.CharSet );
717 return FALSE;
719 if (!set1 && set2)
721 if (diff2) *diff2 = DnsRecordSetCopyEx( set2, 0, set2->Flags.S.CharSet );
722 return FALSE;
725 DNS_RRSET_INIT( rr1 );
726 DNS_RRSET_INIT( rr2 );
728 for (r = set1; r; r = r->pNext)
730 for (t = set2; t; t = t->pNext)
732 u = DnsRecordCopyEx( r, r->Flags.S.CharSet, t->Flags.S.CharSet );
733 if (!u) goto error;
735 if (!DnsRecordCompare( t, u ))
737 DNS_RRSET_ADD( rr1, u );
738 ret = FALSE;
740 else DnsRecordListFree( u, DnsFreeRecordList );
744 for (t = set2; t; t = t->pNext)
746 for (r = set1; r; r = r->pNext)
748 u = DnsRecordCopyEx( t, t->Flags.S.CharSet, r->Flags.S.CharSet );
749 if (!u) goto error;
751 if (!DnsRecordCompare( r, u ))
753 DNS_RRSET_ADD( rr2, u );
754 ret = FALSE;
756 else DnsRecordListFree( u, DnsFreeRecordList );
760 DNS_RRSET_TERMINATE( rr1 );
761 DNS_RRSET_TERMINATE( rr2 );
763 if (diff1) *diff1 = rr1.pFirstRR;
764 else DnsRecordListFree( rr1.pFirstRR, DnsFreeRecordList );
766 if (diff2) *diff2 = rr2.pFirstRR;
767 else DnsRecordListFree( rr2.pFirstRR, DnsFreeRecordList );
769 return ret;
771 error:
772 DNS_RRSET_TERMINATE( rr1 );
773 DNS_RRSET_TERMINATE( rr2 );
775 DnsRecordListFree( rr1.pFirstRR, DnsFreeRecordList );
776 DnsRecordListFree( rr2.pFirstRR, DnsFreeRecordList );
778 return FALSE;
781 /******************************************************************************
782 * DnsRecordSetCopyEx [DNSAPI.@]
785 PDNS_RECORD WINAPI DnsRecordSetCopyEx( PDNS_RECORD src_set, DNS_CHARSET in, DNS_CHARSET out )
787 DNS_RRSET dst_set;
788 DNS_RECORD *src, *dst;
790 TRACE( "(%p,%d,%d)\n", src_set, in, out );
792 DNS_RRSET_INIT( dst_set );
794 for (src = src_set; (src_set = src); src = src_set->pNext)
796 dst = DnsRecordCopyEx( src, in, out );
797 if (!dst)
799 DNS_RRSET_TERMINATE( dst_set );
800 DnsRecordListFree( dst_set.pFirstRR, DnsFreeRecordList );
801 return NULL;
803 DNS_RRSET_ADD( dst_set, dst );
806 DNS_RRSET_TERMINATE( dst_set );
807 return dst_set.pFirstRR;
810 /******************************************************************************
811 * DnsRecordSetDetach [DNSAPI.@]
814 PDNS_RECORD WINAPI DnsRecordSetDetach( PDNS_RECORD set )
816 DNS_RECORD *r, *s;
818 TRACE( "(%p)\n", set );
820 for (r = set; (set = r); r = set->pNext)
822 if (r->pNext && !r->pNext->pNext)
824 s = r->pNext;
825 r->pNext = NULL;
826 return s;
829 return NULL;