Search
Module:
Directory

   Desktop Functions:

   Smart Device Functions:


Show Recent Changes
Subscribe (RSS)
Misc. Pages
Comments
FAQ
Helpful Tools
Playground
Suggested Reading
Website TODO List
Download Visual Studio Add-In

DnsQuery (dnsapi)
 
.
Summary
DNSQueryEx (built off DNSQuery page)
Summary
A generic query interface to the DNS namespace, implemented in multiple forms to facilitate different character encoding.

Provides a more customisable query than DNSQuery - uses an Async callback

C# Signature:

[DllImport("dnsapi", EntryPoint = "DnsQueryEx", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
    private static extern int DnsQueryEx(IntPtr queryRequest, IntPtr queryResults, IntPtr cancelHandle);

None.

    /// <summary>
    /// Provides a DNS query resolution interface
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682016(v=vs.85).aspx
    /// </summary>
    /// <param name="lpstrName">A pointer to a string that represents the DNS name to query</param>
    /// <param name="wType">A value that represents the Resource Record DNS Record Type that is queried</param>
    /// <param name="Options">A value that contains a bitmap of the DNS Query Options to use in the DNS query</param>
    /// <param name="pExtra">Reserved for future use and must be set to NULL</param>
    /// <param name="ppQueryResultsSet">A pointer to a pointer that points to the list of RRs that comprise the response</param>
    /// <param name="pReserved">Reserved for future use and must be set to NULL</param>
    /// <returns>Success (0), or the DNS-specific error defined in Winerror.h</returns>
    [DllImport("dnsapi", EntryPoint = "DnsQuery_W", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
    public static extern int DnsQuery([MarshalAs(UnmanagedType.VBByRefStr)] ref string lpstrName, DnsRecordTypes wType, DnsQueryOptions Options, IntPtr pExtra, ref IntPtr ppQueryResultsSet, IntPtr pReserved);

Notes:

None.

    /// <summary>
    /// Frees memory allocated for DNS records obtained by using the DnsQuery function
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682021(v=vs.85).aspx
    /// </summary>
    /// <param name="pRecordList">A pointer to the DNS_RECORD structure that contains the list of DNS records to be freed</param>
    /// <param name="FreeType">A specifier of how the record list should be freed</param>
    [DllImport("dnsapi", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern void DnsRecordListFree(IntPtr pRecordList, DNS_FREE_TYPE FreeType);

Sample Code:

User-Defined Types:

C#

    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/cc982162(v=vs.85).aspx
    /// </summary>
    [Flags]
    public enum DnsQueryOptions
    {
        DNS_QUERY_STANDARD = 0x0,
        DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE = 0x1,
        DNS_QUERY_USE_TCP_ONLY = 0x2,
        DNS_QUERY_NO_RECURSION = 0x4,
        DNS_QUERY_BYPASS_CACHE = 0x8,
        DNS_QUERY_NO_WIRE_QUERY = 0x10,
        DNS_QUERY_NO_LOCAL_NAME = 0x20,
        DNS_QUERY_NO_HOSTS_FILE = 0x40,
        DNS_QUERY_NO_NETBT = 0x80,
        DNS_QUERY_WIRE_ONLY = 0x100,
        DNS_QUERY_RETURN_MESSAGE = 0x200,
        DNS_QUERY_MULTICAST_ONLY = 0x400,
        DNS_QUERY_NO_MULTICAST = 0x800,
        DNS_QUERY_TREAT_AS_FQDN = 0x1000,
        DNS_QUERY_ADDRCONFIG = 0x2000,
        DNS_QUERY_DUAL_ADDR = 0x4000,
        DNS_QUERY_MULTICAST_WAIT = 0x20000,
        DNS_QUERY_MULTICAST_VERIFY = 0x40000,
        DNS_QUERY_DONT_RESET_TTL_VALUES = 0x100000,
        DNS_QUERY_DISABLE_IDN_ENCODING = 0x200000,
        DNS_QUERY_APPEND_MULTILABEL = 0x800000,
        DNS_QUERY_RESERVED = unchecked((int)0xF0000000)
    }

   using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Net;
    using System.Net.Sockets;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;

    public class DNSQueryer
    {
    private const int DnsRecordsNoInfo = 9501;
    private const int DnsRequestPending = 9506;
    private const int DnsAddrMaxSockaddrLength = 32;
    private const int DNSQueryCancelSize = 32;
    private const short DNSPort = 53;
    private const short AFInet = 2;
    private const short AFInet16 = 23;
    private const int IpAddressV6LengthBytes = 16;
    private const int IpAddressV4LengthBytes = 4;
    private const uint DnsQueryRequestVersion1 = 1;

    private delegate void QueryCompletionRoutineFunctionPointer(IntPtr queryContext, IntPtr queryResults);

    [Flags]
    private enum DnsQueryOptions
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/cc982162(v=vs.85).aspx
    /// Also see http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml
    /// </summary>
    public enum DnsRecordTypes
    {
        DNS_QUERY_STANDARD = 0x0,
        DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE = 0x1,
        DNS_QUERY_USE_TCP_ONLY = 0x2,
        DNS_QUERY_NO_RECURSION = 0x4,
        DNS_QUERY_BYPASS_CACHE = 0x8,
        DNS_QUERY_NO_WIRE_QUERY = 0x10,
        DNS_QUERY_NO_LOCAL_NAME = 0x20,
        DNS_QUERY_NO_HOSTS_FILE = 0x40,
        DNS_QUERY_NO_NETBT = 0x80,
        DNS_QUERY_WIRE_ONLY = 0x100,
        DNS_QUERY_RETURN_MESSAGE = 0x200,
        DNS_QUERY_MULTICAST_ONLY = 0x400,
        DNS_QUERY_NO_MULTICAST = 0x800,
        DNS_QUERY_TREAT_AS_FQDN = 0x1000,
        DNS_QUERY_ADDRCONFIG = 0x2000,
        DNS_QUERY_DUAL_ADDR = 0x4000,
        DNS_QUERY_MULTICAST_WAIT = 0x20000,
        DNS_QUERY_MULTICAST_VERIFY = 0x40000,
        DNS_QUERY_DONT_RESET_TTL_VALUES = 0x100000,
        DNS_QUERY_DISABLE_IDN_ENCODING = 0x200000,
        DNS_QUERY_APPEND_MULTILABEL = 0x800000,
        DNS_QUERY_RESERVED = unchecked((int)0xF0000000)
    }

    public enum DnsRecordTypes
    {
        DNS_TYPE_A = 0x1,
        DNS_TYPE_NS = 0x2,
        DNS_TYPE_MD = 0x3,
        DNS_TYPE_MF = 0x4,
        DNS_TYPE_CNAME = 0x5,
        DNS_TYPE_SOA = 0x6,
        DNS_TYPE_MB = 0x7,
        DNS_TYPE_MG = 0x8,
        DNS_TYPE_MR = 0x9,
        DNS_TYPE_NULL = 0xA,
        DNS_TYPE_WKS = 0xB,
        DNS_TYPE_PTR = 0xC,
        DNS_TYPE_HINFO = 0xD,
        DNS_TYPE_MINFO = 0xE,
        DNS_TYPE_MX = 0xF,
        DNS_TYPE_TXT = 0x10,
        DNS_TYPE_TEXT = 0x10,       // This is how it's specified on MSDN
        DNS_TYPE_TXT = DNS_TYPE_TEXT,
        DNS_TYPE_RP = 0x11,
        DNS_TYPE_AFSDB = 0x12,
        DNS_TYPE_X25 = 0x13,
        DNS_TYPE_ISDN = 0x14,
        DNS_TYPE_RT = 0x15,
        DNS_TYPE_NSAP = 0x16,
        DNS_TYPE_NSAPPTR = 0x17,
        DNS_TYPE_SIG = 0x18,
        DNS_TYPE_KEY = 0x19,
        DNS_TYPE_PX = 0x1A,
        DNS_TYPE_GPOS = 0x1B,
        DNS_TYPE_AAAA = 0x1C,
        DNS_TYPE_SRV = 0x21
        DNS_TYPE_LOC = 0x1D,
        DNS_TYPE_NXT = 0x1E,
        DNS_TYPE_EID = 0x1F,
        DNS_TYPE_NIMLOC = 0x20,
        DNS_TYPE_SRV = 0x21,
        DNS_TYPE_ATMA = 0x22,
        DNS_TYPE_NAPTR = 0x23,
        DNS_TYPE_KX = 0x24,
        DNS_TYPE_CERT = 0x25,
        DNS_TYPE_A6 = 0x26,
        DNS_TYPE_DNAME = 0x27,
        DNS_TYPE_SINK = 0x28,
        DNS_TYPE_OPT = 0x29,
        DNS_TYPE_DS = 0x2B,
        DNS_TYPE_RRSIG = 0x2E,
        DNS_TYPE_NSEC = 0x2F,
        DNS_TYPE_DNSKEY = 0x30,
        DNS_TYPE_DHCID = 0x31,
        DNS_TYPE_UINFO = 0x64,
        DNS_TYPE_UID = 0x65,
        DNS_TYPE_GID = 0x66,
        DNS_TYPE_UNSPEC = 0x67,
        DNS_TYPE_ADDRS = 0xF8,
        DNS_TYPE_TKEY = 0xF9,
        DNS_TYPE_TSIG = 0xFA,
        DNS_TYPE_IXFR = 0xFB,
        DNS_TYPE_AFXR = 0xFC,
        DNS_TYPE_MAILB = 0xFD,
        DNS_TYPE_MAILA = 0xFE,
        DNS_TYPE_ALL = 0xFF,
        DNS_TYPE_ANY = 0xFF,
        DNS_TYPE_WINS = 0xFF01,
        DNS_TYPE_WINSR = 0xFF02,
        DNS_TYPE_NBSTAT = DNS_TYPE_WINSR
    }

    private enum DNS_FREE_TYPE
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682056(v=vs.85).aspx
    /// </summary>
    public enum DNS_FREE_TYPE
    {
        DnsFreeFlat = 0,
        DnsFreeRecordList = 1,
        DnsFreeParsedMessageFields = 2
    }

    public static IDictionary<string, object>[] QueryDNSForRecordTypeSpecificNameServers(string domainName, IPAddress[] dnsServers, DnsRecordTypes recordType)
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682082(v=vs.85).aspx
    /// These field offsets could be different depending on endianness and bitness
    /// </summary>
    [StructLayout(LayoutKind.Explicit)]
    public struct DNS_RECORD
    {
        if (dnsServers == null || dnsServers.Length == 0)
        {
        throw new Exception("At least one DNS Server must be provided to do the query");
        }
        [FieldOffset(0)]
        public IntPtr pNext;    // DNS_RECORD*
        [FieldOffset(4)]
        public IntPtr pName;    // string
        [FieldOffset(8)]
        public ushort wType;
        [FieldOffset(10)]
        public ushort wDataLength;
        [FieldOffset(12)]
        public FlagsUnion Flags;
        [FieldOffset(16)]
        public uint dwTtl;
        [FieldOffset(20)]
        public uint dwReserved;
        [FieldOffset(24)]
        public DataUnion Data;
    }

        IntPtr dnsRequest, addrRequestBuffer, contextBuffer;
    [StructLayout(LayoutKind.Explicit)]
    public struct FlagsUnion
    {
        [FieldOffset(0)]
        public uint DW;
        [FieldOffset(0)]
        public DNS_RECORD_FLAGS S;
    }

        QueryCompletionContext context = new QueryCompletionContext();
        context.eventHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
        context.requestType = recordType;
        context.resultCode = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(int)));
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682084(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_RECORD_FLAGS
    {
        internal uint data;

        List<IDictionary<string, object>> dnsRecords = new List<IDictionary<string, object>>();
        // DWORD Section :2;
        public uint Section
        {
        get { return data & 0x3u; }
        set { data = (data & ~0x3u) | (value & 0x3u); }
        }

        GCHandle handle = GCHandle.Alloc(dnsRecords, GCHandleType.Normal);
        // DWORD Delete :1;
        public uint Delete
        {
        get { return (data >> 2) & 0x1u; }
        set { data = (data & ~(0x1u << 2)) | (value & 0x1u) << 2; }
        }

        context.dnsRecords = GCHandle.ToIntPtr(handle);

        MakeDnsRequest(domainName, dnsServers, context, out dnsRequest, out addrRequestBuffer, out contextBuffer);

        DNSQueryResult queryResult = new DNSQueryResult();
        queryResult.Version = DnsQueryRequestVersion1;

        IntPtr result = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(DNSQueryResult)));
        Marshal.StructureToPtr(queryResult, result, false);

        IntPtr cancelBuffer = Marshal.AllocHGlobal(DNSQueryCancelSize);

        int resCode = DnsQueryEx(dnsRequest, result, cancelBuffer);

        FreeDnsRequest(dnsRequest, addrRequestBuffer, contextBuffer);

        bool requestPending = false;

        switch (resCode)
        // DWORD CharSet :2;
        public uint CharSet
        {
        case 0:
            {
            queryResult = (DNSQueryResult)Marshal.PtrToStructure(result, typeof(DNSQueryResult));
            Marshal.FreeHGlobal(result);
            }
        get { return (data >> 3) & 0x3u; }
        set { data = (data & ~(0x3u << 3)) | (value & 0x3u) << 3; }
        }

            break;
        case DnsRequestPending:
            {
            Marshal.FreeHGlobal(result);
            requestPending = true;
            }
            break;
        case DnsRecordsNoInfo:
            {
            Marshal.FreeHGlobal(result);
            Marshal.FreeHGlobal(cancelBuffer);
            handle.Free();
            return new Dictionary<string, object>[0];
            }

        default:
            {
            Marshal.FreeHGlobal(result);
            Marshal.FreeHGlobal(cancelBuffer);
            handle.Free();
            throw new Win32Exception(resCode);
            }
        }

        if (!requestPending)
        // DWORD Unused :3;
        public uint Unused
        {
        Marshal.FreeHGlobal(cancelBuffer);
        handle.Free();

        if (queryResult.QueryStatus != 0)
        {
            if (queryResult.QueryRecords != IntPtr.Zero)
            {
            DnsRecordListFree(queryResult.QueryRecords, DNS_FREE_TYPE.DnsFreeRecordList);
            }

            throw new Win32Exception(queryResult.QueryStatus);
        }

        dnsRecords.AddRange(ParseRecords(queryResult.QueryRecords, recordType));

        if (queryResult.QueryRecords != IntPtr.Zero)
        {
            DnsRecordListFree(queryResult.QueryRecords, DNS_FREE_TYPE.DnsFreeRecordList);
        }

        return dnsRecords.ToArray();
        get { return (data >> 5) & 0x7u; }
        set { data = (data & ~(0x7u << 5)) | (value & 0x7u) << 5; }
        }

        if (!context.eventHandle.WaitOne(5000))
        // DWORD Reserved :24;
        public uint Reserved
        {
        resCode = DnsCancelQuery(cancelBuffer);
        context.eventHandle.WaitOne();
        if (resCode != 0)
        {
            Marshal.FreeHGlobal(cancelBuffer);
            handle.Free();
            throw new Win32Exception(resCode);
        }
        get { return (data >> 8) & 0xFFFFFFu; }
        set { data = (data & ~(0xFFFFFFu << 8)) | (value & 0xFFFFFFu) << 8; }
        }

        Marshal.FreeHGlobal(cancelBuffer);

        handle.Free();

        int retCode = Marshal.ReadInt32(context.resultCode);

        Marshal.FreeHGlobal(context.resultCode);

        if (retCode != 0)
        {
        throw new Win32Exception(retCode);
        }

        return dnsRecords.ToArray();
    }

    private static void FreeDnsRequest(IntPtr requestBuffer, IntPtr addrBuffer, IntPtr contextBuffer)
    [StructLayout(LayoutKind.Explicit)]
    public struct DataUnion
    {
        if (requestBuffer != IntPtr.Zero)
        {
        Marshal.FreeHGlobal(requestBuffer);
        requestBuffer = IntPtr.Zero;
        }

        if (addrBuffer != IntPtr.Zero)
        {
        Marshal.FreeHGlobal(addrBuffer);
        addrBuffer = IntPtr.Zero;
        }

        if (contextBuffer != IntPtr.Zero)
        {
        Marshal.FreeHGlobal(contextBuffer);
        contextBuffer = IntPtr.Zero;
        }
        [FieldOffset(0)]
        public DNS_A_DATA A;
        [FieldOffset(0)]
        public DNS_SOA_DATA SOA, Soa;
        [FieldOffset(0)]
        public DNS_PTR_DATA PTR, Ptr, NS, Ns, CNAME, Cname, DNAME, Dname, MB, Mb, MD, Md, MF, Mf, MG, Mg, MR, Mr;
        [FieldOffset(0)]
        public DNS_MINFO_DATA MINFO, Minfo, RP, Rp;
        [FieldOffset(0)]
        public DNS_MX_DATA MX, Mx, AFSDB, Afsdb, RT, Rt;
        [FieldOffset(0)]
        public DNS_TXT_DATA HINFO, Hinfo, ISDN, Isdn, TXT, Txt, X25;
        [FieldOffset(0)]
        public DNS_NULL_DATA Null;
        [FieldOffset(0)]
        public DNS_WKS_DATA WKS, Wks;
        [FieldOffset(0)]
        public DNS_AAAA_DATA AAAA;
        [FieldOffset(0)]
        public DNS_KEY_DATA KEY, Key;
        [FieldOffset(0)]
        public DNS_SIG_DATA SIG, Sig;
        [FieldOffset(0)]
        public DNS_ATMA_DATA ATMA, Atma;
        [FieldOffset(0)]
        public DNS_NXT_DATA NXT, Nxt;
        [FieldOffset(0)]
        public DNS_SRV_DATA SRV, Srv;
        [FieldOffset(0)]
        public DNS_NAPTR_DATA NAPTR, Naptr;
        [FieldOffset(0)]
        public DNS_OPT_DATA OPT, Opt;
        [FieldOffset(0)]
        public DNS_DS_DATA DS, Ds;
        [FieldOffset(0)]
        public DNS_RRSIG_DATA RRSIG, Rrsig;
        [FieldOffset(0)]
        public DNS_NSEC_DATA NSEC, Nsec;
        [FieldOffset(0)]
        public DNS_DNSKEY_DATA DNSKEY, Dnskey;
        [FieldOffset(0)]
        public DNS_TKEY_DATA TKEY, Tkey;
        [FieldOffset(0)]
        public DNS_TSIG_DATA TSIG, Tsig;
        [FieldOffset(0)]
        public DNS_WINS_DATA WINS, Wins;
        [FieldOffset(0)]
        public DNS_WINSR_DATA WINSR, WinsR, NBSTAT, Nbstat;
        [FieldOffset(0)]
        public DNS_DHCID_DATA DHCID;
    }

    private static void MakeDnsRequest(string domainName, IPAddress[] dnsServers, QueryCompletionContext context, out IntPtr requestBuffer, out IntPtr addrBuffer, out IntPtr contextBuffer)
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682044(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_A_DATA
    {
        requestBuffer = IntPtr.Zero;
        addrBuffer = IntPtr.Zero;
        contextBuffer = IntPtr.Zero;
        public uint IpAddress;      // IP4_ADDRESS IpAddress;
    }

        DNS_ADDR[] addrList = new DNS_ADDR[dnsServers.Length];
        int curAddress = 0;
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682096(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_SOA_DATA
    {
        public IntPtr pNamePrimaryServer;       // string
        public IntPtr pNameAdministrator;       // string
        public uint dwSerialNo;
        public uint dwRefresh;
        public uint dwRetry;
        public uint dwExpire;
        public uint dwDefaultTtl;
    }

        foreach (IPAddress addr in dnsServers)
        {
        addrList[curAddress] = new DNS_ADDR();
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682080(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_PTR_DATA
    {
        public IntPtr pNameHost;    // string
    }

        if (addr.AddressFamily == AddressFamily.InterNetwork)
        {
            byte[] ipv4AddressBytes = addr.GetAddressBytes();
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682067(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_MINFO_DATA
    {
        public IntPtr pNameMailbox;     // string
        public IntPtr pNameErrorsMailbox;       // string
    }

            SockAddrIn sockAddrIn = new SockAddrIn();
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682070(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_MX_DATA
    {
        public IntPtr pNameExchange;        // string
        public ushort wPreference;
        public ushort Pad;
    }

            Buffer.BlockCopy(ipv4AddressBytes, 0, sockAddrIn.SinAddr, 0, IpAddressV4LengthBytes);
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682109(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_TXT_DATA
    {
        public uint dwStringCount;
        public IntPtr pStringArray;     // PWSTR pStringArray[1];
    }

            sockAddrIn.SinFamily = AFInet;
            sockAddrIn.SinPort = (ushort)IPAddress.HostToNetworkOrder(DNSPort);
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682074(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_NULL_DATA
    {
        public uint dwByteCount;
        public IntPtr Data;           // BYTE  Data[1];
    }

            IntPtr sockAddrInPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SockAddrIn)));
            Marshal.StructureToPtr(sockAddrIn, sockAddrInPtr, false);
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682120(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_WKS_DATA
    {
        public uint IpAddress;      // IP4_ADDRESS IpAddress;
        public byte chProtocol;     // UCHAR       chProtocol;
        public IntPtr BitMask;        // BYTE    BitMask[1];
    }

            Marshal.Copy(sockAddrInPtr, addrList[curAddress].MaxSa, 0, Marshal.SizeOf(typeof(SockAddrIn)));
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682035(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_AAAA_DATA
    {
        // IP6_ADDRESS Ip6Address;
        // DWORD IP6Dword[4];
        // This isn't ideal, but it should work without using the fixed and unsafe keywords
        public uint Ip6Address0;
        public uint Ip6Address1;
        public uint Ip6Address2;
        public uint Ip6Address3;
    }

            Marshal.FreeHGlobal(sockAddrInPtr);
        }
        else if (addr.AddressFamily == AddressFamily.InterNetworkV6)
        {
            SockAddrIn6 sockAddrIn6 = new SockAddrIn6();
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682061(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_KEY_DATA
    {
        public ushort wFlags;
        public byte chProtocol;
        public byte chAlgorithm;
        public IntPtr Key;        // BYTE Key[1];
    }

            sockAddrIn6.Sin6Family = AFInet16;
            sockAddrIn6.Sin6Port = (ushort)IPAddress.HostToNetworkOrder(DNSPort);
            sockAddrIn6.Sin6FlowInfo = 0;
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682094(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_SIG_DATA
    {
        public IntPtr pNameSigner;      // string
        public ushort wTypeCovered;
        public byte chAlgorithm;
        public byte chLabelCount;
        public uint dwOriginalTtl;
        public uint dwExpiration;
        public uint dwTimeSigned;
        public ushort wKeyTag;
        public ushort Pad;
        public IntPtr Signature;      // BYTE  Signature[1];
    }

            byte[] ipv6AddressBytes = addr.GetAddressBytes();
    public const int DNS_ATMA_MAX_ADDR_LENGTH = 20;
    public const int DNS_ATMA_FORMAT_E164 = 1;
    public const int DNS_ATMA_FORMAT_AESA = 2;

            Buffer.BlockCopy(ipv6AddressBytes, 0, sockAddrIn6.Sin6Addr, 0, IpAddressV6LengthBytes);
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682041(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_ATMA_DATA
    {
        public byte AddressType;
        // BYTE Address[DNS_ATMA_MAX_ADDR_LENGTH];
        // This isn't ideal, but it should work without using the fixed and unsafe keywords
        public byte Address0;
        public byte Address1;
        public byte Address2;
        public byte Address3;
        public byte Address4;
        public byte Address5;
        public byte Address6;
        public byte Address7;
        public byte Address8;
        public byte Address9;
        public byte Address10;
        public byte Address11;
        public byte Address12;
        public byte Address13;
        public byte Address14;
        public byte Address15;
        public byte Address16;
        public byte Address17;
        public byte Address18;
        public byte Address19;
    }

            sockAddrIn6.Sin6ScopeId = 0;
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682076(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_NXT_DATA
    {
        public IntPtr pNameNext;    // string
        public ushort wNumTypes;
        public IntPtr wTypes;       // WORD  wTypes[1];
    }

            IntPtr sockAddrv6InPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SockAddrIn6)));
            Marshal.StructureToPtr(sockAddrIn6, sockAddrv6InPtr, false);
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682097(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_SRV_DATA
    {
        public IntPtr pNameTarget;      // string
        public ushort uPriority;
        public ushort wWeight;
        public ushort wPort;
        public ushort Pad;
    }

            Marshal.Copy(sockAddrv6InPtr, addrList[curAddress].MaxSa, 0, Marshal.SizeOf(typeof(SockAddrIn6)));
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/cc982164(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_NAPTR_DATA
    {
        public ushort wOrder;
        public ushort wPreference;
        public IntPtr pFlags;       // string
        public IntPtr pService;     // string
        public IntPtr pRegularExpression;       // string
        public IntPtr pReplacement;     // string
    }

            Marshal.FreeHGlobal(sockAddrv6InPtr);
        }
        else
        {
            throw new Exception(string.Format("Address family {0} not supported", addr.AddressFamily.ToString()));
        }
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/dd392298(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_OPT_DATA
    {
        public ushort wDataLength;
        public ushort wPad;
        public IntPtr Data;           // BYTE Data[1];
    }

        curAddress++;
        }
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/dd392296(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_DS_DATA
    {
        public ushort wKeyTag;
        public byte chAlgorithm;
        public byte chDigestType;
        public ushort wDigestLength;
        public ushort wPad;
        public IntPtr Digest;         // BYTE Digest[1];
    }

        int bufSize = Marshal.SizeOf(typeof(DNS_ADDR_ARRAY)) + (addrList.Length * Marshal.SizeOf(typeof(DNS_ADDR)));
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/dd392301(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_RRSIG_DATA
    {
        public IntPtr pNameSigner;      // string
        public ushort wTypeCovered;
        public byte chAlgorithm;
        public byte chLabelCount;
        public uint dwOriginalTtl;
        public uint dwExpiration;
        public uint dwTimeSigned;
        public ushort wKeyTag;
        public ushort Pad;
        public IntPtr Signature;      // BYTE  Signature[1];
    }

        DNS_ADDR_ARRAY addrArray = new DNS_ADDR_ARRAY();
        addrArray.MaxCount = (uint)dnsServers.Length;
        addrArray.AddrCount = (uint)dnsServers.Length;
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/dd392297(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_NSEC_DATA
    {
        public IntPtr pNextDomainName;    // string
        public ushort wTypeBitMapsLength;
        public ushort wPad;
        public IntPtr TypeBitMaps;    // BYTE  TypeBitMaps[1];
    }

        addrBuffer = Marshal.AllocHGlobal(bufSize);
        Marshal.StructureToPtr(addrArray, addrBuffer, false);
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/dd392295(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_DNSKEY_DATA
    {
        public ushort wFlags;
        public byte chProtocol;
        public byte chAlgorithm;
        public ushort wKeyLength;
        public ushort wPad;
        public IntPtr Key;        // BYTE Key[1];
    }

        IntPtr addrArrayPointer = new IntPtr(addrBuffer.ToInt64() + Marshal.SizeOf(typeof(DNS_ADDR_ARRAY)));
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682104(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_TKEY_DATA
    {
        public IntPtr pNameAlgorithm;   // string
        public IntPtr pAlgorithmPacket; // PBYTE (which is BYTE*)
        public IntPtr pKey;         // PBYTE (which is BYTE*)
        public IntPtr pOtherData;       // PBYTE (which is BYTE*)
        public uint dwCreateTime;
        public uint dwExpireTime;
        public ushort wMode;
        public ushort wError;
        public ushort wKeyLength;
        public ushort wOtherLength;
        public byte cAlgNameLength;     // UCHAR cAlgNameLength;
        public int bPacketPointers;     // BOOL  bPacketPointers;
    }

        for (int i = 0; i < addrList.Length; i++)
        {
        Marshal.StructureToPtr(addrList[i], addrArrayPointer, false);
        addrArrayPointer = new IntPtr(addrArrayPointer.ToInt64() + Marshal.SizeOf(typeof(DNS_ADDR)));
        }

        DNS_QUERY_REQUEST request = new DNS_QUERY_REQUEST();
        request.Version = DnsQueryRequestVersion1;
        request.QueryName = domainName;
        request.QueryType = (ushort)context.requestType;
        request.QueryOptions = (ulong)DnsQueryOptions.DNS_QUERY_STANDARD;
        request.DnsServerList = addrBuffer;
        request.InterfaceIndex = 0;
        request.QueryCompletionCallback = Marshal.GetFunctionPointerForDelegate(new QueryCompletionRoutineFunctionPointer(QueryCompletionRoutine));

        contextBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(context));
        Marshal.StructureToPtr(context, contextBuffer, false);

        request.QueryContext = contextBuffer;

        requestBuffer = Marshal.AllocHGlobal(Marshal.SizeOf(request));
        Marshal.StructureToPtr(request, requestBuffer, false);
    }

    private static void QueryCompletionRoutine(IntPtr queryContext, IntPtr queryResults)
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682106(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_TSIG_DATA
    {
        QueryCompletionContext context = (QueryCompletionContext)Marshal.PtrToStructure(queryContext, typeof(QueryCompletionContext));
        public IntPtr pNameAlgorithm;   // string
        public IntPtr pAlgorithmPacket; // PBYTE (which is BYTE*)
        public IntPtr pSignature;       // PBYTE (which is BYTE*)
        public IntPtr pOtherData;       // PBYTE (which is BYTE*)
        public long i64CreateTime;
        public ushort wFudgeTime;
        public ushort wOriginalXid;
        public ushort wError;
        public ushort wSigLength;
        public ushort wOtherLength;
        public byte cAlgNameLength;     // UCHAR    cAlgNameLength;
        public int bPacketPointers;     // BOOL     bPacketPointers;
    }

        DNSQueryResult queryResult = (DNSQueryResult)Marshal.PtrToStructure(queryResults, typeof(DNSQueryResult));
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682114(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_WINS_DATA
    {
        public uint dwMappingFlag;
        public uint dwLookupTimeout;
        public uint dwCacheTimeout;
        public uint cWinsServerCount;
        public uint WinsServers;    // IP4_ADDRESS WinsServers[1];
    }

        Marshal.WriteInt32(context.resultCode, queryResult.QueryStatus);
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682113(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_WINSR_DATA
    {
        public uint dwMappingFlag;
        public uint dwLookupTimeout;
        public uint dwCacheTimeout;
        public IntPtr pNameResultDomain;    // string
    }

        if (queryResult.QueryStatus != 0)
        {
        if (queryResult.QueryRecords != IntPtr.Zero)
        {
            DnsRecordListFree(queryResult.QueryRecords, DNS_FREE_TYPE.DnsFreeRecordList);
        }

        context.eventHandle.Set();
        return;
        }

        List<IDictionary<string, object>> records = GCHandle.FromIntPtr(context.dnsRecords).Target as List<IDictionary<string, object>>;

        records.AddRange(ParseRecords(queryResult.QueryRecords, context.requestType));

        if (queryResult.QueryRecords != IntPtr.Zero)
        {
        DnsRecordListFree(queryResult.QueryRecords, DNS_FREE_TYPE.DnsFreeRecordList);
        }

        context.eventHandle.Set();
    }

    private static IDictionary<string, object>[] ParseRecords(IntPtr result, DnsRecordTypes recordTypeAskedFor)
    /// <summary>
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/dd392294(v=vs.85).aspx
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct DNS_DHCID_DATA
    {
        DNS_RECORD? record = Marshal.PtrToStructure(result, typeof(DNS_RECORD)) as DNS_RECORD?;
        public uint dwByteCount;
        public IntPtr DHCID;          // BYTE  DHCID[1];
    }

        List<IDictionary<string, object>> records = new List<IDictionary<string, object>>();

Helper Functions:

    /// <summary>
    /// Converts an unsigned int to an ip address object
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/cc982163(v=vs.85).aspx
    /// </summary>
    /// <param name="ipAddress">The unsigned int to convert to an ip address object</param>
    /// <returns>The converted ip address</returns>
    public static IPAddress ConvertUintToIpAddress(uint ipAddress)
    {
        // x86 is in little endian
        // Network byte order (what the IPAddress object requires) is big endian
        // Ex - 0x7F000001 is 127.0.0.1
        var addressBytes = new byte[4];
        addressBytes[0] = (byte)((ipAddress & 0xFF000000u) >> 24);
        addressBytes[1] = (byte)((ipAddress & 0x00FF0000u) >> 16);
        addressBytes[2] = (byte)((ipAddress & 0x0000FF00u) >> 8);
        addressBytes[3] = (byte)(ipAddress & 0x000000FFu);
        return new IPAddress(addressBytes);
    }

        while (record.HasValue)
        {
        if (record.Value.Type == (ushort)recordTypeAskedFor)
        {
            string recordName = Marshal.PtrToStringUni(record.Value.Name);
            switch (record.Value.Type)
            {
            case (ushort)DnsRecordTypes.DNS_TYPE_A:
                {
                string recordValue = ConvertUintToIpAddress(record.Value.Data.A.IpAddress).ToString();
                records.Add(new Dictionary<string, object> { { "Type", "A" }, { "Name", recordName }, { "Value", recordValue } });
                break;
                }
    /// <summary>
    /// Converts the data from the AAAA record into an ip address object
    /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682140(v=vs.85).aspx
    /// </summary>
    /// <param name="data">The AAAA record to convert</param>
    /// <returns>The converted ip address</returns>
    public static IPAddress ConvertAAAAToIpAddress(DNS_AAAA_DATA data)
    {
        var addressBytes = new byte[16];
        addressBytes[0] = (byte)(data.Ip6Address0 & 0x000000FF);
        addressBytes[1] = (byte)((data.Ip6Address0 & 0x0000FF00) >> 8);
        addressBytes[2] = (byte)((data.Ip6Address0 & 0x00FF0000) >> 16);
        addressBytes[3] = (byte)((data.Ip6Address0 & 0xFF000000) >> 24);
        addressBytes[4] = (byte)(data.Ip6Address1 & 0x000000FF);
        addressBytes[5] = (byte)((data.Ip6Address1 & 0x0000FF00) >> 8);
        addressBytes[6] = (byte)((data.Ip6Address1 & 0x00FF0000) >> 16);
        addressBytes[7] = (byte)((data.Ip6Address1 & 0xFF000000) >> 24);
        addressBytes[8] = (byte)(data.Ip6Address2 & 0x000000FF);
        addressBytes[9] = (byte)((data.Ip6Address2 & 0x0000FF00) >> 8);
        addressBytes[10] = (byte)((data.Ip6Address2 & 0x00FF0000) >> 16);
        addressBytes[11] = (byte)((data.Ip6Address2 & 0xFF000000) >> 24);
        addressBytes[12] = (byte)(data.Ip6Address3 & 0x000000FF);
        addressBytes[13] = (byte)((data.Ip6Address3 & 0x0000FF00) >> 8);
        addressBytes[14] = (byte)((data.Ip6Address3 & 0x00FF0000) >> 16);
        addressBytes[15] = (byte)((data.Ip6Address3 & 0xFF000000) >> 24);

            case (ushort)DnsRecordTypes.DNS_TYPE_MX:
                {
                string nameExchange = Marshal.PtrToStringUni(record.Value.Data.MX.NameExchange);
                ushort preference = record.Value.Data.MX.Preference;
                records.Add(new Dictionary<string, object> { { "Type", "MX" }, { "Name", recordName }, { "NameExchange", nameExchange }, { "Preference", preference.ToString() } });
                break;
                }
        return new IPAddress(addressBytes);
    }

            case (ushort)DnsRecordTypes.DNS_TYPE_NS:
            case (ushort)DnsRecordTypes.DNS_TYPE_PTR:
            case (ushort)DnsRecordTypes.DNS_TYPE_CNAME:
                {
                string type = record.Value.Type == (ushort)DnsRecordTypes.DNS_TYPE_NS ? "NS " :
                    (record.Value.Type == (ushort)DnsRecordTypes.DNS_TYPE_PTR ? "PTR" : "CNAME");
                string nameHost = Marshal.PtrToStringUni(record.Value.Data.PTR.NameHost);
                records.Add(new Dictionary<string, object> { { "Type", type }, { "Name", recordName }, { "NameHost", nameHost } });
                break;
                }

Alternative Managed API:

Do you know one? Please contribute it!

            case (ushort)DnsRecordTypes.DNS_TYPE_TXT:
                {
                IntPtr stringsCursor = record.Value.Data.TXT.StringArray;

Notes:

See original example provided by Peter A Bromberg, Ph.D.

http://www.eggheadcafe.com/articles/20050129.asp

                StringBuilder valuesBuffer = new StringBuilder();

New example provided by Dylan Jones (jonesdyn@gmail.com).

                for (uint i = 0; i < record.Value.Data.TXT.StringCount; i++)
                {
                    IntPtr txtString = Marshal.ReadIntPtr(stringsCursor);

Tips & Tricks:

Please add some!

                    string value = Marshal.PtrToStringUni(stringsCursor);

Sample Code:

C#

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Net;
    using System.Runtime.InteropServices;

                    IDictionary<string, object> txtRecord = new Dictionary<string, object>();
                    txtRecord.Add("Type", "TXT");
                    txtRecord.Add("Name", recordName);
                    txtRecord.Add("Value", value);
                    records.Add(txtRecord);
    namespace DnsTest
    {
    public class Dns
    {
        /// <summary>
        /// Returns a list of exchange server names from the MX records found from the given domain
        /// This function can be easily changed to return data from other DNS records
        /// </summary>
        /// <param name="domain">The domain to query for MX records</param>
        /// <returns>A list of exchange server names from the MX records found from the given domain</returns>
        public static List<string> GetMxRecords(string domain)
        {
        if (Environment.OSVersion.Platform != PlatformID.Win32NT)
        {
            throw new NotSupportedException();
        }

                    valuesBuffer.Append(";" + value);
        var recordsArray = IntPtr.Zero;
        try
        {
            var result = DnsQuery(ref domain, DnsRecordTypes.DNS_TYPE_MX, DnsQueryOptions.DNS_QUERY_BYPASS_CACHE,
            IntPtr.Zero, ref recordsArray, IntPtr.Zero);
            if (result != 0)
            {
            throw new Win32Exception(result);
            }

                    stringsCursor += Marshal.SizeOf(typeof(IntPtr));
                }
            DNS_RECORD record;
            var recordList = new List<string>();
            for (var recordPtr = recordsArray; !recordPtr.Equals(IntPtr.Zero); recordPtr = record.pNext)
            {
            record = (DNS_RECORD)Marshal.PtrToStructure(recordPtr, typeof(DNS_RECORD));
            if (record.wType == (int)DnsRecordTypes.DNS_TYPE_MX)
            {
                recordList.Add(Marshal.PtrToStringAuto(record.Data.MX.pNameExchange));
            }
            }

                break;
                }

            case (ushort)DnsRecordTypes.DNS_TYPE_AAAA:
                {
                string recordValue = ConvertAAAAToIpAddress(record.Value.Data.AAAA).ToString();
                records.Add(new Dictionary<string, object> { { "Type", "AAAA" }, { "Name", recordName }, { "Value", recordValue } });
                break;
                }

            case (ushort)DnsRecordTypes.DNS_TYPE_SRV:
                {
                string nameTarget = Marshal.PtrToStringUni(record.Value.Data.SRV.NameTarget);
                ushort priority = record.Value.Data.SRV.Priority;
                ushort weight = record.Value.Data.SRV.Weight;
                ushort port = record.Value.Data.SRV.Port;
                records.Add(new Dictionary<string, object> { { "Type", "SRV" }, { "Name", recordName }, { "NameTarget", nameTarget }, { "Priority", priority.ToString() }, { "Weight", weight.ToString() }, { "Port", port.ToString() } });
                break;
                }
            }
            return recordList;
        }

        record = Marshal.PtrToStructure(record.Value.Next, typeof(DNS_RECORD)) as DNS_RECORD?;
        finally
        {
            if (recordsArray != IntPtr.Zero)
            {
            DnsRecordListFree(recordsArray, DNS_FREE_TYPE.DnsFreeFlat);
            }
        }
        }

        return records.ToArray();
    }
        /// <summary>
        /// Provides a DNS query resolution interface
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682016(v=vs.85).aspx
        /// </summary>
        /// <param name="lpstrName">A pointer to a string that represents the DNS name to query</param>
        /// <param name="wType">A value that represents the Resource Record DNS Record Type that is queried</param>
        /// <param name="Options">A value that contains a bitmap of the DNS Query Options to use in the DNS query</param>
        /// <param name="pExtra">Reserved for future use and must be set to NULL</param>
        /// <param name="ppQueryResultsSet">A pointer to a pointer that points to the list of RRs that comprise the response</param>
        /// <param name="pReserved">Reserved for future use and must be set to NULL</param>
        /// <returns>Success (0), or the DNS-specific error defined in Winerror.h</returns>
        [DllImport("dnsapi", EntryPoint = "DnsQuery_W", CharSet = CharSet.Unicode, SetLastError = true,
        ExactSpelling = true)]
        public static extern int DnsQuery([MarshalAs(UnmanagedType.VBByRefStr)] ref string lpstrName, DnsRecordTypes wType,
        DnsQueryOptions Options, IntPtr pExtra, ref IntPtr ppQueryResultsSet, IntPtr pReserved);

    private static IPAddress ConvertUintToIpAddress(uint ipAddress)
    {
        var addressBytes = new byte[4];
        ipAddress = (uint)IPAddress.NetworkToHostOrder((int)ipAddress);
        addressBytes[0] = (byte)((ipAddress & 0xFF000000u) >> 24);
        addressBytes[1] = (byte)((ipAddress & 0x00FF0000u) >> 16);
        addressBytes[2] = (byte)((ipAddress & 0x0000FF00u) >> 8);
        addressBytes[3] = (byte)(ipAddress & 0x000000FFu);
        return new IPAddress(addressBytes);
    }
        /// <summary>
        /// Frees memory allocated for DNS records obtained by using the DnsQuery function
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682021(v=vs.85).aspx
        /// </summary>
        /// <param name="pRecordList">A pointer to the DNS_RECORD structure that contains the list of DNS records to be freed</param>
        /// <param name="FreeType">A specifier of how the record list should be freed</param>
        [DllImport("dnsapi", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern void DnsRecordListFree(IntPtr pRecordList, DNS_FREE_TYPE FreeType);

    private static IPAddress ConvertAAAAToIpAddress(DNS_AAAA_DATA data)
    {
        var addressBytes = new byte[16];
        addressBytes[0] = (byte)(data.Ip6Address0 & 0x000000FF);
        addressBytes[1] = (byte)((data.Ip6Address0 & 0x0000FF00) >> 8);
        addressBytes[2] = (byte)((data.Ip6Address0 & 0x00FF0000) >> 16);
        addressBytes[3] = (byte)((data.Ip6Address0 & 0xFF000000) >> 24);
        addressBytes[4] = (byte)(data.Ip6Address1 & 0x000000FF);
        addressBytes[5] = (byte)((data.Ip6Address1 & 0x0000FF00) >> 8);
        addressBytes[6] = (byte)((data.Ip6Address1 & 0x00FF0000) >> 16);
        addressBytes[7] = (byte)((data.Ip6Address1 & 0xFF000000) >> 24);
        addressBytes[8] = (byte)(data.Ip6Address2 & 0x000000FF);
        addressBytes[9] = (byte)((data.Ip6Address2 & 0x0000FF00) >> 8);
        addressBytes[10] = (byte)((data.Ip6Address2 & 0x00FF0000) >> 16);
        addressBytes[11] = (byte)((data.Ip6Address2 & 0xFF000000) >> 24);
        addressBytes[12] = (byte)(data.Ip6Address3 & 0x000000FF);
        addressBytes[13] = (byte)((data.Ip6Address3 & 0x0000FF00) >> 8);
        addressBytes[14] = (byte)((data.Ip6Address3 & 0x00FF0000) >> 16);
        addressBytes[15] = (byte)((data.Ip6Address3 & 0xFF000000) >> 24);
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/cc982162(v=vs.85).aspx
        /// </summary>
        [Flags]
        public enum DnsQueryOptions
        {
        DNS_QUERY_STANDARD = 0x0,
        DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE = 0x1,
        DNS_QUERY_USE_TCP_ONLY = 0x2,
        DNS_QUERY_NO_RECURSION = 0x4,
        DNS_QUERY_BYPASS_CACHE = 0x8,
        DNS_QUERY_NO_WIRE_QUERY = 0x10,
        DNS_QUERY_NO_LOCAL_NAME = 0x20,
        DNS_QUERY_NO_HOSTS_FILE = 0x40,
        DNS_QUERY_NO_NETBT = 0x80,
        DNS_QUERY_WIRE_ONLY = 0x100,
        DNS_QUERY_RETURN_MESSAGE = 0x200,
        DNS_QUERY_MULTICAST_ONLY = 0x400,
        DNS_QUERY_NO_MULTICAST = 0x800,
        DNS_QUERY_TREAT_AS_FQDN = 0x1000,
        DNS_QUERY_ADDRCONFIG = 0x2000,
        DNS_QUERY_DUAL_ADDR = 0x4000,
        DNS_QUERY_MULTICAST_WAIT = 0x20000,
        DNS_QUERY_MULTICAST_VERIFY = 0x40000,
        DNS_QUERY_DONT_RESET_TTL_VALUES = 0x100000,
        DNS_QUERY_DISABLE_IDN_ENCODING = 0x200000,
        DNS_QUERY_APPEND_MULTILABEL = 0x800000,
        DNS_QUERY_RESERVED = unchecked((int)0xF0000000)
        }

        return new IPAddress(addressBytes);
    }
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/cc982162(v=vs.85).aspx
        /// Also see http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml
        /// </summary>
        public enum DnsRecordTypes
        {
        DNS_TYPE_A = 0x1,
        DNS_TYPE_NS = 0x2,
        DNS_TYPE_MD = 0x3,
        DNS_TYPE_MF = 0x4,
        DNS_TYPE_CNAME = 0x5,
        DNS_TYPE_SOA = 0x6,
        DNS_TYPE_MB = 0x7,
        DNS_TYPE_MG = 0x8,
        DNS_TYPE_MR = 0x9,
        DNS_TYPE_NULL = 0xA,
        DNS_TYPE_WKS = 0xB,
        DNS_TYPE_PTR = 0xC,
        DNS_TYPE_HINFO = 0xD,
        DNS_TYPE_MINFO = 0xE,
        DNS_TYPE_MX = 0xF,
        DNS_TYPE_TEXT = 0x10,       // This is how it's specified on MSDN
        DNS_TYPE_TXT = DNS_TYPE_TEXT,
        DNS_TYPE_RP = 0x11,
        DNS_TYPE_AFSDB = 0x12,
        DNS_TYPE_X25 = 0x13,
        DNS_TYPE_ISDN = 0x14,
        DNS_TYPE_RT = 0x15,
        DNS_TYPE_NSAP = 0x16,
        DNS_TYPE_NSAPPTR = 0x17,
        DNS_TYPE_SIG = 0x18,
        DNS_TYPE_KEY = 0x19,
        DNS_TYPE_PX = 0x1A,
        DNS_TYPE_GPOS = 0x1B,
        DNS_TYPE_AAAA = 0x1C,
        DNS_TYPE_LOC = 0x1D,
        DNS_TYPE_NXT = 0x1E,
        DNS_TYPE_EID = 0x1F,
        DNS_TYPE_NIMLOC = 0x20,
        DNS_TYPE_SRV = 0x21,
        DNS_TYPE_ATMA = 0x22,
        DNS_TYPE_NAPTR = 0x23,
        DNS_TYPE_KX = 0x24,
        DNS_TYPE_CERT = 0x25,
        DNS_TYPE_A6 = 0x26,
        DNS_TYPE_DNAME = 0x27,
        DNS_TYPE_SINK = 0x28,
        DNS_TYPE_OPT = 0x29,
        DNS_TYPE_DS = 0x2B,
        DNS_TYPE_RRSIG = 0x2E,
        DNS_TYPE_NSEC = 0x2F,
        DNS_TYPE_DNSKEY = 0x30,
        DNS_TYPE_DHCID = 0x31,
        DNS_TYPE_UINFO = 0x64,
        DNS_TYPE_UID = 0x65,
        DNS_TYPE_GID = 0x66,
        DNS_TYPE_UNSPEC = 0x67,
        DNS_TYPE_ADDRS = 0xF8,
        DNS_TYPE_TKEY = 0xF9,
        DNS_TYPE_TSIG = 0xFA,
        DNS_TYPE_IXFR = 0xFB,
        DNS_TYPE_AFXR = 0xFC,
        DNS_TYPE_MAILB = 0xFD,
        DNS_TYPE_MAILA = 0xFE,
        DNS_TYPE_ALL = 0xFF,
        DNS_TYPE_ANY = 0xFF,
        DNS_TYPE_WINS = 0xFF01,
        DNS_TYPE_WINSR = 0xFF02,
        DNS_TYPE_NBSTAT = DNS_TYPE_WINSR
        }

    [DllImport("dnsapi", EntryPoint = "DnsQueryEx", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
    private static extern int DnsQueryEx(IntPtr queryRequest, IntPtr queryResults, IntPtr cancelHandle);
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682056(v=vs.85).aspx
        /// </summary>
        public enum DNS_FREE_TYPE
        {
        DnsFreeFlat = 0,
        DnsFreeRecordList = 1,
        DnsFreeParsedMessageFields = 2
        }

    [DllImport("dnsapi", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern void DnsRecordListFree(IntPtr recordList, DNS_FREE_TYPE freeType);
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682082(v=vs.85).aspx
        /// These field offsets could be different depending on endianness and bitness
        /// </summary>
        [StructLayout(LayoutKind.Explicit)]
        public struct DNS_RECORD
        {
        [FieldOffset(0)]
        public IntPtr pNext;    // DNS_RECORD*
        [FieldOffset(4)]
        public IntPtr pName;    // string
        [FieldOffset(8)]
        public ushort wType;
        [FieldOffset(10)]
        public ushort wDataLength;
        [FieldOffset(12)]
        public FlagsUnion Flags;
        [FieldOffset(16)]
        public uint dwTtl;
        [FieldOffset(20)]
        public uint dwReserved;
        [FieldOffset(24)]
        public DataUnion Data;
        }

    [DllImport("dnsapi", SetLastError = true)]
    private static extern int DnsCancelQuery(IntPtr cancelHandle);
        [StructLayout(LayoutKind.Explicit)]
        public struct FlagsUnion
        {
        [FieldOffset(0)]
        public uint DW;
        [FieldOffset(0)]
        public DNS_RECORD_FLAGS S;
        }

    [StructLayout(LayoutKind.Sequential)]
    private struct QueryCompletionContext
    {
        public DnsRecordTypes requestType;
        public EventWaitHandle eventHandle;
        public IntPtr dnsRecords;
        public IntPtr resultCode;
    }
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682084(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_RECORD_FLAGS
        {
        internal uint data;

    [StructLayout(LayoutKind.Sequential)]
    private struct DNS_QUERY_REQUEST
    {
        public uint Version;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string QueryName;
        public ushort QueryType;
        public ulong QueryOptions;
        public IntPtr DnsServerList;
        public uint InterfaceIndex;
        public IntPtr QueryCompletionCallback;
        public IntPtr QueryContext;
    }
        // DWORD Section :2;
        public uint Section
        {
            get { return data & 0x3u; }
            set { data = (data & ~0x3u) | (value & 0x3u); }
        }

    [StructLayout(LayoutKind.Sequential)]
    private struct DNS_ADDR_ARRAY
    {
        public uint MaxCount;
        public uint AddrCount;
        public uint Tag;
        public ushort Family;
        public ushort WordReserved;
        public uint Flags;
        public uint MatchFlag;
        public uint Reserved1;
        public uint Reserved2;
        //// the array of DNS_ADDR follows this
    }
        // DWORD Delete :1;
        public uint Delete
        {
            get { return (data >> 2) & 0x1u; }
            set { data = (data & ~(0x1u << 2)) | (value & 0x1u) << 2; }
        }

    [StructLayout(LayoutKind.Sequential)]
    private struct DNSQueryResult
    {
        public uint Version;
        public int QueryStatus;
        public ulong QueryOptions;
        public IntPtr QueryRecords;
        public IntPtr Reserved;
    }
        // DWORD CharSet :2;
        public uint CharSet
        {
            get { return (data >> 3) & 0x3u; }
            set { data = (data & ~(0x3u << 3)) | (value & 0x3u) << 3; }
        }

    [StructLayout(LayoutKind.Sequential)]
    private struct DNS_RECORD
    {
        public IntPtr Next;
        public IntPtr Name;
        public ushort Type;
        public ushort DataLength;
        public FlagsUnion Flags;
        public uint TimeToLive;
        public uint Reserved;
        public DataUnion Data;
    }
        // DWORD Unused :3;
        public uint Unused
        {
            get { return (data >> 5) & 0x7u; }
            set { data = (data & ~(0x7u << 5)) | (value & 0x7u) << 5; }
        }

    [StructLayout(LayoutKind.Explicit)]
    private struct FlagsUnion
    {
        [FieldOffset(0)]
        public uint DW;
        [FieldOffset(0)]
        public DNS_RECORD_FLAGS S;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct DNS_RECORD_FLAGS
    {
        internal uint Data;

        public uint Section
        {
        get { return this.Data & 0x3u; }
        set { this.Data = (this.Data & ~0x3u) | (value & 0x3u); }
        // DWORD Reserved :24;
        public uint Reserved
        {
            get { return (data >> 8) & 0xFFFFFFu; }
            set { data = (data & ~(0xFFFFFFu << 8)) | (value & 0xFFFFFFu) << 8; }
        }
        }

        public uint Delete
        [StructLayout(LayoutKind.Explicit)]
        public struct DataUnion
        {
        get { return (this.Data >> 2) & 0x1u; }
        set { this.Data = (this.Data & ~(0x1u << 2)) | (value & 0x1u) << 2; }
        [FieldOffset(0)]
        public DNS_A_DATA A;
        [FieldOffset(0)]
        public DNS_SOA_DATA SOA, Soa;
        [FieldOffset(0)]
        public DNS_PTR_DATA PTR, Ptr, NS, Ns, CNAME, Cname, DNAME, Dname, MB, Mb, MD, Md, MF, Mf, MG, Mg, MR, Mr;
        [FieldOffset(0)]
        public DNS_MINFO_DATA MINFO, Minfo, RP, Rp;
        [FieldOffset(0)]
        public DNS_MX_DATA MX, Mx, AFSDB, Afsdb, RT, Rt;
        [FieldOffset(0)]
        public DNS_TXT_DATA HINFO, Hinfo, ISDN, Isdn, TXT, Txt, X25;
        [FieldOffset(0)]
        public DNS_NULL_DATA Null;
        [FieldOffset(0)]
        public DNS_WKS_DATA WKS, Wks;
        [FieldOffset(0)]
        public DNS_AAAA_DATA AAAA;
        [FieldOffset(0)]
        public DNS_KEY_DATA KEY, Key;
        [FieldOffset(0)]
        public DNS_SIG_DATA SIG, Sig;
        [FieldOffset(0)]
        public DNS_ATMA_DATA ATMA, Atma;
        [FieldOffset(0)]
        public DNS_NXT_DATA NXT, Nxt;
        [FieldOffset(0)]
        public DNS_SRV_DATA SRV, Srv;
        [FieldOffset(0)]
        public DNS_NAPTR_DATA NAPTR, Naptr;
        [FieldOffset(0)]
        public DNS_OPT_DATA OPT, Opt;
        [FieldOffset(0)]
        public DNS_DS_DATA DS, Ds;
        [FieldOffset(0)]
        public DNS_RRSIG_DATA RRSIG, Rrsig;
        [FieldOffset(0)]
        public DNS_NSEC_DATA NSEC, Nsec;
        [FieldOffset(0)]
        public DNS_DNSKEY_DATA DNSKEY, Dnskey;
        [FieldOffset(0)]
        public DNS_TKEY_DATA TKEY, Tkey;
        [FieldOffset(0)]
        public DNS_TSIG_DATA TSIG, Tsig;
        [FieldOffset(0)]
        public DNS_WINS_DATA WINS, Wins;
        [FieldOffset(0)]
        public DNS_WINSR_DATA WINSR, WinsR, NBSTAT, Nbstat;
        [FieldOffset(0)]
        public DNS_DHCID_DATA DHCID;
        }

        public uint CharSet
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682044(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_A_DATA
        {
        get { return (this.Data >> 3) & 0x3u; }
        set { this.Data = (this.Data & ~(0x3u << 3)) | (value & 0x3u) << 3; }
        public uint IpAddress;      // IP4_ADDRESS IpAddress;
        }

        public uint Unused
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682096(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_SOA_DATA
        {
        get { return (this.Data >> 5) & 0x7u; }
        set { this.Data = (this.Data & ~(0x7u << 5)) | (value & 0x7u) << 5; }
        public IntPtr pNamePrimaryServer;       // string
        public IntPtr pNameAdministrator;       // string
        public uint dwSerialNo;
        public uint dwRefresh;
        public uint dwRetry;
        public uint dwExpire;
        public uint dwDefaultTtl;
        }

        public uint Reserved
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682080(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_PTR_DATA
        {
        get { return (this.Data >> 8) & 0xFFFFFFu; }
        set { this.Data = (this.Data & ~(0xFFFFFFu << 8)) | (value & 0xFFFFFFu) << 8; }
        public IntPtr pNameHost;    // string
        }
    }

    [StructLayout(LayoutKind.Explicit)]
    private struct DataUnion
    {
        [FieldOffset(0)]
        public DNS_A_DATA A;
        [FieldOffset(0)]
        public DNS_PTR_DATA PTR, NS, CNAME;
        [FieldOffset(0)]
        public DNS_MX_DATA MX;
        [FieldOffset(0)]
        public DNS_TXT_DATA TXT;
        [FieldOffset(0)]
        public DNS_AAAA_DATA AAAA;
        [FieldOffset(0)]
        public DNS_SRV_DATA SRV;
    }
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682067(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_MINFO_DATA
        {
        public IntPtr pNameMailbox;     // string
        public IntPtr pNameErrorsMailbox;       // string
        }

    [StructLayout(LayoutKind.Sequential)]
    private struct DNS_A_DATA
    {
        public uint IpAddress;
    }
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682070(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_MX_DATA
        {
        public IntPtr pNameExchange;        // string
        public ushort wPreference;
        public ushort Pad;
        }

    [StructLayout(LayoutKind.Sequential)]
    private struct DNS_PTR_DATA
    {
        public IntPtr NameHost;
    }
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682109(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_TXT_DATA
        {
        public uint dwStringCount;
        public IntPtr pStringArray;     // PWSTR pStringArray[1];
        }

    [StructLayout(LayoutKind.Sequential)]
    private struct DNS_MX_DATA
    {
        public IntPtr NameExchange;
        public ushort Preference;
        public ushort Pad;
    }
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682074(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_NULL_DATA
        {
        public uint dwByteCount;
        public IntPtr Data;           // BYTE  Data[1];
        }

    [StructLayout(LayoutKind.Sequential)]
    private struct DNS_TXT_DATA
    {
        public uint StringCount;
        public IntPtr StringArray;
    }
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682120(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_WKS_DATA
        {
        public uint IpAddress;      // IP4_ADDRESS IpAddress;
        public byte chProtocol;     // UCHAR       chProtocol;
        public IntPtr BitMask;        // BYTE    BitMask[1];
        }

    [StructLayout(LayoutKind.Sequential)]
    private struct DNS_AAAA_DATA
    {
        public uint Ip6Address0;
        public uint Ip6Address1;
        public uint Ip6Address2;
        public uint Ip6Address3;
    }
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682035(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_AAAA_DATA
        {
        // IP6_ADDRESS Ip6Address;
        // DWORD IP6Dword[4];
        // This isn't ideal, but it should work without using the fixed and unsafe keywords
        public uint Ip6Address0;
        public uint Ip6Address1;
        public uint Ip6Address2;
        public uint Ip6Address3;
        }

    [StructLayout(LayoutKind.Sequential)]
    private struct DNS_SRV_DATA
    {
        public IntPtr NameTarget;
        public ushort Priority;
        public ushort Weight;
        public ushort Port;
        public ushort Pad;
    }

    [StructLayout(LayoutKind.Sequential)]
    private class DNS_ADDR
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = DnsAddrMaxSockaddrLength)]
        private byte[] maxSa;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        private uint[] dnsAddrUserDword;

        public DNS_ADDR()
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682061(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_KEY_DATA
        {
        this.maxSa = new byte[DnsAddrMaxSockaddrLength];
        this.dnsAddrUserDword = new uint[8];
        public ushort wFlags;
        public byte chProtocol;
        public byte chAlgorithm;
        public IntPtr Key;        // BYTE Key[1];
        }

        public byte[] MaxSa
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682094(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_SIG_DATA
        {
        get
        {
            return this.maxSa;
        }
        public IntPtr pNameSigner;      // string
        public ushort wTypeCovered;
        public byte chAlgorithm;
        public byte chLabelCount;
        public uint dwOriginalTtl;
        public uint dwExpiration;
        public uint dwTimeSigned;
        public ushort wKeyTag;
        public ushort Pad;
        public IntPtr Signature;      // BYTE  Signature[1];
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    private class SockAddrIn
    {
        private short sinFamily;
        private ushort sinPort;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = IpAddressV4LengthBytes)]
        private byte[] sinAddr;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        private byte[] sinZero;
        public const int DNS_ATMA_MAX_ADDR_LENGTH = 20;
        public const int DNS_ATMA_FORMAT_E164 = 1;
        public const int DNS_ATMA_FORMAT_AESA = 2;

        public SockAddrIn()
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682041(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_ATMA_DATA
        {
        this.sinFamily = 0;
        this.sinPort = 0;
        this.sinAddr = new byte[IpAddressV4LengthBytes];
        this.sinZero = new byte[8];
        public byte AddressType;
        // BYTE Address[DNS_ATMA_MAX_ADDR_LENGTH];
        // This isn't ideal, but it should work without using the fixed and unsafe keywords
        public byte Address0;
        public byte Address1;
        public byte Address2;
        public byte Address3;
        public byte Address4;
        public byte Address5;
        public byte Address6;
        public byte Address7;
        public byte Address8;
        public byte Address9;
        public byte Address10;
        public byte Address11;
        public byte Address12;
        public byte Address13;
        public byte Address14;
        public byte Address15;
        public byte Address16;
        public byte Address17;
        public byte Address18;
        public byte Address19;
        }

        public short SinFamily
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682076(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_NXT_DATA
        {
        get
        {
            return this.sinFamily;
        }

        set
        {
            this.sinFamily = value;
        }
        public IntPtr pNameNext;    // string
        public ushort wNumTypes;
        public IntPtr wTypes;       // WORD  wTypes[1];
        }

        public ushort SinPort
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682097(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_SRV_DATA
        {
        get
        {
            return this.sinPort;
        }

        set
        {
            this.sinPort = value;
        }
        public IntPtr pNameTarget;      // string
        public ushort uPriority;
        public ushort wWeight;
        public ushort wPort;
        public ushort Pad;
        }

        public byte[] SinAddr
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/cc982164(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_NAPTR_DATA
        {
        get
        {
            return this.sinAddr;
        }
        public ushort wOrder;
        public ushort wPreference;
        public IntPtr pFlags;       // string
        public IntPtr pService;     // string
        public IntPtr pRegularExpression;       // string
        public IntPtr pReplacement;     // string
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    private class SockAddrIn6
    {
        private short sin6Family;
        private ushort sin6Port;
        private ulong sin6FlowInfo;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = IpAddressV6LengthBytes)]
        private byte[] sin6Addr;
        private ulong sin6ScopeId;

        public SockAddrIn6()
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/dd392298(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_OPT_DATA
        {
        this.sin6Family = AFInet;
        this.sin6Port = 0;
        this.sin6Addr = new byte[IpAddressV6LengthBytes];
        this.sin6ScopeId = 0;
        public ushort wDataLength;
        public ushort wPad;
        public IntPtr Data;           // BYTE Data[1];
        }

        public short Sin6Family
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/dd392296(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_DS_DATA
        {
        get
        {
            return this.sin6Family;
        }

        set
        {
            this.sin6Family = value;
        }
        public ushort wKeyTag;
        public byte chAlgorithm;
        public byte chDigestType;
        public ushort wDigestLength;
        public ushort wPad;
        public IntPtr Digest;         // BYTE Digest[1];
        }

        public ushort Sin6Port
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/dd392301(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_RRSIG_DATA
        {
        get
        {
            return this.sin6Port;
        }

        set
        {
            this.sin6Port = value;
        }
        public IntPtr pNameSigner;      // string
        public ushort wTypeCovered;
        public byte chAlgorithm;
        public byte chLabelCount;
        public uint dwOriginalTtl;
        public uint dwExpiration;
        public uint dwTimeSigned;
        public ushort wKeyTag;
        public ushort Pad;
        public IntPtr Signature;      // BYTE  Signature[1];
        }

        public ulong Sin6FlowInfo
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/dd392297(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_NSEC_DATA
        {
        get
        {
            return this.sin6FlowInfo;
        }

        set
        {
            this.sin6FlowInfo = value;
        }
        public IntPtr pNextDomainName;    // string
        public ushort wTypeBitMapsLength;
        public ushort wPad;
        public IntPtr TypeBitMaps;    // BYTE  TypeBitMaps[1];
        }

        public byte[] Sin6Addr
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/dd392295(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_DNSKEY_DATA
        {
        get
        {
            return this.sin6Addr;
        }
        public ushort wFlags;
        public byte chProtocol;
        public byte chAlgorithm;
        public ushort wKeyLength;
        public ushort wPad;
        public IntPtr Key;        // BYTE Key[1];
        }

        public ulong Sin6ScopeId
        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682104(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_TKEY_DATA
        {
        get
        {
            return this.sin6ScopeId;
        }

        set
        {
            this.sin6ScopeId = value;
        }
        public IntPtr pNameAlgorithm;   // string
        public IntPtr pAlgorithmPacket; // PBYTE (which is BYTE*)
        public IntPtr pKey;         // PBYTE (which is BYTE*)
        public IntPtr pOtherData;       // PBYTE (which is BYTE*)
        public uint dwCreateTime;
        public uint dwExpireTime;
        public ushort wMode;
        public ushort wError;
        public ushort wKeyLength;
        public ushort wOtherLength;
        public byte cAlgNameLength;     // UCHAR cAlgNameLength;
        public int bPacketPointers;     // BOOL  bPacketPointers;
        }
    }
    }

Documentation
DnsQueryEx on MSDN

        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682106(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_TSIG_DATA
        {
        public IntPtr pNameAlgorithm;   // string
        public IntPtr pAlgorithmPacket; // PBYTE (which is BYTE*)
        public IntPtr pSignature;       // PBYTE (which is BYTE*)
        public IntPtr pOtherData;       // PBYTE (which is BYTE*)
        public long i64CreateTime;
        public ushort wFudgeTime;
        public ushort wOriginalXid;
        public ushort wError;
        public ushort wSigLength;
        public ushort wOtherLength;
        public byte cAlgNameLength;     // UCHAR    cAlgNameLength;
        public int bPacketPointers;     // BOOL     bPacketPointers;
        }

        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682114(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_WINS_DATA
        {
        public uint dwMappingFlag;
        public uint dwLookupTimeout;
        public uint dwCacheTimeout;
        public uint cWinsServerCount;
        public uint WinsServers;    // IP4_ADDRESS WinsServers[1];
        }

        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682113(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_WINSR_DATA
        {
        public uint dwMappingFlag;
        public uint dwLookupTimeout;
        public uint dwCacheTimeout;
        public IntPtr pNameResultDomain;    // string
        }

        /// <summary>
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/dd392294(v=vs.85).aspx
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct DNS_DHCID_DATA
        {
        public uint dwByteCount;
        public IntPtr DHCID;          // BYTE  DHCID[1];
        }

        /// <summary>
        /// Converts an unsigned int to an ip address object
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/cc982163(v=vs.85).aspx
        /// </summary>
        /// <param name="ipAddress">The unsigned int to convert to an ip address object</param>
        /// <returns>The converted ip address</returns>
        public static IPAddress ConvertUintToIpAddress(uint ipAddress)
        {
        // x86 is in little endian
        // Network byte order (what the IPAddress object requires) is big endian
        // Ex - 0x7F000001 is 127.0.0.1
        var addressBytes = new byte[4];
        addressBytes[0] = (byte)((ipAddress & 0xFF000000u) >> 24);
        addressBytes[1] = (byte)((ipAddress & 0x00FF0000u) >> 16);
        addressBytes[2] = (byte)((ipAddress & 0x0000FF00u) >> 8);
        addressBytes[3] = (byte)(ipAddress & 0x000000FFu);
        return new IPAddress(addressBytes);
        }

        /// <summary>
        /// Converts the data from the AAAA record into an ip address object
        /// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682140(v=vs.85).aspx
        /// </summary>
        /// <param name="data">The AAAA record to convert</param>
        /// <returns>The converted ip address</returns>
        public static IPAddress ConvertAAAAToIpAddress(DNS_AAAA_DATA data)
        {
        var addressBytes = new byte[16];
        addressBytes[0] = (byte)(data.Ip6Address0 & 0x000000FF);
        addressBytes[1] = (byte)((data.Ip6Address0 & 0x0000FF00) >> 8);
        addressBytes[2] = (byte)((data.Ip6Address0 & 0x00FF0000) >> 16);
        addressBytes[3] = (byte)((data.Ip6Address0 & 0xFF000000) >> 24);
        addressBytes[4] = (byte)(data.Ip6Address1 & 0x000000FF);
        addressBytes[5] = (byte)((data.Ip6Address1 & 0x0000FF00) >> 8);
        addressBytes[6] = (byte)((data.Ip6Address1 & 0x00FF0000) >> 16);
        addressBytes[7] = (byte)((data.Ip6Address1 & 0xFF000000) >> 24);
        addressBytes[8] = (byte)(data.Ip6Address2 & 0x000000FF);
        addressBytes[9] = (byte)((data.Ip6Address2 & 0x0000FF00) >> 8);
        addressBytes[10] = (byte)((data.Ip6Address2 & 0x00FF0000) >> 16);
        addressBytes[11] = (byte)((data.Ip6Address2 & 0xFF000000) >> 24);
        addressBytes[12] = (byte)(data.Ip6Address3 & 0x000000FF);
        addressBytes[13] = (byte)((data.Ip6Address3 & 0x0000FF00) >> 8);
        addressBytes[14] = (byte)((data.Ip6Address3 & 0x00FF0000) >> 16);
        addressBytes[15] = (byte)((data.Ip6Address3 & 0xFF000000) >> 24);

        return new IPAddress(addressBytes);
        }
    }
    }

Documentation

Alternative Managed API:

System.Net.Dns.GetHostEntry(Name)

Please edit this page!

Do you have...

  • helpful tips or sample code to share for using this API in managed code?
  • corrections to the existing content?
  • variations of the signature you want to share?
  • additional languages you want to include?

Select "Edit This Page" on the right hand toolbar and edit it! Or add new pages containing supporting types needed for this API (structures, delegates, and more).

 
Access PInvoke.net directly from VS:
Terms of Use
Edit This Page
Find References
Show Printable Version
Revisions