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
14 #include <internal/windns.h>
15 #define NTOS_MODE_USER
16 #include <ndk/ntndk.h>
18 /* DnsQuery ****************************
19 * Begin a DNS query, and allow the result to be placed in the application
20 * supplied result pointer. The result can be manipulated with the record
23 * Name -- The DNS object to be queried.
24 * Type -- The type of records to be returned. These are
26 * Options -- Query options. DNS_QUERY_STANDARD is the base
27 * state, and every other option takes precedence.
28 * multiple options can be combined. Listed in
30 * Servers -- List of alternate servers (optional)
31 * QueryResultSet -- Pointer to the result pointer that will be filled
32 * when the response is available.
33 * Reserved -- Response as it appears on the wire. Optional.
36 char *xstrsave(const char *str
) {
39 p
= RtlAllocateHeap( RtlGetProcessHeap(), 0, strlen(str
)+1 );
44 DNS_STATUS WINAPI DnsQuery_A
49 PDNS_RECORD
*QueryResultSet
,
60 adns_error
= adns_init( &astate
,
65 if( adns_error
!= adns_s_ok
) {
66 return DnsIntTranslateAdnsToDNS_STATUS( adns_error
);
69 adns_error
= adns_synchronous( astate
,
75 if( adns_error
!= adns_s_ok
) {
76 adns_finish( astate
);
77 return DnsIntTranslateAdnsToDNS_STATUS( adns_error
);
80 if( answer
&& answer
->rrs
.addr
) {
82 (PDNS_RECORD
)RtlAllocateHeap( RtlGetProcessHeap(), 0,
83 sizeof( DNS_RECORD
) );
84 (*QueryResultSet
)->pNext
= NULL
;
85 (*QueryResultSet
)->wType
= Type
;
86 (*QueryResultSet
)->pName
= xstrsave( Name
);
87 (*QueryResultSet
)->wDataLength
= sizeof(DNS_A_DATA
);
88 (*QueryResultSet
)->Data
.A
.IpAddress
=
89 answer
->rrs
.addr
->addr
.inet
.sin_addr
.s_addr
;
90 adns_finish( astate
);
93 return ERROR_FILE_NOT_FOUND
;
95 return ERROR_OUTOFMEMORY
; /* XXX arty: find a better error code. */
99 static PCHAR
DnsWToC( const WCHAR
*WideString
) {
100 int chars
= wcstombs( NULL
, WideString
, 0 );
101 PCHAR out
= RtlAllocateHeap( RtlGetProcessHeap(), 0, chars
+ 1 );
102 wcstombs( out
, WideString
, chars
+ 1 );
106 static PWCHAR
DnsCToW( const CHAR
*NarrowString
) {
107 int chars
= mbstowcs( NULL
, NarrowString
, 0 );
108 PWCHAR out
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
109 (chars
+ 1) * sizeof(WCHAR
) );
110 mbstowcs( out
, NarrowString
, chars
+ 1 );
114 DNS_STATUS WINAPI DnsQuery_W
119 PDNS_RECORD
*QueryResultSet
,
124 PDNS_RECORD QueryResultWide
;
125 PDNS_RECORD ConvertedRecord
= 0, LastRecord
= 0;
127 Buffer
= DnsWToC( Name
);
129 Status
= DnsQuery_A( Buffer
, Type
, Options
, Servers
, &QueryResultWide
,
132 while( Status
== ERROR_SUCCESS
&& QueryResultWide
) {
133 switch( QueryResultWide
->wType
) {
140 ConvertedRecord
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
141 sizeof(DNS_RECORD
) );
142 ConvertedRecord
->pName
= (PCHAR
)DnsCToW( QueryResultWide
->pName
);
143 ConvertedRecord
->wType
= QueryResultWide
->wType
;
144 ConvertedRecord
->wDataLength
= QueryResultWide
->wDataLength
;
145 memcpy( ConvertedRecord
, QueryResultWide
,
146 QueryResultWide
->wDataLength
);
157 ConvertedRecord
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
158 sizeof(DNS_RECORD
) );
159 ConvertedRecord
->pName
= (PCHAR
)DnsCToW( QueryResultWide
->pName
);
160 ConvertedRecord
->wType
= QueryResultWide
->wType
;
161 ConvertedRecord
->wDataLength
= sizeof(DNS_PTR_DATA
);
162 ConvertedRecord
->Data
.PTR
.pNameHost
=
163 (PCHAR
)DnsCToW( QueryResultWide
->Data
.PTR
.pNameHost
);
169 ConvertedRecord
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
170 sizeof(DNS_RECORD
) );
171 ConvertedRecord
->pName
= (PCHAR
)DnsCToW( QueryResultWide
->pName
);
172 ConvertedRecord
->wType
= QueryResultWide
->wType
;
173 ConvertedRecord
->wDataLength
= sizeof(DNS_MINFO_DATA
);
174 ConvertedRecord
->Data
.MINFO
.pNameMailbox
=
175 (PCHAR
)DnsCToW( QueryResultWide
->Data
.MINFO
.pNameMailbox
);
176 ConvertedRecord
->Data
.MINFO
.pNameErrorsMailbox
=
177 (PCHAR
)DnsCToW( QueryResultWide
->Data
.MINFO
.pNameErrorsMailbox
);
185 ConvertedRecord
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
186 sizeof(DNS_RECORD
) );
187 ConvertedRecord
->pName
= (PCHAR
)DnsCToW( QueryResultWide
->pName
);
188 ConvertedRecord
->wType
= QueryResultWide
->wType
;
189 ConvertedRecord
->wDataLength
= sizeof(DNS_MX_DATA
);
190 ConvertedRecord
->Data
.MX
.pNameExchange
=
191 (PCHAR
)DnsCToW( QueryResultWide
->Data
.MX
.pNameExchange
);
192 ConvertedRecord
->Data
.MX
.wPreference
=
193 QueryResultWide
->Data
.MX
.wPreference
;
201 ConvertedRecord
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
202 sizeof(DNS_TXT_DATA
) +
204 Data
.TXT
.dwStringCount
);
205 ConvertedRecord
->pName
= (PCHAR
)DnsCToW( QueryResultWide
->pName
);
206 ConvertedRecord
->wType
= QueryResultWide
->wType
;
207 ConvertedRecord
->wDataLength
=
208 sizeof(DNS_TXT_DATA
) +
209 (sizeof(PWCHAR
) * QueryResultWide
->Data
.TXT
.dwStringCount
);
210 ConvertedRecord
->Data
.TXT
.dwStringCount
=
211 QueryResultWide
->Data
.TXT
.dwStringCount
;
212 for( i
= 0; i
< ConvertedRecord
->Data
.TXT
.dwStringCount
; i
++ ) {
213 ConvertedRecord
->Data
.TXT
.pStringArray
[i
] =
214 (PCHAR
)DnsCToW( QueryResultWide
->Data
.TXT
.pStringArray
[i
] );
219 ConvertedRecord
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
220 sizeof(DNS_NULL_DATA
) +
222 Data
.Null
.dwByteCount
);
223 ConvertedRecord
->pName
= (PCHAR
)DnsCToW( QueryResultWide
->pName
);
224 ConvertedRecord
->wType
= QueryResultWide
->wType
;
225 ConvertedRecord
->wDataLength
=
226 sizeof(DNS_NULL_DATA
) + QueryResultWide
->Data
.Null
.dwByteCount
;
227 ConvertedRecord
->Data
.Null
.dwByteCount
=
228 QueryResultWide
->Data
.Null
.dwByteCount
;
229 memcpy( &ConvertedRecord
->Data
.Null
.Data
,
230 &QueryResultWide
->Data
.Null
.Data
,
231 QueryResultWide
->Data
.Null
.dwByteCount
);
236 ConvertedRecord
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
237 sizeof(DNS_RECORDA
) );
238 ConvertedRecord
->pName
= DnsCToW( QueryResultWide
->pName
);
239 ConvertedRecord
->wType
= QueryResultWide
->wType
;
240 ConvertedRecord
->wDataLength
= sizeof(DNS_SIG_DATAA
);
241 memcpy( &ConvertedRecord
->Data
.SIG
,
242 &QueryResultWide
->Data
.SIG
,
243 sizeof(QueryResultWide
->Data
.SIG
) );
244 ConvertedRecord
->Data
.SIG
.pNameSigner
=
245 DnsCToW( QueryResultWide
->Data
.SIG
.pNameSigner
);
249 ConvertedRecord
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
250 sizeof(DNS_RECORDA
) );
251 ConvertedRecord
->pName
= DnsCToW( QueryResultWide
->pName
);
252 ConvertedRecord
->wType
= QueryResultWide
->wType
;
253 ConvertedRecord
->wDataLength
= sizeof(DNS_NXT_DATAA
);
254 memcpy( &ConvertedRecord
->Data
.NXT
,
255 &QueryResultWide
->Data
.NXT
,
256 sizeof(QueryResultWide
->Data
.NXT
) );
257 ConvertedRecord
->Data
.NXT
.pNameNext
=
258 DnsCToW( QueryResultWide
->Data
.NXT
.pNameNext
);
262 ConvertedRecord
= RtlAllocateHeap( RtlGetProcessHeap(), 0,
263 sizeof(DNS_RECORDA
) );
264 ConvertedRecord
->pName
= DnsCToW( QueryResultWide
->pName
);
265 ConvertedRecord
->wType
= QueryResultWide
->wType
;
266 ConvertedRecord
->wDataLength
= sizeof(DNS_SRV_DATAA
);
267 memcpy( &ConvertedRecord
->Data
.SRV
,
268 &QueryResultWide
->Data
.SRV
,
269 sizeof(QueryResultWide
->Data
.SRV
) );
270 ConvertedRecord
->Data
.SRV
.pNameTarget
=
271 DnsCToW( QueryResultWide
->Data
.SRV
.pNameTarget
);
277 LastRecord
->pNext
= ConvertedRecord
;
278 LastRecord
= LastRecord
->pNext
;
280 LastRecord
= *QueryResultSet
= ConvertedRecord
;
284 LastRecord
->pNext
= 0;
287 RtlFreeHeap( RtlGetProcessHeap(), 0, Buffer
);
292 DNS_STATUS WINAPI DnsQuery_UTF8
297 PDNS_RECORD
*QueryResultSet
,
299 return DnsQuery_UTF8( Name
, Type
, Options
, Servers
, QueryResultSet
,
303 void DnsIntFreeRecordList( PDNS_RECORD ToDelete
) {
305 PDNS_RECORD next
= 0;
308 if( ToDelete
->pName
)
309 RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete
->pName
);
310 switch( ToDelete
->wType
) {
319 RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete
->Data
.PTR
.pNameHost
);
324 RtlFreeHeap( RtlGetProcessHeap(), 0,
325 ToDelete
->Data
.MINFO
.pNameMailbox
);
326 RtlFreeHeap( RtlGetProcessHeap(), 0,
327 ToDelete
->Data
.MINFO
.pNameErrorsMailbox
);
334 RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete
->Data
.MX
.pNameExchange
);
342 for( i
= 0; i
< ToDelete
->Data
.TXT
.dwStringCount
; i
++ ) {
343 RtlFreeHeap( RtlGetProcessHeap(), 0,
344 ToDelete
->Data
.TXT
.pStringArray
[i
] );
346 RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete
->Data
.TXT
.pStringArray
);
351 RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete
->Data
.SIG
.pNameSigner
);
355 RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete
->Data
.NXT
.pNameNext
);
359 RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete
->Data
.SRV
.pNameTarget
);
364 next
= ToDelete
->pNext
;
365 RtlFreeHeap( RtlGetProcessHeap(), 0, ToDelete
);