d3drm/tests: Spelling fixes for a couple of ok() messages.
[wine.git] / dlls / dnsapi / query.c
bloba66db37e9e52e1176adaef1bef45fa46c68a21f3
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[5];
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:
222 size += rr->rdlength - 1;
223 break;
225 case ns_t_nxt:
226 case ns_t_wks:
227 case 0xff01: /* WINS */
229 FIXME( "unhandled type: %s\n", dns_type_to_str( rr->type ) );
230 break;
232 default:
233 break;
235 return size;
238 static DNS_STATUS dns_copy_rdata( ns_msg msg, const ns_rr *rr, DNS_RECORDA *r, WORD *dlen )
240 DNS_STATUS ret = ERROR_SUCCESS;
241 const unsigned char *pos = rr->rdata;
242 unsigned int i, size;
244 switch (rr->type)
246 case ns_t_a:
248 r->Data.A.IpAddress = *(const DWORD *)pos;
249 *dlen = sizeof(DNS_A_DATA);
250 break;
252 case ns_t_aaaa:
254 for (i = 0; i < sizeof(IP6_ADDRESS)/sizeof(DWORD); i++)
256 r->Data.AAAA.Ip6Address.IP6Dword[i] = *(const DWORD *)pos;
257 pos += sizeof(DWORD);
260 *dlen = sizeof(DNS_AAAA_DATA);
261 break;
263 case ns_t_key:
265 /* FIXME: byte order? */
266 r->Data.KEY.wFlags = *(const WORD *)pos; pos += sizeof(WORD);
267 r->Data.KEY.chProtocol = *pos++;
268 r->Data.KEY.chAlgorithm = *pos++;
270 size = rr->rdata + rr->rdlength - pos;
272 for (i = 0; i < size; i++)
273 r->Data.KEY.Key[i] = *pos++;
275 *dlen = sizeof(DNS_KEY_DATA) + (size - 1) * sizeof(BYTE);
276 break;
278 case ns_t_rp:
279 case ns_t_minfo:
281 r->Data.MINFO.pNameMailbox = dns_dname_from_msg( msg, pos );
282 if (!r->Data.MINFO.pNameMailbox) return ERROR_NOT_ENOUGH_MEMORY;
284 if (dns_ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
285 return DNS_ERROR_BAD_PACKET;
287 r->Data.MINFO.pNameErrorsMailbox = dns_dname_from_msg( msg, pos );
288 if (!r->Data.MINFO.pNameErrorsMailbox)
290 heap_free( r->Data.MINFO.pNameMailbox );
291 return ERROR_NOT_ENOUGH_MEMORY;
294 *dlen = sizeof(DNS_MINFO_DATAA);
295 break;
297 case ns_t_afsdb:
298 case ns_t_rt:
299 case ns_t_mx:
301 r->Data.MX.wPreference = ntohs( *(const WORD *)pos );
302 r->Data.MX.pNameExchange = dns_dname_from_msg( msg, pos + sizeof(WORD) );
303 if (!r->Data.MX.pNameExchange) return ERROR_NOT_ENOUGH_MEMORY;
305 *dlen = sizeof(DNS_MX_DATAA);
306 break;
308 case ns_t_null:
310 r->Data.Null.dwByteCount = rr->rdlength;
311 memcpy( r->Data.Null.Data, rr->rdata, rr->rdlength );
313 *dlen = sizeof(DNS_NULL_DATA) + rr->rdlength - 1;
314 break;
316 case ns_t_cname:
317 case ns_t_ns:
318 case ns_t_mb:
319 case ns_t_md:
320 case ns_t_mf:
321 case ns_t_mg:
322 case ns_t_mr:
323 case ns_t_ptr:
325 r->Data.PTR.pNameHost = dns_dname_from_msg( msg, pos );
326 if (!r->Data.PTR.pNameHost) return ERROR_NOT_ENOUGH_MEMORY;
328 *dlen = sizeof(DNS_PTR_DATAA);
329 break;
331 case ns_t_sig:
333 r->Data.SIG.pNameSigner = dns_dname_from_msg( msg, pos );
334 if (!r->Data.SIG.pNameSigner) return ERROR_NOT_ENOUGH_MEMORY;
336 if (dns_ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
337 return DNS_ERROR_BAD_PACKET;
339 /* FIXME: byte order? */
340 r->Data.SIG.wTypeCovered = *(const WORD *)pos; pos += sizeof(WORD);
341 r->Data.SIG.chAlgorithm = *pos++;
342 r->Data.SIG.chLabelCount = *pos++;
343 r->Data.SIG.dwOriginalTtl = *(const DWORD *)pos; pos += sizeof(DWORD);
344 r->Data.SIG.dwExpiration = *(const DWORD *)pos; pos += sizeof(DWORD);
345 r->Data.SIG.dwTimeSigned = *(const DWORD *)pos; pos += sizeof(DWORD);
346 r->Data.SIG.wKeyTag = *(const WORD *)pos;
348 size = rr->rdata + rr->rdlength - pos;
350 for (i = 0; i < size; i++)
351 r->Data.SIG.Signature[i] = *pos++;
353 *dlen = sizeof(DNS_SIG_DATAA) + (size - 1) * sizeof(BYTE);
354 break;
356 case ns_t_soa:
358 r->Data.SOA.pNamePrimaryServer = dns_dname_from_msg( msg, pos );
359 if (!r->Data.SOA.pNamePrimaryServer) return ERROR_NOT_ENOUGH_MEMORY;
361 if (dns_ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
362 return DNS_ERROR_BAD_PACKET;
364 r->Data.SOA.pNameAdministrator = dns_dname_from_msg( msg, pos );
365 if (!r->Data.SOA.pNameAdministrator)
367 heap_free( r->Data.SOA.pNamePrimaryServer );
368 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.dwSerialNo = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
375 r->Data.SOA.dwRefresh = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
376 r->Data.SOA.dwRetry = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
377 r->Data.SOA.dwExpire = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
378 r->Data.SOA.dwDefaultTtl = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
380 *dlen = sizeof(DNS_SOA_DATAA);
381 break;
383 case ns_t_srv:
385 r->Data.SRV.wPriority = ntohs( *(const WORD *)pos ); pos += sizeof(WORD);
386 r->Data.SRV.wWeight = ntohs( *(const WORD *)pos ); pos += sizeof(WORD);
387 r->Data.SRV.wPort = ntohs( *(const WORD *)pos ); pos += sizeof(WORD);
389 r->Data.SRV.pNameTarget = dns_dname_from_msg( msg, pos );
390 if (!r->Data.SRV.pNameTarget) return ERROR_NOT_ENOUGH_MEMORY;
392 *dlen = sizeof(DNS_SRV_DATAA);
393 break;
395 case ns_t_hinfo:
396 case ns_t_isdn:
397 case ns_t_x25:
398 case ns_t_txt:
400 i = 0;
401 while (pos[0] && pos < rr->rdata + rr->rdlength)
403 r->Data.TXT.pStringArray[i] = dns_str_from_rdata( pos );
404 if (!r->Data.TXT.pStringArray[i])
406 while (i > 0) heap_free( r->Data.TXT.pStringArray[--i] );
407 return ERROR_NOT_ENOUGH_MEMORY;
409 i++;
410 pos += pos[0] + 1;
412 r->Data.TXT.dwStringCount = i;
413 *dlen = sizeof(DNS_TXT_DATAA) + (i - 1) * sizeof(PCHAR);
414 break;
416 case ns_t_atma:
417 case ns_t_loc:
418 case ns_t_nxt:
419 case ns_t_tsig:
420 case ns_t_wks:
421 case 0x00f9: /* TKEY */
422 case 0xff01: /* WINS */
423 case 0xff02: /* WINSR */
424 default:
425 FIXME( "unhandled type: %s\n", dns_type_to_str( rr->type ) );
426 return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
429 return ret;
432 static DNS_STATUS dns_copy_record( ns_msg msg, ns_sect section,
433 unsigned short num, DNS_RECORDA **recp )
435 DNS_STATUS ret;
436 DNS_RECORDA *record;
437 WORD dlen;
438 ns_rr rr;
440 if (dns_ns_parserr( &msg, section, num, &rr ) < 0)
441 return DNS_ERROR_BAD_PACKET;
443 if (!(record = heap_alloc_zero( dns_get_record_size( &rr ) )))
444 return ERROR_NOT_ENOUGH_MEMORY;
446 record->pName = dns_strdup_u( rr.name );
447 if (!record->pName)
449 heap_free( record );
450 return ERROR_NOT_ENOUGH_MEMORY;
453 record->wType = rr.type;
454 record->Flags.S.Section = section;
455 record->Flags.S.CharSet = DnsCharSetUtf8;
456 record->dwTtl = rr.ttl;
458 if ((ret = dns_copy_rdata( msg, &rr, record, &dlen )))
460 heap_free( record->pName );
461 heap_free( record );
462 return ret;
464 record->wDataLength = dlen;
465 *recp = record;
467 TRACE( "found %s record in %s section\n",
468 dns_type_to_str( rr.type ), dns_section_to_str( section ) );
469 return ERROR_SUCCESS;
472 #define DEFAULT_TTL 1200
474 static DNS_STATUS dns_do_query_netbios( PCSTR name, DNS_RECORDA **recp )
476 NCB ncb;
477 UCHAR ret;
478 DNS_RRSET rrset;
479 FIND_NAME_BUFFER *buffer;
480 FIND_NAME_HEADER *header;
481 DNS_RECORDA *record = NULL;
482 unsigned int i, len;
483 DNS_STATUS status = ERROR_INVALID_NAME;
485 len = strlen( name );
486 if (len >= NCBNAMSZ) return DNS_ERROR_RCODE_NAME_ERROR;
488 DNS_RRSET_INIT( rrset );
490 memset( &ncb, 0, sizeof(ncb) );
491 ncb.ncb_command = NCBFINDNAME;
493 memset( ncb.ncb_callname, ' ', sizeof(ncb.ncb_callname) );
494 memcpy( ncb.ncb_callname, name, len );
495 ncb.ncb_callname[NCBNAMSZ - 1] = '\0';
497 ret = Netbios( &ncb );
498 if (ret != NRC_GOODRET) return ERROR_INVALID_NAME;
500 header = (FIND_NAME_HEADER *)ncb.ncb_buffer;
501 buffer = (FIND_NAME_BUFFER *)((char *)header + sizeof(FIND_NAME_HEADER));
503 for (i = 0; i < header->node_count; i++)
505 record = heap_alloc_zero( sizeof(DNS_RECORDA) );
506 if (!record)
508 status = ERROR_NOT_ENOUGH_MEMORY;
509 goto exit;
511 else
513 record->pName = dns_strdup_u( name );
514 if (!record->pName)
516 status = ERROR_NOT_ENOUGH_MEMORY;
517 goto exit;
520 record->wType = DNS_TYPE_A;
521 record->Flags.S.Section = DnsSectionAnswer;
522 record->Flags.S.CharSet = DnsCharSetUtf8;
523 record->dwTtl = DEFAULT_TTL;
525 /* FIXME: network byte order? */
526 record->Data.A.IpAddress = *(DWORD *)((char *)buffer[i].destination_addr + 2);
528 DNS_RRSET_ADD( rrset, (DNS_RECORD *)record );
531 status = ERROR_SUCCESS;
533 exit:
534 DNS_RRSET_TERMINATE( rrset );
536 if (status != ERROR_SUCCESS)
537 DnsRecordListFree( rrset.pFirstRR, DnsFreeRecordList );
538 else
539 *recp = (DNS_RECORDA *)rrset.pFirstRR;
541 return status;
544 /* res_init() must have been called before calling these three functions.
546 static DNS_STATUS dns_set_serverlist( const IP4_ARRAY *addrs )
548 int i;
550 if (addrs->AddrCount > MAXNS)
552 WARN( "too many servers: %d only using the first: %d\n",
553 addrs->AddrCount, MAXNS );
554 _res.nscount = MAXNS;
556 else _res.nscount = addrs->AddrCount;
558 for (i = 0; i < _res.nscount; i++)
559 _res.nsaddr_list[i].sin_addr.s_addr = addrs->AddrArray[i];
561 return ERROR_SUCCESS;
564 static DNS_STATUS dns_get_serverlist( PIP4_ARRAY addrs, PDWORD len )
566 unsigned int size;
567 int i;
569 size = FIELD_OFFSET(IP4_ARRAY, AddrArray[_res.nscount]);
570 if (!addrs || *len < size)
572 *len = size;
573 return ERROR_INSUFFICIENT_BUFFER;
576 addrs->AddrCount = _res.nscount;
578 for (i = 0; i < _res.nscount; i++)
579 addrs->AddrArray[i] = _res.nsaddr_list[i].sin_addr.s_addr;
581 return ERROR_SUCCESS;
584 #define DNS_MAX_PACKET_SIZE 4096
585 static DNS_STATUS dns_do_query( PCSTR name, WORD type, DWORD options, PDNS_RECORDA *result )
587 DNS_STATUS ret = DNS_ERROR_RCODE_NOT_IMPLEMENTED;
589 unsigned int i, num;
590 unsigned char answer[DNS_MAX_PACKET_SIZE];
591 ns_sect sections[] = { ns_s_an, ns_s_ar };
592 ns_msg msg;
594 DNS_RECORDA *record = NULL;
595 DNS_RRSET rrset;
596 int len;
598 DNS_RRSET_INIT( rrset );
600 len = res_query( name, ns_c_in, type, answer, sizeof(answer) );
601 if (len < 0)
603 ret = dns_map_h_errno( h_errno );
604 goto exit;
607 if (dns_ns_initparse( answer, len, &msg ) < 0)
609 ret = DNS_ERROR_BAD_PACKET;
610 goto exit;
613 #define RCODE_MASK 0x0f
614 if ((msg._flags & RCODE_MASK) != ns_r_noerror)
616 ret = dns_map_error( msg._flags & RCODE_MASK );
617 goto exit;
620 for (i = 0; i < sizeof(sections)/sizeof(sections[0]); i++)
622 for (num = 0; num < ns_msg_count( msg, sections[i] ); num++)
624 ret = dns_copy_record( msg, sections[i], num, &record );
625 if (ret != ERROR_SUCCESS) goto exit;
627 DNS_RRSET_ADD( rrset, (DNS_RECORD *)record );
631 exit:
632 DNS_RRSET_TERMINATE( rrset );
634 if (ret != ERROR_SUCCESS)
635 DnsRecordListFree( rrset.pFirstRR, DnsFreeRecordList );
636 else
637 *result = (DNS_RECORDA *)rrset.pFirstRR;
639 return ret;
642 #endif /* HAVE_RESOLV */
644 static const char *debugstr_query_request(const DNS_QUERY_REQUEST *req)
646 if (!req)
647 return "(null)";
649 return wine_dbg_sprintf("{%d %s %s %x%08x %p %d %p %p}", req->Version,
650 debugstr_w(req->QueryName), dns_type_to_str(req->QueryType),
651 (UINT32)(req->QueryOptions>>32u), (UINT32)req->QueryOptions, req->pDnsServerList,
652 req->InterfaceIndex, req->pQueryCompletionCallback, req->pQueryContext);
655 /******************************************************************************
656 * DnsQueryEx [DNSAPI.@]
659 DNS_STATUS WINAPI DnsQueryEx(DNS_QUERY_REQUEST *request, DNS_QUERY_RESULT *result, DNS_QUERY_CANCEL *cancel)
661 FIXME("(%s %p %p)\n", debugstr_query_request(request), result, cancel);
662 return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
665 /******************************************************************************
666 * DnsQuery_A [DNSAPI.@]
669 DNS_STATUS WINAPI DnsQuery_A( PCSTR name, WORD type, DWORD options, PVOID servers,
670 PDNS_RECORDA *result, PVOID *reserved )
672 WCHAR *nameW;
673 DNS_RECORDW *resultW;
674 DNS_STATUS status;
676 TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_a(name), dns_type_to_str( type ),
677 options, servers, result, reserved );
679 if (!name || !result)
680 return ERROR_INVALID_PARAMETER;
682 nameW = dns_strdup_aw( name );
683 if (!nameW) return ERROR_NOT_ENOUGH_MEMORY;
685 status = DnsQuery_W( nameW, type, options, servers, &resultW, reserved );
687 if (status == ERROR_SUCCESS)
689 *result = (DNS_RECORDA *)DnsRecordSetCopyEx(
690 (DNS_RECORD *)resultW, DnsCharSetUnicode, DnsCharSetAnsi );
692 if (!*result) status = ERROR_NOT_ENOUGH_MEMORY;
693 DnsRecordListFree( (DNS_RECORD *)resultW, DnsFreeRecordList );
696 heap_free( nameW );
697 return status;
700 /******************************************************************************
701 * DnsQuery_UTF8 [DNSAPI.@]
704 DNS_STATUS WINAPI DnsQuery_UTF8( PCSTR name, WORD type, DWORD options, PVOID servers,
705 PDNS_RECORDA *result, PVOID *reserved )
707 DNS_STATUS ret = DNS_ERROR_RCODE_NOT_IMPLEMENTED;
708 #ifdef HAVE_RESOLV
710 TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_a(name), dns_type_to_str( type ),
711 options, servers, result, reserved );
713 if (!name || !result)
714 return ERROR_INVALID_PARAMETER;
716 initialise_resolver();
717 _res.options |= dns_map_options( options );
719 if (servers && (ret = dns_set_serverlist( servers )))
720 return ret;
722 ret = dns_do_query( name, type, options, result );
724 if (ret == DNS_ERROR_RCODE_NAME_ERROR && type == DNS_TYPE_A &&
725 !(options & DNS_QUERY_NO_NETBT))
727 TRACE( "dns lookup failed, trying netbios query\n" );
728 ret = dns_do_query_netbios( name, result );
731 #endif
732 return ret;
735 /******************************************************************************
736 * DnsQuery_W [DNSAPI.@]
739 DNS_STATUS WINAPI DnsQuery_W( PCWSTR name, WORD type, DWORD options, PVOID servers,
740 PDNS_RECORDW *result, PVOID *reserved )
742 char *nameU;
743 DNS_RECORDA *resultA;
744 DNS_STATUS status;
746 TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_w(name), dns_type_to_str( type ),
747 options, servers, result, reserved );
749 if (!name || !result)
750 return ERROR_INVALID_PARAMETER;
752 nameU = dns_strdup_wu( name );
753 if (!nameU) return ERROR_NOT_ENOUGH_MEMORY;
755 status = DnsQuery_UTF8( nameU, type, options, servers, &resultA, reserved );
757 if (status == ERROR_SUCCESS)
759 *result = (DNS_RECORDW *)DnsRecordSetCopyEx(
760 (DNS_RECORD *)resultA, DnsCharSetUtf8, DnsCharSetUnicode );
762 if (!*result) status = ERROR_NOT_ENOUGH_MEMORY;
763 DnsRecordListFree( (DNS_RECORD *)resultA, DnsFreeRecordList );
766 heap_free( nameU );
767 return status;
770 static DNS_STATUS dns_get_hostname_a( COMPUTER_NAME_FORMAT format,
771 PSTR buffer, PDWORD len )
773 char name[256];
774 DWORD size = sizeof(name)/sizeof(name[0]);
776 if (!GetComputerNameExA( format, name, &size ))
777 return DNS_ERROR_NAME_DOES_NOT_EXIST;
779 if (!buffer || (size = lstrlenA( name ) + 1) > *len)
781 *len = size;
782 return ERROR_INSUFFICIENT_BUFFER;
785 lstrcpyA( buffer, name );
786 return ERROR_SUCCESS;
789 static DNS_STATUS dns_get_hostname_w( COMPUTER_NAME_FORMAT format,
790 PWSTR buffer, PDWORD len )
792 WCHAR name[256];
793 DWORD size = sizeof(name)/sizeof(name[0]);
795 if (!GetComputerNameExW( format, name, &size ))
796 return DNS_ERROR_NAME_DOES_NOT_EXIST;
798 if (!buffer || (size = lstrlenW( name ) + 1) > *len)
800 *len = size;
801 return ERROR_INSUFFICIENT_BUFFER;
804 lstrcpyW( buffer, name );
805 return ERROR_SUCCESS;
808 /******************************************************************************
809 * DnsQueryConfig [DNSAPI.@]
812 DNS_STATUS WINAPI DnsQueryConfig( DNS_CONFIG_TYPE config, DWORD flag, PCWSTR adapter,
813 PVOID reserved, PVOID buffer, PDWORD len )
815 DNS_STATUS ret = ERROR_INVALID_PARAMETER;
817 TRACE( "(%d,0x%08x,%s,%p,%p,%p)\n", config, flag, debugstr_w(adapter),
818 reserved, buffer, len );
820 if (!len) return ERROR_INVALID_PARAMETER;
822 switch (config)
824 case DnsConfigDnsServerList:
826 #ifdef HAVE_RESOLV
827 initialise_resolver();
828 ret = dns_get_serverlist( buffer, len );
829 break;
830 #else
831 WARN( "compiled without resolver support\n" );
832 break;
833 #endif
835 case DnsConfigHostName_A:
836 case DnsConfigHostName_UTF8:
837 return dns_get_hostname_a( ComputerNameDnsHostname, buffer, len );
839 case DnsConfigFullHostName_A:
840 case DnsConfigFullHostName_UTF8:
841 return dns_get_hostname_a( ComputerNameDnsFullyQualified, buffer, len );
843 case DnsConfigPrimaryDomainName_A:
844 case DnsConfigPrimaryDomainName_UTF8:
845 return dns_get_hostname_a( ComputerNameDnsDomain, buffer, len );
847 case DnsConfigHostName_W:
848 return dns_get_hostname_w( ComputerNameDnsHostname, buffer, len );
850 case DnsConfigFullHostName_W:
851 return dns_get_hostname_w( ComputerNameDnsFullyQualified, buffer, len );
853 case DnsConfigPrimaryDomainName_W:
854 return dns_get_hostname_w( ComputerNameDnsDomain, buffer, len );
856 case DnsConfigAdapterDomainName_A:
857 case DnsConfigAdapterDomainName_W:
858 case DnsConfigAdapterDomainName_UTF8:
859 case DnsConfigSearchList:
860 case DnsConfigAdapterInfo:
861 case DnsConfigPrimaryHostNameRegistrationEnabled:
862 case DnsConfigAdapterHostNameRegistrationEnabled:
863 case DnsConfigAddressRegistrationMaxCount:
864 FIXME( "unimplemented config type %d\n", config );
865 break;
867 default:
868 WARN( "unknown config type: %d\n", config );
869 break;
871 return ret;