using System; using System.Collections.Generic; using System.Runtime.InteropServices; namespace DnsMarshallingTest { #region Data structures [Flags] internal enum DnsRecordType : ushort { TEXT = 0x0010, } [Flags] internal enum DnsQueryType : uint { STANDARD = 0x00000000, } internal enum DnsFreeType : uint { FreeFlat = 0, FreeRecordList } [StructLayout(LayoutKind.Sequential)] internal struct DnsRecord { public IntPtr Next; // 4 bytes public string Name; // 4 bytes (ptr) [MarshalAs(UnmanagedType.U2)] public DnsRecordType RecordType; // 2 bytes [MarshalAs(UnmanagedType.U2)] public ushort DataLength; // 2 bytes [StructLayout(LayoutKind.Explicit)] // 4 bytes internal struct DnsRecordFlags { [FieldOffset(0)] [MarshalAs(UnmanagedType.U4)] public uint DW; [FieldOffset(0)] [MarshalAs(UnmanagedType.U4)] public uint S; } public DnsRecordFlags Flags; [MarshalAs(UnmanagedType.U4)] public uint Ttl; // 4 bytes [MarshalAs(UnmanagedType.U4)] public uint Reserved; // 4 bytes } [StructLayout(LayoutKind.Sequential)] internal struct DNS_TXT_DATA { public uint dwStringCount; [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 1, ArraySubType = UnmanagedType.SysUInt)] public IntPtr[] pStringArray; } #endregion internal class Program { #region Imports [DllImport("dnsapi", EntryPoint = "DnsQuery_A")] private static extern uint DnsQuery( [MarshalAs(UnmanagedType.LPStr)] string Name, [MarshalAs(UnmanagedType.U2)] DnsRecordType Type, [MarshalAs(UnmanagedType.U4)] DnsQueryType Options, IntPtr Servers, [In, Out] ref IntPtr QueryResultsSet, IntPtr Reserved ); [DllImport("dnsapi", EntryPoint = "DnsRecordListFree")] private static extern void DnsRecordListFree(IntPtr RecordList, DnsFreeType FreeType); #endregion private static void Main(string[] args) { var domain = "enter-your-own-value-here"; var pServers = IntPtr.Zero; var ppQueryResultsSet = IntPtr.Zero; var ret = DnsQuery(domain, DnsRecordType.TEXT, DnsQueryType.STANDARD, pServers, ref ppQueryResultsSet, IntPtr.Zero); if (ret != 0) throw new ApplicationException("DnsQuery failed: " + ret); // Marshal DnsRecord and advance pointer to start of DNS_TXT_DATA record var dnsRecord = (DnsRecord) Marshal.PtrToStructure(ppQueryResultsSet, typeof (DnsRecord)); var ptr = new IntPtr(ppQueryResultsSet.ToInt32() + Marshal.SizeOf(dnsRecord)); // Marshal DNS_TXT_DATA and any pointers beyond pStringArray var txtData = (DNS_TXT_DATA) Marshal.PtrToStructure(ptr, typeof (DNS_TXT_DATA)); ptr = new IntPtr(ptr.ToInt32() + sizeof (uint)); var ptrs = new IntPtr[txtData.dwStringCount]; Marshal.Copy(ptr, ptrs, 0, ptrs.Length); // Each pointer in ptrs points to a string. Marshal those too. var strings = new List(); for (var i = 0; i < ptrs.Length; ++i) { strings.Add(Marshal.PtrToStringAnsi(ptrs[i])); } DnsRecordListFree(ppQueryResultsSet, DnsFreeType.FreeRecordList); } } }