wined3d: Correctly destroy the adapter on format initialization failure in no3d mode.
[wine/zf.git] / dlls / dnsapi / query.c
blobf540662dfd2673553f5fe8600eb06b813aff0441
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"
25 #include <stdarg.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <sys/types.h>
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 #ifdef HAVE_NETDB_H
40 # include <netdb.h>
41 #endif
43 #include "windef.h"
44 #include "winbase.h"
45 #include "winerror.h"
46 #include "winnls.h"
47 #include "windns.h"
48 #include "nb30.h"
50 #include "dnsapi.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(dnsapi);
54 #ifdef HAVE_RESOLV
56 /* call res_init() just once because of a bug in Mac OS X 10.4 */
57 /* call once per thread on systems that have per-thread _res */
58 static void initialise_resolver( void )
60 if ((_res.options & RES_INIT) == 0)
61 res_init();
64 static const char *dns_section_to_str( ns_sect section )
66 switch (section)
68 case ns_s_qd: return "Question";
69 case ns_s_an: return "Answer";
70 case ns_s_ns: return "Authority";
71 case ns_s_ar: return "Additional";
72 default:
74 static char tmp[11];
75 FIXME( "unknown section: 0x%02x\n", section );
76 sprintf( tmp, "0x%02x", section );
77 return tmp;
82 static unsigned long dns_map_options( DWORD options )
84 unsigned long ret = 0;
86 if (options == DNS_QUERY_STANDARD)
87 return RES_DEFAULT;
89 if (options & DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE)
90 ret |= RES_IGNTC;
91 if (options & DNS_QUERY_USE_TCP_ONLY)
92 ret |= RES_USEVC;
93 if (options & DNS_QUERY_NO_RECURSION)
94 ret &= ~RES_RECURSE;
95 if (options & DNS_QUERY_NO_LOCAL_NAME)
96 ret &= ~RES_DNSRCH;
97 if (options & DNS_QUERY_NO_HOSTS_FILE)
98 ret |= RES_NOALIASES;
99 if (options & DNS_QUERY_TREAT_AS_FQDN)
100 ret &= ~RES_DEFNAMES;
102 if (options & DNS_QUERY_DONT_RESET_TTL_VALUES)
103 FIXME( "option DNS_QUERY_DONT_RESET_TTL_VALUES not implemented\n" );
104 if (options & DNS_QUERY_RESERVED)
105 FIXME( "option DNS_QUERY_RESERVED not implemented\n" );
106 if (options & DNS_QUERY_WIRE_ONLY)
107 FIXME( "option DNS_QUERY_WIRE_ONLY not implemented\n" );
108 if (options & DNS_QUERY_NO_WIRE_QUERY)
109 FIXME( "option DNS_QUERY_NO_WIRE_QUERY not implemented\n" );
110 if (options & DNS_QUERY_BYPASS_CACHE)
111 FIXME( "option DNS_QUERY_BYPASS_CACHE not implemented\n" );
112 if (options & DNS_QUERY_RETURN_MESSAGE)
113 FIXME( "option DNS_QUERY_RETURN_MESSAGE not implemented\n" );
115 if (options & DNS_QUERY_NO_NETBT)
116 TRACE( "netbios query disabled\n" );
118 return ret;
121 static DNS_STATUS dns_map_error( int error )
123 switch (error)
125 case ns_r_noerror: return ERROR_SUCCESS;
126 case ns_r_formerr: return DNS_ERROR_RCODE_FORMAT_ERROR;
127 case ns_r_servfail: return DNS_ERROR_RCODE_SERVER_FAILURE;
128 case ns_r_nxdomain: return DNS_ERROR_RCODE_NAME_ERROR;
129 case ns_r_notimpl: return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
130 case ns_r_refused: return DNS_ERROR_RCODE_REFUSED;
131 case ns_r_yxdomain: return DNS_ERROR_RCODE_YXDOMAIN;
132 case ns_r_yxrrset: return DNS_ERROR_RCODE_YXRRSET;
133 case ns_r_nxrrset: return DNS_ERROR_RCODE_NXRRSET;
134 case ns_r_notauth: return DNS_ERROR_RCODE_NOTAUTH;
135 case ns_r_notzone: return DNS_ERROR_RCODE_NOTZONE;
136 default:
137 FIXME( "unmapped error code: %d\n", error );
138 return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
142 static DNS_STATUS dns_map_h_errno( int error )
144 switch (error)
146 case NO_DATA:
147 case HOST_NOT_FOUND: return DNS_ERROR_RCODE_NAME_ERROR;
148 case TRY_AGAIN: return DNS_ERROR_RCODE_SERVER_FAILURE;
149 case NO_RECOVERY: return DNS_ERROR_RCODE_REFUSED;
150 #ifdef NETDB_INTERNAL
151 case NETDB_INTERNAL: return DNS_ERROR_RCODE;
152 #endif
153 default:
154 FIXME( "unmapped error code: %d\n", error );
155 return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
159 static char *dns_dname_from_msg( ns_msg msg, const unsigned char *pos )
161 int len;
162 char *str, dname[NS_MAXDNAME] = ".";
164 /* returns *compressed* length, ignore it */
165 dns_ns_name_uncompress( ns_msg_base(msg), ns_msg_end(msg), pos, dname, sizeof(dname) );
167 len = strlen( dname );
168 str = heap_alloc( len + 1 );
169 if (str) strcpy( str, dname );
170 return str;
173 static char *dns_str_from_rdata( const unsigned char *rdata )
175 char *str;
176 unsigned int len = rdata[0];
178 str = heap_alloc( len + 1 );
179 if (str)
181 memcpy( str, ++rdata, len );
182 str[len] = '\0';
184 return str;
187 static unsigned int dns_get_record_size( const ns_rr *rr )
189 const unsigned char *pos = rr->rdata;
190 unsigned int num = 0, size = sizeof(DNS_RECORDA);
192 switch (rr->type)
194 case ns_t_key:
196 pos += sizeof(WORD) + sizeof(BYTE) + sizeof(BYTE);
197 size += rr->rdata + rr->rdlength - pos - 1;
198 break;
200 case ns_t_sig:
202 pos += sizeof(PCHAR) + sizeof(WORD) + 2 * sizeof(BYTE);
203 pos += 3 * sizeof(DWORD) + 2 * sizeof(WORD);
204 size += rr->rdata + rr->rdlength - pos - 1;
205 break;
207 case ns_t_hinfo:
208 case ns_t_isdn:
209 case ns_t_txt:
210 case ns_t_x25:
212 while (pos[0] && pos < rr->rdata + rr->rdlength)
214 num++;
215 pos += pos[0] + 1;
217 size += (num - 1) * sizeof(PCHAR);
218 break;
220 case ns_t_null:
221 case ns_t_opt:
223 size += rr->rdlength - 1;
224 break;
226 case ns_t_nxt:
227 case ns_t_wks:
228 case 0xff01: /* WINS */
230 FIXME( "unhandled type: %s\n", dns_type_to_str( rr->type ) );
231 break;
233 default:
234 break;
236 return size;
239 static DNS_STATUS dns_copy_rdata( ns_msg msg, const ns_rr *rr, DNS_RECORDA *r, WORD *dlen )
241 DNS_STATUS ret = ERROR_SUCCESS;
242 const unsigned char *pos = rr->rdata;
243 unsigned int i, size;
245 switch (rr->type)
247 case ns_t_a:
249 r->Data.A.IpAddress = *(const DWORD *)pos;
250 *dlen = sizeof(DNS_A_DATA);
251 break;
253 case ns_t_aaaa:
255 for (i = 0; i < sizeof(IP6_ADDRESS)/sizeof(DWORD); i++)
257 r->Data.AAAA.Ip6Address.IP6Dword[i] = *(const DWORD *)pos;
258 pos += sizeof(DWORD);
261 *dlen = sizeof(DNS_AAAA_DATA);
262 break;
264 case ns_t_key:
266 /* FIXME: byte order? */
267 r->Data.KEY.wFlags = *(const WORD *)pos; pos += sizeof(WORD);
268 r->Data.KEY.chProtocol = *pos++;
269 r->Data.KEY.chAlgorithm = *pos++;
271 size = rr->rdata + rr->rdlength - pos;
273 for (i = 0; i < size; i++)
274 r->Data.KEY.Key[i] = *pos++;
276 *dlen = sizeof(DNS_KEY_DATA) + (size - 1) * sizeof(BYTE);
277 break;
279 case ns_t_rp:
280 case ns_t_minfo:
282 r->Data.MINFO.pNameMailbox = dns_dname_from_msg( msg, pos );
283 if (!r->Data.MINFO.pNameMailbox) return ERROR_NOT_ENOUGH_MEMORY;
285 if (dns_ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
286 return DNS_ERROR_BAD_PACKET;
288 r->Data.MINFO.pNameErrorsMailbox = dns_dname_from_msg( msg, pos );
289 if (!r->Data.MINFO.pNameErrorsMailbox)
291 heap_free( r->Data.MINFO.pNameMailbox );
292 return ERROR_NOT_ENOUGH_MEMORY;
295 *dlen = sizeof(DNS_MINFO_DATAA);
296 break;
298 case ns_t_afsdb:
299 case ns_t_rt:
300 case ns_t_mx:
302 r->Data.MX.wPreference = ntohs( *(const WORD *)pos );
303 r->Data.MX.pNameExchange = dns_dname_from_msg( msg, pos + sizeof(WORD) );
304 if (!r->Data.MX.pNameExchange) return ERROR_NOT_ENOUGH_MEMORY;
306 *dlen = sizeof(DNS_MX_DATAA);
307 break;
309 case ns_t_null:
311 r->Data.Null.dwByteCount = rr->rdlength;
312 memcpy( r->Data.Null.Data, rr->rdata, rr->rdlength );
314 *dlen = sizeof(DNS_NULL_DATA) + rr->rdlength - 1;
315 break;
317 case ns_t_opt:
319 r->Data.OPT.wDataLength = rr->rdlength;
320 r->Data.OPT.wPad = 0;
321 memcpy( r->Data.OPT.Data, rr->rdata, rr->rdlength );
323 *dlen = sizeof(DNS_OPT_DATA) + rr->rdlength - 1;
324 break;
326 case ns_t_cname:
327 case ns_t_ns:
328 case ns_t_mb:
329 case ns_t_md:
330 case ns_t_mf:
331 case ns_t_mg:
332 case ns_t_mr:
333 case ns_t_ptr:
335 r->Data.PTR.pNameHost = dns_dname_from_msg( msg, pos );
336 if (!r->Data.PTR.pNameHost) return ERROR_NOT_ENOUGH_MEMORY;
338 *dlen = sizeof(DNS_PTR_DATAA);
339 break;
341 case ns_t_sig:
343 r->Data.SIG.pNameSigner = dns_dname_from_msg( msg, pos );
344 if (!r->Data.SIG.pNameSigner) return ERROR_NOT_ENOUGH_MEMORY;
346 if (dns_ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
347 return DNS_ERROR_BAD_PACKET;
349 /* FIXME: byte order? */
350 r->Data.SIG.wTypeCovered = *(const WORD *)pos; pos += sizeof(WORD);
351 r->Data.SIG.chAlgorithm = *pos++;
352 r->Data.SIG.chLabelCount = *pos++;
353 r->Data.SIG.dwOriginalTtl = *(const DWORD *)pos; pos += sizeof(DWORD);
354 r->Data.SIG.dwExpiration = *(const DWORD *)pos; pos += sizeof(DWORD);
355 r->Data.SIG.dwTimeSigned = *(const DWORD *)pos; pos += sizeof(DWORD);
356 r->Data.SIG.wKeyTag = *(const WORD *)pos;
358 size = rr->rdata + rr->rdlength - pos;
360 for (i = 0; i < size; i++)
361 r->Data.SIG.Signature[i] = *pos++;
363 *dlen = sizeof(DNS_SIG_DATAA) + (size - 1) * sizeof(BYTE);
364 break;
366 case ns_t_soa:
368 r->Data.SOA.pNamePrimaryServer = dns_dname_from_msg( msg, pos );
369 if (!r->Data.SOA.pNamePrimaryServer) return ERROR_NOT_ENOUGH_MEMORY;
371 if (dns_ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
372 return DNS_ERROR_BAD_PACKET;
374 r->Data.SOA.pNameAdministrator = dns_dname_from_msg( msg, pos );
375 if (!r->Data.SOA.pNameAdministrator)
377 heap_free( r->Data.SOA.pNamePrimaryServer );
378 return ERROR_NOT_ENOUGH_MEMORY;
381 if (dns_ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
382 return DNS_ERROR_BAD_PACKET;
384 r->Data.SOA.dwSerialNo = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
385 r->Data.SOA.dwRefresh = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
386 r->Data.SOA.dwRetry = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
387 r->Data.SOA.dwExpire = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
388 r->Data.SOA.dwDefaultTtl = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
390 *dlen = sizeof(DNS_SOA_DATAA);
391 break;
393 case ns_t_srv:
395 r->Data.SRV.wPriority = ntohs( *(const WORD *)pos ); pos += sizeof(WORD);
396 r->Data.SRV.wWeight = ntohs( *(const WORD *)pos ); pos += sizeof(WORD);
397 r->Data.SRV.wPort = ntohs( *(const WORD *)pos ); pos += sizeof(WORD);
399 r->Data.SRV.pNameTarget = dns_dname_from_msg( msg, pos );
400 if (!r->Data.SRV.pNameTarget) return ERROR_NOT_ENOUGH_MEMORY;
402 *dlen = sizeof(DNS_SRV_DATAA);
403 break;
405 case ns_t_hinfo:
406 case ns_t_isdn:
407 case ns_t_x25:
408 case ns_t_txt:
410 i = 0;
411 while (pos[0] && pos < rr->rdata + rr->rdlength)
413 r->Data.TXT.pStringArray[i] = dns_str_from_rdata( pos );
414 if (!r->Data.TXT.pStringArray[i])
416 while (i > 0) heap_free( r->Data.TXT.pStringArray[--i] );
417 return ERROR_NOT_ENOUGH_MEMORY;
419 i++;
420 pos += pos[0] + 1;
422 r->Data.TXT.dwStringCount = i;
423 *dlen = sizeof(DNS_TXT_DATAA) + (i - 1) * sizeof(PCHAR);
424 break;
426 case ns_t_atma:
427 case ns_t_loc:
428 case ns_t_nxt:
429 case ns_t_tsig:
430 case ns_t_wks:
431 case 0x00f9: /* TKEY */
432 case 0xff01: /* WINS */
433 case 0xff02: /* WINSR */
434 default:
435 FIXME( "unhandled type: %s\n", dns_type_to_str( rr->type ) );
436 return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
439 return ret;
442 static DNS_STATUS dns_copy_record( ns_msg msg, ns_sect section,
443 unsigned short num, DNS_RECORDA **recp )
445 DNS_STATUS ret;
446 DNS_RECORDA *record;
447 WORD dlen;
448 ns_rr rr;
450 if (dns_ns_parserr( &msg, section, num, &rr ) < 0)
451 return DNS_ERROR_BAD_PACKET;
453 if (!(record = heap_alloc_zero( dns_get_record_size( &rr ) )))
454 return ERROR_NOT_ENOUGH_MEMORY;
456 record->pName = dns_strdup_u( rr.name );
457 if (!record->pName)
459 heap_free( record );
460 return ERROR_NOT_ENOUGH_MEMORY;
463 record->wType = rr.type;
464 record->Flags.S.Section = section;
465 record->Flags.S.CharSet = DnsCharSetUtf8;
466 record->dwTtl = rr.ttl;
468 if ((ret = dns_copy_rdata( msg, &rr, record, &dlen )))
470 heap_free( record->pName );
471 heap_free( record );
472 return ret;
474 record->wDataLength = dlen;
475 *recp = record;
477 TRACE( "found %s record in %s section\n",
478 dns_type_to_str( rr.type ), dns_section_to_str( section ) );
479 return ERROR_SUCCESS;
482 #define DEFAULT_TTL 1200
484 static DNS_STATUS dns_do_query_netbios( PCSTR name, DNS_RECORDA **recp )
486 NCB ncb;
487 UCHAR ret;
488 DNS_RRSET rrset;
489 FIND_NAME_BUFFER *buffer;
490 FIND_NAME_HEADER *header;
491 DNS_RECORDA *record = NULL;
492 unsigned int i, len;
493 DNS_STATUS status = ERROR_INVALID_NAME;
495 len = strlen( name );
496 if (len >= NCBNAMSZ) return DNS_ERROR_RCODE_NAME_ERROR;
498 DNS_RRSET_INIT( rrset );
500 memset( &ncb, 0, sizeof(ncb) );
501 ncb.ncb_command = NCBFINDNAME;
503 memset( ncb.ncb_callname, ' ', sizeof(ncb.ncb_callname) );
504 memcpy( ncb.ncb_callname, name, len );
505 ncb.ncb_callname[NCBNAMSZ - 1] = '\0';
507 ret = Netbios( &ncb );
508 if (ret != NRC_GOODRET) return ERROR_INVALID_NAME;
510 header = (FIND_NAME_HEADER *)ncb.ncb_buffer;
511 buffer = (FIND_NAME_BUFFER *)((char *)header + sizeof(FIND_NAME_HEADER));
513 for (i = 0; i < header->node_count; i++)
515 record = heap_alloc_zero( sizeof(DNS_RECORDA) );
516 if (!record)
518 status = ERROR_NOT_ENOUGH_MEMORY;
519 goto exit;
521 else
523 record->pName = dns_strdup_u( name );
524 if (!record->pName)
526 status = ERROR_NOT_ENOUGH_MEMORY;
527 goto exit;
530 record->wType = DNS_TYPE_A;
531 record->Flags.S.Section = DnsSectionAnswer;
532 record->Flags.S.CharSet = DnsCharSetUtf8;
533 record->dwTtl = DEFAULT_TTL;
535 /* FIXME: network byte order? */
536 record->Data.A.IpAddress = *(DWORD *)((char *)buffer[i].destination_addr + 2);
538 DNS_RRSET_ADD( rrset, (DNS_RECORD *)record );
541 status = ERROR_SUCCESS;
543 exit:
544 DNS_RRSET_TERMINATE( rrset );
546 if (status != ERROR_SUCCESS)
547 DnsRecordListFree( rrset.pFirstRR, DnsFreeRecordList );
548 else
549 *recp = (DNS_RECORDA *)rrset.pFirstRR;
551 return status;
554 /* res_init() must have been called before calling these three functions.
556 static DNS_STATUS dns_set_serverlist( const IP4_ARRAY *addrs )
558 int i;
560 if (!addrs || !addrs->AddrCount) return ERROR_SUCCESS;
561 if (addrs->AddrCount > MAXNS)
563 WARN( "too many servers: %d only using the first: %d\n",
564 addrs->AddrCount, MAXNS );
565 _res.nscount = MAXNS;
567 else _res.nscount = addrs->AddrCount;
569 for (i = 0; i < _res.nscount; i++)
570 _res.nsaddr_list[i].sin_addr.s_addr = addrs->AddrArray[i];
572 return ERROR_SUCCESS;
575 static DNS_STATUS dns_get_serverlist( PIP4_ARRAY addrs, PDWORD len )
577 unsigned int size;
578 int i;
580 size = FIELD_OFFSET(IP4_ARRAY, AddrArray[_res.nscount]);
581 if (!addrs || *len < size)
583 *len = size;
584 return ERROR_INSUFFICIENT_BUFFER;
587 addrs->AddrCount = _res.nscount;
589 for (i = 0; i < _res.nscount; i++)
590 addrs->AddrArray[i] = _res.nsaddr_list[i].sin_addr.s_addr;
592 return ERROR_SUCCESS;
595 #define DNS_MAX_PACKET_SIZE 4096
596 static DNS_STATUS dns_do_query( PCSTR name, WORD type, DWORD options, PDNS_RECORDA *result )
598 DNS_STATUS ret = DNS_ERROR_RCODE_NOT_IMPLEMENTED;
600 unsigned int i, num;
601 unsigned char answer[DNS_MAX_PACKET_SIZE];
602 ns_sect sections[] = { ns_s_an, ns_s_ar };
603 ns_msg msg;
605 DNS_RECORDA *record = NULL;
606 DNS_RRSET rrset;
607 int len;
609 DNS_RRSET_INIT( rrset );
611 len = res_query( name, ns_c_in, type, answer, sizeof(answer) );
612 if (len < 0)
614 ret = dns_map_h_errno( h_errno );
615 goto exit;
618 if (dns_ns_initparse( answer, len, &msg ) < 0)
620 ret = DNS_ERROR_BAD_PACKET;
621 goto exit;
624 #define RCODE_MASK 0x0f
625 if ((msg._flags & RCODE_MASK) != ns_r_noerror)
627 ret = dns_map_error( msg._flags & RCODE_MASK );
628 goto exit;
631 for (i = 0; i < ARRAY_SIZE(sections); i++)
633 for (num = 0; num < ns_msg_count( msg, sections[i] ); num++)
635 ret = dns_copy_record( msg, sections[i], num, &record );
636 if (ret != ERROR_SUCCESS) goto exit;
638 DNS_RRSET_ADD( rrset, (DNS_RECORD *)record );
642 exit:
643 DNS_RRSET_TERMINATE( rrset );
645 if (ret != ERROR_SUCCESS)
646 DnsRecordListFree( rrset.pFirstRR, DnsFreeRecordList );
647 else
648 *result = (DNS_RECORDA *)rrset.pFirstRR;
650 return ret;
653 #endif /* HAVE_RESOLV */
655 static const char *debugstr_query_request(const DNS_QUERY_REQUEST *req)
657 if (!req)
658 return "(null)";
660 return wine_dbg_sprintf("{%d %s %s %x%08x %p %d %p %p}", req->Version,
661 debugstr_w(req->QueryName), dns_type_to_str(req->QueryType),
662 (UINT32)(req->QueryOptions>>32u), (UINT32)req->QueryOptions, req->pDnsServerList,
663 req->InterfaceIndex, req->pQueryCompletionCallback, req->pQueryContext);
666 /******************************************************************************
667 * DnsQueryEx [DNSAPI.@]
670 DNS_STATUS WINAPI DnsQueryEx(DNS_QUERY_REQUEST *request, DNS_QUERY_RESULT *result, DNS_QUERY_CANCEL *cancel)
672 FIXME("(%s %p %p)\n", debugstr_query_request(request), result, cancel);
673 return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
676 /******************************************************************************
677 * DnsQuery_A [DNSAPI.@]
680 DNS_STATUS WINAPI DnsQuery_A( PCSTR name, WORD type, DWORD options, PVOID servers,
681 PDNS_RECORDA *result, PVOID *reserved )
683 WCHAR *nameW;
684 DNS_RECORDW *resultW;
685 DNS_STATUS status;
687 TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_a(name), dns_type_to_str( type ),
688 options, servers, result, reserved );
690 if (!name || !result)
691 return ERROR_INVALID_PARAMETER;
693 nameW = dns_strdup_aw( name );
694 if (!nameW) return ERROR_NOT_ENOUGH_MEMORY;
696 status = DnsQuery_W( nameW, type, options, servers, &resultW, reserved );
698 if (status == ERROR_SUCCESS)
700 *result = (DNS_RECORDA *)DnsRecordSetCopyEx(
701 (DNS_RECORD *)resultW, DnsCharSetUnicode, DnsCharSetAnsi );
703 if (!*result) status = ERROR_NOT_ENOUGH_MEMORY;
704 DnsRecordListFree( (DNS_RECORD *)resultW, DnsFreeRecordList );
707 heap_free( nameW );
708 return status;
711 /******************************************************************************
712 * DnsQuery_UTF8 [DNSAPI.@]
715 DNS_STATUS WINAPI DnsQuery_UTF8( PCSTR name, WORD type, DWORD options, PVOID servers,
716 PDNS_RECORDA *result, PVOID *reserved )
718 DNS_STATUS ret = DNS_ERROR_RCODE_NOT_IMPLEMENTED;
719 #ifdef HAVE_RESOLV
721 TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_a(name), dns_type_to_str( type ),
722 options, servers, result, reserved );
724 if (!name || !result)
725 return ERROR_INVALID_PARAMETER;
727 initialise_resolver();
728 _res.options |= dns_map_options( options );
730 if ((ret = dns_set_serverlist( servers ))) return ret;
732 ret = dns_do_query( name, type, options, result );
734 if (ret == DNS_ERROR_RCODE_NAME_ERROR && type == DNS_TYPE_A &&
735 !(options & DNS_QUERY_NO_NETBT))
737 TRACE( "dns lookup failed, trying netbios query\n" );
738 ret = dns_do_query_netbios( name, result );
741 #endif
742 return ret;
745 /******************************************************************************
746 * DnsQuery_W [DNSAPI.@]
749 DNS_STATUS WINAPI DnsQuery_W( PCWSTR name, WORD type, DWORD options, PVOID servers,
750 PDNS_RECORDW *result, PVOID *reserved )
752 char *nameU;
753 DNS_RECORDA *resultA;
754 DNS_STATUS status;
756 TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_w(name), dns_type_to_str( type ),
757 options, servers, result, reserved );
759 if (!name || !result)
760 return ERROR_INVALID_PARAMETER;
762 nameU = dns_strdup_wu( name );
763 if (!nameU) return ERROR_NOT_ENOUGH_MEMORY;
765 status = DnsQuery_UTF8( nameU, type, options, servers, &resultA, reserved );
767 if (status == ERROR_SUCCESS)
769 *result = (DNS_RECORDW *)DnsRecordSetCopyEx(
770 (DNS_RECORD *)resultA, DnsCharSetUtf8, DnsCharSetUnicode );
772 if (!*result) status = ERROR_NOT_ENOUGH_MEMORY;
773 DnsRecordListFree( (DNS_RECORD *)resultA, DnsFreeRecordList );
776 heap_free( nameU );
777 return status;
780 static DNS_STATUS dns_get_hostname_a( COMPUTER_NAME_FORMAT format,
781 PSTR buffer, PDWORD len )
783 char name[256];
784 DWORD size = ARRAY_SIZE(name);
786 if (!GetComputerNameExA( format, name, &size ))
787 return DNS_ERROR_NAME_DOES_NOT_EXIST;
789 if (!buffer || (size = lstrlenA( name ) + 1) > *len)
791 *len = size;
792 return ERROR_INSUFFICIENT_BUFFER;
795 lstrcpyA( buffer, name );
796 return ERROR_SUCCESS;
799 static DNS_STATUS dns_get_hostname_w( COMPUTER_NAME_FORMAT format,
800 PWSTR buffer, PDWORD len )
802 WCHAR name[256];
803 DWORD size = ARRAY_SIZE(name);
805 if (!GetComputerNameExW( format, name, &size ))
806 return DNS_ERROR_NAME_DOES_NOT_EXIST;
808 if (!buffer || (size = lstrlenW( name ) + 1) > *len)
810 *len = size;
811 return ERROR_INSUFFICIENT_BUFFER;
814 lstrcpyW( buffer, name );
815 return ERROR_SUCCESS;
818 /******************************************************************************
819 * DnsQueryConfig [DNSAPI.@]
822 DNS_STATUS WINAPI DnsQueryConfig( DNS_CONFIG_TYPE config, DWORD flag, PCWSTR adapter,
823 PVOID reserved, PVOID buffer, PDWORD len )
825 DNS_STATUS ret = ERROR_INVALID_PARAMETER;
827 TRACE( "(%d,0x%08x,%s,%p,%p,%p)\n", config, flag, debugstr_w(adapter),
828 reserved, buffer, len );
830 if (!len) return ERROR_INVALID_PARAMETER;
832 switch (config)
834 case DnsConfigDnsServerList:
836 #ifdef HAVE_RESOLV
837 initialise_resolver();
838 ret = dns_get_serverlist( buffer, len );
839 break;
840 #else
841 WARN( "compiled without resolver support\n" );
842 break;
843 #endif
845 case DnsConfigHostName_A:
846 case DnsConfigHostName_UTF8:
847 return dns_get_hostname_a( ComputerNameDnsHostname, buffer, len );
849 case DnsConfigFullHostName_A:
850 case DnsConfigFullHostName_UTF8:
851 return dns_get_hostname_a( ComputerNameDnsFullyQualified, buffer, len );
853 case DnsConfigPrimaryDomainName_A:
854 case DnsConfigPrimaryDomainName_UTF8:
855 return dns_get_hostname_a( ComputerNameDnsDomain, buffer, len );
857 case DnsConfigHostName_W:
858 return dns_get_hostname_w( ComputerNameDnsHostname, buffer, len );
860 case DnsConfigFullHostName_W:
861 return dns_get_hostname_w( ComputerNameDnsFullyQualified, buffer, len );
863 case DnsConfigPrimaryDomainName_W:
864 return dns_get_hostname_w( ComputerNameDnsDomain, buffer, len );
866 case DnsConfigAdapterDomainName_A:
867 case DnsConfigAdapterDomainName_W:
868 case DnsConfigAdapterDomainName_UTF8:
869 case DnsConfigSearchList:
870 case DnsConfigAdapterInfo:
871 case DnsConfigPrimaryHostNameRegistrationEnabled:
872 case DnsConfigAdapterHostNameRegistrationEnabled:
873 case DnsConfigAddressRegistrationMaxCount:
874 FIXME( "unimplemented config type %d\n", config );
875 break;
877 default:
878 WARN( "unknown config type: %d\n", config );
879 break;
881 return ret;