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
30 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(dnsapi
);
35 #define DEFAULT_TTL 1200
37 static DNS_STATUS
do_query_netbios( PCSTR name
, DNS_RECORDA
**recp
)
42 FIND_NAME_BUFFER
*buffer
;
43 FIND_NAME_HEADER
*header
;
44 DNS_RECORDA
*record
= NULL
;
46 DNS_STATUS status
= ERROR_INVALID_NAME
;
49 if (len
>= NCBNAMSZ
) return DNS_ERROR_RCODE_NAME_ERROR
;
51 DNS_RRSET_INIT( rrset
);
53 memset( &ncb
, 0, sizeof(ncb
) );
54 ncb
.ncb_command
= NCBFINDNAME
;
56 memset( ncb
.ncb_callname
, ' ', sizeof(ncb
.ncb_callname
) );
57 memcpy( ncb
.ncb_callname
, name
, len
);
58 ncb
.ncb_callname
[NCBNAMSZ
- 1] = '\0';
60 ret
= Netbios( &ncb
);
61 if (ret
!= NRC_GOODRET
) return ERROR_INVALID_NAME
;
63 header
= (FIND_NAME_HEADER
*)ncb
.ncb_buffer
;
64 buffer
= (FIND_NAME_BUFFER
*)((char *)header
+ sizeof(FIND_NAME_HEADER
));
66 for (i
= 0; i
< header
->node_count
; i
++)
68 record
= heap_alloc_zero( sizeof(DNS_RECORDA
) );
71 status
= ERROR_NOT_ENOUGH_MEMORY
;
76 record
->pName
= strdup_u( name
);
79 status
= ERROR_NOT_ENOUGH_MEMORY
;
83 record
->wType
= DNS_TYPE_A
;
84 record
->Flags
.S
.Section
= DnsSectionAnswer
;
85 record
->Flags
.S
.CharSet
= DnsCharSetUtf8
;
86 record
->dwTtl
= DEFAULT_TTL
;
88 /* FIXME: network byte order? */
89 record
->Data
.A
.IpAddress
= *(DWORD
*)((char *)buffer
[i
].destination_addr
+ 2);
91 DNS_RRSET_ADD( rrset
, (DNS_RECORD
*)record
);
94 status
= ERROR_SUCCESS
;
97 DNS_RRSET_TERMINATE( rrset
);
99 if (status
!= ERROR_SUCCESS
)
100 DnsRecordListFree( rrset
.pFirstRR
, DnsFreeRecordList
);
102 *recp
= (DNS_RECORDA
*)rrset
.pFirstRR
;
107 static const char *debugstr_query_request(const DNS_QUERY_REQUEST
*req
)
112 return wine_dbg_sprintf("{%d %s %s %x%08x %p %d %p %p}", req
->Version
,
113 debugstr_w(req
->QueryName
), type_to_str(req
->QueryType
),
114 (UINT32
)(req
->QueryOptions
>>32u), (UINT32
)req
->QueryOptions
, req
->pDnsServerList
,
115 req
->InterfaceIndex
, req
->pQueryCompletionCallback
, req
->pQueryContext
);
118 /******************************************************************************
119 * DnsQueryEx [DNSAPI.@]
122 DNS_STATUS WINAPI
DnsQueryEx(DNS_QUERY_REQUEST
*request
, DNS_QUERY_RESULT
*result
, DNS_QUERY_CANCEL
*cancel
)
124 FIXME("(%s %p %p)\n", debugstr_query_request(request
), result
, cancel
);
125 return DNS_ERROR_RCODE_NOT_IMPLEMENTED
;
128 /******************************************************************************
129 * DnsQuery_A [DNSAPI.@]
132 DNS_STATUS WINAPI
DnsQuery_A( PCSTR name
, WORD type
, DWORD options
, PVOID servers
,
133 PDNS_RECORDA
*result
, PVOID
*reserved
)
136 DNS_RECORDW
*resultW
;
139 TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_a(name
), type_to_str( type
),
140 options
, servers
, result
, reserved
);
142 if (!name
|| !result
)
143 return ERROR_INVALID_PARAMETER
;
145 nameW
= strdup_aw( name
);
146 if (!nameW
) return ERROR_NOT_ENOUGH_MEMORY
;
148 status
= DnsQuery_W( nameW
, type
, options
, servers
, &resultW
, reserved
);
150 if (status
== ERROR_SUCCESS
)
152 *result
= (DNS_RECORDA
*)DnsRecordSetCopyEx(
153 (DNS_RECORD
*)resultW
, DnsCharSetUnicode
, DnsCharSetAnsi
);
155 if (!*result
) status
= ERROR_NOT_ENOUGH_MEMORY
;
156 DnsRecordListFree( (DNS_RECORD
*)resultW
, DnsFreeRecordList
);
163 /******************************************************************************
164 * DnsQuery_UTF8 [DNSAPI.@]
167 DNS_STATUS WINAPI
DnsQuery_UTF8( PCSTR name
, WORD type
, DWORD options
, PVOID servers
,
168 PDNS_RECORDA
*result
, PVOID
*reserved
)
170 DNS_STATUS ret
= DNS_ERROR_RCODE_NOT_IMPLEMENTED
;
172 TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_a(name
), type_to_str( type
),
173 options
, servers
, result
, reserved
);
175 if (!name
|| !result
)
176 return ERROR_INVALID_PARAMETER
;
178 if ((ret
= resolv_funcs
->set_serverlist( servers
))) return ret
;
180 ret
= resolv_funcs
->query( name
, type
, options
, result
);
182 if (ret
== DNS_ERROR_RCODE_NAME_ERROR
&& type
== DNS_TYPE_A
&&
183 !(options
& DNS_QUERY_NO_NETBT
))
185 TRACE( "dns lookup failed, trying netbios query\n" );
186 ret
= do_query_netbios( name
, result
);
192 /******************************************************************************
193 * DnsQuery_W [DNSAPI.@]
196 DNS_STATUS WINAPI
DnsQuery_W( PCWSTR name
, WORD type
, DWORD options
, PVOID servers
,
197 PDNS_RECORDW
*result
, PVOID
*reserved
)
200 DNS_RECORDA
*resultA
;
203 TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_w(name
), type_to_str( type
),
204 options
, servers
, result
, reserved
);
206 if (!name
|| !result
)
207 return ERROR_INVALID_PARAMETER
;
209 nameU
= strdup_wu( name
);
210 if (!nameU
) return ERROR_NOT_ENOUGH_MEMORY
;
212 status
= DnsQuery_UTF8( nameU
, type
, options
, servers
, &resultA
, reserved
);
214 if (status
== ERROR_SUCCESS
)
216 *result
= (DNS_RECORDW
*)DnsRecordSetCopyEx(
217 (DNS_RECORD
*)resultA
, DnsCharSetUtf8
, DnsCharSetUnicode
);
219 if (!*result
) status
= ERROR_NOT_ENOUGH_MEMORY
;
220 DnsRecordListFree( (DNS_RECORD
*)resultA
, DnsFreeRecordList
);
227 static DNS_STATUS
get_hostname_a( COMPUTER_NAME_FORMAT format
, PSTR buffer
, PDWORD len
)
230 DWORD size
= ARRAY_SIZE(name
);
232 if (!GetComputerNameExA( format
, name
, &size
))
233 return DNS_ERROR_NAME_DOES_NOT_EXIST
;
235 if (!buffer
|| (size
= lstrlenA( name
) + 1) > *len
)
238 return ERROR_INSUFFICIENT_BUFFER
;
241 lstrcpyA( buffer
, name
);
242 return ERROR_SUCCESS
;
245 static DNS_STATUS
get_hostname_w( COMPUTER_NAME_FORMAT format
, PWSTR buffer
, PDWORD len
)
248 DWORD size
= ARRAY_SIZE(name
);
250 if (!GetComputerNameExW( format
, name
, &size
))
251 return DNS_ERROR_NAME_DOES_NOT_EXIST
;
253 if (!buffer
|| (size
= lstrlenW( name
) + 1) > *len
)
256 return ERROR_INSUFFICIENT_BUFFER
;
259 lstrcpyW( buffer
, name
);
260 return ERROR_SUCCESS
;
263 static DNS_STATUS
get_dns_server_list( IP4_ARRAY
*out
, DWORD
*len
)
265 char buf
[FIELD_OFFSET(DNS_ADDR_ARRAY
, AddrArray
[3])];
266 DNS_ADDR_ARRAY
*servers
= (DNS_ADDR_ARRAY
*)buf
;
267 DWORD ret
, needed
, i
, num
, array_len
= sizeof(buf
);
271 ret
= resolv_funcs
->get_serverlist( AF_INET
, servers
, &array_len
);
272 if (ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
) goto err
;
273 num
= (array_len
- FIELD_OFFSET(DNS_ADDR_ARRAY
, AddrArray
[0])) / sizeof(DNS_ADDR
);
274 needed
= FIELD_OFFSET(IP4_ARRAY
, AddrArray
[num
]);
275 if (!out
|| *len
< needed
)
278 ret
= !out
? ERROR_SUCCESS
: ERROR_MORE_DATA
;
283 if ((char *)servers
!= buf
) heap_free( servers
);
284 servers
= heap_alloc( array_len
);
287 ret
= ERROR_NOT_ENOUGH_MEMORY
;
292 out
->AddrCount
= num
;
293 for (i
= 0; i
< num
; i
++)
294 out
->AddrArray
[i
] = ((SOCKADDR_IN
*)servers
->AddrArray
[i
].MaxSa
)->sin_addr
.s_addr
;
299 if ((char *)servers
!= buf
) heap_free( servers
);
303 /******************************************************************************
304 * DnsQueryConfig [DNSAPI.@]
307 DNS_STATUS WINAPI
DnsQueryConfig( DNS_CONFIG_TYPE config
, DWORD flag
, PCWSTR adapter
,
308 PVOID reserved
, PVOID buffer
, PDWORD len
)
310 DNS_STATUS ret
= ERROR_INVALID_PARAMETER
;
312 TRACE( "(%d,0x%08x,%s,%p,%p,%p)\n", config
, flag
, debugstr_w(adapter
),
313 reserved
, buffer
, len
);
315 if (!len
) return ERROR_INVALID_PARAMETER
;
319 case DnsConfigDnsServerList
:
320 return get_dns_server_list( buffer
, len
);
322 case DnsConfigHostName_A
:
323 case DnsConfigHostName_UTF8
:
324 return get_hostname_a( ComputerNameDnsHostname
, buffer
, len
);
326 case DnsConfigFullHostName_A
:
327 case DnsConfigFullHostName_UTF8
:
328 return get_hostname_a( ComputerNameDnsFullyQualified
, buffer
, len
);
330 case DnsConfigPrimaryDomainName_A
:
331 case DnsConfigPrimaryDomainName_UTF8
:
332 return get_hostname_a( ComputerNameDnsDomain
, buffer
, len
);
334 case DnsConfigHostName_W
:
335 return get_hostname_w( ComputerNameDnsHostname
, buffer
, len
);
337 case DnsConfigFullHostName_W
:
338 return get_hostname_w( ComputerNameDnsFullyQualified
, buffer
, len
);
340 case DnsConfigPrimaryDomainName_W
:
341 return get_hostname_w( ComputerNameDnsDomain
, buffer
, len
);
343 case DnsConfigAdapterDomainName_A
:
344 case DnsConfigAdapterDomainName_W
:
345 case DnsConfigAdapterDomainName_UTF8
:
346 case DnsConfigAdapterInfo
:
347 case DnsConfigPrimaryHostNameRegistrationEnabled
:
348 case DnsConfigAdapterHostNameRegistrationEnabled
:
349 case DnsConfigAddressRegistrationMaxCount
:
350 FIXME( "unimplemented config type %d\n", config
);
353 case DnsConfigDnsServersUnspec
:
354 return resolv_funcs
->get_serverlist( AF_UNSPEC
, buffer
, len
);
355 case DnsConfigDnsServersIpv4
:
356 return resolv_funcs
->get_serverlist( AF_INET
, buffer
, len
);
357 case DnsConfigDnsServersIpv6
:
358 return resolv_funcs
->get_serverlist( AF_INET6
, buffer
, len
);
360 case DnsConfigSearchList
:
361 return resolv_funcs
->get_searchlist( buffer
, len
);
364 WARN( "unknown config type: %d\n", config
);