diff --git a/PInvoke/DnsApi/WinDns.Funcs.cs b/PInvoke/DnsApi/WinDns.Funcs.cs
index 9048eede..869c7f8e 100644
--- a/PInvoke/DnsApi/WinDns.Funcs.cs
+++ b/PInvoke/DnsApi/WinDns.Funcs.cs
@@ -200,6 +200,16 @@ namespace Vanara.PInvoke
[PInvokeData("windns.h", MSDNShortId = "4c69d548-3bb5-4609-9fc5-3a829a285956")]
public static extern void DnsFreeProxyName(IntPtr proxyName);
+ /// Gets a list of cached domain names in the DNS client.
+ /// The cached data list.
+ ///
+ /// Returns success confirmation upon successful completion. Otherwise, returns the appropriate DNS-specific error code as defined
+ /// in Winerror.h.
+ ///
+ [DllImport(Lib.Dnsapi, SetLastError = true, ExactSpelling = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool DnsGetCacheDataTable(out SafeDnsCacheDataTable ppCacheData);
+
///
/// The DnsGetProxyInformation function returns the proxy information for a DNS server's name resolution policy table.
///
@@ -1327,6 +1337,41 @@ namespace Vanara.PInvoke
public IntPtr DangerousGetHandle() => handle;
}
+ /// Provides a for a list of allocated DNS_CACHE_ENTRY values that is disposed using .
+ public class SafeDnsCacheDataTable : SafeHANDLE, IEnumerable
+ {
+ /// Initializes a new instance of the class and assigns an existing handle.
+ /// An object that represents the pre-existing handle to use.
+ /// to reliably release the handle during the finalization phase; otherwise, (not recommended).
+ public SafeDnsCacheDataTable(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { }
+
+ /// Initializes a new instance of the class.
+ private SafeDnsCacheDataTable() : base() { }
+
+ /// Returns an enumerator that iterates through the collection.
+ /// A that can be used to iterate through the collection.
+ public IEnumerator GetEnumerator() => handle.LinkedListToIEnum(r => r.pNext).GetEnumerator();
+
+ /// Returns an enumerator that iterates through a collection.
+ /// An object that can be used to iterate through the collection.
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+
+ ///
+ 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();
+ DnsFree((IntPtr)s.pszName, DNS_FREE_TYPE.DnsFreeFlat);
+ DnsFree(p, DNS_FREE_TYPE.DnsFreeFlat);
+ p = s.pNext;
+ }
+ return true;
+ }
+ }
+
/// Provides a for a DNS record list that is disposed using .
public class SafeDnsRecordList : SafeHANDLE, IEnumerable
{
diff --git a/PInvoke/DnsApi/WinDns.cs b/PInvoke/DnsApi/WinDns.cs
index 1062b660..e12b75d3 100644
--- a/PInvoke/DnsApi/WinDns.cs
+++ b/PInvoke/DnsApi/WinDns.cs
@@ -925,6 +925,26 @@ namespace Vanara.PInvoke
public byte[] Address;
}
+ /// Undocumented.
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ public struct DNS_CACHE_ENTRY
+ {
+ /// Pointer to next entry.
+ public IntPtr pNext;
+
+ /// DNS Record Name.
+ public StrPtrUni pszName;
+
+ /// DNS Record Type.
+ public DNS_TYPE wType;
+
+ /// Undocumented.
+ public ushort wDataLength;
+
+ /// Undocumented.
+ public DNS_RECORD_FLAGS dwFlags;
+ }
+
///
/// The DNS_DHCID_DATA structure represents a DNS Dynamic Host Configuration Protocol Information (DHCID) resource record
/// (RR) as specified in section 3 of RFC 4701.
diff --git a/UnitTests/PInvoke/DnsApi/DnsApiTests.cs b/UnitTests/PInvoke/DnsApi/DnsApiTests.cs
index 5d8fc655..00a3a246 100644
--- a/UnitTests/PInvoke/DnsApi/DnsApiTests.cs
+++ b/UnitTests/PInvoke/DnsApi/DnsApiTests.cs
@@ -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()
{