4 * Copyright (C) 2006 Hans Leidekker
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
22 #include "wine/port.h"
23 #include "wine/debug.h"
28 #include <sys/types.h>
30 #ifdef HAVE_NETINET_IN_H
31 # include <netinet/in.h>
33 #ifdef HAVE_ARPA_NAMESER_H
34 # include <arpa/nameser.h>
52 WINE_DEFAULT_DEBUG_CHANNEL(dnsapi
);
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)
64 static const char *dns_section_to_str( ns_sect 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";
75 FIXME( "unknown section: 0x%02x\n", section
);
76 sprintf( tmp
, "0x%02x", section
);
82 static unsigned long dns_map_options( DWORD options
)
84 unsigned long ret
= 0;
86 if (options
== DNS_QUERY_STANDARD
)
89 if (options
& DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE
)
91 if (options
& DNS_QUERY_USE_TCP_ONLY
)
93 if (options
& DNS_QUERY_NO_RECURSION
)
95 if (options
& DNS_QUERY_NO_LOCAL_NAME
)
97 if (options
& DNS_QUERY_NO_HOSTS_FILE
)
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" );
121 static DNS_STATUS
dns_map_error( int 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
;
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
)
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
;
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
)
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
);
173 static char *dns_str_from_rdata( const unsigned char *rdata
)
176 unsigned int len
= rdata
[0];
178 str
= heap_alloc( len
+ 1 );
181 memcpy( str
, ++rdata
, len
);
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
);
196 pos
+= sizeof(WORD
) + sizeof(BYTE
) + sizeof(BYTE
);
197 size
+= rr
->rdata
+ rr
->rdlength
- pos
- 1;
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;
212 while (pos
[0] && pos
< rr
->rdata
+ rr
->rdlength
)
217 size
+= (num
- 1) * sizeof(PCHAR
);
223 size
+= rr
->rdlength
- 1;
228 case 0xff01: /* WINS */
230 FIXME( "unhandled type: %s\n", dns_type_to_str( rr
->type
) );
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
;
249 r
->Data
.A
.IpAddress
= *(const DWORD
*)pos
;
250 *dlen
= sizeof(DNS_A_DATA
);
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
);
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
);
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
);
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
);
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;
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;
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
);
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
);
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
);
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
);
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
;
422 r
->Data
.TXT
.dwStringCount
= i
;
423 *dlen
= sizeof(DNS_TXT_DATAA
) + (i
- 1) * sizeof(PCHAR
);
431 case 0x00f9: /* TKEY */
432 case 0xff01: /* WINS */
433 case 0xff02: /* WINSR */
435 FIXME( "unhandled type: %s\n", dns_type_to_str( rr
->type
) );
436 return DNS_ERROR_RCODE_NOT_IMPLEMENTED
;
442 static DNS_STATUS
dns_copy_record( ns_msg msg
, ns_sect section
,
443 unsigned short num
, DNS_RECORDA
**recp
)
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
);
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
);
474 record
->wDataLength
= dlen
;
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
)
489 FIND_NAME_BUFFER
*buffer
;
490 FIND_NAME_HEADER
*header
;
491 DNS_RECORDA
*record
= NULL
;
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
) );
518 status
= ERROR_NOT_ENOUGH_MEMORY
;
523 record
->pName
= dns_strdup_u( name
);
526 status
= ERROR_NOT_ENOUGH_MEMORY
;
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
;
544 DNS_RRSET_TERMINATE( rrset
);
546 if (status
!= ERROR_SUCCESS
)
547 DnsRecordListFree( rrset
.pFirstRR
, DnsFreeRecordList
);
549 *recp
= (DNS_RECORDA
*)rrset
.pFirstRR
;
554 /* res_init() must have been called before calling these three functions.
556 static DNS_STATUS
dns_set_serverlist( const IP4_ARRAY
*addrs
)
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
)
580 size
= FIELD_OFFSET(IP4_ARRAY
, AddrArray
[_res
.nscount
]);
581 if (!addrs
|| *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
;
601 unsigned char answer
[DNS_MAX_PACKET_SIZE
];
602 ns_sect sections
[] = { ns_s_an
, ns_s_ar
};
605 DNS_RECORDA
*record
= NULL
;
609 DNS_RRSET_INIT( rrset
);
611 len
= res_query( name
, ns_c_in
, type
, answer
, sizeof(answer
) );
614 ret
= dns_map_h_errno( h_errno
);
618 if (dns_ns_initparse( answer
, len
, &msg
) < 0)
620 ret
= DNS_ERROR_BAD_PACKET
;
624 #define RCODE_MASK 0x0f
625 if ((msg
._flags
& RCODE_MASK
) != ns_r_noerror
)
627 ret
= dns_map_error( msg
._flags
& RCODE_MASK
);
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
);
643 DNS_RRSET_TERMINATE( rrset
);
645 if (ret
!= ERROR_SUCCESS
)
646 DnsRecordListFree( rrset
.pFirstRR
, DnsFreeRecordList
);
648 *result
= (DNS_RECORDA
*)rrset
.pFirstRR
;
653 #endif /* HAVE_RESOLV */
655 static const char *debugstr_query_request(const DNS_QUERY_REQUEST
*req
)
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
)
684 DNS_RECORDW
*resultW
;
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
);
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
;
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
);
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
)
753 DNS_RECORDA
*resultA
;
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
);
780 static DNS_STATUS
dns_get_hostname_a( COMPUTER_NAME_FORMAT format
,
781 PSTR buffer
, PDWORD len
)
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
)
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
)
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
)
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
;
834 case DnsConfigDnsServerList
:
837 initialise_resolver();
838 ret
= dns_get_serverlist( buffer
, len
);
841 WARN( "compiled without resolver support\n" );
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
);
878 WARN( "unknown config type: %d\n", config
);