diff --git a/dlls/dnsapi/Makefile.in b/dlls/dnsapi/Makefile.in index 6ff2c14c5e3..b7785e5ebeb 100644 --- a/dlls/dnsapi/Makefile.in +++ b/dlls/dnsapi/Makefile.in @@ -1,4 +1,5 @@ MODULE = dnsapi.dll +UNIXLIB = dnsapi.so IMPORTLIB = dnsapi DELAYIMPORTS = netapi32 EXTRALIBS = $(RESOLV_LIBS) diff --git a/dlls/dnsapi/dnsapi.h b/dlls/dnsapi/dnsapi.h index 2558390674a..7acb9d3cf8e 100644 --- a/dlls/dnsapi/dnsapi.h +++ b/dlls/dnsapi/dnsapi.h @@ -18,7 +18,12 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include "windef.h" +#include "winbase.h" +#include "winnls.h" +#include "winternl.h" #include "wine/heap.h" +#include "wine/unixlib.h" static inline char *strdup_a( const char *src ) { @@ -121,12 +126,41 @@ static inline char *strdup_ua( const char *src ) extern const char *debugstr_type( unsigned short ) DECLSPEC_HIDDEN; -struct resolv_funcs +struct get_searchlist_params { - DNS_STATUS (CDECL *get_searchlist)( DNS_TXT_DATAW *list, DWORD *len ); - DNS_STATUS (CDECL *get_serverlist)( USHORT family, DNS_ADDR_ARRAY *addrs, DWORD *len ); - DNS_STATUS (CDECL *query)( const char *name, WORD type, DWORD options, void *buf, DWORD *len ); - DNS_STATUS (CDECL *set_serverlist)( const IP4_ARRAY *addrs ); + DNS_TXT_DATAW *list; + DWORD *len; }; -extern const struct resolv_funcs *resolv_funcs; +struct get_serverlist_params +{ + USHORT family; + DNS_ADDR_ARRAY *addrs; + DWORD *len; +}; + +struct set_serverlist_params +{ + const IP4_ARRAY *addrs; +}; + +struct query_params +{ + const char *name; + WORD type; + DWORD options; + void *buf; + DWORD *len; +}; + +enum unix_funcs +{ + unix_get_searchlist, + unix_get_serverlist, + unix_set_serverlist, + unix_query, +}; + +extern unixlib_handle_t resolv_handle; + +#define RESOLV_CALL( func, params ) __wine_unix_call( resolv_handle, unix_ ## func, params ) diff --git a/dlls/dnsapi/libresolv.c b/dlls/dnsapi/libresolv.c index 85b4c0d1aa8..9e12683b8a8 100644 --- a/dlls/dnsapi/libresolv.c +++ b/dlls/dnsapi/libresolv.c @@ -49,66 +49,16 @@ #include "windef.h" #include "winternl.h" #include "winbase.h" -#include "winnls.h" #include "windns.h" #define USE_WS_PREFIX #include "ws2def.h" #include "ws2ipdef.h" #include "wine/debug.h" -#include "wine/heap.h" #include "dnsapi.h" WINE_DEFAULT_DEBUG_CHANNEL(dnsapi); -static CPTABLEINFO unix_cptable; -static ULONG unix_cp = CP_UTF8; - -static DWORD WINAPI get_unix_codepage_once( RTL_RUN_ONCE *once, void *param, void **context ) -{ - static const WCHAR wineunixcpW[] = { 'W','I','N','E','U','N','I','X','C','P',0 }; - UNICODE_STRING name, value; - WCHAR value_buffer[13]; - SIZE_T size; - void *ptr; - - RtlInitUnicodeString( &name, wineunixcpW ); - value.Buffer = value_buffer; - value.MaximumLength = sizeof(value_buffer); - if (!RtlQueryEnvironmentVariable_U( NULL, &name, &value )) - RtlUnicodeStringToInteger( &value, 10, &unix_cp ); - if (unix_cp != CP_UTF8 && !NtGetNlsSectionPtr( 11, unix_cp, NULL, &ptr, &size )) - RtlInitCodePageTable( ptr, &unix_cptable ); - return TRUE; -} - -static BOOL get_unix_codepage( void ) -{ - static RTL_RUN_ONCE once = RTL_RUN_ONCE_INIT; - - return !RtlRunOnceExecuteOnce( &once, get_unix_codepage_once, NULL, NULL ); -} - -static DWORD dnsapi_umbstowcs( const char *src, WCHAR *dst, DWORD dstlen ) -{ - DWORD srclen = strlen( src ) + 1; - DWORD len; - - get_unix_codepage(); - - if (unix_cp == CP_UTF8) - { - RtlUTF8ToUnicodeN( dst, dstlen, &len, src, srclen ); - return len; - } - else - { - len = srclen * sizeof(WCHAR); - if (dst) RtlCustomCPToUnicodeN( &unix_cptable, dst, dstlen, &len, src, srclen ); - return len; - } -} - /* call res_init() just once because of a bug in Mac OS X 10.4 */ /* call once per thread on systems that have per-thread _res */ static void init_resolver( void ) @@ -172,25 +122,27 @@ static DNS_STATUS map_h_errno( int error ) } } -static DNS_STATUS CDECL resolv_get_searchlist( DNS_TXT_DATAW *list, DWORD *len ) +static NTSTATUS resolv_get_searchlist( void *args ) { + struct get_searchlist_params *params = args; + DNS_TXT_DATAW *list = params->list; DWORD i, needed, str_needed = 0; char *ptr, *end; init_resolver(); for (i = 0; i < MAXDNSRCH + 1 && _res.dnsrch[i]; i++) - str_needed += dnsapi_umbstowcs( _res.dnsrch[i], NULL, 0 ); + str_needed += (strlen(_res.dnsrch[i]) + 1) * sizeof(WCHAR); needed = FIELD_OFFSET(DNS_TXT_DATAW, pStringArray[i]) + str_needed; - if (!list || *len < needed) + if (!list || *params->len < needed) { - *len = needed; + *params->len = needed; return !list ? ERROR_SUCCESS : ERROR_MORE_DATA; } - *len = needed; + *params->len = needed; list->dwStringCount = i; ptr = (char *)(list->pStringArray + i); @@ -198,7 +150,8 @@ static DNS_STATUS CDECL resolv_get_searchlist( DNS_TXT_DATAW *list, DWORD *len ) for (i = 0; i < MAXDNSRCH + 1 && _res.dnsrch[i]; i++) { list->pStringArray[i] = (WCHAR *)ptr; - ptr += dnsapi_umbstowcs( _res.dnsrch[i], list->pStringArray[i], end - ptr ); + ptr += ntdll_umbstowcs( _res.dnsrch[i], strlen(_res.dnsrch[i]) + 1, + list->pStringArray[i], end - ptr ); } return ERROR_SUCCESS; } @@ -215,8 +168,10 @@ static inline int filter( unsigned short sin_family, USHORT family ) #ifdef HAVE_RES_GETSERVERS -static DNS_STATUS CDECL resolv_get_serverlist( USHORT family, DNS_ADDR_ARRAY *addrs, DWORD *len ) +static NTSTATUS resolv_get_serverlist( void *args ) { + struct get_serverlist_params *params = args; + DNS_ADDR_ARRAY *addrs = params->addrs; struct __res_state *state = &_res; DWORD i, found, total, needed; union res_sockaddr_union *buf; @@ -226,9 +181,9 @@ static DNS_STATUS CDECL resolv_get_serverlist( USHORT family, DNS_ADDR_ARRAY *ad total = res_getservers( state, NULL, 0 ); if (!total) return DNS_ERROR_NO_DNS_SERVERS; - if (!addrs && family != WS_AF_INET && family != WS_AF_INET6) + if (!addrs && params->family != WS_AF_INET && params->family != WS_AF_INET6) { - *len = FIELD_OFFSET(DNS_ADDR_ARRAY, AddrArray[total]); + *params->len = FIELD_OFFSET(DNS_ADDR_ARRAY, AddrArray[total]); return ERROR_SUCCESS; } @@ -239,24 +194,24 @@ static DNS_STATUS CDECL resolv_get_serverlist( USHORT family, DNS_ADDR_ARRAY *ad for (i = 0, found = 0; i < total; i++) { - if (filter( buf[i].sin.sin_family, family )) continue; + if (filter( buf[i].sin.sin_family, params->family )) continue; found++; } if (!found) return DNS_ERROR_NO_DNS_SERVERS; needed = FIELD_OFFSET(DNS_ADDR_ARRAY, AddrArray[found]); - if (!addrs || *len < needed) + if (!addrs || *params->len < needed) { - *len = needed; + *params->len = needed; return !addrs ? ERROR_SUCCESS : ERROR_MORE_DATA; } - *len = needed; + *params->len = needed; memset( addrs, 0, needed ); addrs->AddrCount = addrs->MaxCount = found; for (i = 0, found = 0; i < total; i++) { - if (filter( buf[i].sin.sin_family, family )) continue; + if (filter( buf[i].sin.sin_family, params->family )) continue; if (buf[i].sin6.sin6_family == AF_INET6) { @@ -281,16 +236,18 @@ static DNS_STATUS CDECL resolv_get_serverlist( USHORT family, DNS_ADDR_ARRAY *ad #else -static DNS_STATUS CDECL resolv_get_serverlist( USHORT family, DNS_ADDR_ARRAY *addrs, DWORD *len ) +static NTSTATUS resolv_get_serverlist( void *args ) { + struct get_serverlist_params *params = args; + DNS_ADDR_ARRAY *addrs = params->addrs; DWORD needed, found, i; init_resolver(); if (!_res.nscount) return DNS_ERROR_NO_DNS_SERVERS; - if (!addrs && family != WS_AF_INET && family != WS_AF_INET6) + if (!addrs && params->family != WS_AF_INET && params->family != WS_AF_INET6) { - *len = FIELD_OFFSET(DNS_ADDR_ARRAY, AddrArray[_res.nscount]); + *params->len = FIELD_OFFSET(DNS_ADDR_ARRAY, AddrArray[_res.nscount]); return ERROR_SUCCESS; } @@ -300,18 +257,18 @@ static DNS_STATUS CDECL resolv_get_serverlist( USHORT family, DNS_ADDR_ARRAY *ad #ifdef HAVE_STRUCT___RES_STATE__U__EXT_NSCOUNT6 if (_res._u._ext.nsaddrs[i]) sin_family = _res._u._ext.nsaddrs[i]->sin6_family; #endif - if (filter( sin_family, family )) continue; + if (filter( sin_family, params->family )) continue; found++; } if (!found) return DNS_ERROR_NO_DNS_SERVERS; needed = FIELD_OFFSET(DNS_ADDR_ARRAY, AddrArray[found]); - if (!addrs || *len < needed) + if (!addrs || *params->len < needed) { - *len = needed; + *params->len = needed; return !addrs ? ERROR_SUCCESS : ERROR_MORE_DATA; } - *len = needed; + *params->len = needed; memset( addrs, 0, needed ); addrs->AddrCount = addrs->MaxCount = found; @@ -321,7 +278,7 @@ static DNS_STATUS CDECL resolv_get_serverlist( USHORT family, DNS_ADDR_ARRAY *ad #ifdef HAVE_STRUCT___RES_STATE__U__EXT_NSCOUNT6 if (_res._u._ext.nsaddrs[i]) sin_family = _res._u._ext.nsaddrs[i]->sin6_family; #endif - if (filter( sin_family, family )) continue; + if (filter( sin_family, params->family )) continue; #ifdef HAVE_STRUCT___RES_STATE__U__EXT_NSCOUNT6 if (sin_family == AF_INET6) @@ -346,8 +303,10 @@ static DNS_STATUS CDECL resolv_get_serverlist( USHORT family, DNS_ADDR_ARRAY *ad } #endif -static DNS_STATUS CDECL resolv_set_serverlist( const IP4_ARRAY *addrs ) +static NTSTATUS resolv_set_serverlist( void *args ) { + struct set_serverlist_params *params = args; + const IP4_ARRAY *addrs = params->addrs; int i; init_resolver(); @@ -367,34 +326,28 @@ static DNS_STATUS CDECL resolv_set_serverlist( const IP4_ARRAY *addrs ) return ERROR_SUCCESS; } -static DNS_STATUS CDECL resolv_query( const char *name, WORD type, DWORD options, void *answer, DWORD *retlen ) +static NTSTATUS resolv_query( void *args ) { + struct query_params *params = args; DNS_STATUS ret = ERROR_SUCCESS; int len; init_resolver(); - _res.options |= map_options( options ); + _res.options |= map_options( params->options ); - if ((len = res_query( name, ns_c_in, type, answer, *retlen )) < 0) + if ((len = res_query( params->name, ns_c_in, params->type, params->buf, *params->len )) < 0) ret = map_h_errno( h_errno ); else - *retlen = len; + *params->len = len; return ret; } -static const struct resolv_funcs funcs = +unixlib_entry_t __wine_unix_call_funcs[] = { resolv_get_searchlist, resolv_get_serverlist, + resolv_set_serverlist, resolv_query, - resolv_set_serverlist }; -NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out ) -{ - if (reason != DLL_PROCESS_ATTACH) return STATUS_SUCCESS; - *(const struct resolv_funcs **)ptr_out = &funcs; - return STATUS_SUCCESS; -} - #endif /* HAVE_RESOLV */ diff --git a/dlls/dnsapi/main.c b/dlls/dnsapi/main.c index 3beef6a1fd3..5d766416ecc 100644 --- a/dlls/dnsapi/main.c +++ b/dlls/dnsapi/main.c @@ -26,12 +26,13 @@ #include "winbase.h" #include "winerror.h" #include "windns.h" +#include "dnsapi.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(dnsapi); -const struct resolv_funcs *resolv_funcs = NULL; +unixlib_handle_t resolv_handle = 0; BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) { @@ -41,7 +42,8 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) { case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls( hinst ); - if (__wine_init_unix_lib( hinst, reason, NULL, &resolv_funcs )) + if (NtQueryVirtualMemory( GetCurrentProcess(), hinst, MemoryWineUnixFuncs, + &resolv_handle, sizeof(resolv_handle), NULL )) ERR( "No libresolv support, expect problems\n" ); break; case DLL_PROCESS_DETACH: diff --git a/dlls/dnsapi/query.c b/dlls/dnsapi/query.c index 46405d344a8..e21527c15b3 100644 --- a/dlls/dnsapi/query.c +++ b/dlls/dnsapi/query.c @@ -170,6 +170,8 @@ DNS_STATUS WINAPI DnsQuery_UTF8( PCSTR name, WORD type, DWORD options, PVOID ser DNS_STATUS ret = DNS_ERROR_RCODE_NOT_IMPLEMENTED; unsigned char answer[4096]; DWORD len = sizeof(answer); + struct set_serverlist_params servlist_params = { servers }; + struct query_params query_params = { name, type, options, answer, &len }; TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_a(name), debugstr_type( type ), options, servers, result, reserved ); @@ -177,9 +179,9 @@ DNS_STATUS WINAPI DnsQuery_UTF8( PCSTR name, WORD type, DWORD options, PVOID ser if (!name || !result) return ERROR_INVALID_PARAMETER; - if ((ret = resolv_funcs->set_serverlist( servers ))) return ret; + if ((ret = RESOLV_CALL( set_serverlist, &servlist_params ))) return ret; - ret = resolv_funcs->query( name, type, options, answer, &len ); + ret = RESOLV_CALL( query, &query_params ); if (!ret) { DNS_MESSAGE_BUFFER *buffer = (DNS_MESSAGE_BUFFER *)answer; @@ -289,10 +291,10 @@ static DNS_STATUS get_dns_server_list( IP4_ARRAY *out, DWORD *len ) char buf[FIELD_OFFSET(DNS_ADDR_ARRAY, AddrArray[3])]; DNS_ADDR_ARRAY *servers = (DNS_ADDR_ARRAY *)buf; DWORD ret, needed, i, num, array_len = sizeof(buf); - + struct get_serverlist_params params = { AF_INET, servers, &array_len }; for (;;) { - ret = resolv_funcs->get_serverlist( AF_INET, servers, &array_len ); + ret = RESOLV_CALL( get_serverlist, ¶ms ); if (ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA) goto err; num = (array_len - FIELD_OFFSET(DNS_ADDR_ARRAY, AddrArray[0])) / sizeof(DNS_ADDR); needed = FIELD_OFFSET(IP4_ARRAY, AddrArray[num]); @@ -375,15 +377,25 @@ DNS_STATUS WINAPI DnsQueryConfig( DNS_CONFIG_TYPE config, DWORD flag, PCWSTR ada break; case DnsConfigDnsServersUnspec: - return resolv_funcs->get_serverlist( AF_UNSPEC, buffer, len ); + { + struct get_serverlist_params params = { AF_UNSPEC, buffer, len }; + return RESOLV_CALL( get_serverlist, ¶ms ); + } case DnsConfigDnsServersIpv4: - return resolv_funcs->get_serverlist( AF_INET, buffer, len ); + { + struct get_serverlist_params params = { AF_INET, buffer, len }; + return RESOLV_CALL( get_serverlist, ¶ms ); + } case DnsConfigDnsServersIpv6: - return resolv_funcs->get_serverlist( AF_INET6, buffer, len ); - + { + struct get_serverlist_params params = { AF_INET6, buffer, len }; + return RESOLV_CALL( get_serverlist, ¶ms ); + } case DnsConfigSearchList: - return resolv_funcs->get_searchlist( buffer, len ); - + { + struct get_searchlist_params params = { buffer, len }; + return RESOLV_CALL( get_searchlist, ¶ms ); + } default: WARN( "unknown config type: %d\n", config ); break;