Home > Blockchain >  How to query multiple lines of DNS TXT data using WinAPI
How to query multiple lines of DNS TXT data using WinAPI

Time:07-19

I'm trying to get DNS TXT data:

#include <Windows.h>
#include <WinDNS.h>
#include <winsock.h>
#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "Dnsapi.lib")
#include <iostream>
#include <string>

using namespace std;

const std::string dnsAddress = "8.8.8.8";

int main()
{
    IP4_ARRAY dnsServerIp;
    dnsServerIp.AddrCount        = 1;
    dnsServerIp.AddrArray[0]     = inet_addr(dnsAddress.data());
    const std::wstring domain    = L"mydomain.com";
    DNS_RECORD*        dnsRecord = nullptr;
    auto error = DnsQuery(domain.data(), DNS_TYPE_TEXT, DNS_QUERY_BYPASS_CACHE, &dnsServerIp, &dnsRecord, NULL);
    if (!error) {
        if (dnsRecord) {
            cout << "DNS TXT strings count: " << dnsRecord->Data.TXT.dwStringCount << endl;
            for (size_t i = 0; i < dnsRecord->Data.TXT.dwStringCount;   i) {
                wcout << i << L": " << std::wstring(dnsRecord->Data.TXT.pStringArray[i]) << endl;
            }
            DnsRecordListFree(dnsRecord, DnsFreeRecordListDeep);
        }
    }
}

With this code I always have dnsRecord->Data.TXT.dwStringCount == 1 and it prints the first line only. I've found that WinDNS.h normally defines array for one line:

typedef struct
{
    DWORD           dwStringCount;
#ifdef MIDL_PASS
    [size_is(dwStringCount)] PWSTR pStringArray[];
#else
    PWSTR           pStringArray[1];
#endif
}
DNS_TXT_DATAW, *PDNS_TXT_DATAW;

What does this MIDL_PASS macro mean? When I enable it I get a lot of compile errors like identifier not found, attribute not found etc.`

CodePudding user response:

DNSQuery can return multiple records, each with multiple strings. You need to enumerate the list of returned records as well as the strings within them.

    DNS_RECORD* pResult = dnsRecord;
    while (pResult != nullptr)
    {
        if (pResult->wType == DNS_TYPE_TEXT)
        {
            DNS_TXT_DATAW* pData = &pResult->Data.TXT;
            for (DWORD s = 0; s < pData->dwStringCount; s  )
            {
                // do something with pData->pStringArray[s]
            }
        }
        pResult = pResult->pNext;
    }
  • Related