Added DnsGetCacheDataTable w/ unit test (#121)

pull/133/head
dahall 2020-05-11 10:24:10 -06:00
parent df99d91f26
commit efcd560dbd
3 changed files with 74 additions and 0 deletions

View File

@ -200,6 +200,16 @@ namespace Vanara.PInvoke
[PInvokeData("windns.h", MSDNShortId = "4c69d548-3bb5-4609-9fc5-3a829a285956")]
public static extern void DnsFreeProxyName(IntPtr proxyName);
/// <summary>Gets a list of cached domain names in the DNS client.</summary>
/// <param name="ppCacheData">The cached data list.</param>
/// <returns>
/// Returns success confirmation upon successful completion. Otherwise, returns the appropriate DNS-specific error code as defined
/// in Winerror.h.
/// </returns>
[DllImport(Lib.Dnsapi, SetLastError = true, ExactSpelling = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DnsGetCacheDataTable(out SafeDnsCacheDataTable ppCacheData);
/// <summary>
/// The <c>DnsGetProxyInformation</c> function returns the proxy information for a DNS server's name resolution policy table.
/// </summary>
@ -1327,6 +1337,41 @@ namespace Vanara.PInvoke
public IntPtr DangerousGetHandle() => handle;
}
/// <summary>Provides a <see cref="SafeHandle"/> for a list of allocated <c>DNS_CACHE_ENTRY</c> values that is disposed using <see cref="DnsFree"/>.</summary>
public class SafeDnsCacheDataTable : SafeHANDLE, IEnumerable<DNS_CACHE_ENTRY>
{
/// <summary>Initializes a new instance of the <see cref="SafeDnsCacheDataTable"/> class and assigns an existing handle.</summary>
/// <param name="preexistingHandle">An <see cref="IntPtr"/> object that represents the pre-existing handle to use.</param>
/// <param name="ownsHandle"><see langword="true"/> to reliably release the handle during the finalization phase; otherwise, <see langword="false"/> (not recommended).</param>
public SafeDnsCacheDataTable(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
/// <summary>Initializes a new instance of the <see cref="SafeDnsCacheDataTable"/> class.</summary>
private SafeDnsCacheDataTable() : base() { }
/// <summary>Returns an enumerator that iterates through the collection.</summary>
/// <returns>A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.</returns>
public IEnumerator<DNS_CACHE_ENTRY> GetEnumerator() => handle.LinkedListToIEnum<DNS_CACHE_ENTRY>(r => r.pNext).GetEnumerator();
/// <summary>Returns an enumerator that iterates through a collection.</summary>
/// <returns>An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.</returns>
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
/// <inheritdoc/>
protected override bool InternalReleaseHandle()
{
// From https://stackoverflow.com/questions/31889957/memory-leak-when-using-dnsgetcachedatatable
var p = handle;
while (p != IntPtr.Zero)
{
var s = p.ToStructure<DNS_CACHE_ENTRY>();
DnsFree((IntPtr)s.pszName, DNS_FREE_TYPE.DnsFreeFlat);
DnsFree(p, DNS_FREE_TYPE.DnsFreeFlat);
p = s.pNext;
}
return true;
}
}
/// <summary>Provides a <see cref="SafeHandle"/> for a DNS record list that is disposed using <see cref="DnsRecordListFree"/>.</summary>
public class SafeDnsRecordList : SafeHANDLE, IEnumerable<DNS_RECORD>
{

View File

@ -925,6 +925,26 @@ namespace Vanara.PInvoke
public byte[] Address;
}
/// <summary>Undocumented.</summary>
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct DNS_CACHE_ENTRY
{
/// <summary>Pointer to next entry.</summary>
public IntPtr pNext;
/// <summary>DNS Record Name.</summary>
public StrPtrUni pszName;
/// <summary>DNS Record Type.</summary>
public DNS_TYPE wType;
/// <summary>Undocumented.</summary>
public ushort wDataLength;
/// <summary>Undocumented.</summary>
public DNS_RECORD_FLAGS dwFlags;
}
/// <summary>
/// The <c>DNS_DHCID_DATA</c> structure represents a DNS Dynamic Host Configuration Protocol Information (DHCID) resource record
/// (RR) as specified in section 3 of RFC 4701.

View File

@ -30,6 +30,15 @@ namespace Vanara.PInvoke.Tests
Assert.That(DnsExtractRecordsFromMessage(mem, (ushort)(uint)mem.Size, out var results), ResultIs.Successful);
}
[Test]
public void DnsGetCacheDataTableTest()
{
Assert.That(DnsGetCacheDataTable(out var table), ResultIs.Successful);
foreach (var d in table)
TestContext.WriteLine($"{d.pszName} => {d.wType}");
Assert.That(() => table.Dispose(), Throws.Nothing);
}
[Test]
public void DnsGetProxyInformationTest()
{