Added helper ctos to DNS_ADDR_ARRAY, DNS_QUERY_REQUEST, DNS_QUERY_RESULT and IP4_ARRAY. Added DNS_QUERY_REQUEST3 and DnsQueryEx overloads for it.

pull/328/head
dahall 2022-07-26 17:04:05 -06:00
parent c2fb30345d
commit 8162d0923d
2 changed files with 281 additions and 5 deletions

View File

@ -769,6 +769,108 @@ namespace Vanara.PInvoke
[PInvokeData("windns.h", MSDNShortId = "22664B9A-5010-42E7-880B-8D5B16A9F2DC")]
public static extern DNS_STATUS DnsQueryEx(in DNS_QUERY_REQUEST pQueryRequest, ref DNS_QUERY_RESULT pQueryResults, ref DNS_QUERY_CANCEL pCancelHandle);
/// <summary>
/// <para>
/// The <c>DnsQueryEx</c> function is the asynchronous generic query interface to the DNS namespace, and provides application
/// developers with a DNS query resolution interface.
/// </para>
/// <para>Like DnsQuery, <c>DnsQueryEx</c> can be used to make synchronous queries to the DNS namespace as well.</para>
/// </summary>
/// <param name="pQueryRequest">
/// <para>A pointer to a DNS_QUERY_REQUEST structure that contains the query request information.</para>
/// <para>
/// <c>Note</c> By omitting the DNS_QUERY_COMPLETION_ROUTINE callback from the <c>pQueryCompleteCallback</c> member of this
/// structure, <c>DnsQueryEx</c> is called synchronously.
/// </para>
/// </param>
/// <param name="pQueryResults">
/// <para>
/// A pointer to a DNS_QUERY_RESULT structure that contains the results of the query. On input, the <c>version</c> member of
/// pQueryResults must be <c>DNS_QUERY_REQUEST_VERSION1</c> and all other members should be <c>NULL</c>. On output, the remaining
/// members will be filled as part of the query complete.
/// </para>
/// <para>
/// <c>Note</c> For asynchronous queries, an application should not free this structure until the DNS_QUERY_COMPLETION_ROUTINE
/// callback is invoked. When the query completes, the DNS_QUERY_RESULT structure contains a pointer to a list of DNS_RECORDS that
/// should be freed using DnsRecordListFree.
/// </para>
/// </param>
/// <param name="pCancelHandle">
/// <para>A pointer to a DNS_QUERY_CANCEL structure that can be used to cancel a pending asynchronous query.</para>
/// <para><c>Note</c> An application should not free this structure until the DNS_QUERY_COMPLETION_ROUTINE callback is invoked.</para>
/// </param>
/// <returns>
/// <para>The <c>DnsQueryEx</c> function has the following possible return values:</para>
/// <list type="table">
/// <listheader>
/// <term>Return code</term>
/// <term>Description</term>
/// </listheader>
/// <item>
/// <term>ERROR_SUCCESS</term>
/// <term>The call was successful.</term>
/// </item>
/// <item>
/// <term>ERROR_INVALID_PARAMETER</term>
/// <term>Either the pQueryRequest or pQueryRequest parameters are uninitialized or contain the wrong version.</term>
/// </item>
/// <item>
/// <term>DNS RCODE</term>
/// <term>The call resulted in an RCODE error.</term>
/// </item>
/// <item>
/// <term>DNS_INFO_NO_RECORDS</term>
/// <term>No records in the response.</term>
/// </item>
/// <item>
/// <term>DNS_REQUEST_PENDING</term>
/// <term>The query will be completed asynchronously.</term>
/// </item>
/// </list>
/// </returns>
/// <remarks>
/// <para>
/// If a call to <c>DnsQueryEx</c> completes synchronously (i.e., the function return value is not <c>DNS_REQUEST_PENDING</c>), the
/// <c>pQueryRecords</c> member of pQueryResults contains a pointer to a list of DNS_RECORDS and <c>DnsQueryEx</c> will return
/// either error or success.
/// </para>
/// <para>The following conditions invoke a synchronous call to <c>DnsQueryEx</c> and do not utilize the DNS callback:</para>
/// <list type="bullet">
/// <item>
/// <term>The DNS_QUERY_COMPLETION_ROUTINE callback is omitted from the <c>pQueryCompleteCallback</c> member of pQueryRequest.</term>
/// </item>
/// <item>
/// <term>A query is for the local machine name and A or AAAA type Resource Records (RR).</term>
/// </item>
/// <item>
/// <term>A call to <c>DnsQueryEx</c> queries an IPv4 or IPv6 address.</term>
/// </item>
/// <item>
/// <term>A call to <c>DnsQueryEx</c> returns in error.</term>
/// </item>
/// </list>
/// <para>
/// If a call to <c>DnsQueryEx</c> completes asynchronously, the results of the query are returned by the
/// DNS_QUERY_COMPLETION_ROUTINE callback in pQueryRequest, the <c>QueryStatus</c> member of pQueryResults contains
/// <c>DNS_REQUEST_PENDING</c>, and <c>DnsQueryEx</c> returns <c>DNS_REQUEST_PENDING</c>. Applications should track the
/// pQueryResults structure that is passed into <c>DnsQueryEx</c> until the DNS callback succeeds. Applications can cancel an
/// asynchronous query using the pCancelHandle handle returned by <c>DnsQueryEx</c>.
/// </para>
/// <para>
/// pCancelHandle returned from an asynchronous call to <c>DnsQueryEx</c> and pQueryContext is valid until the
/// DNS_QUERY_COMPLETION_ROUTINE DNS callback is invoked.
/// </para>
/// <para>
/// <c>Note</c> Applications are notified of asynchronous <c>DnsQueryEx</c> completion through the DNS_QUERY_COMPLETION_ROUTINE
/// callback within the same process context.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/windns/nf-windns-dnsqueryex DNS_STATUS DnsQueryEx( PDNS_QUERY_REQUEST
// pQueryRequest, PDNS_QUERY_RESULT pQueryResults, PDNS_QUERY_CANCEL pCancelHandle );
[DllImport(Lib.Dnsapi, SetLastError = false, ExactSpelling = true)]
[PInvokeData("windns.h", MSDNShortId = "22664B9A-5010-42E7-880B-8D5B16A9F2DC")]
public static extern DNS_STATUS DnsQueryEx(in DNS_QUERY_REQUEST3 pQueryRequest, ref DNS_QUERY_RESULT pQueryResults, ref DNS_QUERY_CANCEL pCancelHandle);
/// <summary>The <c>DnsRecordCompare</c> function compares two DNS resource records (RR).</summary>
/// <param name="pRecord1">A pointer to a DNS_RECORD structure that contains the first DNS RR of the comparison pair.</param>
/// <param name="pRecord2">A pointer to a DNS_RECORD structure that contains the second DNS RR of the comparison pair.</param>

View File

@ -32,6 +32,9 @@ namespace Vanara.PInvoke
/// <summary/>
public const uint DNS_QUERY_REQUEST_VERSION2 = 0x2;
/// <summary/>
public const uint DNS_QUERY_REQUEST_VERSION3 = 0x3;
/// <summary/>
public const uint DNS_QUERY_RESULTS_VERSION1 = 0x1;
@ -978,6 +981,24 @@ namespace Vanara.PInvoke
/// <summary>An array of DNS_ADDR structures that each contain an IP address.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public DNS_ADDR[] AddrArray;
/// <summary>Initializes a new instance of the <see cref="DNS_ADDR_ARRAY"/> struct with IPv4 addresses.</summary>
/// <param name="addrs">The list of IPv4 addresses.</param>
public DNS_ADDR_ARRAY(params SOCKADDR_IN[] addrs) : this()
{
MaxCount = AddrCount = (uint)(addrs?.Length ?? 0);
Family = ADDRESS_FAMILY.AF_INET;
AddrArray = Array.ConvertAll(addrs, a => new DNS_ADDR() { MaxSa = new SOCKADDR(a).GetBytes() });
}
/// <summary>Initializes a new instance of the <see cref="DNS_ADDR_ARRAY"/> struct with IPv6 addresses.</summary>
/// <param name="addrs">The list of IPv4 addresses.</param>
public DNS_ADDR_ARRAY(params SOCKADDR_IN6[] addrs) : this()
{
MaxCount = AddrCount = (uint)(addrs?.Length ?? 0);
Family = ADDRESS_FAMILY.AF_INET6;
AddrArray = Array.ConvertAll(addrs, a => new DNS_ADDR() { MaxSa = new SOCKADDR(a).GetBytes() });
}
}
/// <summary>Represents per-application DNS settings.</summary>
@ -1898,7 +1919,8 @@ namespace Vanara.PInvoke
/// <para>A pointer to a string that represents the DNS name to query.</para>
/// <para><c>Note</c> If <c>QueryName</c> is NULL, the query is for the local machine name.</para>
/// </summary>
[MarshalAs(UnmanagedType.LPWStr)] public string QueryName;
[MarshalAs(UnmanagedType.LPWStr)]
public string QueryName;
/// <summary>
/// A value that represents the Resource Record (RR) DNS Record Type that is queried. <c>QueryType</c> determines the format of
@ -1940,6 +1962,150 @@ namespace Vanara.PInvoke
/// <summary>A pointer to a user context.</summary>
public IntPtr pQueryContext;
/// <summary>Initializes a new instance of the <see cref="DNS_QUERY_REQUEST"/> struct.</summary>
/// <param name="type">The Resource Record (RR) DNS Record Type that is queried.</param>
/// <param name="queryName">The DNS name to query.</param>
/// <param name="options">The DNS Query Options to use in the DNS query.</param>
public DNS_QUERY_REQUEST(DNS_TYPE type, string queryName = null, DNS_QUERY_OPTIONS options = 0) : this()
{
Version = DNS_QUERY_REQUEST_VERSION1;
QueryName = queryName;
QueryType = type;
QueryOptions = options;
}
}
/// <summary>Contains the DNS query parameters used in a call to DnsQueryEx.</summary>
/// <remarks>
/// <para>The custom servers specified in pCustomServers bypass the system-configured DNS servers.</para>
/// <para>
/// If the query name matches a rule in the <c>Name Resolution Policy Table (NRPT)</c>, then the custom servers are ignored, and only
/// the servers from the <c>NRPT</c> rule are used.
/// </para>
/// </remarks>
// https://docs.microsoft.com/en-us/windows/win32/api/windns/ns-windns-dns_query_request3 typedef struct _DNS_QUERY_REQUEST3 { ULONG
// Version; PCWSTR QueryName; WORD QueryType; ULONG64 QueryOptions; PDNS_ADDR_ARRAY pDnsServerList; ULONG InterfaceIndex;
// PDNS_QUERY_COMPLETION_ROUTINE pQueryCompletionCallback; PVOID pQueryContext; BOOL IsNetworkQueryRequired; DWORD
// RequiredNetworkIndex; DWORD cCustomServers; DNS_CUSTOM_SERVER *pCustomServers; } DNS_QUERY_REQUEST3, *PDNS_QUERY_REQUEST3;
[PInvokeData("windns.h", MSDNShortId = "NS:windns._DNS_QUERY_REQUEST3")]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct DNS_QUERY_REQUEST3
{
/// <summary>
/// <para>Type: <c>ULONG</c></para>
/// <para>The structure version must be the <c>DNS_QUERY_REQUEST_VERSION3</c>; which has a value of 3.</para>
/// </summary>
public uint Version;
/// <summary>
/// <para>Type: <c>PCWSTR</c></para>
/// <para>A pointer to a string that represents the DNS name to query.</para>
/// <para>
/// <para>Note</para>
/// <para>If QueryName is <c>NULL</c>, then the query is for the local machine name.</para>
/// </para>
/// </summary>
[MarshalAs(UnmanagedType.LPWStr)]
public string QueryName;
/// <summary>
/// <para>Type: <c>WORD</c></para>
/// <para>
/// A value that represents the Resource Record (RR) DNS Record Type that is queried. QueryType determines the format of data
/// pointed to by pQueryRecords returned in the DNS_QUERY_RESULT structure. For example, if the value of wType is DNS_TYPE_A,
/// then the format of data pointed to by pQueryRecords is DNS_A_DATA.
/// </para>
/// </summary>
public DNS_TYPE QueryType;
// Hack to make this the right size even though the enum is a UInt32.
private ulong _QueryOptions;
/// <summary>
/// A value that contains a bitmap of DNS Query Options to use in the DNS query. Options can be combined and all options
/// override <c>DNS_QUERY_STANDARD</c>
/// </summary>
public DNS_QUERY_OPTIONS QueryOptions { get => (DNS_QUERY_OPTIONS)_QueryOptions; set => _QueryOptions = (ulong)value; }
/// <summary>
/// <para>Type: <c>PDNS_ADDR_ARRAY</c></para>
/// <para>A pointer to a DNS_ADDR_ARRAY structure that contains a list of DNS servers to use in the query.</para>
/// </summary>
public IntPtr pDnsServerList;
/// <summary>
/// <para>Type: <c>ULONG</c></para>
/// <para>
/// A value that contains the interface index over which the query is sent. If InterfaceIndex is 0, then all interfaces will be considered.
/// </para>
/// </summary>
public uint InterfaceIndex;
/// <summary>
/// <para>Type: <c>PDNS_QUERY_COMPLETION_ROUTINE</c></para>
/// <para>
/// A pointer to a DNS_QUERY_COMPLETION_ROUTINE callback that is used to return the results of an asynchronous query from a call
/// to DnsQueryEx.
/// </para>
/// <para>
/// <para>Note</para>
/// <para>If <c>NULL</c>, then DnsQueryEx is called synchronously.</para>
/// </para>
/// </summary>
[MarshalAs(UnmanagedType.FunctionPtr)]
public DNS_QUERY_COMPLETION_ROUTINE pQueryCompletionCallback;
/// <summary>
/// <para>Type: <c>PVOID</c></para>
/// <para>A pointer to a user context.</para>
/// </summary>
public IntPtr pQueryContext;
/// <summary>
/// <para>Type: <c>BOOL</c></para>
/// <para>Reserved.</para>
/// </summary>
[MarshalAs(UnmanagedType.Bool)]
public bool IsNetworkQueryRequired;
/// <summary>
/// <para>Type: <c>DWORD</c></para>
/// <para>Reserved.</para>
/// </summary>
public uint RequiredNetworkIndex;
/// <summary>
/// <para>Type: <c>DWORD</c></para>
/// <para>The number of custom servers pointed to by the pCustomServers member.</para>
/// </summary>
public uint cCustomServers;
/// <summary>
/// <para>Type: _Field_size_(cCustomServers) <c>DNS_CUSTOM_SERVER*</c></para>
/// <para>A pointer to an array of N (where N is given in the cCustomServers field) DNS_CUSTOM_SERVER objects.</para>
/// <para>If cCustomServers is 0, then pCustomServers must be <c>NULL</c>.</para>
/// <para>
/// <para>Note</para>
/// <para>
/// At least one of pCustomServers and pDnsServerList must be <c>NULL</c>. Both set to non- <c>NULL</c> values at the same time
/// is not supported.
/// </para>
/// </para>
/// </summary>
public IntPtr pCustomServers;
/// <summary>Initializes a new instance of the <see cref="DNS_QUERY_REQUEST3"/> struct.</summary>
/// <param name="type">The Resource Record (RR) DNS Record Type that is queried.</param>
/// <param name="queryName">The DNS name to query.</param>
/// <param name="options">The DNS Query Options to use in the DNS query.</param>
public DNS_QUERY_REQUEST3(DNS_TYPE type, string queryName = null, DNS_QUERY_OPTIONS options = 0) : this()
{
Version = DNS_QUERY_REQUEST_VERSION1;
QueryName = queryName;
QueryType = type;
QueryOptions = options;
}
}
/// <summary>A <c>DNS_QUERY_RESULT</c> structure contains the DNS query results returned from a call to DnsQueryEx.</summary>
@ -1989,6 +2155,9 @@ namespace Vanara.PInvoke
/// <summary/>
public IntPtr Reserved;
/// <summary>An instance of <see cref="DNS_QUERY_RESULT"/> with the <see cref="Version"/> field set to <see cref="DNS_QUERY_RESULTS_VERSION1"/>.</summary>
public static readonly DNS_QUERY_RESULT Default = new() { Version = DNS_QUERY_RESULTS_VERSION1 };
}
/// <summary>The <c>DNS_RECORD</c> structure stores a DNS resource record (RR).</summary>
@ -3197,6 +3366,14 @@ namespace Vanara.PInvoke
/// <summary>An array of IP4_ADDRESS data types that contains a list of IPv4 address.</summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public IP4_ADDRESS[] AddrArray;
/// <summary>Initializes a new instance of the <see cref="IP4_ARRAY"/> struct.</summary>
/// <param name="addrs">The list of IPv4 address.</param>
public IP4_ARRAY(params IP4_ADDRESS[] addrs)
{
AddrCount = (uint)(addrs?.Length ?? 0);
AddrArray = addrs;
}
}
/// <summary>Contains information related to an ongoing MDNS query. Your application must not modify its contents.</summary>
@ -3380,10 +3557,7 @@ namespace Vanara.PInvoke
internal class SafeDNS_NSEC3_DATA : SafeAnysizeStructBase<DNS_NSEC3_DATA>
{
internal SafeDNS_NSEC3_DATA(DNS_NSEC3_DATA value) : base(baseSz)
{
ToNative(value);
}
internal SafeDNS_NSEC3_DATA(DNS_NSEC3_DATA value) : base(baseSz) => ToNative(value);
internal SafeDNS_NSEC3_DATA(IntPtr allocatedMemory, SizeT size) : base(allocatedMemory, size, false)
{