[PATCH 3/5] dnsapi: Move libresolv support to a new Unix library.

Hans Leidekker hans at codeweavers.com
Tue Mar 30 03:35:28 CDT 2021


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/dnsapi/Makefile.in |   1 +
 dlls/dnsapi/dnsapi.h    |  19 +-
 dlls/dnsapi/libresolv.c | 742 ++++++++++++++++++++++++++++++++++++++++
 dlls/dnsapi/main.c      |  20 ++
 dlls/dnsapi/name.c      |  23 +-
 dlls/dnsapi/query.c     | 582 +------------------------------
 dlls/dnsapi/record.c    |  66 +---
 7 files changed, 809 insertions(+), 644 deletions(-)
 create mode 100644 dlls/dnsapi/libresolv.c

diff --git a/dlls/dnsapi/Makefile.in b/dlls/dnsapi/Makefile.in
index d1f66723fc6..a4f80e83fd4 100644
--- a/dlls/dnsapi/Makefile.in
+++ b/dlls/dnsapi/Makefile.in
@@ -4,6 +4,7 @@ IMPORTS   = netapi32
 EXTRALIBS = $(RESOLV_LIBS)
 
 C_SRCS = \
+	libresolv.c \
 	main.c \
 	name.c \
 	query.c \
diff --git a/dlls/dnsapi/dnsapi.h b/dlls/dnsapi/dnsapi.h
index d0a31ea0981..bcd6a6d5bc3 100644
--- a/dlls/dnsapi/dnsapi.h
+++ b/dlls/dnsapi/dnsapi.h
@@ -18,10 +18,6 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#ifndef __WINE_CONFIG_H
-# error You must include config.h to use this header
-#endif
-
 #include "wine/heap.h"
 
 static inline char *strdup_a( const char *src )
@@ -123,4 +119,17 @@ static inline char *strdup_ua( const char *src )
     return dst;
 }
 
-const char *type_to_str( unsigned short ) DECLSPEC_HIDDEN;
+extern const char *type_to_str( unsigned short ) DECLSPEC_HIDDEN;
+
+extern DNS_STATUS CDECL resolv_get_serverlist( IP4_ARRAY *, DWORD * ) DECLSPEC_HIDDEN;
+extern DNS_STATUS CDECL resolv_query( const char *, WORD, DWORD, DNS_RECORDA ** ) DECLSPEC_HIDDEN;
+extern DNS_STATUS CDECL resolv_set_serverlist( const IP4_ARRAY * ) DECLSPEC_HIDDEN;
+
+struct resolv_funcs
+{
+    DNS_STATUS (CDECL *get_serverlist)( IP4_ARRAY *addrs, DWORD *len );
+    DNS_STATUS (CDECL *query)( const char *name, WORD type, DWORD options, DNS_RECORDA **result );
+    DNS_STATUS (CDECL *set_serverlist)( const IP4_ARRAY *addrs );
+};
+
+extern const struct resolv_funcs *resolv_funcs;
diff --git a/dlls/dnsapi/libresolv.c b/dlls/dnsapi/libresolv.c
new file mode 100644
index 00000000000..ac52147af01
--- /dev/null
+++ b/dlls/dnsapi/libresolv.c
@@ -0,0 +1,742 @@
+/*
+ * Unix interface for libresolv
+ *
+ * Copyright 2021 Hans Leidekker for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#if 0
+#pragma makedep unix
+#endif
+
+#include "config.h"
+
+#ifdef HAVE_RESOLV
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#ifdef HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_NAMESER_H
+# include <arpa/nameser.h>
+#endif
+#ifdef HAVE_RESOLV_H
+# include <resolv.h>
+#endif
+#ifdef HAVE_NETDB_H
+# include <netdb.h>
+#endif
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winternl.h"
+#include "winbase.h"
+#include "winnls.h"
+#include "windns.h"
+
+#include "wine/debug.h"
+#include "wine/heap.h"
+#include "dnsapi.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dnsapi);
+
+static const char *debugstr_type( unsigned short type )
+{
+    const char *str;
+
+    switch (type)
+    {
+#define X(x)    case (x): str = #x; break;
+    X(DNS_TYPE_ZERO)
+    X(DNS_TYPE_A)
+    X(DNS_TYPE_NS)
+    X(DNS_TYPE_MD)
+    X(DNS_TYPE_MF)
+    X(DNS_TYPE_CNAME)
+    X(DNS_TYPE_SOA)
+    X(DNS_TYPE_MB)
+    X(DNS_TYPE_MG)
+    X(DNS_TYPE_MR)
+    X(DNS_TYPE_NULL)
+    X(DNS_TYPE_WKS)
+    X(DNS_TYPE_PTR)
+    X(DNS_TYPE_HINFO)
+    X(DNS_TYPE_MINFO)
+    X(DNS_TYPE_MX)
+    X(DNS_TYPE_TEXT)
+    X(DNS_TYPE_RP)
+    X(DNS_TYPE_AFSDB)
+    X(DNS_TYPE_X25)
+    X(DNS_TYPE_ISDN)
+    X(DNS_TYPE_RT)
+    X(DNS_TYPE_NSAP)
+    X(DNS_TYPE_NSAPPTR)
+    X(DNS_TYPE_SIG)
+    X(DNS_TYPE_KEY)
+    X(DNS_TYPE_PX)
+    X(DNS_TYPE_GPOS)
+    X(DNS_TYPE_AAAA)
+    X(DNS_TYPE_LOC)
+    X(DNS_TYPE_NXT)
+    X(DNS_TYPE_EID)
+    X(DNS_TYPE_NIMLOC)
+    X(DNS_TYPE_SRV)
+    X(DNS_TYPE_ATMA)
+    X(DNS_TYPE_NAPTR)
+    X(DNS_TYPE_KX)
+    X(DNS_TYPE_CERT)
+    X(DNS_TYPE_A6)
+    X(DNS_TYPE_DNAME)
+    X(DNS_TYPE_SINK)
+    X(DNS_TYPE_OPT)
+    X(DNS_TYPE_UINFO)
+    X(DNS_TYPE_UID)
+    X(DNS_TYPE_GID)
+    X(DNS_TYPE_UNSPEC)
+    X(DNS_TYPE_ADDRS)
+    X(DNS_TYPE_TKEY)
+    X(DNS_TYPE_TSIG)
+    X(DNS_TYPE_IXFR)
+    X(DNS_TYPE_AXFR)
+    X(DNS_TYPE_MAILB)
+    X(DNS_TYPE_MAILA)
+    X(DNS_TYPE_ANY)
+    X(DNS_TYPE_WINS)
+    X(DNS_TYPE_WINSR)
+#undef X
+    default:
+        return wine_dbg_sprintf( "0x%04x", type );
+    }
+
+    return wine_dbg_sprintf( "%s", str );
+}
+
+static const char *debugstr_section( ns_sect section )
+{
+    switch (section)
+    {
+    case ns_s_qd:   return "Question";
+    case ns_s_an:   return "Answer";
+    case ns_s_ns:   return "Authority";
+    case ns_s_ar:   return "Additional";
+    default:
+        return wine_dbg_sprintf( "0x%02x", section );
+    }
+}
+
+/* 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 )
+{
+    if (!(_res.options & RES_INIT)) res_init();
+}
+
+static unsigned long map_options( DWORD options )
+{
+    unsigned long ret = 0;
+
+    if (options == DNS_QUERY_STANDARD)
+        return RES_DEFAULT;
+
+    if (options & DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE)
+        ret |= RES_IGNTC;
+    if (options & DNS_QUERY_USE_TCP_ONLY)
+        ret |= RES_USEVC;
+    if (options & DNS_QUERY_NO_RECURSION)
+        ret &= ~RES_RECURSE;
+    if (options & DNS_QUERY_NO_LOCAL_NAME)
+        ret &= ~RES_DNSRCH;
+    if (options & DNS_QUERY_NO_HOSTS_FILE)
+        ret |= RES_NOALIASES;
+    if (options & DNS_QUERY_TREAT_AS_FQDN)
+        ret &= ~RES_DEFNAMES;
+
+    if (options & DNS_QUERY_DONT_RESET_TTL_VALUES)
+        FIXME( "option DNS_QUERY_DONT_RESET_TTL_VALUES not implemented\n" );
+    if (options & DNS_QUERY_RESERVED)
+        FIXME( "option DNS_QUERY_RESERVED not implemented\n" );
+    if (options & DNS_QUERY_WIRE_ONLY)
+        FIXME( "option DNS_QUERY_WIRE_ONLY not implemented\n" );
+    if (options & DNS_QUERY_NO_WIRE_QUERY)
+        FIXME( "option DNS_QUERY_NO_WIRE_QUERY not implemented\n" );
+    if (options & DNS_QUERY_BYPASS_CACHE)
+        FIXME( "option DNS_QUERY_BYPASS_CACHE not implemented\n" );
+    if (options & DNS_QUERY_RETURN_MESSAGE)
+        FIXME( "option DNS_QUERY_RETURN_MESSAGE not implemented\n" );
+
+    if (options & DNS_QUERY_NO_NETBT)
+        TRACE( "netbios query disabled\n" );
+
+    return ret;
+}
+
+static DNS_STATUS map_error( int error )
+{
+    switch (error)
+    {
+    case ns_r_noerror:  return ERROR_SUCCESS;
+    case ns_r_formerr:  return DNS_ERROR_RCODE_FORMAT_ERROR;
+    case ns_r_servfail: return DNS_ERROR_RCODE_SERVER_FAILURE;
+    case ns_r_nxdomain: return DNS_ERROR_RCODE_NAME_ERROR;
+    case ns_r_notimpl:  return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
+    case ns_r_refused:  return DNS_ERROR_RCODE_REFUSED;
+    case ns_r_yxdomain: return DNS_ERROR_RCODE_YXDOMAIN;
+    case ns_r_yxrrset:  return DNS_ERROR_RCODE_YXRRSET;
+    case ns_r_nxrrset:  return DNS_ERROR_RCODE_NXRRSET;
+    case ns_r_notauth:  return DNS_ERROR_RCODE_NOTAUTH;
+    case ns_r_notzone:  return DNS_ERROR_RCODE_NOTZONE;
+    default:
+        FIXME( "unmapped error code: %d\n", error );
+        return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
+    }
+}
+
+static DNS_STATUS map_h_errno( int error )
+{
+    switch (error)
+    {
+    case NO_DATA:
+    case HOST_NOT_FOUND: return DNS_ERROR_RCODE_NAME_ERROR;
+    case TRY_AGAIN:      return DNS_ERROR_RCODE_SERVER_FAILURE;
+    case NO_RECOVERY:    return DNS_ERROR_RCODE_REFUSED;
+#ifdef NETDB_INTERNAL
+    case NETDB_INTERNAL: return DNS_ERROR_RCODE;
+#endif
+    default:
+        FIXME( "unmapped error code: %d\n", error );
+        return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
+    }
+}
+
+DNS_STATUS CDECL resolv_get_serverlist( IP4_ARRAY *addrs, DWORD *len )
+{
+    unsigned int size;
+    int i;
+
+    init_resolver();
+
+    size = FIELD_OFFSET(IP4_ARRAY, AddrArray[_res.nscount]);
+    if (!addrs || *len < size)
+    {
+        *len = size;
+        return ERROR_INSUFFICIENT_BUFFER;
+    }
+
+    addrs->AddrCount = _res.nscount;
+
+    for (i = 0; i < _res.nscount; i++)
+        addrs->AddrArray[i] = _res.nsaddr_list[i].sin_addr.s_addr;
+
+    return ERROR_SUCCESS;
+}
+
+DNS_STATUS CDECL resolv_set_serverlist( const IP4_ARRAY *addrs )
+{
+    int i;
+
+    init_resolver();
+
+    if (!addrs || !addrs->AddrCount) return ERROR_SUCCESS;
+    if (addrs->AddrCount > MAXNS)
+    {
+        WARN( "too many servers: %d only using the first: %d\n",
+              addrs->AddrCount, MAXNS );
+        _res.nscount = MAXNS;
+    }
+    else _res.nscount = addrs->AddrCount;
+
+    for (i = 0; i < _res.nscount; i++)
+        _res.nsaddr_list[i].sin_addr.s_addr = addrs->AddrArray[i];
+
+    return ERROR_SUCCESS;
+}
+
+static char *dname_from_msg( ns_msg msg, const unsigned char *pos )
+{
+    char *str, dname[NS_MAXDNAME] = ".";
+
+    /* returns *compressed* length, ignore it */
+    ns_name_uncompress( ns_msg_base(msg), ns_msg_end(msg), pos, dname, sizeof(dname) );
+
+    if ((str = RtlAllocateHeap( GetProcessHeap(), 0, strlen(dname) + 1 ))) strcpy( str, dname );
+    return str;
+}
+
+static char *str_from_rdata( const unsigned char *rdata )
+{
+    char *str;
+    unsigned int len = rdata[0];
+
+    if ((str = RtlAllocateHeap( GetProcessHeap(), 0, len + 1 )))
+    {
+        memcpy( str, ++rdata, len );
+        str[len] = 0;
+    }
+    return str;
+}
+
+static unsigned int get_record_size( const ns_rr *rr )
+{
+    const unsigned char *pos = rr->rdata;
+    unsigned int num = 0, size = sizeof(DNS_RECORDA);
+
+    switch (rr->type)
+    {
+    case ns_t_key:
+    {
+        pos += sizeof(WORD) + sizeof(BYTE) + sizeof(BYTE);
+        size += rr->rdata + rr->rdlength - pos - 1;
+        break;
+    }
+    case ns_t_sig:
+    {
+        pos += sizeof(PCHAR) + sizeof(WORD) + 2 * sizeof(BYTE);
+        pos += 3 * sizeof(DWORD) + 2 * sizeof(WORD);
+        size += rr->rdata + rr->rdlength - pos - 1;
+        break;
+    }
+    case ns_t_hinfo:
+    case ns_t_isdn:
+    case ns_t_txt:
+    case ns_t_x25:
+    {
+        while (pos[0] && pos < rr->rdata + rr->rdlength)
+        {
+            num++;
+            pos += pos[0] + 1;
+        }
+        size += (num - 1) * sizeof(PCHAR);
+        break;
+    }
+    case ns_t_null:
+    case ns_t_opt:
+    {
+        size += rr->rdlength - 1;
+        break;
+    }
+    case ns_t_nxt:
+    case ns_t_wks:
+    case 0xff01:  /* WINS */
+    {
+        FIXME( "unhandled type: %s\n", debugstr_type( rr->type ) );
+        break;
+    }
+    default:
+        break;
+    }
+    return size;
+}
+
+static DNS_STATUS copy_rdata( ns_msg msg, const ns_rr *rr, DNS_RECORDA *r, WORD *dlen )
+{
+    DNS_STATUS ret = ERROR_SUCCESS;
+    const unsigned char *pos = rr->rdata;
+    unsigned int i, size;
+
+    switch (rr->type)
+    {
+    case ns_t_a:
+    {
+        r->Data.A.IpAddress = *(const DWORD *)pos;
+        *dlen = sizeof(DNS_A_DATA);
+        break;
+    }
+    case ns_t_aaaa:
+    {
+        for (i = 0; i < sizeof(IP6_ADDRESS)/sizeof(DWORD); i++)
+        {
+            r->Data.AAAA.Ip6Address.IP6Dword[i] = *(const DWORD *)pos;
+            pos += sizeof(DWORD);
+        }
+
+        *dlen = sizeof(DNS_AAAA_DATA);
+        break;
+    }
+    case ns_t_key:
+    {
+        /* FIXME: byte order? */
+        r->Data.KEY.wFlags      = *(const WORD *)pos;   pos += sizeof(WORD);
+        r->Data.KEY.chProtocol  = *pos++;
+        r->Data.KEY.chAlgorithm = *pos++;
+
+        size = rr->rdata + rr->rdlength - pos;
+
+        for (i = 0; i < size; i++)
+            r->Data.KEY.Key[i] = *pos++;
+
+        *dlen = sizeof(DNS_KEY_DATA) + (size - 1) * sizeof(BYTE);
+        break;
+    }
+    case ns_t_rp:
+    case ns_t_minfo:
+    {
+        r->Data.MINFO.pNameMailbox = dname_from_msg( msg, pos );
+        if (!r->Data.MINFO.pNameMailbox) return ERROR_NOT_ENOUGH_MEMORY;
+
+        if (ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
+            return DNS_ERROR_BAD_PACKET;
+
+        r->Data.MINFO.pNameErrorsMailbox = dname_from_msg( msg, pos );
+        if (!r->Data.MINFO.pNameErrorsMailbox)
+        {
+            RtlFreeHeap( GetProcessHeap(), 0, r->Data.MINFO.pNameMailbox );
+            return ERROR_NOT_ENOUGH_MEMORY;
+        }
+
+        *dlen = sizeof(DNS_MINFO_DATAA);
+        break;
+    }
+    case ns_t_afsdb:
+    case ns_t_rt:
+    case ns_t_mx:
+    {
+        r->Data.MX.wPreference = ntohs( *(const WORD *)pos );
+        r->Data.MX.pNameExchange = dname_from_msg( msg, pos + sizeof(WORD) );
+        if (!r->Data.MX.pNameExchange) return ERROR_NOT_ENOUGH_MEMORY;
+
+        *dlen = sizeof(DNS_MX_DATAA);
+        break;
+    }
+    case ns_t_null:
+    {
+        r->Data.Null.dwByteCount = rr->rdlength;
+        memcpy( r->Data.Null.Data, rr->rdata, rr->rdlength );
+
+        *dlen = sizeof(DNS_NULL_DATA) + rr->rdlength - 1;
+        break;
+    }
+    case ns_t_opt:
+    {
+        r->Data.OPT.wDataLength = rr->rdlength;
+        r->Data.OPT.wPad        = 0;
+        memcpy( r->Data.OPT.Data, rr->rdata, rr->rdlength );
+
+        *dlen = sizeof(DNS_OPT_DATA) + rr->rdlength - 1;
+        break;
+    }
+    case ns_t_cname:
+    case ns_t_ns:
+    case ns_t_mb:
+    case ns_t_md:
+    case ns_t_mf:
+    case ns_t_mg:
+    case ns_t_mr:
+    case ns_t_ptr:
+    {
+        r->Data.PTR.pNameHost = dname_from_msg( msg, pos );
+        if (!r->Data.PTR.pNameHost) return ERROR_NOT_ENOUGH_MEMORY;
+
+        *dlen = sizeof(DNS_PTR_DATAA);
+        break;
+    }
+    case ns_t_sig:
+    {
+        r->Data.SIG.pNameSigner = dname_from_msg( msg, pos );
+        if (!r->Data.SIG.pNameSigner) return ERROR_NOT_ENOUGH_MEMORY;
+
+        if (ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
+            return DNS_ERROR_BAD_PACKET;
+
+        /* FIXME: byte order? */
+        r->Data.SIG.wTypeCovered  = *(const WORD *)pos;   pos += sizeof(WORD);
+        r->Data.SIG.chAlgorithm   = *pos++;
+        r->Data.SIG.chLabelCount  = *pos++;
+        r->Data.SIG.dwOriginalTtl = *(const DWORD *)pos;  pos += sizeof(DWORD);
+        r->Data.SIG.dwExpiration  = *(const DWORD *)pos;  pos += sizeof(DWORD);
+        r->Data.SIG.dwTimeSigned  = *(const DWORD *)pos;  pos += sizeof(DWORD);
+        r->Data.SIG.wKeyTag       = *(const WORD *)pos;
+
+        size = rr->rdata + rr->rdlength - pos;
+
+        for (i = 0; i < size; i++)
+            r->Data.SIG.Signature[i] = *pos++;
+
+        *dlen = sizeof(DNS_SIG_DATAA) + (size - 1) * sizeof(BYTE);
+        break;
+    }
+    case ns_t_soa:
+    {
+        r->Data.SOA.pNamePrimaryServer = dname_from_msg( msg, pos );
+        if (!r->Data.SOA.pNamePrimaryServer) return ERROR_NOT_ENOUGH_MEMORY;
+
+        if (ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
+            return DNS_ERROR_BAD_PACKET;
+
+        r->Data.SOA.pNameAdministrator = dname_from_msg( msg, pos );
+        if (!r->Data.SOA.pNameAdministrator)
+        {
+            RtlFreeHeap( GetProcessHeap(), 0, r->Data.SOA.pNamePrimaryServer );
+            return ERROR_NOT_ENOUGH_MEMORY;
+        }
+
+        if (ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
+            return DNS_ERROR_BAD_PACKET;
+
+        r->Data.SOA.dwSerialNo   = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
+        r->Data.SOA.dwRefresh    = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
+        r->Data.SOA.dwRetry      = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
+        r->Data.SOA.dwExpire     = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
+        r->Data.SOA.dwDefaultTtl = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
+
+        *dlen = sizeof(DNS_SOA_DATAA);
+        break;
+    }
+    case ns_t_srv:
+    {
+        r->Data.SRV.wPriority = ntohs( *(const WORD *)pos ); pos += sizeof(WORD);
+        r->Data.SRV.wWeight   = ntohs( *(const WORD *)pos ); pos += sizeof(WORD);
+        r->Data.SRV.wPort     = ntohs( *(const WORD *)pos ); pos += sizeof(WORD);
+
+        r->Data.SRV.pNameTarget = dname_from_msg( msg, pos );
+        if (!r->Data.SRV.pNameTarget) return ERROR_NOT_ENOUGH_MEMORY;
+
+        *dlen = sizeof(DNS_SRV_DATAA);
+        break;
+    }
+    case ns_t_hinfo:
+    case ns_t_isdn:
+    case ns_t_x25:
+    case ns_t_txt:
+    {
+        i = 0;
+        while (pos[0] && pos < rr->rdata + rr->rdlength)
+        {
+            r->Data.TXT.pStringArray[i] = str_from_rdata( pos );
+            if (!r->Data.TXT.pStringArray[i])
+            {
+                while (i > 0) RtlFreeHeap( GetProcessHeap(), 0, r->Data.TXT.pStringArray[--i] );
+                return ERROR_NOT_ENOUGH_MEMORY;
+            }
+            i++;
+            pos += pos[0] + 1;
+        }
+        r->Data.TXT.dwStringCount = i;
+        *dlen = sizeof(DNS_TXT_DATAA) + (i - 1) * sizeof(PCHAR);
+        break;
+    }
+    case ns_t_atma:
+    case ns_t_loc:
+    case ns_t_nxt:
+    case ns_t_tsig:
+    case ns_t_wks:
+    case 0x00f9:  /* TKEY */
+    case 0xff01:  /* WINS */
+    case 0xff02:  /* WINSR */
+    default:
+        FIXME( "unhandled type: %s\n", debugstr_type( rr->type ) );
+        return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
+    }
+
+    return ret;
+}
+
+static inline char *heap_strdup( const char *src )
+{
+    char *dst;
+    if (!src) return NULL;
+    if ((dst = RtlAllocateHeap( GetProcessHeap(), 0, (strlen( src ) + 1) * sizeof(char) ))) strcpy( dst, src );
+    return dst;
+}
+
+static DNS_STATUS copy_record( ns_msg msg, ns_sect section, unsigned short num, DNS_RECORDA **recp )
+{
+    DNS_STATUS ret;
+    DNS_RECORDA *record;
+    WORD dlen;
+    ns_rr rr;
+
+    if (ns_parserr( &msg, section, num, &rr ) < 0)
+        return DNS_ERROR_BAD_PACKET;
+
+    if (!(record = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, get_record_size( &rr ) )))
+        return ERROR_NOT_ENOUGH_MEMORY;
+
+    if (!(record->pName = heap_strdup( rr.name )))
+    {
+        RtlFreeHeap( GetProcessHeap(), 0, record );
+        return ERROR_NOT_ENOUGH_MEMORY;
+    }
+
+    record->wType = rr.type;
+    record->Flags.S.Section = section;
+    record->Flags.S.CharSet = DnsCharSetUtf8;
+    record->dwTtl = rr.ttl;
+
+    if ((ret = copy_rdata( msg, &rr, record, &dlen )))
+    {
+        RtlFreeHeap( GetProcessHeap(), 0, record->pName );
+        RtlFreeHeap( GetProcessHeap(), 0, record );
+        return ret;
+    }
+    record->wDataLength = dlen;
+    *recp = record;
+
+    TRACE( "found %s record in %s section\n", debugstr_type( rr.type ), debugstr_section( section ) );
+    return ERROR_SUCCESS;
+}
+
+static void free_record_list( DNS_RECORD *list )
+{
+    DNS_RECORD *r, *next;
+    unsigned int i;
+
+    for (r = list; (list = r); r = next)
+    {
+        RtlFreeHeap( GetProcessHeap(), 0, r->pName );
+
+        switch (r->wType)
+        {
+        case DNS_TYPE_HINFO:
+        case DNS_TYPE_ISDN:
+        case DNS_TYPE_TEXT:
+        case DNS_TYPE_X25:
+        {
+            for (i = 0; i < r->Data.TXT.dwStringCount; i++)
+                RtlFreeHeap( GetProcessHeap(), 0, r->Data.TXT.pStringArray[i] );
+            break;
+        }
+        case DNS_TYPE_MINFO:
+        case DNS_TYPE_RP:
+        {
+            RtlFreeHeap( GetProcessHeap(), 0, r->Data.MINFO.pNameMailbox );
+            RtlFreeHeap( GetProcessHeap(), 0, r->Data.MINFO.pNameErrorsMailbox );
+            break;
+        }
+        case DNS_TYPE_AFSDB:
+        case DNS_TYPE_RT:
+        case DNS_TYPE_MX:
+        {
+            RtlFreeHeap( GetProcessHeap(), 0, r->Data.MX.pNameExchange );
+            break;
+        }
+        case DNS_TYPE_NXT:
+        {
+            RtlFreeHeap( GetProcessHeap(), 0, r->Data.NXT.pNameNext );
+            break;
+        }
+        case DNS_TYPE_CNAME:
+        case DNS_TYPE_MB:
+        case DNS_TYPE_MD:
+        case DNS_TYPE_MF:
+        case DNS_TYPE_MG:
+        case DNS_TYPE_MR:
+        case DNS_TYPE_NS:
+        case DNS_TYPE_PTR:
+        {
+            RtlFreeHeap( GetProcessHeap(), 0, r->Data.PTR.pNameHost );
+            break;
+        }
+        case DNS_TYPE_SIG:
+        {
+            RtlFreeHeap( GetProcessHeap(), 0, r->Data.SIG.pNameSigner );
+            break;
+        }
+        case DNS_TYPE_SOA:
+        {
+            RtlFreeHeap( GetProcessHeap(), 0, r->Data.SOA.pNamePrimaryServer );
+            RtlFreeHeap( GetProcessHeap(), 0, r->Data.SOA.pNameAdministrator );
+            break;
+        }
+        case DNS_TYPE_SRV:
+        {
+            RtlFreeHeap( GetProcessHeap(), 0, r->Data.SRV.pNameTarget );
+            break;
+        }
+        default: break;
+        }
+
+        next = r->pNext;
+        RtlFreeHeap( GetProcessHeap(), 0, r );
+    }
+}
+
+#define DNS_MAX_PACKET_SIZE 4096
+DNS_STATUS CDECL resolv_query( const char *name, WORD type, DWORD options, DNS_RECORDA **result )
+{
+    DNS_STATUS ret = DNS_ERROR_RCODE_NOT_IMPLEMENTED;
+    unsigned int i, num;
+    unsigned char answer[DNS_MAX_PACKET_SIZE];
+    ns_sect sections[] = { ns_s_an, ns_s_ar };
+    ns_msg msg;
+    DNS_RECORDA *record = NULL;
+    DNS_RRSET rrset;
+    int len;
+
+    DNS_RRSET_INIT( rrset );
+
+    init_resolver();
+    _res.options |= map_options( options );
+
+    if ((len = res_query( name, ns_c_in, type, answer, sizeof(answer) )) < 0)
+    {
+        ret = map_h_errno( h_errno );
+        goto exit;
+    }
+
+    if (ns_initparse( answer, len, &msg ) < 0)
+    {
+        ret = DNS_ERROR_BAD_PACKET;
+        goto exit;
+    }
+
+#define RCODE_MASK 0x0f
+    if ((msg._flags & RCODE_MASK) != ns_r_noerror)
+    {
+        ret = map_error( msg._flags & RCODE_MASK );
+        goto exit;
+    }
+
+    for (i = 0; i < ARRAY_SIZE(sections); i++)
+    {
+        for (num = 0; num < ns_msg_count( msg, sections[i] ); num++)
+        {
+            ret = copy_record( msg, sections[i], num, &record );
+            if (ret != ERROR_SUCCESS) goto exit;
+
+            DNS_RRSET_ADD( rrset, (DNS_RECORD *)record );
+        }
+    }
+
+exit:
+    DNS_RRSET_TERMINATE( rrset );
+
+    if (ret != ERROR_SUCCESS)
+        free_record_list( rrset.pFirstRR );
+    else
+        *result = (DNS_RECORDA *)rrset.pFirstRR;
+
+    return ret;
+}
+
+static const struct resolv_funcs funcs =
+{
+    resolv_get_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 4ab294c7c07..f83a54d1469 100644
--- a/dlls/dnsapi/main.c
+++ b/dlls/dnsapi/main.c
@@ -22,6 +22,7 @@
 #include <stdarg.h>
 
 #include "windef.h"
+#include "winternl.h"
 #include "winbase.h"
 #include "winerror.h"
 #include "windns.h"
@@ -30,6 +31,25 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dnsapi);
 
+const struct resolv_funcs *resolv_funcs = NULL;
+
+BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
+{
+    TRACE( "(%p,%u,%p)\n", hinst, reason, reserved );
+
+    switch (reason)
+    {
+    case DLL_PROCESS_ATTACH:
+        DisableThreadLibraryCalls( hinst );
+        if (__wine_init_unix_lib( hinst, reason, NULL, &resolv_funcs ))
+            ERR( "No libresolv support, expect problems\n" );
+        break;
+    case DLL_PROCESS_DETACH:
+        break;
+    }
+    return TRUE;
+}
+
 /******************************************************************************
  * DnsAcquireContextHandle_A              [DNSAPI.@]
  *
diff --git a/dlls/dnsapi/name.c b/dlls/dnsapi/name.c
index 9404200e443..4f4ba507cac 100644
--- a/dlls/dnsapi/name.c
+++ b/dlls/dnsapi/name.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2006 Matthew Kehrer
  * Copyright (C) 2006 Hans Leidekker
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
@@ -19,30 +19,15 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "config.h"
-#include "wine/debug.h"
-#include "wine/unicode.h"
-
 #include <stdarg.h>
-#include <sys/types.h>
-
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-#ifdef HAVE_ARPA_NAMESER_H
-# include <arpa/nameser.h>
-# undef NOERROR
-#endif
-#ifdef HAVE_RESOLV_H
-# include <resolv.h>
-#endif
-
 #include "windef.h"
 #include "winbase.h"
 #include "winerror.h"
 #include "winnls.h"
 #include "windns.h"
 
+#include "wine/debug.h"
+#include "wine/unicode.h"
 #include "dnsapi.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(dnsapi);
@@ -81,7 +66,7 @@ BOOL WINAPI DnsNameCompare_W( PCWSTR name1, PCWSTR name2 )
 
     if (!name1 && !name2) return TRUE;
     if (!name1 || !name2) return FALSE;
- 
+
     p = name1 + lstrlenW( name1 ) - 1;
     q = name2 + lstrlenW( name2 ) - 1;
 
diff --git a/dlls/dnsapi/query.c b/dlls/dnsapi/query.c
index 3bef65e9731..a7ae77148be 100644
--- a/dlls/dnsapi/query.c
+++ b/dlls/dnsapi/query.c
@@ -2,7 +2,7 @@
  * DNS support
  *
  * Copyright (C) 2006 Hans Leidekker
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
@@ -18,28 +18,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "config.h"
-#include "wine/port.h"
-#include "wine/debug.h"
-
 #include <stdarg.h>
-#include <string.h>
-#include <stdio.h>
-#include <sys/types.h>
-
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-#ifdef HAVE_ARPA_NAMESER_H
-# include <arpa/nameser.h>
-#endif
-#ifdef HAVE_RESOLV_H
-# include <resolv.h>
-#endif
-#ifdef HAVE_NETDB_H
-# include <netdb.h>
-#endif
-
 #include "windef.h"
 #include "winbase.h"
 #include "winerror.h"
@@ -47,438 +26,11 @@
 #include "windns.h"
 #include "nb30.h"
 
+#include "wine/debug.h"
 #include "dnsapi.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(dnsapi);
 
-#ifdef HAVE_RESOLV
-
-/* 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 initialise_resolver( void )
-{
-    if ((_res.options & RES_INIT) == 0)
-        res_init();
-}
-
-static const char *section_to_str( ns_sect section )
-{
-    switch (section)
-    {
-    case ns_s_qd:   return "Question";
-    case ns_s_an:   return "Answer";
-    case ns_s_ns:   return "Authority";
-    case ns_s_ar:   return "Additional";
-    default:
-    {
-        static char tmp[11];
-        FIXME( "unknown section: 0x%02x\n", section );
-        sprintf( tmp, "0x%02x", section );
-        return tmp;
-    }
-    }
-}
-
-static unsigned long map_options( DWORD options )
-{
-    unsigned long ret = 0;
-            
-    if (options == DNS_QUERY_STANDARD)
-        return RES_DEFAULT;
-
-    if (options & DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE)
-        ret |= RES_IGNTC;
-    if (options & DNS_QUERY_USE_TCP_ONLY)
-        ret |= RES_USEVC;
-    if (options & DNS_QUERY_NO_RECURSION)
-        ret &= ~RES_RECURSE;
-    if (options & DNS_QUERY_NO_LOCAL_NAME)
-        ret &= ~RES_DNSRCH;
-    if (options & DNS_QUERY_NO_HOSTS_FILE)
-        ret |= RES_NOALIASES;
-    if (options & DNS_QUERY_TREAT_AS_FQDN)
-        ret &= ~RES_DEFNAMES;
-
-    if (options & DNS_QUERY_DONT_RESET_TTL_VALUES)
-        FIXME( "option DNS_QUERY_DONT_RESET_TTL_VALUES not implemented\n" );
-    if (options & DNS_QUERY_RESERVED)
-        FIXME( "option DNS_QUERY_RESERVED not implemented\n" );
-    if (options & DNS_QUERY_WIRE_ONLY)
-        FIXME( "option DNS_QUERY_WIRE_ONLY not implemented\n" );
-    if (options & DNS_QUERY_NO_WIRE_QUERY)
-        FIXME( "option DNS_QUERY_NO_WIRE_QUERY not implemented\n" );
-    if (options & DNS_QUERY_BYPASS_CACHE)
-        FIXME( "option DNS_QUERY_BYPASS_CACHE not implemented\n" );
-    if (options & DNS_QUERY_RETURN_MESSAGE)
-        FIXME( "option DNS_QUERY_RETURN_MESSAGE not implemented\n" );
-
-    if (options & DNS_QUERY_NO_NETBT)
-        TRACE( "netbios query disabled\n" );
-
-    return ret;
-}
-
-static DNS_STATUS map_error( int error )
-{
-    switch (error)
-    {
-    case ns_r_noerror:  return ERROR_SUCCESS;
-    case ns_r_formerr:  return DNS_ERROR_RCODE_FORMAT_ERROR;
-    case ns_r_servfail: return DNS_ERROR_RCODE_SERVER_FAILURE;
-    case ns_r_nxdomain: return DNS_ERROR_RCODE_NAME_ERROR;
-    case ns_r_notimpl:  return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
-    case ns_r_refused:  return DNS_ERROR_RCODE_REFUSED;
-    case ns_r_yxdomain: return DNS_ERROR_RCODE_YXDOMAIN;
-    case ns_r_yxrrset:  return DNS_ERROR_RCODE_YXRRSET;
-    case ns_r_nxrrset:  return DNS_ERROR_RCODE_NXRRSET;
-    case ns_r_notauth:  return DNS_ERROR_RCODE_NOTAUTH;
-    case ns_r_notzone:  return DNS_ERROR_RCODE_NOTZONE;
-    default:
-        FIXME( "unmapped error code: %d\n", error );
-        return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
-    }
-}
-
-static DNS_STATUS map_h_errno( int error )
-{
-    switch (error)
-    {
-    case NO_DATA:
-    case HOST_NOT_FOUND: return DNS_ERROR_RCODE_NAME_ERROR;
-    case TRY_AGAIN:      return DNS_ERROR_RCODE_SERVER_FAILURE;
-    case NO_RECOVERY:    return DNS_ERROR_RCODE_REFUSED;
-#ifdef NETDB_INTERNAL
-    case NETDB_INTERNAL: return DNS_ERROR_RCODE;
-#endif
-    default:
-        FIXME( "unmapped error code: %d\n", error );
-        return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
-    }
-}
-
-static char *dname_from_msg( ns_msg msg, const unsigned char *pos )
-{
-    int len;
-    char *str, dname[NS_MAXDNAME] = ".";
-
-    /* returns *compressed* length, ignore it */
-    ns_name_uncompress( ns_msg_base(msg), ns_msg_end(msg), pos, dname, sizeof(dname) );
-
-    len = strlen( dname );
-    str = heap_alloc( len + 1 );
-    if (str) strcpy( str, dname );
-    return str;
-}
-
-static char *str_from_rdata( const unsigned char *rdata )
-{
-    char *str;
-    unsigned int len = rdata[0];
-
-    str = heap_alloc( len + 1 );
-    if (str)
-    {
-        memcpy( str, ++rdata, len );
-        str[len] = '\0';
-    }
-    return str;
-}
-
-static unsigned int get_record_size( const ns_rr *rr )
-{
-    const unsigned char *pos = rr->rdata;
-    unsigned int num = 0, size = sizeof(DNS_RECORDA);
-
-    switch (rr->type)
-    {
-    case ns_t_key:
-    {
-        pos += sizeof(WORD) + sizeof(BYTE) + sizeof(BYTE);
-        size += rr->rdata + rr->rdlength - pos - 1;
-        break;
-    }
-    case ns_t_sig:
-    {
-        pos += sizeof(PCHAR) + sizeof(WORD) + 2 * sizeof(BYTE);
-        pos += 3 * sizeof(DWORD) + 2 * sizeof(WORD);
-        size += rr->rdata + rr->rdlength - pos - 1;
-        break;
-    }
-    case ns_t_hinfo:
-    case ns_t_isdn:
-    case ns_t_txt:
-    case ns_t_x25:
-    {
-        while (pos[0] && pos < rr->rdata + rr->rdlength)
-        {
-            num++;
-            pos += pos[0] + 1;
-        }
-        size += (num - 1) * sizeof(PCHAR);
-        break;
-    }
-    case ns_t_null:
-    case ns_t_opt:
-    {
-        size += rr->rdlength - 1;
-        break;
-    }
-    case ns_t_nxt:
-    case ns_t_wks:
-    case 0xff01:  /* WINS */
-    {
-        FIXME( "unhandled type: %s\n", type_to_str( rr->type ) );
-        break;
-    }
-    default:
-        break;
-    }
-    return size;
-}
-
-static DNS_STATUS copy_rdata( ns_msg msg, const ns_rr *rr, DNS_RECORDA *r, WORD *dlen )
-{
-    DNS_STATUS ret = ERROR_SUCCESS;
-    const unsigned char *pos = rr->rdata;
-    unsigned int i, size;
-
-    switch (rr->type)
-    {
-    case ns_t_a:
-    {
-        r->Data.A.IpAddress = *(const DWORD *)pos;
-        *dlen = sizeof(DNS_A_DATA);
-        break; 
-    }
-    case ns_t_aaaa:
-    {
-        for (i = 0; i < sizeof(IP6_ADDRESS)/sizeof(DWORD); i++)
-        {
-            r->Data.AAAA.Ip6Address.IP6Dword[i] = *(const DWORD *)pos;
-            pos += sizeof(DWORD);
-        }
-
-        *dlen = sizeof(DNS_AAAA_DATA);
-        break;
-    }
-    case ns_t_key:
-    {
-        /* FIXME: byte order? */
-        r->Data.KEY.wFlags      = *(const WORD *)pos;   pos += sizeof(WORD);
-        r->Data.KEY.chProtocol  = *pos++;
-        r->Data.KEY.chAlgorithm = *pos++;
-
-        size = rr->rdata + rr->rdlength - pos;
-
-        for (i = 0; i < size; i++)
-            r->Data.KEY.Key[i] = *pos++;
-
-        *dlen = sizeof(DNS_KEY_DATA) + (size - 1) * sizeof(BYTE);
-        break;
-    }
-    case ns_t_rp:
-    case ns_t_minfo:
-    {
-        r->Data.MINFO.pNameMailbox = dname_from_msg( msg, pos );
-        if (!r->Data.MINFO.pNameMailbox) return ERROR_NOT_ENOUGH_MEMORY;
-
-        if (ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
-            return DNS_ERROR_BAD_PACKET;
-
-        r->Data.MINFO.pNameErrorsMailbox = dname_from_msg( msg, pos );
-        if (!r->Data.MINFO.pNameErrorsMailbox)
-        {
-            heap_free( r->Data.MINFO.pNameMailbox );
-            return ERROR_NOT_ENOUGH_MEMORY;
-        }
-
-        *dlen = sizeof(DNS_MINFO_DATAA);
-        break; 
-    }
-    case ns_t_afsdb:
-    case ns_t_rt:
-    case ns_t_mx:
-    {
-        r->Data.MX.wPreference = ntohs( *(const WORD *)pos );
-        r->Data.MX.pNameExchange = dname_from_msg( msg, pos + sizeof(WORD) );
-        if (!r->Data.MX.pNameExchange) return ERROR_NOT_ENOUGH_MEMORY;
-
-        *dlen = sizeof(DNS_MX_DATAA);
-        break; 
-    }
-    case ns_t_null:
-    {
-        r->Data.Null.dwByteCount = rr->rdlength;
-        memcpy( r->Data.Null.Data, rr->rdata, rr->rdlength );
-
-        *dlen = sizeof(DNS_NULL_DATA) + rr->rdlength - 1;
-        break;
-    }
-    case ns_t_opt:
-    {
-        r->Data.OPT.wDataLength = rr->rdlength;
-        r->Data.OPT.wPad        = 0;
-        memcpy( r->Data.OPT.Data, rr->rdata, rr->rdlength );
-
-        *dlen = sizeof(DNS_OPT_DATA) + rr->rdlength - 1;
-        break;
-    }
-    case ns_t_cname:
-    case ns_t_ns:
-    case ns_t_mb:
-    case ns_t_md:
-    case ns_t_mf:
-    case ns_t_mg:
-    case ns_t_mr:
-    case ns_t_ptr:
-    {
-        r->Data.PTR.pNameHost = dname_from_msg( msg, pos );
-        if (!r->Data.PTR.pNameHost) return ERROR_NOT_ENOUGH_MEMORY;
-
-        *dlen = sizeof(DNS_PTR_DATAA);
-        break;
-    }
-    case ns_t_sig:
-    {
-        r->Data.SIG.pNameSigner = dname_from_msg( msg, pos );
-        if (!r->Data.SIG.pNameSigner) return ERROR_NOT_ENOUGH_MEMORY;
-
-        if (ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
-            return DNS_ERROR_BAD_PACKET;
-
-        /* FIXME: byte order? */
-        r->Data.SIG.wTypeCovered  = *(const WORD *)pos;   pos += sizeof(WORD);
-        r->Data.SIG.chAlgorithm   = *pos++;
-        r->Data.SIG.chLabelCount  = *pos++;
-        r->Data.SIG.dwOriginalTtl = *(const DWORD *)pos;  pos += sizeof(DWORD);
-        r->Data.SIG.dwExpiration  = *(const DWORD *)pos;  pos += sizeof(DWORD);
-        r->Data.SIG.dwTimeSigned  = *(const DWORD *)pos;  pos += sizeof(DWORD);
-        r->Data.SIG.wKeyTag       = *(const WORD *)pos;
-
-        size = rr->rdata + rr->rdlength - pos;
-
-        for (i = 0; i < size; i++)
-            r->Data.SIG.Signature[i] = *pos++;
-
-        *dlen = sizeof(DNS_SIG_DATAA) + (size - 1) * sizeof(BYTE);
-        break; 
-    }
-    case ns_t_soa:
-    {
-        r->Data.SOA.pNamePrimaryServer = dname_from_msg( msg, pos );
-        if (!r->Data.SOA.pNamePrimaryServer) return ERROR_NOT_ENOUGH_MEMORY;
-
-        if (ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
-            return DNS_ERROR_BAD_PACKET;
-
-        r->Data.SOA.pNameAdministrator = dname_from_msg( msg, pos );
-        if (!r->Data.SOA.pNameAdministrator)
-        {
-            heap_free( r->Data.SOA.pNamePrimaryServer );
-            return ERROR_NOT_ENOUGH_MEMORY;
-        }
-
-        if (ns_name_skip( &pos, ns_msg_end( msg ) ) < 0)
-            return DNS_ERROR_BAD_PACKET;
-
-        r->Data.SOA.dwSerialNo   = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
-        r->Data.SOA.dwRefresh    = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
-        r->Data.SOA.dwRetry      = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
-        r->Data.SOA.dwExpire     = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
-        r->Data.SOA.dwDefaultTtl = ntohl( *(const DWORD *)pos ); pos += sizeof(DWORD);
-
-        *dlen = sizeof(DNS_SOA_DATAA);
-        break; 
-    }
-    case ns_t_srv:
-    {
-        r->Data.SRV.wPriority = ntohs( *(const WORD *)pos ); pos += sizeof(WORD);
-        r->Data.SRV.wWeight   = ntohs( *(const WORD *)pos ); pos += sizeof(WORD);
-        r->Data.SRV.wPort     = ntohs( *(const WORD *)pos ); pos += sizeof(WORD);
-
-        r->Data.SRV.pNameTarget = dname_from_msg( msg, pos );
-        if (!r->Data.SRV.pNameTarget) return ERROR_NOT_ENOUGH_MEMORY;
-
-        *dlen = sizeof(DNS_SRV_DATAA);
-        break; 
-    }
-    case ns_t_hinfo:
-    case ns_t_isdn:
-    case ns_t_x25:
-    case ns_t_txt:
-    {
-        i = 0;
-        while (pos[0] && pos < rr->rdata + rr->rdlength)
-        {
-            r->Data.TXT.pStringArray[i] = str_from_rdata( pos );
-            if (!r->Data.TXT.pStringArray[i])
-            {
-                while (i > 0) heap_free( r->Data.TXT.pStringArray[--i] );
-                return ERROR_NOT_ENOUGH_MEMORY;
-            }
-            i++;
-            pos += pos[0] + 1;
-        }
-        r->Data.TXT.dwStringCount = i;
-        *dlen = sizeof(DNS_TXT_DATAA) + (i - 1) * sizeof(PCHAR);
-        break;
-    }
-    case ns_t_atma:
-    case ns_t_loc:
-    case ns_t_nxt:
-    case ns_t_tsig:
-    case ns_t_wks:
-    case 0x00f9:  /* TKEY */
-    case 0xff01:  /* WINS */
-    case 0xff02:  /* WINSR */
-    default:
-        FIXME( "unhandled type: %s\n", type_to_str( rr->type ) );
-        return DNS_ERROR_RCODE_NOT_IMPLEMENTED;
-    }
-
-    return ret;
-} 
-
-static DNS_STATUS copy_record( ns_msg msg, ns_sect section,
-                                   unsigned short num, DNS_RECORDA **recp )
-{
-    DNS_STATUS ret;
-    DNS_RECORDA *record;
-    WORD dlen;
-    ns_rr rr;
-
-    if (ns_parserr( &msg, section, num, &rr ) < 0)
-        return DNS_ERROR_BAD_PACKET;
-
-    if (!(record = heap_alloc_zero( get_record_size( &rr ) )))
-        return ERROR_NOT_ENOUGH_MEMORY;
-
-    record->pName = strdup_u( rr.name );
-    if (!record->pName)
-    {
-        heap_free( record );
-        return ERROR_NOT_ENOUGH_MEMORY;
-    }
-
-    record->wType = rr.type;
-    record->Flags.S.Section = section;
-    record->Flags.S.CharSet = DnsCharSetUtf8;
-    record->dwTtl = rr.ttl;
-
-    if ((ret = copy_rdata( msg, &rr, record, &dlen )))
-    {
-        heap_free( record->pName );
-        heap_free( record );
-        return ret;
-    }
-    record->wDataLength = dlen;
-    *recp = record;
-
-    TRACE( "found %s record in %s section\n",
-           type_to_str( rr.type ), section_to_str( section ) );
-    return ERROR_SUCCESS;
-}
-
 #define DEFAULT_TTL  1200
 
 static DNS_STATUS do_query_netbios( PCSTR name, DNS_RECORDA **recp )
@@ -510,7 +62,7 @@ static DNS_STATUS do_query_netbios( PCSTR name, DNS_RECORDA **recp )
     header = (FIND_NAME_HEADER *)ncb.ncb_buffer;
     buffer = (FIND_NAME_BUFFER *)((char *)header + sizeof(FIND_NAME_HEADER));
 
-    for (i = 0; i < header->node_count; i++) 
+    for (i = 0; i < header->node_count; i++)
     {
         record = heap_alloc_zero( sizeof(DNS_RECORDA) );
         if (!record)
@@ -551,107 +103,6 @@ exit:
     return status;
 }
 
-/* res_init() must have been called before calling these three functions.
- */
-static DNS_STATUS set_serverlist( const IP4_ARRAY *addrs )
-{
-    int i;
-
-    if (!addrs || !addrs->AddrCount) return ERROR_SUCCESS;
-    if (addrs->AddrCount > MAXNS) 
-    {
-        WARN( "too many servers: %d only using the first: %d\n",
-              addrs->AddrCount, MAXNS );
-        _res.nscount = MAXNS;
-    }
-    else _res.nscount = addrs->AddrCount;
-
-    for (i = 0; i < _res.nscount; i++)
-        _res.nsaddr_list[i].sin_addr.s_addr = addrs->AddrArray[i];
-
-    return ERROR_SUCCESS;
-}
-
-static DNS_STATUS get_serverlist( PIP4_ARRAY addrs, PDWORD len )
-{
-    unsigned int size;
-    int i;
-
-    size = FIELD_OFFSET(IP4_ARRAY, AddrArray[_res.nscount]);
-    if (!addrs || *len < size)
-    {
-        *len = size;
-        return ERROR_INSUFFICIENT_BUFFER;
-    }
-
-    addrs->AddrCount = _res.nscount;
-
-    for (i = 0; i < _res.nscount; i++)
-        addrs->AddrArray[i] = _res.nsaddr_list[i].sin_addr.s_addr;
-
-    return ERROR_SUCCESS;
-}
-
-#define DNS_MAX_PACKET_SIZE 4096
-static DNS_STATUS do_query( PCSTR name, WORD type, DWORD options, PDNS_RECORDA *result )
-{
-    DNS_STATUS ret = DNS_ERROR_RCODE_NOT_IMPLEMENTED;
-
-    unsigned int i, num;
-    unsigned char answer[DNS_MAX_PACKET_SIZE];
-    ns_sect sections[] = { ns_s_an, ns_s_ar };
-    ns_msg msg;
-
-    DNS_RECORDA *record = NULL;
-    DNS_RRSET rrset;
-    int len;
-
-    DNS_RRSET_INIT( rrset );
-
-    len = res_query( name, ns_c_in, type, answer, sizeof(answer) );
-    if (len < 0)
-    {
-        ret = map_h_errno( h_errno );
-        goto exit;
-    }
-
-    if (ns_initparse( answer, len, &msg ) < 0)
-    {
-        ret = DNS_ERROR_BAD_PACKET;
-        goto exit;
-    }
-
-#define RCODE_MASK 0x0f
-    if ((msg._flags & RCODE_MASK) != ns_r_noerror)
-    {
-        ret = map_error( msg._flags & RCODE_MASK );
-        goto exit;
-    }
-
-    for (i = 0; i < ARRAY_SIZE(sections); i++)
-    {
-        for (num = 0; num < ns_msg_count( msg, sections[i] ); num++)
-        {
-            ret = copy_record( msg, sections[i], num, &record );
-            if (ret != ERROR_SUCCESS) goto exit;
-
-            DNS_RRSET_ADD( rrset, (DNS_RECORD *)record );
-        }
-    }
-
-exit:
-    DNS_RRSET_TERMINATE( rrset );
-
-    if (ret != ERROR_SUCCESS)
-        DnsRecordListFree( rrset.pFirstRR, DnsFreeRecordList );
-    else
-        *result = (DNS_RECORDA *)rrset.pFirstRR;
-
-    return ret;
-}
-
-#endif /* HAVE_RESOLV */
-
 static const char *debugstr_query_request(const DNS_QUERY_REQUEST *req)
 {
     if (!req)
@@ -693,7 +144,7 @@ DNS_STATUS WINAPI DnsQuery_A( PCSTR name, WORD type, DWORD options, PVOID server
     nameW = strdup_aw( name );
     if (!nameW) return ERROR_NOT_ENOUGH_MEMORY;
 
-    status = DnsQuery_W( nameW, type, options, servers, &resultW, reserved ); 
+    status = DnsQuery_W( nameW, type, options, servers, &resultW, reserved );
 
     if (status == ERROR_SUCCESS)
     {
@@ -716,7 +167,6 @@ DNS_STATUS WINAPI DnsQuery_UTF8( PCSTR name, WORD type, DWORD options, PVOID ser
                                  PDNS_RECORDA *result, PVOID *reserved )
 {
     DNS_STATUS ret = DNS_ERROR_RCODE_NOT_IMPLEMENTED;
-#ifdef HAVE_RESOLV
 
     TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_a(name), type_to_str( type ),
            options, servers, result, reserved );
@@ -724,12 +174,9 @@ DNS_STATUS WINAPI DnsQuery_UTF8( PCSTR name, WORD type, DWORD options, PVOID ser
     if (!name || !result)
         return ERROR_INVALID_PARAMETER;
 
-    initialise_resolver();
-    _res.options |= map_options( options );
-
-    if ((ret = set_serverlist( servers ))) return ret;
+    if ((ret = resolv_funcs->set_serverlist( servers ))) return ret;
 
-    ret = do_query( name, type, options, result );
+    ret = resolv_funcs->query( name, type, options, result );
 
     if (ret == DNS_ERROR_RCODE_NAME_ERROR && type == DNS_TYPE_A &&
         !(options & DNS_QUERY_NO_NETBT))
@@ -738,7 +185,6 @@ DNS_STATUS WINAPI DnsQuery_UTF8( PCSTR name, WORD type, DWORD options, PVOID ser
         ret = do_query_netbios( name, result );
     }
 
-#endif
     return ret;
 }
 
@@ -762,7 +208,7 @@ DNS_STATUS WINAPI DnsQuery_W( PCWSTR name, WORD type, DWORD options, PVOID serve
     nameU = strdup_wu( name );
     if (!nameU) return ERROR_NOT_ENOUGH_MEMORY;
 
-    status = DnsQuery_UTF8( nameU, type, options, servers, &resultA, reserved ); 
+    status = DnsQuery_UTF8( nameU, type, options, servers, &resultA, reserved );
 
     if (status == ERROR_SUCCESS)
     {
@@ -777,8 +223,7 @@ DNS_STATUS WINAPI DnsQuery_W( PCWSTR name, WORD type, DWORD options, PVOID serve
     return status;
 }
 
-static DNS_STATUS get_hostname_a( COMPUTER_NAME_FORMAT format,
-                                      PSTR buffer, PDWORD len )
+static DNS_STATUS get_hostname_a( COMPUTER_NAME_FORMAT format, PSTR buffer, PDWORD len )
 {
     char name[256];
     DWORD size = ARRAY_SIZE(name);
@@ -796,8 +241,7 @@ static DNS_STATUS get_hostname_a( COMPUTER_NAME_FORMAT format,
     return ERROR_SUCCESS;
 }
 
-static DNS_STATUS get_hostname_w( COMPUTER_NAME_FORMAT format,
-                                      PWSTR buffer, PDWORD len )
+static DNS_STATUS get_hostname_w( COMPUTER_NAME_FORMAT format, PWSTR buffer, PDWORD len )
 {
     WCHAR name[256];
     DWORD size = ARRAY_SIZE(name);
@@ -833,14 +277,8 @@ DNS_STATUS WINAPI DnsQueryConfig( DNS_CONFIG_TYPE config, DWORD flag, PCWSTR ada
     {
     case DnsConfigDnsServerList:
     {
-#ifdef HAVE_RESOLV
-        initialise_resolver();
-        ret = get_serverlist( buffer, len );
-        break;
-#else
-        WARN( "compiled without resolver support\n" );
+        ret = resolv_funcs->get_serverlist( buffer, len );
         break;
-#endif
     }
     case DnsConfigHostName_A:
     case DnsConfigHostName_UTF8:
diff --git a/dlls/dnsapi/record.c b/dlls/dnsapi/record.c
index 51d9e8fd2d7..4697438df57 100644
--- a/dlls/dnsapi/record.c
+++ b/dlls/dnsapi/record.c
@@ -2,7 +2,7 @@
  * DNS support
  *
  * Copyright (C) 2006 Hans Leidekker
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
@@ -18,31 +18,14 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "config.h"
-#include "wine/port.h"
-#include "wine/debug.h"
-#include "wine/unicode.h"
-
 #include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-#ifdef HAVE_ARPA_NAMESER_H
-# include <arpa/nameser.h>
-#endif
-#ifdef HAVE_RESOLV_H
-# include <resolv.h>
-#endif
-
 #include "windef.h"
 #include "winbase.h"
 #include "winnls.h"
 #include "windns.h"
 
+#include "wine/debug.h"
+#include "wine/unicode.h"
 #include "dnsapi.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(dnsapi);
@@ -158,10 +141,8 @@ BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 )
             r1->Data.SOA.dwExpire     != r2->Data.SOA.dwExpire   ||
             r1->Data.SOA.dwDefaultTtl != r2->Data.SOA.dwDefaultTtl)
             return FALSE;
-        if (strcmpX( r1->Data.SOA.pNamePrimaryServer,
-                         r2->Data.SOA.pNamePrimaryServer, wide ) ||
-            strcmpX( r1->Data.SOA.pNameAdministrator,
-                         r2->Data.SOA.pNameAdministrator, wide ))
+        if (strcmpX( r1->Data.SOA.pNamePrimaryServer, r2->Data.SOA.pNamePrimaryServer, wide ) ||
+            strcmpX( r1->Data.SOA.pNameAdministrator, r2->Data.SOA.pNameAdministrator, wide ))
             return FALSE;
         break;
     }
@@ -174,17 +155,14 @@ BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 )
     case DNS_TYPE_MG:
     case DNS_TYPE_MR:
     {
-        if (strcmpX( r1->Data.PTR.pNameHost,
-                         r2->Data.PTR.pNameHost, wide )) return FALSE;
+        if (strcmpX( r1->Data.PTR.pNameHost, r2->Data.PTR.pNameHost, wide )) return FALSE;
         break;
     }
     case DNS_TYPE_MINFO:
     case DNS_TYPE_RP:
     {
-        if (strcmpX( r1->Data.MINFO.pNameMailbox,
-                         r2->Data.MINFO.pNameMailbox, wide ) ||
-            strcmpX( r1->Data.MINFO.pNameErrorsMailbox,
-                         r2->Data.MINFO.pNameErrorsMailbox, wide ))
+        if (strcmpX( r1->Data.MINFO.pNameMailbox, r2->Data.MINFO.pNameMailbox, wide ) ||
+            strcmpX( r1->Data.MINFO.pNameErrorsMailbox, r2->Data.MINFO.pNameErrorsMailbox, wide ))
             return FALSE;
         break;
     }
@@ -194,8 +172,7 @@ BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 )
     {
         if (r1->Data.MX.wPreference != r2->Data.MX.wPreference)
             return FALSE;
-        if (strcmpX( r1->Data.MX.pNameExchange,
-                         r2->Data.MX.pNameExchange, wide ))
+        if (strcmpX( r1->Data.MX.pNameExchange, r2->Data.MX.pNameExchange, wide ))
             return FALSE;
         break;
     }
@@ -208,8 +185,7 @@ BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 )
             return FALSE;
         for (i = 0; i < r1->Data.TXT.dwStringCount; i++)
         {
-            if (strcmpX( r1->Data.TXT.pStringArray[i],
-                             r2->Data.TXT.pStringArray[i], wide ))
+            if (strcmpX( r1->Data.TXT.pStringArray[i], r2->Data.TXT.pStringArray[i], wide ))
                 return FALSE;
         }
         break;
@@ -255,8 +231,7 @@ BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 )
     }
     case DNS_TYPE_SIG:
     {
-        if (strcmpX( r1->Data.SIG.pNameSigner,
-                         r2->Data.SIG.pNameSigner, wide ))
+        if (strcmpX( r1->Data.SIG.pNameSigner, r2->Data.SIG.pNameSigner, wide ))
             return FALSE;
         if (r1->Data.SIG.wTypeCovered  != r2->Data.SIG.wTypeCovered  ||
             r1->Data.SIG.chAlgorithm   != r2->Data.SIG.chAlgorithm   ||
@@ -284,8 +259,7 @@ BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 )
     }
     case DNS_TYPE_NXT:
     {
-        if (strcmpX( r1->Data.NXT.pNameNext,
-                         r2->Data.NXT.pNameNext, wide )) return FALSE;
+        if (strcmpX( r1->Data.NXT.pNameNext, r2->Data.NXT.pNameNext, wide )) return FALSE;
         if (r1->Data.NXT.wNumTypes != r2->Data.NXT.wNumTypes) return FALSE;
         if (memcmp( r1->Data.NXT.wTypes, r2->Data.NXT.wTypes,
                     r1->wDataLength - sizeof(DNS_NXT_DATAA) + sizeof(WORD) ))
@@ -294,8 +268,7 @@ BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 )
     }
     case DNS_TYPE_SRV:
     {
-        if (strcmpX( r1->Data.SRV.pNameTarget,
-                         r2->Data.SRV.pNameTarget, wide )) return FALSE;
+        if (strcmpX( r1->Data.SRV.pNameTarget, r2->Data.SRV.pNameTarget, wide )) return FALSE;
         if (r1->Data.SRV.wPriority != r2->Data.SRV.wPriority ||
             r1->Data.SRV.wWeight   != r2->Data.SRV.wWeight   ||
             r1->Data.SRV.wPort     != r2->Data.SRV.wPort)
@@ -304,8 +277,7 @@ BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 )
     }
     case DNS_TYPE_TKEY:
     {
-        if (strcmpX( r1->Data.TKEY.pNameAlgorithm,
-                         r2->Data.TKEY.pNameAlgorithm, wide ))
+        if (strcmpX( r1->Data.TKEY.pNameAlgorithm, r2->Data.TKEY.pNameAlgorithm, wide ))
             return FALSE;
         if (r1->Data.TKEY.dwCreateTime    != r2->Data.TKEY.dwCreateTime     ||
             r1->Data.TKEY.dwExpireTime    != r2->Data.TKEY.dwExpireTime     ||
@@ -326,8 +298,7 @@ BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 )
     }
     case DNS_TYPE_TSIG:
     {
-        if (strcmpX( r1->Data.TSIG.pNameAlgorithm,
-                         r2->Data.TSIG.pNameAlgorithm, wide ))
+        if (strcmpX( r1->Data.TSIG.pNameAlgorithm, r2->Data.TSIG.pNameAlgorithm, wide ))
             return FALSE;
         if (r1->Data.TSIG.i64CreateTime   != r2->Data.TSIG.i64CreateTime    ||
             r1->Data.TSIG.wFudgeTime      != r2->Data.TSIG.wFudgeTime       ||
@@ -364,8 +335,7 @@ BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 )
             r1->Data.WINSR.dwLookupTimeout != r2->Data.WINSR.dwLookupTimeout ||
             r1->Data.WINSR.dwCacheTimeout  != r2->Data.WINSR.dwCacheTimeout)
             return FALSE;
-        if (strcmpX( r1->Data.WINSR.pNameResultDomain,
-                         r2->Data.WINSR.pNameResultDomain, wide ))
+        if (strcmpX( r1->Data.WINSR.pNameResultDomain, r2->Data.WINSR.pNameResultDomain, wide ))
             return FALSE;
         break;
     }
@@ -748,7 +718,7 @@ BOOL WINAPI DnsRecordSetCompare( PDNS_RECORD set1, PDNS_RECORD set2,
 
     DNS_RRSET_TERMINATE( rr1 );
     DNS_RRSET_TERMINATE( rr2 );
-    
+
     if (diff1) *diff1 = rr1.pFirstRR;
     else DnsRecordListFree( rr1.pFirstRR, DnsFreeRecordList );
 
@@ -763,7 +733,7 @@ error:
 
     DnsRecordListFree( rr1.pFirstRR, DnsFreeRecordList );
     DnsRecordListFree( rr2.pFirstRR, DnsFreeRecordList );
-    
+
     return FALSE;
 }
 
-- 
2.30.2




More information about the wine-devel mailing list