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
29 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(dnsapi
);
34 #define DEFAULT_TTL 1200
36 static DNS_STATUS
do_query_netbios( PCSTR name
, DNS_RECORDA
**recp
)
41 FIND_NAME_BUFFER
*buffer
;
42 FIND_NAME_HEADER
*header
;
43 DNS_RECORDA
*record
= NULL
;
45 DNS_STATUS status
= ERROR_INVALID_NAME
;
48 if (len
>= NCBNAMSZ
) return DNS_ERROR_RCODE_NAME_ERROR
;
50 DNS_RRSET_INIT( rrset
);
52 memset( &ncb
, 0, sizeof(ncb
) );
53 ncb
.ncb_command
= NCBFINDNAME
;
55 memset( ncb
.ncb_callname
, ' ', sizeof(ncb
.ncb_callname
) );
56 memcpy( ncb
.ncb_callname
, name
, len
);
57 ncb
.ncb_callname
[NCBNAMSZ
- 1] = '\0';
59 ret
= Netbios( &ncb
);
60 if (ret
!= NRC_GOODRET
) return ERROR_INVALID_NAME
;
62 header
= (FIND_NAME_HEADER
*)ncb
.ncb_buffer
;
63 buffer
= (FIND_NAME_BUFFER
*)((char *)header
+ sizeof(FIND_NAME_HEADER
));
65 for (i
= 0; i
< header
->node_count
; i
++)
67 record
= heap_alloc_zero( sizeof(DNS_RECORDA
) );
70 status
= ERROR_NOT_ENOUGH_MEMORY
;
75 record
->pName
= strdup_u( name
);
78 status
= ERROR_NOT_ENOUGH_MEMORY
;
82 record
->wType
= DNS_TYPE_A
;
83 record
->Flags
.S
.Section
= DnsSectionAnswer
;
84 record
->Flags
.S
.CharSet
= DnsCharSetUtf8
;
85 record
->dwTtl
= DEFAULT_TTL
;
87 /* FIXME: network byte order? */
88 record
->Data
.A
.IpAddress
= *(DWORD
*)((char *)buffer
[i
].destination_addr
+ 2);
90 DNS_RRSET_ADD( rrset
, (DNS_RECORD
*)record
);
93 status
= ERROR_SUCCESS
;
96 DNS_RRSET_TERMINATE( rrset
);
98 if (status
!= ERROR_SUCCESS
)
99 DnsRecordListFree( rrset
.pFirstRR
, DnsFreeRecordList
);
101 *recp
= (DNS_RECORDA
*)rrset
.pFirstRR
;
106 static const char *debugstr_query_request(const DNS_QUERY_REQUEST
*req
)
111 return wine_dbg_sprintf("{%d %s %s %x%08x %p %d %p %p}", req
->Version
,
112 debugstr_w(req
->QueryName
), type_to_str(req
->QueryType
),
113 (UINT32
)(req
->QueryOptions
>>32u), (UINT32
)req
->QueryOptions
, req
->pDnsServerList
,
114 req
->InterfaceIndex
, req
->pQueryCompletionCallback
, req
->pQueryContext
);
117 /******************************************************************************
118 * DnsQueryEx [DNSAPI.@]
121 DNS_STATUS WINAPI
DnsQueryEx(DNS_QUERY_REQUEST
*request
, DNS_QUERY_RESULT
*result
, DNS_QUERY_CANCEL
*cancel
)
123 FIXME("(%s %p %p)\n", debugstr_query_request(request
), result
, cancel
);
124 return DNS_ERROR_RCODE_NOT_IMPLEMENTED
;
127 /******************************************************************************
128 * DnsQuery_A [DNSAPI.@]
131 DNS_STATUS WINAPI
DnsQuery_A( PCSTR name
, WORD type
, DWORD options
, PVOID servers
,
132 PDNS_RECORDA
*result
, PVOID
*reserved
)
135 DNS_RECORDW
*resultW
;
138 TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_a(name
), type_to_str( type
),
139 options
, servers
, result
, reserved
);
141 if (!name
|| !result
)
142 return ERROR_INVALID_PARAMETER
;
144 nameW
= strdup_aw( name
);
145 if (!nameW
) return ERROR_NOT_ENOUGH_MEMORY
;
147 status
= DnsQuery_W( nameW
, type
, options
, servers
, &resultW
, reserved
);
149 if (status
== ERROR_SUCCESS
)
151 *result
= (DNS_RECORDA
*)DnsRecordSetCopyEx(
152 (DNS_RECORD
*)resultW
, DnsCharSetUnicode
, DnsCharSetAnsi
);
154 if (!*result
) status
= ERROR_NOT_ENOUGH_MEMORY
;
155 DnsRecordListFree( (DNS_RECORD
*)resultW
, DnsFreeRecordList
);
162 /******************************************************************************
163 * DnsQuery_UTF8 [DNSAPI.@]
166 DNS_STATUS WINAPI
DnsQuery_UTF8( PCSTR name
, WORD type
, DWORD options
, PVOID servers
,
167 PDNS_RECORDA
*result
, PVOID
*reserved
)
169 DNS_STATUS ret
= DNS_ERROR_RCODE_NOT_IMPLEMENTED
;
171 TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_a(name
), type_to_str( type
),
172 options
, servers
, result
, reserved
);
174 if (!name
|| !result
)
175 return ERROR_INVALID_PARAMETER
;
177 if ((ret
= resolv_funcs
->set_serverlist( servers
))) return ret
;
179 ret
= resolv_funcs
->query( name
, type
, options
, result
);
181 if (ret
== DNS_ERROR_RCODE_NAME_ERROR
&& type
== DNS_TYPE_A
&&
182 !(options
& DNS_QUERY_NO_NETBT
))
184 TRACE( "dns lookup failed, trying netbios query\n" );
185 ret
= do_query_netbios( name
, result
);
191 /******************************************************************************
192 * DnsQuery_W [DNSAPI.@]
195 DNS_STATUS WINAPI
DnsQuery_W( PCWSTR name
, WORD type
, DWORD options
, PVOID servers
,
196 PDNS_RECORDW
*result
, PVOID
*reserved
)
199 DNS_RECORDA
*resultA
;
202 TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_w(name
), type_to_str( type
),
203 options
, servers
, result
, reserved
);
205 if (!name
|| !result
)
206 return ERROR_INVALID_PARAMETER
;
208 nameU
= strdup_wu( name
);
209 if (!nameU
) return ERROR_NOT_ENOUGH_MEMORY
;
211 status
= DnsQuery_UTF8( nameU
, type
, options
, servers
, &resultA
, reserved
);
213 if (status
== ERROR_SUCCESS
)
215 *result
= (DNS_RECORDW
*)DnsRecordSetCopyEx(
216 (DNS_RECORD
*)resultA
, DnsCharSetUtf8
, DnsCharSetUnicode
);
218 if (!*result
) status
= ERROR_NOT_ENOUGH_MEMORY
;
219 DnsRecordListFree( (DNS_RECORD
*)resultA
, DnsFreeRecordList
);
226 static DNS_STATUS
get_hostname_a( COMPUTER_NAME_FORMAT format
, PSTR buffer
, PDWORD len
)
229 DWORD size
= ARRAY_SIZE(name
);
231 if (!GetComputerNameExA( format
, name
, &size
))
232 return DNS_ERROR_NAME_DOES_NOT_EXIST
;
234 if (!buffer
|| (size
= lstrlenA( name
) + 1) > *len
)
237 return ERROR_INSUFFICIENT_BUFFER
;
240 lstrcpyA( buffer
, name
);
241 return ERROR_SUCCESS
;
244 static DNS_STATUS
get_hostname_w( COMPUTER_NAME_FORMAT format
, PWSTR buffer
, PDWORD len
)
247 DWORD size
= ARRAY_SIZE(name
);
249 if (!GetComputerNameExW( format
, name
, &size
))
250 return DNS_ERROR_NAME_DOES_NOT_EXIST
;
252 if (!buffer
|| (size
= lstrlenW( name
) + 1) > *len
)
255 return ERROR_INSUFFICIENT_BUFFER
;
258 lstrcpyW( buffer
, name
);
259 return ERROR_SUCCESS
;
262 /******************************************************************************
263 * DnsQueryConfig [DNSAPI.@]
266 DNS_STATUS WINAPI
DnsQueryConfig( DNS_CONFIG_TYPE config
, DWORD flag
, PCWSTR adapter
,
267 PVOID reserved
, PVOID buffer
, PDWORD len
)
269 DNS_STATUS ret
= ERROR_INVALID_PARAMETER
;
271 TRACE( "(%d,0x%08x,%s,%p,%p,%p)\n", config
, flag
, debugstr_w(adapter
),
272 reserved
, buffer
, len
);
274 if (!len
) return ERROR_INVALID_PARAMETER
;
278 case DnsConfigDnsServerList
:
280 ret
= resolv_funcs
->get_serverlist( buffer
, len
);
283 case DnsConfigHostName_A
:
284 case DnsConfigHostName_UTF8
:
285 return get_hostname_a( ComputerNameDnsHostname
, buffer
, len
);
287 case DnsConfigFullHostName_A
:
288 case DnsConfigFullHostName_UTF8
:
289 return get_hostname_a( ComputerNameDnsFullyQualified
, buffer
, len
);
291 case DnsConfigPrimaryDomainName_A
:
292 case DnsConfigPrimaryDomainName_UTF8
:
293 return get_hostname_a( ComputerNameDnsDomain
, buffer
, len
);
295 case DnsConfigHostName_W
:
296 return get_hostname_w( ComputerNameDnsHostname
, buffer
, len
);
298 case DnsConfigFullHostName_W
:
299 return get_hostname_w( ComputerNameDnsFullyQualified
, buffer
, len
);
301 case DnsConfigPrimaryDomainName_W
:
302 return get_hostname_w( ComputerNameDnsDomain
, buffer
, len
);
304 case DnsConfigAdapterDomainName_A
:
305 case DnsConfigAdapterDomainName_W
:
306 case DnsConfigAdapterDomainName_UTF8
:
307 case DnsConfigSearchList
:
308 case DnsConfigAdapterInfo
:
309 case DnsConfigPrimaryHostNameRegistrationEnabled
:
310 case DnsConfigAdapterHostNameRegistrationEnabled
:
311 case DnsConfigAddressRegistrationMaxCount
:
312 FIXME( "unimplemented config type %d\n", config
);
316 WARN( "unknown config type: %d\n", config
);