DnsQuery function (Windows)

Switch View :
ScriptFree
DnsQuery function

Applies to: desktop apps only

The DnsQuery function type is the generic query interface to the DNS namespace, and provides application developers with a DNS query resolution interface. Like many DNS functions, the DnsQuery function type is implemented in multiple forms to facilitate different character encoding. Based on the character encoding involved, use one of the following functions:

  • DnsQuery_A (for ANSI encoding)
  • DnsQuery_W (for Unicode encoding)
  • DnsQuery_UTF8 (for UTF-8 encoding)

Windows 8 Consumer Preview: The DnsQueryEx function should be used if an application requires asynchronous querries to the DNS namespace.

Syntax

DNS_STATUS WINAPI DnsQuery(
  __in         PCTSTR lpstrName,
  __in         WORD wType,
  __in         DWORD Options,
  __inout_opt  PVOID pExtra,
  __out_opt    PDNS_RECORD *ppQueryResultsSet,
  __out_opt    PVOID *pReserved
);

Parameters

lpstrName [in]

A pointer to a string that represents the DNS name to query.

wType [in]

A value that represents the Resource Record (RR)DNS Record Type that is queried. wType determines the format of data pointed to by ppQueryResultsSet. For example, if the value of wType is DNS_TYPE_A, the format of data pointed to by ppQueryResultsSet is DNS_A_DATA.

Options [in]

A value that contains a bitmap of DNS Query Options to use in the DNS query. Options can be combined and all options override DNS_QUERY_STANDARD.

pExtra [in, out, optional]

This parameter is reserved for future use and must be set to NULL.

ppQueryResultsSet [out, optional]

Optional. A pointer to a pointer that points to the list of RRs that comprise the response. For more information, see the Remarks section.

pReserved [out, optional]

This parameter is reserved for future use and must be set to NULL.

Return value

Returns success confirmation upon successful completion. Otherwise, returns the appropriate DNS-specific error code as defined in Winerror.h.

Remarks

Applications that call the DnsQuery function build a query using a fully qualified DNS name and Resource Record (RR) type, and set query options depending on the type of service desired. When the DNS_QUERY_STANDARD option is set, DNS uses the resolver cache, queries first with UDP, then retries with TCP if the response is truncated, and requests that the server to perform recursive resolution on behalf of the client to resolve the query.

Applications must free returned RR sets with the DnsRecordListFree function.

Note  When calling one of the DnsQuery function types, be aware that a DNS server may return multiple records in response to a query. A computer that is multihomed, for example, will receive multiple A records for the same IP address. The caller must use as many of the returned records as necessary.

Consider the following scenario, in which multiple returned records require additional activity on behalf of the application: A DnsQuery_A function call is made for a multihomed computer and the application finds that the address associated with the first A record is not responding. The application should then attempt to use other IP addresses specified in the (additional) A records returned from the DnsQuery_A function call.

If the lpstrName parameter is set to NULL, the DnsQuery function fails with the error INVALID_PARAMETER.

Requirements

Minimum supported client

Windows 2000 Professional

Minimum supported server

Windows 2000 Server

Header

Windns.h

Library

Dnsapi.lib

DLL

Dnsapi.dll

Unicode and ANSI names

DnsQuery_W (Unicode) and DnsQuery_A (ANSI)

See also

DNS_RECORD
DnsRecordListFree
DnsQueryEx

 

 

Send comments about this topic to Microsoft

Build date: 3/6/2012

Community Content

Breese
Using pExtra to provide DNS server IP addresses in a PIP4_ARRAY from C#
Just a quick tip on passing your own DNS server IP Addresses in from C#. Make sure you implement the IP4_ARRAY struct and use it in the Pinoke declaration used to call the DnsQuery API function as shown below. The below code only shows this particular piece. You still have to implement the rest of the data structures necessary for your required functionality as shown above. private static extern UInt32 DnsQuery([MarshalAs(UnmanagedType.LPStr)]string lpstrName, [MarshalAs(UnmanagedType.U2)]UInt16 wType, [MarshalAs(UnmanagedType.U4)]UInt32 fOptions, ref IP4_ARRAY dnsServerIpArray, ref UInt32 prr, [MarshalAs(UnmanagedType.U4)]UInt32 t3); [StructLayout(LayoutKind.Sequential)] public struct IP4_ARRAY { /// DWORD->unsigned int public UInt32 AddrCount; /// IP4_ADDRESS[1] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1, ArraySubType = UnmanagedType.U4)] public UInt32[] AddrArray; } uint address = BitConverter.ToUInt32(IPAddress.Parse("208.67.222.222").GetAddressBytes(), 0); uint[] ipArray = new uint[1]; ipArray.SetValue(address, 0); IP4_ARRAY dnsServerArray = new IP4_ARRAY(); dnsServerArray.AddrCount = 1; dnsServerArray.AddrArray = new uint[1]; dnsServerArray.AddrArray[0] = address; DnsQuery(strDomain, dnstype, querytype, ref dnsServerArray, ref ppQueryResultsSet, (UInt32)0)

JamieSee
pExtra Description Inaccurate
As seen in the How to use the DnsQuery function to resolve host names and host addresses with Visual C++ .NET article
(http://support.microsoft.com/kb/831226
) pExtra accepts NULL or a PIP4_ARRAY containing the specific DNS servers to be queried.

pfleduc
Great Example here

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

by Peter A. Bromberg, Ph.D.

namespace PAB.DnsUtils
{
using System;
using System.Collections;
using System.ComponentModel;
using System.Runtime.InteropServices;

public class DnsMx
{
public DnsMx()
{
}
[DllImport("dnsapi", EntryPoint="DnsQuery_W", CharSet=CharSet.Unicode, SetLastError=true, ExactSpelling=true)]
private static extern int DnsQuery([MarshalAs(UnmanagedType.VBByRefStr)]ref string pszName, QueryTypes wType, QueryOptions options, int aipServers, ref IntPtr ppQueryResults, int pReserved);

[DllImport("dnsapi", CharSet=CharSet.Auto, SetLastError=true)]
private static extern void DnsRecordListFree(IntPtr pRecordList, int FreeType);

public static string[] GetMXRecords(string domain)
{

IntPtr ptr1=IntPtr.Zero ;
IntPtr ptr2=IntPtr.Zero ;
MXRecord recMx;
if (Environment.OSVersion.Platform != PlatformID.Win32NT)
{
throw new NotSupportedException();
}
ArrayList list1 = new ArrayList();
int num1 = DnsMx.DnsQuery(ref domain, QueryTypes.DNS_TYPE_MX, QueryOptions.DNS_QUERY_BYPASS_CACHE, 0, ref ptr1, 0);
if (num1 != 0)
{
throw new Win32Exception(num1);
}
for (ptr2 = ptr1; !ptr2.Equals(IntPtr.Zero); ptr2 = recMx.pNext)
{
recMx = ( MXRecord) Marshal.PtrToStructure(ptr2, typeof(MXRecord));
if (recMx.wType == 15)
{
string text1 = Marshal.PtrToStringAuto(recMx.pNameExchange);
list1.Add(text1);
}
}
DnsMx.DnsRecordListFree(ptr2, 0);
return (string[]) list1.ToArray(typeof(string));
}

private enum QueryOptions
{
DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE = 1,
DNS_QUERY_BYPASS_CACHE = 8,
DNS_QUERY_DONT_RESET_TTL_VALUES = 0x100000,
DNS_QUERY_NO_HOSTS_FILE = 0x40,
DNS_QUERY_NO_LOCAL_NAME = 0x20,
DNS_QUERY_NO_NETBT = 0x80,
DNS_QUERY_NO_RECURSION = 4,
DNS_QUERY_NO_WIRE_QUERY = 0x10,
DNS_QUERY_RESERVED = -16777216,
DNS_QUERY_RETURN_MESSAGE = 0x200,
DNS_QUERY_STANDARD = 0,
DNS_QUERY_TREAT_AS_FQDN = 0x1000,
DNS_QUERY_USE_TCP_ONLY = 2,
DNS_QUERY_WIRE_ONLY = 0x100
}

private enum QueryTypes
{
DNS_TYPE_MX = 15
}

[StructLayout(LayoutKind.Sequential)]
private struct MXRecord
{
public IntPtr pNext;
public string pName;
public short wType;
public short wDataLength;
public int flags;
public int dwTtl;
public int dwReserved;
public IntPtr pNameExchange;
public short wPreference;
public short Pad;
}
}
}


static void Main(string[] args)
{
string[] s= PAB.DnsUtils.DnsMx.GetMXRecords("microsoft.com");
foreach (string st in s)
Console.WriteLine("Server: {0}",st);
Console.ReadLine();


steveren
Beware of mixing ANSI/Unicode
There's a problem in the header file WinDNS.h in that all the DnsQuery_x functions are defined as taking a a parameter of type PDNS_RECORD *, not PDNS_RECORDx *. Thus in, say, a Unicode build, DnsQuery_A() appears to take a PDNS_RECORDW * because that's what the generic parameter is defined as.

I don't think there's a good workaround other than editing the WinDNS.h file to specify the correct types explicitly.

Other functions (eg, DnsRecordListFree()) have the same problem.