shell32: Use S_OK as successful return code name.
[wine/multimedia.git] / dlls / dnsapi / query.c
blob8de33e6ec8d474961abd5fde1d1a09e7d33dc975
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 <sys/types.h>
29 #ifdef HAVE_NETINET_IN_H
30 # include <netinet/in.h>
31 #endif
32 #ifdef HAVE_ARPA_NAMESER_H
33 # include <arpa/nameser.h>
34 #endif
35 #ifdef HAVE_RESOLV_H
36 # include <resolv.h>
37 #endif
38 #ifdef HAVE_NETDB_H
39 # include <netdb.h>
40 #endif
42 #include "windef.h"
43 #include "winbase.h"
44 #include "winerror.h"
45 #include "winnls.h"
46 #include "windns.h"
47 #include "nb30.h"
49 #include "dnsapi.h"
51 WINE_DEFAULT_DEBUG_CHANNEL(dnsapi);
53 #ifdef HAVE_RESOLV
55 /* call res_init() just once because of a bug in Mac OS X 10.4 */
56 /* call once per thread on systems that have per-thread _res */
57 static void initialise_resolver( void )
59 if ((_res.options & RES_INIT) == 0)
60 res_init();
63 static const char *dns_section_to_str( ns_sect section )
65 switch (section)
67 case ns_s_qd: return "Question";
68 case ns_s_an: return "Answer";
69 case ns_s_ns: return "Authority";
70 case ns_s_ar: return "Additional";
71 default:
73 static char tmp[5];
74 FIXME( "unknown section: 0x%02x\n", section );
75 sprintf( tmp, "0x%02x", section );
76 return tmp;
81 static unsigned long dns_map_options( DWORD options )
83 unsigned long ret = 0;
85 if (options == DNS_QUERY_STANDARD)
86 return RES_DEFAULT;
88 if (options & DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE)
89 ret |= RES_IGNTC;
90 if (options & DNS_QUERY_USE_TCP_ONLY)
91 ret |= RES_USEVC;
92 if (options & DNS_QUERY_NO_RECURSION)
93 ret &= ~RES_RECURSE;
94 if (options & DNS_QUERY_NO_LOCAL_NAME)
95 ret &= ~RES_DNSRCH;
96 if (options & DNS_QUERY_NO_HOSTS_FILE)
97 ret |= RES_NOALIASES;
98 if (options & DNS_QUERY_TREAT_AS_FQDN)
99 ret &= ~RES_DEFNAMES;
101 if (options & DNS_QUERY_DONT_RESET_TTL_VALUES)
102 FIXME( "option DNS_QUERY_DONT_RESET_TTL_VALUES not implemented\n" );
103 if (options & DNS_QUERY_RESERVED)
104 FIXME( "option DNS_QUERY_RESERVED not implemented\n" );
105 if (options & DNS_QUERY_WIRE_ONLY)
106 FIXME( "option DNS_QUERY_WIRE_ONLY not implemented\n" );
107 if (options & DNS_QUERY_NO_WIRE_QUERY)
108 FIXME( "option DNS_QUERY_NO_WIRE_QUERY not implemented\n" );
109 if (options & DNS_QUERY_BYPASS_CACHE)
110 FIXME( "option DNS_QUERY_BYPASS_CACHE not implemented\n" );
111 if (options & DNS_QUERY_RETURN_MESSAGE)
112 FIXME( "option DNS_QUERY_RETURN_MESSAGE not implemented\n" );
114 if (options & DNS_QUERY_NO_NETBT)
115 TRACE( "netbios query disabled\n" );
117 return ret;
120 static DNS_STATUS dns_map_error( int error )
122 switch (error)
124 case ns_r_noerror: return ERROR_SUCCESS;
125 case ns_r_formerr: return DNS_ERROR_RCODE_FORMAT_ERROR;
126 case ns_r_servfail: return DNS_ERROR_RCODE_SERVER_FAILURE;
127 case ns_r_nxdomain: return DNS_ERROR_RCODE_NAME_ERROR;
128 case ns_r_notimpl: return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
129 case ns_r_refused: return DNS_ERROR_RCODE_REFUSED;
130 case ns_r_yxdomain: return DNS_ERROR_RCODE_YXDOMAIN;
131 case ns_r_yxrrset: return DNS_ERROR_RCODE_YXRRSET;
132 case ns_r_nxrrset: return DNS_ERROR_RCODE_NXRRSET;
133 case ns_r_notauth: return DNS_ERROR_RCODE_NOTAUTH;
134 case ns_r_notzone: return DNS_ERROR_RCODE_NOTZONE;
135 default:
136 FIXME( "unmapped error code: %d\n", error );
137 return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
141 static DNS_STATUS dns_map_h_errno( int error )
143 switch (error)
145 case NO_DATA:
146 case HOST_NOT_FOUND: return DNS_ERROR_RCODE_NAME_ERROR;
147 case TRY_AGAIN: return DNS_ERROR_RCODE_SERVER_FAILURE;
148 case NO_RECOVERY: return DNS_ERROR_RCODE_REFUSED;
149 case NETDB_INTERNAL: return DNS_ERROR_RCODE;
150 default:
151 FIXME( "unmapped error code: %d\n", error );
152 return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
156 static char *dns_dname_from_msg( ns_msg msg, const unsigned char *pos )
158 int len;
159 char *str, dname[NS_MAXDNAME] = ".";
161 /* returns *compressed* length, ignore it */
162 len = dns_ns_name_uncompress( ns_msg_base( msg ), ns_msg_end( msg ),
163 pos, dname, sizeof(dname) );
165 len = strlen( dname );
166 str = heap_alloc( len + 1 );
167 if (str) strcpy( str, dname );
168 return str;
171 static char *dns_str_from_rdata( const unsigned char *rdata )
173 char *str;
174 unsigned int len = rdata[0];
176 str = heap_alloc( len + 1 );
177 if (str)
179 memcpy( str, ++rdata, len );
180 str[len] = '\0';
182 return str;
185 static unsigned int dns_get_record_size( const ns_rr *rr )
187 const unsigned char *pos = rr->rdata;
188 unsigned int num = 0, size = sizeof(DNS_RECORDA);
190 switch (rr->type)
192 case ns_t_key:
194 pos += sizeof(WORD) + sizeof(BYTE) + sizeof(BYTE);
195 size += rr->rdata + rr->rdlength - pos - 1;
196 break;
198 case ns_t_sig:
200 pos += sizeof(PCHAR) + sizeof(WORD) + 2 * sizeof(BYTE);
201 pos += 3 * sizeof(DWORD) + 2 * sizeof(WORD);
202 size += rr->rdata + rr->rdlength - pos - 1;
203 break;
205 case ns_t_hinfo:
206 case ns_t_isdn:
207 case ns_t_txt:
208 case ns_t_x25:
210 while (pos[0] && pos < rr->rdata + rr->rdlength)
212 num++;
213 pos += pos[0] + 1;
215 size += (num - 1) * sizeof(PCHAR);
216 break;
218 case ns_t_null:
220 size += rr->rdlength - 1;
221 break;
223 case ns_t_nxt:
224 case ns_t_wks:
225 case 0xff01: /* WINS */
227 FIXME( "unhandled type: %s\n", dns_type_to_str( rr->type ) );
228 break;
230 default:
231 break;
233 return size;
236 static DNS_STATUS dns_copy_rdata( ns_msg msg, const ns_rr *rr, DNS_RECORDA *r, WORD *dlen )
238 DNS_STATUS ret = ERROR_SUCCESS;
239 const unsigned char *pos = rr->rdata;
240 unsigned int i, size;
242 switch (rr->type)
244 case ns_t_a:
246 r->Data.A.IpAddress = *(const DWORD *)pos;
247 *dlen = sizeof(DNS_A_DATA);
248 break;
250 case ns_t_aaaa:
252 for (i = 0; i < sizeof(IP6_ADDRESS)/sizeof(DWORD); i++)
254 r->Data.AAAA.Ip6Address.IP6Dword[i] = *(const DWORD *)pos;
255 pos += sizeof(DWORD);
258 *dlen = sizeof(DNS_AAAA_DATA);
259 break;
261 case ns_t_key:
263 /* FIXME: byte order? */
264 r->Data.KEY.wFlags = *(const WORD *)pos; pos += sizeof(WORD);
265 r->Data.KEY.chProtocol = *pos++;
266 r->Data.KEY.chAlgorithm = *pos++;
268 size = rr->rdata + rr->rdlength - pos;
270 for (i = 0; i < size; i++)
271 r->Data.KEY.Key[i] = *pos++;
273 *dlen = sizeof(DNS_KEY_DATA) + (size - 1) * sizeof(BYTE);
274 break;
276 case ns_t_rp:
277 case ns_t_minfo:
279 r->Data.MINFO.pNameMailbox = dns_dname_from_msg( msg, pos );
280 if (!r->Data.MINFO.pNameMailbox) return ERROR_NOT_ENOUGH_MEMORY;
282 if (dns_ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
283 return DNS_ERROR_BAD_PACKET;
285 r->Data.MINFO.pNameErrorsMailbox = dns_dname_from_msg( msg, pos );
286 if (!r->Data.MINFO.pNameErrorsMailbox)
288 heap_free( r->Data.MINFO.pNameMailbox );
289 return ERROR_NOT_ENOUGH_MEMORY;
292 *dlen = sizeof(DNS_MINFO_DATAA);
293 break;
295 case ns_t_afsdb:
296 case ns_t_rt:
297 case ns_t_mx:
299 r->Data.MX.wPreference = ntohs( *(const WORD *)pos );
300 r->Data.MX.pNameExchange = dns_dname_from_msg( msg, pos + sizeof(WORD) );
301 if (!r->Data.MX.pNameExchange) return ERROR_NOT_ENOUGH_MEMORY;
303 *dlen = sizeof(DNS_MX_DATAA);
304 break;
306 case ns_t_null:
308 r->Data.Null.dwByteCount = rr->rdlength;
309 memcpy( r->Data.Null.Data, rr->rdata, rr->rdlength );
311 *dlen = sizeof(DNS_NULL_DATA) + rr->rdlength - 1;
312 break;
314 case ns_t_cname:
315 case ns_t_ns:
316 case ns_t_mb:
317 case ns_t_md:
318 case ns_t_mf:
319 case ns_t_mg:
320 case ns_t_mr:
321 case ns_t_ptr:
323 r->Data.PTR.pNameHost = dns_dname_from_msg( msg, pos );
324 if (!r->Data.PTR.pNameHost) return ERROR_NOT_ENOUGH_MEMORY;
326 *dlen = sizeof(DNS_PTR_DATAA);
327 break;
329 case ns_t_sig:
331 r->Data.SIG.pNameSigner = dns_dname_from_msg( msg, pos );
332 if (!r->Data.SIG.pNameSigner) return ERROR_NOT_ENOUGH_MEMORY;
334 if (dns_ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
335 return DNS_ERROR_BAD_PACKET;
337 /* FIXME: byte order? */
338 r->Data.SIG.wTypeCovered = *(const WORD *)pos; pos += sizeof(WORD);
339 r->Data.SIG.chAlgorithm = *pos++;
340 r->Data.SIG.chLabelCount = *pos++;
341 r->Data.SIG.dwOriginalTtl = *(const DWORD *)pos; pos += sizeof(DWORD);
342 r->Data.SIG.dwExpiration = *(const DWORD *)pos; pos += sizeof(DWORD);
343 r->Data.SIG.dwTimeSigned = *(const DWORD *)pos; pos += sizeof(DWORD);
344 r->Data.SIG.wKeyTag = *(const WORD *)pos;
346 size = rr->rdata + rr->rdlength - pos;
348 for (i = 0; i < size; i++)
349 r->Data.SIG.Signature[i] = *pos++;
351 *dlen = sizeof(DNS_SIG_DATAA) + (size - 1) * sizeof(BYTE);
352 break;
354 case ns_t_soa:
356 r->Data.SOA.pNamePrimaryServer = dns_dname_from_msg( msg, pos );
357 if (!r->Data.SOA.pNamePrimaryServer) return ERROR_NOT_ENOUGH_MEMORY;
359 if (dns_ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
360 return DNS_ERROR_BAD_PACKET;
362 r->Data.SOA.pNameAdministrator = dns_dname_from_msg( msg, pos );
363 if (!r->Data.SOA.pNameAdministrator)
365 heap_free( r->Data.SOA.pNamePrimaryServer );
366 return ERROR_NOT_ENOUGH_MEMORY;
369 if (dns_ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
370 return DNS_ERROR_BAD_PACKET;
372 r->Data.SOA.dwSerialNo = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
373 r->Data.SOA.dwRefresh = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
374 r->Data.SOA.dwRetry = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
375 r->Data.SOA.dwExpire = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
376 r->Data.SOA.dwDefaultTtl = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
378 *dlen = sizeof(DNS_SOA_DATAA);
379 break;
381 case ns_t_srv:
383 r->Data.SRV.wPriority = ntohs( *(const WORD *)pos ); pos += sizeof(WORD);
384 r->Data.SRV.wWeight = ntohs( *(const WORD *)pos ); pos += sizeof(WORD);
385 r->Data.SRV.wPort = ntohs( *(const WORD *)pos ); pos += sizeof(WORD);
387 r->Data.SRV.pNameTarget = dns_dname_from_msg( msg, pos );
388 if (!r->Data.SRV.pNameTarget) return ERROR_NOT_ENOUGH_MEMORY;
390 *dlen = sizeof(DNS_SRV_DATAA);
391 break;
393 case ns_t_hinfo:
394 case ns_t_isdn:
395 case ns_t_x25:
396 case ns_t_txt:
398 i = 0;
399 while (pos[0] && pos < rr->rdata + rr->rdlength)
401 r->Data.TXT.pStringArray[i] = dns_str_from_rdata( pos );
402 if (!r->Data.TXT.pStringArray[i])
404 while (i > 0) heap_free( r->Data.TXT.pStringArray[--i] );
405 return ERROR_NOT_ENOUGH_MEMORY;
407 i++;
408 pos += pos[0] + 1;
410 r->Data.TXT.dwStringCount = i;
411 *dlen = sizeof(DNS_TXT_DATAA) + (i - 1) * sizeof(PCHAR);
412 break;
414 case ns_t_atma:
415 case ns_t_loc:
416 case ns_t_nxt:
417 case ns_t_tsig:
418 case ns_t_wks:
419 case 0x00f9: /* TKEY */
420 case 0xff01: /* WINS */
421 case 0xff02: /* WINSR */
422 default:
423 FIXME( "unhandled type: %s\n", dns_type_to_str( rr->type ) );
424 return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
427 return ret;
430 static DNS_STATUS dns_copy_record( ns_msg msg, ns_sect section,
431 unsigned short num, DNS_RECORDA **recp )
433 DNS_STATUS ret;
434 DNS_RECORDA *record;
435 WORD dlen;
436 ns_rr rr;
438 if (dns_ns_parserr( &msg, section, num, &rr ) < 0)
439 return DNS_ERROR_BAD_PACKET;
441 if (!(record = heap_alloc_zero( dns_get_record_size( &rr ) )))
442 return ERROR_NOT_ENOUGH_MEMORY;
444 record->pName = dns_strdup_u( rr.name );
445 if (!record->pName)
447 heap_free( record );
448 return ERROR_NOT_ENOUGH_MEMORY;
451 record->wType = rr.type;
452 record->Flags.S.Section = section;
453 record->Flags.S.CharSet = DnsCharSetUtf8;
454 record->dwTtl = rr.ttl;
456 if ((ret = dns_copy_rdata( msg, &rr, record, &dlen )))
458 heap_free( record->pName );
459 heap_free( record );
460 return ret;
462 record->wDataLength = dlen;
463 *recp = record;
465 TRACE( "found %s record in %s section\n",
466 dns_type_to_str( rr.type ), dns_section_to_str( section ) );
467 return ERROR_SUCCESS;
470 #define DEFAULT_TTL 1200
472 static DNS_STATUS dns_do_query_netbios( PCSTR name, DNS_RECORDA **recp )
474 NCB ncb;
475 UCHAR ret;
476 DNS_RRSET rrset;
477 FIND_NAME_BUFFER *buffer;
478 FIND_NAME_HEADER *header;
479 DNS_RECORDA *record = NULL;
480 unsigned int i, len;
481 DNS_STATUS status = ERROR_INVALID_NAME;
483 len = strlen( name );
484 if (len >= NCBNAMSZ) return DNS_ERROR_RCODE_NAME_ERROR;
486 DNS_RRSET_INIT( rrset );
488 memset( &ncb, 0, sizeof(ncb) );
489 ncb.ncb_command = NCBFINDNAME;
491 memset( ncb.ncb_callname, ' ', sizeof(ncb.ncb_callname) );
492 memcpy( ncb.ncb_callname, name, len );
493 ncb.ncb_callname[NCBNAMSZ - 1] = '\0';
495 ret = Netbios( &ncb );
496 if (ret != NRC_GOODRET) return ERROR_INVALID_NAME;
498 header = (FIND_NAME_HEADER *)ncb.ncb_buffer;
499 buffer = (FIND_NAME_BUFFER *)((char *)header + sizeof(FIND_NAME_HEADER));
501 for (i = 0; i < header->node_count; i++)
503 record = heap_alloc_zero( sizeof(DNS_RECORDA) );
504 if (!record)
506 status = ERROR_NOT_ENOUGH_MEMORY;
507 goto exit;
509 else
511 record->pName = dns_strdup_u( name );
512 if (!record->pName)
514 status = ERROR_NOT_ENOUGH_MEMORY;
515 goto exit;
518 record->wType = DNS_TYPE_A;
519 record->Flags.S.Section = DnsSectionAnswer;
520 record->Flags.S.CharSet = DnsCharSetUtf8;
521 record->dwTtl = DEFAULT_TTL;
523 /* FIXME: network byte order? */
524 record->Data.A.IpAddress = *(DWORD *)((char *)buffer[i].destination_addr + 2);
526 DNS_RRSET_ADD( rrset, (DNS_RECORD *)record );
529 status = ERROR_SUCCESS;
531 exit:
532 DNS_RRSET_TERMINATE( rrset );
534 if (status != ERROR_SUCCESS)
535 DnsRecordListFree( rrset.pFirstRR, DnsFreeRecordList );
536 else
537 *recp = (DNS_RECORDA *)rrset.pFirstRR;
539 return status;
542 /* res_init() must have been called before calling these three functions.
544 static DNS_STATUS dns_set_serverlist( const IP4_ARRAY *addrs )
546 int i;
548 if (addrs->AddrCount > MAXNS)
550 WARN( "too many servers: %d only using the first: %d\n",
551 addrs->AddrCount, MAXNS );
552 _res.nscount = MAXNS;
554 else _res.nscount = addrs->AddrCount;
556 for (i = 0; i < _res.nscount; i++)
557 _res.nsaddr_list[i].sin_addr.s_addr = addrs->AddrArray[i];
559 return ERROR_SUCCESS;
562 static DNS_STATUS dns_get_serverlist( PIP4_ARRAY addrs, PDWORD len )
564 unsigned int size;
565 int i;
567 size = sizeof(IP4_ARRAY) + sizeof(IP4_ADDRESS) * (_res.nscount - 1);
568 if (!addrs || *len < size)
570 *len = size;
571 return ERROR_INSUFFICIENT_BUFFER;
574 addrs->AddrCount = _res.nscount;
576 for (i = 0; i < _res.nscount; i++)
577 addrs->AddrArray[i] = _res.nsaddr_list[i].sin_addr.s_addr;
579 return ERROR_SUCCESS;
582 static DNS_STATUS dns_do_query( PCSTR name, WORD type, DWORD options,
583 PDNS_RECORDA *result )
585 DNS_STATUS ret = DNS_ERROR_RCODE_NOT_IMPLEMENTED;
587 unsigned int i, num;
588 unsigned char answer[NS_PACKETSZ];
589 ns_sect sections[] = { ns_s_an, ns_s_ar };
590 ns_msg msg;
592 DNS_RECORDA *record = NULL;
593 DNS_RRSET rrset;
594 int len;
596 DNS_RRSET_INIT( rrset );
598 len = res_query( name, ns_c_in, type, answer, sizeof(answer) );
599 if (len < 0)
601 ret = dns_map_h_errno( h_errno );
602 goto exit;
605 if (dns_ns_initparse( answer, len, &msg ) < 0)
607 ret = DNS_ERROR_BAD_PACKET;
608 goto exit;
611 #define RCODE_MASK 0x0f
612 if ((msg._flags & RCODE_MASK) != ns_r_noerror)
614 ret = dns_map_error( msg._flags & RCODE_MASK );
615 goto exit;
618 for (i = 0; i < sizeof(sections)/sizeof(sections[0]); i++)
620 for (num = 0; num < ns_msg_count( msg, sections[i] ); num++)
622 ret = dns_copy_record( msg, sections[i], num, &record );
623 if (ret != ERROR_SUCCESS) goto exit;
625 DNS_RRSET_ADD( rrset, (DNS_RECORD *)record );
629 exit:
630 DNS_RRSET_TERMINATE( rrset );
632 if (ret != ERROR_SUCCESS)
633 DnsRecordListFree( rrset.pFirstRR, DnsFreeRecordList );
634 else
635 *result = (DNS_RECORDA *)rrset.pFirstRR;
637 return ret;
640 #endif /* HAVE_RESOLV */
642 /******************************************************************************
643 * DnsQuery_A [DNSAPI.@]
646 DNS_STATUS WINAPI DnsQuery_A( PCSTR name, WORD type, DWORD options, PVOID servers,
647 PDNS_RECORDA *result, PVOID *reserved )
649 WCHAR *nameW;
650 DNS_RECORDW *resultW;
651 DNS_STATUS status;
653 TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_a(name), dns_type_to_str( type ),
654 options, servers, result, reserved );
656 if (!name || !result)
657 return ERROR_INVALID_PARAMETER;
659 nameW = dns_strdup_aw( name );
660 if (!nameW) return ERROR_NOT_ENOUGH_MEMORY;
662 status = DnsQuery_W( nameW, type, options, servers, &resultW, reserved );
664 if (status == ERROR_SUCCESS)
666 *result = (DNS_RECORDA *)DnsRecordSetCopyEx(
667 (DNS_RECORD *)resultW, DnsCharSetUnicode, DnsCharSetAnsi );
669 if (!*result) status = ERROR_NOT_ENOUGH_MEMORY;
670 DnsRecordListFree( (DNS_RECORD *)resultW, DnsFreeRecordList );
673 heap_free( nameW );
674 return status;
677 /******************************************************************************
678 * DnsQuery_UTF8 [DNSAPI.@]
681 DNS_STATUS WINAPI DnsQuery_UTF8( PCSTR name, WORD type, DWORD options, PVOID servers,
682 PDNS_RECORDA *result, PVOID *reserved )
684 DNS_STATUS ret = DNS_ERROR_RCODE_NOT_IMPLEMENTED;
685 #ifdef HAVE_RESOLV
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 initialise_resolver();
694 _res.options |= dns_map_options( options );
696 if (servers && (ret = dns_set_serverlist( servers )))
697 return ret;
699 ret = dns_do_query( name, type, options, result );
701 if (ret == DNS_ERROR_RCODE_NAME_ERROR && type == DNS_TYPE_A &&
702 !(options & DNS_QUERY_NO_NETBT))
704 TRACE( "dns lookup failed, trying netbios query\n" );
705 ret = dns_do_query_netbios( name, result );
708 #endif
709 return ret;
712 /******************************************************************************
713 * DnsQuery_W [DNSAPI.@]
716 DNS_STATUS WINAPI DnsQuery_W( PCWSTR name, WORD type, DWORD options, PVOID servers,
717 PDNS_RECORDW *result, PVOID *reserved )
719 char *nameU;
720 DNS_RECORDA *resultA;
721 DNS_STATUS status;
723 TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_w(name), dns_type_to_str( type ),
724 options, servers, result, reserved );
726 if (!name || !result)
727 return ERROR_INVALID_PARAMETER;
729 nameU = dns_strdup_wu( name );
730 if (!nameU) return ERROR_NOT_ENOUGH_MEMORY;
732 status = DnsQuery_UTF8( nameU, type, options, servers, &resultA, reserved );
734 if (status == ERROR_SUCCESS)
736 *result = (DNS_RECORDW *)DnsRecordSetCopyEx(
737 (DNS_RECORD *)resultA, DnsCharSetUtf8, DnsCharSetUnicode );
739 if (!*result) status = ERROR_NOT_ENOUGH_MEMORY;
740 DnsRecordListFree( (DNS_RECORD *)resultA, DnsFreeRecordList );
743 heap_free( nameU );
744 return status;
747 static DNS_STATUS dns_get_hostname_a( COMPUTER_NAME_FORMAT format,
748 PSTR buffer, PDWORD len )
750 char name[256];
751 DWORD size = sizeof(name)/sizeof(name[0]);
753 if (!GetComputerNameExA( format, name, &size ))
754 return DNS_ERROR_NAME_DOES_NOT_EXIST;
756 if (!buffer || (size = lstrlenA( name ) + 1) > *len)
758 *len = size;
759 return ERROR_INSUFFICIENT_BUFFER;
762 lstrcpyA( buffer, name );
763 return ERROR_SUCCESS;
766 static DNS_STATUS dns_get_hostname_w( COMPUTER_NAME_FORMAT format,
767 PWSTR buffer, PDWORD len )
769 WCHAR name[256];
770 DWORD size = sizeof(name)/sizeof(name[0]);
772 if (!GetComputerNameExW( format, name, &size ))
773 return DNS_ERROR_NAME_DOES_NOT_EXIST;
775 if (!buffer || (size = lstrlenW( name ) + 1) > *len)
777 *len = size;
778 return ERROR_INSUFFICIENT_BUFFER;
781 lstrcpyW( buffer, name );
782 return ERROR_SUCCESS;
785 /******************************************************************************
786 * DnsQueryConfig [DNSAPI.@]
789 DNS_STATUS WINAPI DnsQueryConfig( DNS_CONFIG_TYPE config, DWORD flag, PCWSTR adapter,
790 PVOID reserved, PVOID buffer, PDWORD len )
792 DNS_STATUS ret = ERROR_INVALID_PARAMETER;
794 TRACE( "(%d,0x%08x,%s,%p,%p,%p)\n", config, flag, debugstr_w(adapter),
795 reserved, buffer, len );
797 if (!len) return ERROR_INVALID_PARAMETER;
799 switch (config)
801 case DnsConfigDnsServerList:
803 #ifdef HAVE_RESOLV
804 initialise_resolver();
805 ret = dns_get_serverlist( buffer, len );
806 break;
807 #else
808 WARN( "compiled without resolver support\n" );
809 break;
810 #endif
812 case DnsConfigHostName_A:
813 case DnsConfigHostName_UTF8:
814 return dns_get_hostname_a( ComputerNameDnsHostname, buffer, len );
816 case DnsConfigFullHostName_A:
817 case DnsConfigFullHostName_UTF8:
818 return dns_get_hostname_a( ComputerNameDnsFullyQualified, buffer, len );
820 case DnsConfigPrimaryDomainName_A:
821 case DnsConfigPrimaryDomainName_UTF8:
822 return dns_get_hostname_a( ComputerNameDnsDomain, buffer, len );
824 case DnsConfigHostName_W:
825 return dns_get_hostname_w( ComputerNameDnsHostname, buffer, len );
827 case DnsConfigFullHostName_W:
828 return dns_get_hostname_w( ComputerNameDnsFullyQualified, buffer, len );
830 case DnsConfigPrimaryDomainName_W:
831 return dns_get_hostname_w( ComputerNameDnsDomain, buffer, len );
833 case DnsConfigAdapterDomainName_A:
834 case DnsConfigAdapterDomainName_W:
835 case DnsConfigAdapterDomainName_UTF8:
836 case DnsConfigSearchList:
837 case DnsConfigAdapterInfo:
838 case DnsConfigPrimaryHostNameRegistrationEnabled:
839 case DnsConfigAdapterHostNameRegistrationEnabled:
840 case DnsConfigAddressRegistrationMaxCount:
841 FIXME( "unimplemented config type %d\n", config );
842 break;
844 default:
845 WARN( "unknown config type: %d\n", config );
846 break;
848 return ret;