- NDK fix: don't undef a million status codes, instead, have apps define WIN32_NO_STATUS.
[reactos.git] / reactos / lib / dnsapi / dnsapi / query.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/dnsapi/dnsapi/query.c
5 * PURPOSE: DNSAPI functions built on the ADNS library.
6 * PROGRAMER: Art Yerkes
7 * UPDATE HISTORY:
8 * 12/15/03 -- Created
9 */
10
11 #include "precomp.h"
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /* DnsQuery ****************************
17 * Begin a DNS query, and allow the result to be placed in the application
18 * supplied result pointer. The result can be manipulated with the record
19 * functions.
20 *
21 * Name -- The DNS object to be queried.
22 * Type -- The type of records to be returned. These are
23 * listed in windns.h
24 * Options -- Query options. DNS_QUERY_STANDARD is the base
25 * state, and every other option takes precedence.
26 * multiple options can be combined. Listed in
27 * windns.h
28 * Servers -- List of alternate servers (optional)
29 * QueryResultSet -- Pointer to the result pointer that will be filled
30 * when the response is available.
31 * Reserved -- Response as it appears on the wire. Optional.
32 */
33
34 char *xstrsave(const char *str) {
35 char *p;
36
37 p= RtlAllocateHeap( RtlGetProcessHeap(), 0, strlen(str)+1 );
38 strcpy(p,str);
39 return p;
40 }
41
42 DNS_STATUS WINAPI DnsQuery_A
43 ( LPCSTR Name,
44 WORD Type,
45 DWORD Options,
46 PIP4_ARRAY Servers,
47 PDNS_RECORD *QueryResultSet,
48 PVOID *Reserved ) {
49 adns_state astate;
50 int quflags = 0;
51 int adns_error;
52 adns_answer *answer;
53
54 *QueryResultSet = 0;
55
56 switch( Type ) {
57 case DNS_TYPE_A:
58 adns_error = adns_init( &astate,
59 adns_if_noenv |
60 adns_if_noerrprint |
61 adns_if_noserverwarn,
62 0 );
63 if( adns_error != adns_s_ok ) {
64 return DnsIntTranslateAdnsToDNS_STATUS( adns_error );
65 }
66
67 adns_error = adns_synchronous( astate,
68 Name,
69 adns_r_addr,
70 quflags,
71 &answer );
72
73 if( adns_error != adns_s_ok ) {
74 adns_finish( astate );
75 return DnsIntTranslateAdnsToDNS_STATUS( adns_error );
76 }
77
78 if( answer && answer->rrs.addr ) {
79 *QueryResultSet =
80 (PDNS_RECORD)RtlAllocateHeap( RtlGetProcessHeap(), 0,
81 sizeof( DNS_RECORD ) );
82 (*QueryResultSet)->pNext = NULL;
83 (*QueryResultSet)->wType = Type;
84 (*QueryResultSet)->pName = xstrsave( Name );
85 (*QueryResultSet)->wDataLength = sizeof(DNS_A_DATA);
86 (*QueryResultSet)->Data.A.IpAddress =
87 answer->rrs.addr->addr.inet.sin_addr.s_addr;
88 adns_finish( astate );
89 return ERROR_SUCCESS;
90 } else
91 return ERROR_FILE_NOT_FOUND;
92 default:
93 return ERROR_OUTOFMEMORY; /* XXX arty: find a better error code. */
94 }
95 }
96
97 static PCHAR DnsWToC( const WCHAR *WideString ) {
98 int chars = wcstombs( NULL, WideString, 0 );
99 PCHAR out = RtlAllocateHeap( RtlGetProcessHeap(), 0, chars + 1 );
100 wcstombs( out, WideString, chars + 1 );
101 return out;
102 }
103
104 static PWCHAR DnsCToW( const CHAR *NarrowString ) {
105 int chars = mbstowcs( NULL, NarrowString, 0 );
106 PWCHAR out = RtlAllocateHeap( RtlGetProcessHeap(), 0,
107 (chars + 1) * sizeof(WCHAR) );
108 mbstowcs( out, NarrowString, chars + 1 );
109 return out;
110 }
111
112 DNS_STATUS WINAPI DnsQuery_W
113 ( LPCWSTR Name,
114 WORD Type,
115 DWORD Options,
116 PIP4_ARRAY Servers,
117 PDNS_RECORD *QueryResultSet,
118 PVOID *Reserved ) {
119 UINT i;
120 PCHAR Buffer;
121 DNS_STATUS Status;
122 PDNS_RECORD QueryResultWide;
123 PDNS_RECORD ConvertedRecord = 0, LastRecord = 0;
124
125 Buffer = DnsWToC( Name );
126
127 Status = DnsQuery_A( Buffer, Type, Options, Servers, &QueryResultWide,
128 Reserved );
129
130 while( Status == ERROR_SUCCESS && QueryResultWide ) {
131 switch( QueryResultWide->wType ) {
132 case DNS_TYPE_A:
133 case DNS_TYPE_WKS:
134 #ifndef __USE_W32API
135 case DNS_TYPE_AAAA:
136 case DNS_TYPE_KEY:
137 #endif
138 ConvertedRecord = RtlAllocateHeap( RtlGetProcessHeap(), 0,
139 sizeof(DNS_RECORD) );
140 ConvertedRecord->pName = (PCHAR)DnsCToW( QueryResultWide->pName );
141 ConvertedRecord->wType = QueryResultWide->wType;
142 ConvertedRecord->wDataLength = QueryResultWide->wDataLength;
143 memcpy( ConvertedRecord, QueryResultWide,
144 QueryResultWide->wDataLength );
145 break;
146
147 case DNS_TYPE_CNAME:
148 case DNS_TYPE_PTR:
149 case DNS_TYPE_NS:
150 case DNS_TYPE_MB:
151 case DNS_TYPE_MD:
152 case DNS_TYPE_MF:
153 case DNS_TYPE_MG:
154 case DNS_TYPE_MR:
155 ConvertedRecord = RtlAllocateHeap( RtlGetProcessHeap(), 0,
156 sizeof(DNS_RECORD) );
157 ConvertedRecord->pName = (PCHAR)DnsCToW( QueryResultWide->pName );
158 ConvertedRecord->wType = QueryResultWide->wType;
159 ConvertedRecord->wDataLength = sizeof(DNS_PTR_DATA);
160 ConvertedRecord->Data.PTR.pNameHost =
161 (PCHAR)DnsCToW( QueryResultWide->Data.PTR.pNameHost );
162 break;
163 case DNS_TYPE_MINFO:
164 #ifndef __USE_W32API
165 case DNS_TYPE_RP:
166 #endif
167 ConvertedRecord = RtlAllocateHeap( RtlGetProcessHeap(), 0,
168 sizeof(DNS_RECORD) );
169 ConvertedRecord->pName = (PCHAR)DnsCToW( QueryResultWide->pName );
170 ConvertedRecord->wType = QueryResultWide->wType;
171 ConvertedRecord->wDataLength = sizeof(DNS_MINFO_DATA);
172 ConvertedRecord->Data.MINFO.pNameMailbox =
173 (PCHAR)DnsCToW( QueryResultWide->Data.MINFO.pNameMailbox );
174 ConvertedRecord->Data.MINFO.pNameErrorsMailbox =
175 (PCHAR)DnsCToW( QueryResultWide->Data.MINFO.pNameErrorsMailbox );
176 break;
177
178 case DNS_TYPE_MX:
179 #ifndef __USE_W32API
180 case DNS_TYPE_AFSDB:
181 case DNS_TYPE_RT:
182 #endif
183 ConvertedRecord = RtlAllocateHeap( RtlGetProcessHeap(), 0,
184 sizeof(DNS_RECORD) );
185 ConvertedRecord->pName = (PCHAR)DnsCToW( QueryResultWide->pName );
186 ConvertedRecord->wType = QueryResultWide->wType;
187 ConvertedRecord->wDataLength = sizeof(DNS_MX_DATA);
188 ConvertedRecord->Data.MX.pNameExchange =
189 (PCHAR)DnsCToW( QueryResultWide->Data.MX.pNameExchange );
190 ConvertedRecord->Data.MX.wPreference =
191 QueryResultWide->Data.MX.wPreference;
192 break;
193
194 #ifndef __USE_W32API
195 case DNS_TYPE_TXT:
196 case DNS_TYPE_ISDN:
197 #endif
198 case DNS_TYPE_HINFO:
199 ConvertedRecord = RtlAllocateHeap( RtlGetProcessHeap(), 0,
200 sizeof(DNS_TXT_DATA) +
201 QueryResultWide->
202 Data.TXT.dwStringCount );
203 ConvertedRecord->pName = (PCHAR)DnsCToW( QueryResultWide->pName );
204 ConvertedRecord->wType = QueryResultWide->wType;
205 ConvertedRecord->wDataLength =
206 sizeof(DNS_TXT_DATA) +
207 (sizeof(PWCHAR) * QueryResultWide->Data.TXT.dwStringCount);
208 ConvertedRecord->Data.TXT.dwStringCount =
209 QueryResultWide->Data.TXT.dwStringCount;
210 for( i = 0; i < ConvertedRecord->Data.TXT.dwStringCount; i++ ) {
211 ConvertedRecord->Data.TXT.pStringArray[i] =
212 (PCHAR)DnsCToW( QueryResultWide->Data.TXT.pStringArray[i] );
213 }
214 break;
215
216 case DNS_TYPE_NULL:
217 ConvertedRecord = RtlAllocateHeap( RtlGetProcessHeap(), 0,
218 sizeof(DNS_NULL_DATA) +
219 QueryResultWide->
220 Data.Null.dwByteCount );
221 ConvertedRecord->pName = (PCHAR)DnsCToW( QueryResultWide->pName );
222 ConvertedRecord->wType = QueryResultWide->wType;
223 ConvertedRecord->wDataLength =
224 sizeof(DNS_NULL_DATA) + QueryResultWide->Data.Null.dwByteCount;
225 ConvertedRecord->Data.Null.dwByteCount =
226 QueryResultWide->Data.Null.dwByteCount;
227 memcpy( &ConvertedRecord->Data.Null.Data,
228 &QueryResultWide->Data.Null.Data,
229 QueryResultWide->Data.Null.dwByteCount );
230 break;
231
232 #ifndef __USE_W32API
233 case DNS_TYPE_SIG:
234 ConvertedRecord = RtlAllocateHeap( RtlGetProcessHeap(), 0,
235 sizeof(DNS_RECORDA) );
236 ConvertedRecord->pName = DnsCToW( QueryResultWide->pName );
237 ConvertedRecord->wType = QueryResultWide->wType;
238 ConvertedRecord->wDataLength = sizeof(DNS_SIG_DATAA);
239 memcpy( &ConvertedRecord->Data.SIG,
240 &QueryResultWide->Data.SIG,
241 sizeof(QueryResultWide->Data.SIG) );
242 ConvertedRecord->Data.SIG.pNameSigner =
243 DnsCToW( QueryResultWide->Data.SIG.pNameSigner );
244 break;
245
246 case DNS_TYPE_NXT:
247 ConvertedRecord = RtlAllocateHeap( RtlGetProcessHeap(), 0,
248 sizeof(DNS_RECORDA) );
249 ConvertedRecord->pName = DnsCToW( QueryResultWide->pName );
250 ConvertedRecord->wType = QueryResultWide->wType;
251 ConvertedRecord->wDataLength = sizeof(DNS_NXT_DATAA);
252 memcpy( &ConvertedRecord->Data.NXT,
253 &QueryResultWide->Data.NXT,
254 sizeof(QueryResultWide->Data.NXT) );
255 ConvertedRecord->Data.NXT.pNameNext =
256 DnsCToW( QueryResultWide->Data.NXT.pNameNext );
257 break;
258
259 case DNS_TYPE_SRV:
260 ConvertedRecord = RtlAllocateHeap( RtlGetProcessHeap(), 0,
261 sizeof(DNS_RECORDA) );
262 ConvertedRecord->pName = DnsCToW( QueryResultWide->pName );
263 ConvertedRecord->wType = QueryResultWide->wType;
264 ConvertedRecord->wDataLength = sizeof(DNS_SRV_DATAA);
265 memcpy( &ConvertedRecord->Data.SRV,
266 &QueryResultWide->Data.SRV,
267 sizeof(QueryResultWide->Data.SRV) );
268 ConvertedRecord->Data.SRV.pNameTarget =
269 DnsCToW( QueryResultWide->Data.SRV.pNameTarget );
270 break;
271 #endif
272 }
273
274 if( LastRecord ) {
275 LastRecord->pNext = ConvertedRecord;
276 LastRecord = LastRecord->pNext;
277 } else {
278 LastRecord = *QueryResultSet = ConvertedRecord;
279 }
280 }
281
282 LastRecord->pNext = 0;
283
284 /* The name */
285 RtlFreeHeap( RtlGetProcessHeap(), 0, Buffer );
286
287 return Status;
288 }
289
290 DNS_STATUS WINAPI DnsQuery_UTF8
291 ( LPCSTR Name,
292 WORD Type,
293 DWORD Options,
294 PIP4_ARRAY Servers,
295 PDNS_RECORD *QueryResultSet,
296 PVOID *Reserved ) {
297 return DnsQuery_UTF8( Name, Type, Options, Servers, QueryResultSet,
298 Reserved );
299 }
300
301 void DnsIntFreeRecordList( PDNS_RECORD ToDelete ) {
302 UINT i;
303 PDNS_RECORD next = 0;
304
305 while( ToDelete ) {
306 if( ToDelete->pName )
307 RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete->pName );
308 switch( ToDelete->wType ) {
309 case DNS_TYPE_CNAME:
310 case DNS_TYPE_PTR:
311 case DNS_TYPE_NS:
312 case DNS_TYPE_MB:
313 case DNS_TYPE_MD:
314 case DNS_TYPE_MF:
315 case DNS_TYPE_MG:
316 case DNS_TYPE_MR:
317 RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete->Data.PTR.pNameHost );
318 break;
319 case DNS_TYPE_MINFO:
320 #ifndef __USE_W32API
321 case DNS_TYPE_RP:
322 RtlFreeHeap( RtlGetProcessHeap(), 0,
323 ToDelete->Data.MINFO.pNameMailbox );
324 RtlFreeHeap( RtlGetProcessHeap(), 0,
325 ToDelete->Data.MINFO.pNameErrorsMailbox );
326 break;
327
328 case DNS_TYPE_AFSDB:
329 case DNS_TYPE_RT:
330 #endif
331 case DNS_TYPE_MX:
332 RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete->Data.MX.pNameExchange );
333 break;
334
335 #ifndef __USE_W32API
336 case DNS_TYPE_TXT:
337 case DNS_TYPE_ISDN:
338 #endif
339 case DNS_TYPE_HINFO:
340 for( i = 0; i < ToDelete->Data.TXT.dwStringCount; i++ ) {
341 RtlFreeHeap( RtlGetProcessHeap(), 0,
342 ToDelete->Data.TXT.pStringArray[i] );
343 }
344 RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete->Data.TXT.pStringArray );
345 break;
346
347 #ifndef __USE_W32API
348 case DNS_TYPE_SIG:
349 RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete->Data.SIG.pNameSigner );
350 break;
351
352 case DNS_TYPE_NXT:
353 RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete->Data.NXT.pNameNext );
354 break;
355
356 case DNS_TYPE_SRV:
357 RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete->Data.SRV.pNameTarget );
358 break;
359 #endif
360 }
361
362 next = ToDelete->pNext;
363 RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete );
364 ToDelete = next;
365 }
366 }