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