' ########################################################################################
' Microsoft Windows
' File: WinDns.inc
' Contents: Domain Name System (DNS) API
' Copyright (c) 2011 Jos? Roca
' Portions Copyright (c) Microsoft Corporation.
' All Rights Reserved.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################
#IF NOT %DEF(PBX_WinDNS_PBI)
#DEFINE PBX_WinDNS_PBI
%EQUATE `WINDNS_INC = 1
#INCLUDE ONCE "Core/Windows.inc"
'//
'// Define QWORD -- not yet defined globally
'//
'typedef unsigned __int64 QWORD, *PQWORD;
'//
'// DNS public types
'//
'typedef __success(return == 0) LONG DNS_STATUS;
'typedef DNS_STATUS *PDNS_STATUS;
'//
'// IP Address
'//
'typedef DWORD IP4_ADDRESS, *PIP4_ADDRESS;
%EQUATE `SIZEOF_IP4_ADDRESS = 4
%EQUATE `IP4_ADDRESS_STRING_LENGTH = 16
'// Backcompat only -- length def contains terminating NULL
%EQUATE `IP4_ADDRESS_STRING_BUFFER_LENGTH = 16
'//
'// IP Address Array type
'//
'typedef struct _IP4_ARRAY
'{
' DWORD AddrCount;
'#ifdef MIDL_PASS
' [size_is( AddrCount )] IP4_ADDRESS AddrArray[];
'#else
' IP4_ADDRESS AddrArray[1];
'#endif
'}
'IP4_ARRAY, *PIP4_ARRAY;
' // Size = 8 bytes
TYPE IP4_ARRAY
 AddrCount AS DWORD
 AddrArray(0) AS DWORD
END TYPE
'//
'// IPv6 Address
'//
'#ifdef MIDL_PASS
'#ifdef _WIN64
'#pragma pack(push, 8)
'#else
'#pragma pack(push, 4)
'#endif
'typedef struct
'{
' QWORD IP6Qword[2];
'}
'IP6_ADDRESS, *PIP6_ADDRESS;
'#pragma pack(pop)
'#else // MIDL_PASS
'typedef union
'{
'#ifdef _WIN64
' QWORD IP6Qword[2];
'#endif
' DWORD IP6Dword[4];
' WORD IP6Word[8];
' BYTE IP6Byte[16];
'#ifdef IN6_ADDR
' IN6_ADDR In6;
'#endif
'}
'IP6_ADDRESS, *PIP6_ADDRESS;
'#endif // MIDL_PASS
' // Size = 16 bytes
UNION IP6_ADDRESS BYTE
 IP6Dword(3) AS DWORD
 IP6Word(7) AS WORD
 IP6Byte(15) AS BYTE
END UNION
'//
'// IP6 string max is 45 bytes
'// - 6 WORDs in colon+hex (5 chars)
'// - last DWORD as IP4 (15 chars)
'// but include
'// - 11 bytes for scope ID
'// - 6 bytes for port (inc. colon)
'// - two bytes to bracket address with port
'// - terminating NULL
'//
'// Note: this is a change to previous def, but a single
'// definition continaing space for ALL possible IPv6
'// address strings, we elminate many possible errors
%EQUATE `IP6_ADDRESS_STRING_LENGTH = 65
%EQUATE `IP6_ADDRESS_STRING_BUFFER_LENGTH = 65
'//
'// IP4/IP6 combined maximum
'//
%EQUATE `DNS_ADDRESS_STRING_LENGTH = %IP6_ADDRESS_STRING_LENGTH
'//
'// Inline byte flipping -- can be done in registers
'//
'#define INLINE_WORD_FLIP(out, in) \
' { \
' WORD _in = (in); \
' (out) = (_in << 8) | (_in >> 8); \
' }
SUB INLINE_WORD_FLIP (BYREF wOut AS WORD, BYVAL wIn AS WORD)
 LOCAL wTmp1, wTmp2 AS WORD
 wTmp1 = wIn
 wTmp2 = wIn
 SHIFT LEFT wTmp1, 8
 SHIFT RIGHT wTmp2, 8
 wOut = wTmp1 OR wTmp2
END SUB
'#define INLINE_HTONS(out, in) INLINE_WORD_FLIP(out, in)
'#define INLINE_NTOHS(out, in) INLINE_WORD_FLIP(out, in)
MACRO INLINE_HTONS(wOut, wIn) = INLINE_WORD_FLIP(wOut, wIn)
MACRO INLINE_NTONS(wOut, wIn) = INLINE_WORD_FLIP(wOut, wIn)
'#define INLINE_DWORD_FLIP(out, in) \
' { \
' DWORD _in = (in); \
' (out) = ((_in << 8) & 0x00ff0000) | \
' (_in << 24) | \
' ((_in >> 8) & 0x0000ff00) | \
' (_in >> 24); \
' }
SUB INLINE_DWORD_FLIP (BYREF dwOut AS DWORD, BYVAL dwIn AS DWORD)
 LOCAL dwTmp1, dwTmp2, dwTmp3, dwTmp4 AS DWORD
 dwTmp1 = dwIn
 dwTmp2 = dwIn
 dwTmp3 = dwIn
 dwTmp4 = dwIn
 SHIFT LEFT dwTmp1, 8
 dwTmp1 = dwTmp1 AND &H00ff0000
 SHIFT LEFT dwTmp2, 24
 SHIFT RIGHT dwTmp3, 8
 dwTmp3 = dwTmp3 AND &H0000ff00
 SHIFT RIGHT dwTmp4, 24
 dwOut = dwTmp1 OR dwTmp2 OR dwTmp3 OR dwTmp4
END SUB
'#define INLINE_NTOHL(out, in) INLINE_DWORD_FLIP(out, in)
'#define INLINE_HTONL(out, in) INLINE_DWORD_FLIP(out, in)
MACRO INLINE_NTOHL(dwOut, dwIn) = INLINE_DWORD_FLIP(dwOut, dwIn)
MACRO INLINE_HTONL(dwOut, dwIn) = INLINE_DWORD_FLIP(dwOut, dwIn)
'//
'// Inline byte flip and write to packet (unaligned)
'//
'#define INLINE_WRITE_FLIPPED_WORD( pout, in ) \
' INLINE_WORD_FLIP( *((UNALIGNED WORD *)(pout)), in )
'#define INLINE_WRITE_FLIPPED_DWORD( pout, in ) \
' INLINE_DWORD_FLIP( *((UNALIGNED DWORD *)(pout)), in )
SUB INLINE_WRITE_FLIPPED_WORD (BYVAL pwOut AS WORD PTR, BYVAL wIn AS WORD)
 INLINE_WORD_FLIP @pwOut, wIn
END SUB
SUB INLINE_WRITE_FLIPPED_DWORD (BYVAL pdwOut AS DWORD PTR, BYVAL dwIn AS DWORD)
 INLINE_DWORD_FLIP @pdwOut, dwIn
END SUB
'//
'// Basic DNS definitions
'//
'//
'// DNS port for both UDP and TCP is 53.
'//
%EQUATE `DNS_PORT_HOST_ORDER = &H0035 ' // port 53
%EQUATE `DNS_PORT_NET_ORDER = &H3500
'//
'// DNS UDP packets no more than 512 bytes
'//
%EQUATE `DNS_RFC_MAX_UDP_PACKET_LENGTH = 512
'//
'// DNS Names limited to 255, 63 in any one label
'//
%EQUATE `DNS_MAX_NAME_LENGTH = 255
%EQUATE `DNS_MAX_LABEL_LENGTH = 63
%EQUATE `DNS_MAX_NAME_BUFFER_LENGTH = 256
%EQUATE `DNS_MAX_LABEL_BUFFER_LENGTH = 64
'//
'// Reverse lookup domain names
'//
'#define DNS_IP4_REVERSE_DOMAIN_STRING_A ("in-addr.arpa.")
'#define DNS_IP4_REVERSE_DOMAIN_STRING_W (L"in-addr.arpa.")
$DNS_IP4_REVERSE_DOMAIN_STRING = "in-addr.arpa."
'#define DNS_MAX_IP4_REVERSE_NAME_LENGTH (IP4_ADDRESS_STRING_LENGTH+15)
' //(IP4_ADDRESS_STRING_LENGTH+1+sizeof(DNS_IP4_REVERSE_DOMAIN_STRING_A))
%EQUATE `DNS_MAX_IP4_REVERSE_NAME_LENGTH = %IP4_ADDRESS_STRING_LENGTH + 15
'#define DNS_IP6_REVERSE_DOMAIN_STRING_A ("ip6.arpa.")
'#define DNS_IP6_REVERSE_DOMAIN_STRING_W (L"ip6.arpa.")
$DNS_IP6_REVERSE_DOMAIN_STRING = "ip6.arpa."
'#define DNS_MAX_IP6_REVERSE_NAME_LENGTH (75)
' //(64+sizeof(DNS_IP6_REVERSE_DOMAIN_STRING_A))
%EQUATE `DNS_MAX_IP6_REVERSE_NAME_LENGTH = 75
'// Combined
%EQUATE `DNS_MAX_REVERSE_NAME_LENGTH = %DNS_MAX_IP6_REVERSE_NAME_LENGTH
'#ifdef UNICODE
'#define DNS_IP4_REVERSE_DOMAIN_STRING DNS_IP4_REVERSE_DOMAIN_STRING_W
'#define DNS_IP6_REVERSE_DOMAIN_STRING DNS_IP6_REVERSE_DOMAIN_STRING_W
'#else
'#define DNS_IP4_REVERSE_DOMAIN_STRING DNS_IP4_REVERSE_DOMAIN_STRING_A
'#define DNS_IP6_REVERSE_DOMAIN_STRING DNS_IP6_REVERSE_DOMAIN_STRING_A
'#endif
'//
'// Backcompat only -- name def contains terminating NULL
'//
%EQUATE `DNS_MAX_IP4_REVERSE_NAME_BUFFER_LENGTH = %DNS_MAX_IP4_REVERSE_NAME_LENGTH
%EQUATE `DNS_MAX_IP6_REVERSE_NAME_BUFFER_LENGTH = %DNS_MAX_IP6_REVERSE_NAME_LENGTH
%EQUATE `DNS_MAX_REVERSE_NAME_BUFFER_LENGTH = %DNS_MAX_REVERSE_NAME_LENGTH
'//
'// DNS Text string limited by size representable
'// in a single byte length field
%EQUATE `DNS_MAX_TEXT_STRING_LENGTH = 255
'//
'// DNS On-The-Wire Structures
'//
'#pragma pack(1)
'//
'// DNS Message Header
'//
'typedef struct _DNS_HEADER
'{
' WORD Xid;
' BYTE RecursionDesired : 1;
' BYTE Truncation : 1;
' BYTE Authoritative : 1;
' BYTE Opcode : 4;
' BYTE IsResponse : 1;
' BYTE ResponseCode : 4;
' BYTE Reserved : 3;
' BYTE RecursionAvailable : 1;
' WORD QuestionCount;
' WORD AnswerCount;
' WORD NameServerCount;
' WORD AdditionalCount;
'}
'DNS_HEADER, *PDNS_HEADER;
' // Size = 12 bytes
TYPE DNS_HEADER BYTE
 Xid AS WORD
 RecursionDesired AS BIT * 1 IN BYTE
 Truncation AS BIT * 1
 Authoritative AS BIT * 1
 Opcode AS BIT * 4
 IsResponse AS BIT * 1
 ResponseCode AS BIT * 4 IN BYTE
 CheckingDisabled AS BIT * 1
 AuthenticatedData AS BIT * 1
 Reserved AS BIT * 1
 RecursionAvailable AS BIT * 1
 QuestionCount AS WORD
 AnswerCount AS WORD
 NameServerCount AS WORD
 AdditionalCount AS WORD
END TYPE
' // Size = 4 bytes
TYPE DNS_HEADER_EXT BYTE
 Reserved AS BIT * 15 IN WORD
 DnssecOk AS BIT * 1
 chRcode AS BYTE
 chVersion AS BYTE
END TYPE
'//
'// Flags as WORD
'//
'#define DNS_HEADER_FLAGS(pHead) ( *((PWORD)(pHead)+1) )
'//
'// Byte flip DNS header to\from host order.
'//
'// Note that this does NOT flip flags, as definition above defines
'// flags as individual bytes for direct access to net byte order.
'//
'#define DNS_BYTE_FLIP_HEADER_COUNTS(pHeader) \
' { \
' PDNS_HEADER _head = (pHeader); \
' INLINE_HTONS(_head->Xid, _head->Xid ); \
' INLINE_HTONS(_head->QuestionCount, _head->QuestionCount ); \
' INLINE_HTONS(_head->AnswerCount, _head->AnswerCount ); \
' INLINE_HTONS(_head->NameServerCount,_head->NameServerCount ); \
' INLINE_HTONS(_head->AdditionalCount,_head->AdditionalCount ); \
' }
'//
'// Question name follows header
'//
'#define DNS_OFFSET_TO_QUESTION_NAME sizeof(DNS_HEADER)
'//
'// Question immediately follows header so compressed question name
'// 0xC000 | sizeof(DNS_HEADER)
%EQUATE `DNS_COMPRESSED_QUESTION_NAME = &HC00C
'//
'// Packet extraction macros
'//
'#define DNS_QUESTION_NAME_FROM_HEADER( _pHeader_ ) \
' ( (PCHAR)( (PDNS_HEADER)(_pHeader_) + 1 ) )
'#define DNS_ANSWER_FROM_QUESTION( _pQuestion_ ) \
' ( (PCHAR)( (PDNS_QUESTION)(_pQuestion_) + 1 ) )
'//
'// DNS Question
'//
'typedef struct _DNS_WIRE_QUESTION
'{
' // Preceded by question name
' WORD QuestionType;
' WORD QuestionClass;
'}
'DNS_WIRE_QUESTION, *PDNS_WIRE_QUESTION;
' // Size = 4 bytes
TYPE DNS_WIRE_QUESTION WORD
 QuestionType AS WORD
 QuestionClass AS WORD
END TYPE
'//
'// DNS Resource Record
'//
'typedef struct _DNS_WIRE_RECORD
'{
' // Preceded by record owner name
' WORD RecordType;
' WORD RecordClass;
' DWORD TimeToLive;
' WORD DataLength;
' // Followed by record data
'}
'DNS_WIRE_RECORD, *PDNS_WIRE_RECORD;
' // Size = 10 bytes
TYPE DNS_WIRE_RECORD WORD
 RecordType AS WORD
 RecordClass AS WORD
 TimeToLive AS DWORD
 DataLength AS WORD
END TYPE
'#pragma pack()
'//
'// DNS Query Types
'//
%EQUATE `DNS_OPCODE_QUERY = 0 ' // Query
%EQUATE `DNS_OPCODE_IQUERY = 1 ' // Obsolete: IP to name
%EQUATE `DNS_OPCODE_SERVER_STATUS = 2 ' // Obsolete: DNS ping
%EQUATE `DNS_OPCODE_UNKNOWN = 3 ' // Unknown
%EQUATE `DNS_OPCODE_NOTIFY = 4 ' // Notify
%EQUATE `DNS_OPCODE_UPDATE = 5 ' // Dynamic Update
'//
'// DNS response codes.
'//
'// Sent in the "ResponseCode" field of a DNS_HEADER.
'//
%EQUATE `DNS_RCODE_NOERROR = 0
%EQUATE `DNS_RCODE_FORMERR = 1 ' // Format error
%EQUATE `DNS_RCODE_SERVFAIL = 2 ' // Server failure
%EQUATE `DNS_RCODE_NXDOMAIN = 3 ' // Name error
%EQUATE `DNS_RCODE_NOTIMPL = 4 ' // Not implemented
%EQUATE `DNS_RCODE_REFUSED = 5 ' // Refused
%EQUATE `DNS_RCODE_YXDOMAIN = 6 ' // Domain name should not exist
%EQUATE `DNS_RCODE_YXRRSET = 7 ' // RR set should not exist
%EQUATE `DNS_RCODE_NXRRSET = 8 ' // RR set does not exist
%EQUATE `DNS_RCODE_NOTAUTH = 9 ' // Not authoritative for zone
%EQUATE `DNS_RCODE_NOTZONE = 10 ' // Name is not zone
%EQUATE `DNS_RCODE_MAX = 15
'//
'// Extended RCODEs
'//
%EQUATE `DNS_RCODE_BADVERS = 16 ' // Bad EDNS version
%EQUATE `DNS_RCODE_BADSIG = 16 ' // Bad signature
%EQUATE `DNS_RCODE_BADKEY = 17 ' // Bad key
%EQUATE `DNS_RCODE_BADTIME = 18 ' // Bad timestamp
'//
'// Mappings to friendly names
'//
%EQUATE `DNS_RCODE_NO_ERROR = %DNS_RCODE_NOERROR
%EQUATE `DNS_RCODE_FORMAT_ERROR = %DNS_RCODE_FORMERR
%EQUATE `DNS_RCODE_SERVER_FAILURE = %DNS_RCODE_SERVFAIL
%EQUATE `DNS_RCODE_NAME_ERROR = %DNS_RCODE_NXDOMAIN
%EQUATE `DNS_RCODE_NOT_IMPLEMENTED = %DNS_RCODE_NOTIMPL
'//
'// DNS Classes
'//
'// Classes are on the wire as WORDs.
'//
'// _CLASS_ defines in host order.
'// _RCLASS_ defines in net byte order.
'//
'// Generally we'll avoid byte flip and test class in net byte order.
'//
%EQUATE `DNS_CLASS_INTERNET = &h0001?? ' // 1
%EQUATE `DNS_CLASS_CSNET = &h0002?? ' // 2
%EQUATE `DNS_CLASS_CHAOS = &h0003?? ' // 3
%EQUATE `DNS_CLASS_HESIOD = &h0004?? ' // 4
%EQUATE `DNS_CLASS_NONE = &h00fe?? ' // 254
%EQUATE `DNS_CLASS_ALL = &h00ff?? ' // 255
%EQUATE `DNS_CLASS_ANY = &h00ff?? ' // 255
%EQUATE `DNS_RCLASS_INTERNET = &h0100?? ' // 1
%EQUATE `DNS_RCLASS_CSNET = &h0200?? ' // 2
%EQUATE `DNS_RCLASS_CHAOS = &h0300?? ' // 3
%EQUATE `DNS_RCLASS_HESIOD = &h0400?? ' // 4
%EQUATE `DNS_RCLASS_NONE = &hfe00?? ' // 254
%EQUATE `DNS_RCLASS_ALL = &hff00?? ' // 255
%EQUATE `DNS_RCLASS_ANY = &hff00?? ' // 255
'//
'// DNS Record Types
'//
'// _TYPE_ defines are in host byte order.
'// _RTYPE_ defines are in net byte order.
'//
'// Generally always deal with types in host byte order as we index
'// resource record functions by type.
'//
%EQUATE `DNS_TYPE_ZERO = &h0000
'// RFC 1034/1035
%EQUATE `DNS_TYPE_A = &h0001 ' // 1
%EQUATE `DNS_TYPE_NS = &h0002 ' // 2
%EQUATE `DNS_TYPE_MD = &h0003 ' // 3
%EQUATE `DNS_TYPE_MF = &h0004 ' // 4
%EQUATE `DNS_TYPE_CNAME = &h0005 ' // 5
%EQUATE `DNS_TYPE_SOA = &h0006 ' // 6
%EQUATE `DNS_TYPE_MB = &h0007 ' // 7
%EQUATE `DNS_TYPE_MG = &h0008 ' // 8
%EQUATE `DNS_TYPE_MR = &h0009 ' // 9
%EQUATE `DNS_TYPE_NULL = &h000a ' // 10
%EQUATE `DNS_TYPE_WKS = &h000b ' // 11
%EQUATE `DNS_TYPE_PTR = &h000c ' // 12
%EQUATE `DNS_TYPE_HINFO = &h000d ' // 13
%EQUATE `DNS_TYPE_MINFO = &h000e ' // 14
%EQUATE `DNS_TYPE_MX = &h000f ' // 15
%EQUATE `DNS_TYPE_TEXT = &h0010 ' // 16
'// RFC 1183
%EQUATE `DNS_TYPE_RP = &h0011 ' // 17
%EQUATE `DNS_TYPE_AFSDB = &h0012 ' // 18
%EQUATE `DNS_TYPE_X25 = &h0013 ' // 19
%EQUATE `DNS_TYPE_ISDN = &h0014 ' // 20
%EQUATE `DNS_TYPE_RT = &h0015 ' // 21
'// RFC 1348
%EQUATE `DNS_TYPE_NSAP = &h0016 ' // 22
%EQUATE `DNS_TYPE_NSAPPTR = &h0017 ' // 23
'// RFC 2065 (DNS security)
%EQUATE `DNS_TYPE_SIG = &h0018 ' // 24
%EQUATE `DNS_TYPE_KEY = &h0019 ' // 25
'// RFC 1664 (X.400 mail)
%EQUATE `DNS_TYPE_PX = &h001a ' // 26
'// RFC 1712 (Geographic position)
%EQUATE `DNS_TYPE_GPOS = &h001b ' // 27
'// RFC 1886 (IPv6 Address)
%EQUATE `DNS_TYPE_AAAA = &h001c ' // 28
'// RFC 1876 (Geographic location)
%EQUATE `DNS_TYPE_LOC = &h001d ' // 29
'// RFC 2065 (Secure negative response)
%EQUATE `DNS_TYPE_NXT = &h001e ' // 30
'// Patton (Endpoint Identifier)
%EQUATE `DNS_TYPE_EID = &h001f ' // 31
'// Patton (Nimrod Locator)
%EQUATE `DNS_TYPE_NIMLOC = &h0020 ' // 32
'// RFC 2052 (Service location)
%EQUATE `DNS_TYPE_SRV = &h0021 ' // 33
'// ATM Standard something-or-another (ATM Address)
%EQUATE `DNS_TYPE_ATMA = &h0022 ' // 34
'// RFC 2168 (Naming Authority Pointer)
%EQUATE `DNS_TYPE_NAPTR = &h0023 ' // 35
'// RFC 2230 (Key Exchanger)
%EQUATE `DNS_TYPE_KX = &h0024 ' // 36
'// RFC 2538 (CERT)
%EQUATE `DNS_TYPE_CERT = &h0025 ' // 37
'// A6 Draft (A6)
%EQUATE `DNS_TYPE_A6 = &h0026 ' // 38
'// DNAME Draft (DNAME)
%EQUATE `DNS_TYPE_DNAME = &h0027 ' // 39
'// Eastlake (Kitchen Sink)
%EQUATE `DNS_TYPE_SINK = &h0028 ' // 40
'// RFC 2671 (EDNS OPT)
%EQUATE `DNS_TYPE_OPT = &h0029 ' // 41
'// RFC 4034 (DNSSEC DS)
%EQUATE `DNS_TYPE_DS = &H002b ' // 43
'// RFC 4034 (DNSSEC RRSIG)
%EQUATE `DNS_TYPE_RRSIG = &H002e ' // 46
'// RFC 4034 (DNSSEC NSEC)
%EQUATE `DNS_TYPE_NSEC = &H002f ' // 47
'// RFC 4034 (DNSSEC DNSKEY)
%EQUATE `DNS_TYPE_DNSKEY = &H0030 ' // 48
'// RFC 4701 (DHCID)
%EQUATE `DNS_TYPE_DHCID = &H0031 ' // 49
'//
'// IANA Reserved
'//
%EQUATE `DNS_TYPE_UINFO = &h0064 ' // 100
%EQUATE `DNS_TYPE_UID = &h0065 ' // 101
%EQUATE `DNS_TYPE_GID = &h0066 ' // 102
%EQUATE `DNS_TYPE_UNSPEC = &h0067 ' // 103
'//
'// Query only types (1035, 1995)
'// - Crawford (ADDRS)
'// - TKEY draft (TKEY)
'// - TSIG draft (TSIG)
'// - RFC 1995 (IXFR)
'// - RFC 1035 (AXFR up)
'//
%EQUATE `DNS_TYPE_ADDRS = &h00f8 ' // 248
%EQUATE `DNS_TYPE_TKEY = &h00f9 ' // 249
%EQUATE `DNS_TYPE_TSIG = &h00fa ' // 250
%EQUATE `DNS_TYPE_IXFR = &h00fb ' // 251
%EQUATE `DNS_TYPE_AXFR = &h00fc ' // 252
%EQUATE `DNS_TYPE_MAILB = &h00fd ' // 253
%EQUATE `DNS_TYPE_MAILA = &h00fe ' // 254
%EQUATE `DNS_TYPE_ALL = &h00ff ' // 255
%EQUATE `DNS_TYPE_ANY = &h00ff ' // 255
'//
'// Temp Microsoft types -- use until get IANA approval for real type
'//
%EQUATE `DNS_TYPE_WINS = &hff01?? ' // 64K - 255
%EQUATE `DNS_TYPE_WINSR = &hff02?? ' // 64K - 254
%EQUATE `DNS_TYPE_NBSTAT = %DNS_TYPE_WINSR
'//
'// DNS Record Types -- Net Byte Order
'//
%EQUATE `DNS_RTYPE_A = &h0100 ' // 1
%EQUATE `DNS_RTYPE_NS = &h0200 ' // 2
%EQUATE `DNS_RTYPE_MD = &h0300 ' // 3
%EQUATE `DNS_RTYPE_MF = &h0400 ' // 4
%EQUATE `DNS_RTYPE_CNAME = &h0500 ' // 5
%EQUATE `DNS_RTYPE_SOA = &h0600 ' // 6
%EQUATE `DNS_RTYPE_MB = &h0700 ' // 7
%EQUATE `DNS_RTYPE_MG = &h0800 ' // 8
%EQUATE `DNS_RTYPE_MR = &h0900 ' // 9
%EQUATE `DNS_RTYPE_NULL = &h0a00 ' // 10
%EQUATE `DNS_RTYPE_WKS = &h0b00 ' // 11
%EQUATE `DNS_RTYPE_PTR = &h0c00 ' // 12
%EQUATE `DNS_RTYPE_HINFO = &h0d00 ' // 13
%EQUATE `DNS_RTYPE_MINFO = &h0e00 ' // 14
%EQUATE `DNS_RTYPE_MX = &h0f00 ' // 15
%EQUATE `DNS_RTYPE_TEXT = &h1000 ' // 16
%EQUATE `DNS_RTYPE_RP = &h1100 ' // 17
%EQUATE `DNS_RTYPE_AFSDB = &h1200 ' // 18
%EQUATE `DNS_RTYPE_X25 = &h1300 ' // 19
%EQUATE `DNS_RTYPE_ISDN = &h1400 ' // 20
%EQUATE `DNS_RTYPE_RT = &h1500 ' // 21
%EQUATE `DNS_RTYPE_NSAP = &h1600 ' // 22
%EQUATE `DNS_RTYPE_NSAPPTR = &h1700 ' // 23
%EQUATE `DNS_RTYPE_SIG = &h1800 ' // 24
%EQUATE `DNS_RTYPE_KEY = &h1900 ' // 25
%EQUATE `DNS_RTYPE_PX = &h1a00 ' // 26
%EQUATE `DNS_RTYPE_GPOS = &h1b00 ' // 27
%EQUATE `DNS_RTYPE_AAAA = &h1c00 ' // 28
%EQUATE `DNS_RTYPE_LOC = &h1d00 ' // 29
%EQUATE `DNS_RTYPE_NXT = &h1e00 ' // 30
%EQUATE `DNS_RTYPE_EID = &h1f00 ' // 31
%EQUATE `DNS_RTYPE_NIMLOC = &h2000 ' // 32
%EQUATE `DNS_RTYPE_SRV = &h2100 ' // 33
%EQUATE `DNS_RTYPE_ATMA = &h2200 ' // 34
%EQUATE `DNS_RTYPE_NAPTR = &h2300 ' // 35
%EQUATE `DNS_RTYPE_KX = &h2400 ' // 36
%EQUATE `DNS_RTYPE_CERT = &h2500 ' // 37
%EQUATE `DNS_RTYPE_A6 = &h2600 ' // 38
%EQUATE `DNS_RTYPE_DNAME = &h2700 ' // 39
%EQUATE `DNS_RTYPE_SINK = &h2800 ' // 40
%EQUATE `DNS_RTYPE_OPT = &h2900 ' // 41
%EQUATE `DNS_RTYPE_DS = &H2b00 ' // 43
%EQUATE `DNS_RTYPE_RRSIG = &H2e00 ' // 46
%EQUATE `DNS_RTYPE_NSEC = &H2f00 ' // 47
%EQUATE `DNS_RTYPE_DNSKEY = &H3000 ' // 48
%EQUATE `DNS_RTYPE_DHCID = &H3100 ' // 49
'//
'// IANA Reserved
'//
%EQUATE `DNS_RTYPE_UINFO = &h6400 ' // 100
%EQUATE `DNS_RTYPE_UID = &h6500 ' // 101
%EQUATE `DNS_RTYPE_GID = &h6600 ' // 102
%EQUATE `DNS_RTYPE_UNSPEC = &h6700 ' // 103
'//
'// Query only types
'//
%EQUATE `DNS_RTYPE_TKEY = &hf900?? ' // 249
%EQUATE `DNS_RTYPE_TSIG = &hfa00?? ' // 250
%EQUATE `DNS_RTYPE_IXFR = &hfb00?? ' // 251
%EQUATE `DNS_RTYPE_AXFR = &hfc00?? ' // 252
%EQUATE `DNS_RTYPE_MAILB = &hfd00?? ' // 253
%EQUATE `DNS_RTYPE_MAILA = &hfe00?? ' // 254
%EQUATE `DNS_RTYPE_ALL = &hff00?? ' // 255
%EQUATE `DNS_RTYPE_ANY = &hff00?? ' // 255
'//
'// Temp Microsoft types -- use until get IANA approval for real type
'//
%EQUATE `DNS_RTYPE_WINS = &h01ff ' // 64K - 255
%EQUATE `DNS_RTYPE_WINSR = &h02ff ' // 64K - 254
'//
'// Record type specific definitions
'//
'//
'// ATMA (ATM address type) formats
'//
'// Define these directly for any environment (ex NT4)
'// without winsock2 ATM support (ws2atm.h)
'//
#IF NOT %DEF(%ATMA_E164)
%EQUATE `DNS_ATMA_FORMAT_E164 = 1
%EQUATE `DNS_ATMA_FORMAT_AESA = 2
%EQUATE `DNS_ATMA_MAX_ADDR_LENGTH = 20
#ELSE
%EQUATE `DNS_ATMA_FORMAT_E164 = %ATM_E164
%EQUATE `DNS_ATMA_FORMAT_AESA = %ATM_AESA
%EQUATE `DNS_ATMA_MAX_ADDR_LENGTH = %ATM_ADDR_SIZE
#ENDIF
%EQUATE `DNS_ATMA_AESA_ADDR_LENGTH = 20
%EQUATE `DNS_ATMA_MAX_RECORD_LENGTH = %DNS_ATMA_MAX_ADDR_LENGTH + 1
'//
'// DNSSEC defs
'//
'// DNSSEC algorithms
%EQUATE `DNSSEC_ALGORITHM_RSAMD5 = 1
%EQUATE `DNSSEC_ALGORITHM_RSASHA1 = 5
%EQUATE `DNSSEC_ALGORITHM_NULL = 253
%EQUATE `DNSSEC_ALGORITHM_PRIVATE = 254
'// DNSSEC KEY protocol table
%EQUATE `DNSSEC_PROTOCOL_NONE = 0
%EQUATE `DNSSEC_PROTOCOL_TLS = 1
%EQUATE `DNSSEC_PROTOCOL_EMAIL = 2
%EQUATE `DNSSEC_PROTOCOL_DNSSEC = 3
%EQUATE `DNSSEC_PROTOCOL_IPSEC = 4
'// DNSSEC KEY flag field
%EQUATE `DNSSEC_KEY_FLAG_NOAUTH = &H0001
%EQUATE `DNSSEC_KEY_FLAG_NOCONF = &H0002
%EQUATE `DNSSEC_KEY_FLAG_FLAG2 = &H0004
%EQUATE `DNSSEC_KEY_FLAG_EXTEND = &H0008
%EQUATE `DNSSEC_KEY_FLAG_FLAG4 = &H0010
%EQUATE `DNSSEC_KEY_FLAG_FLAG5 = &H0020
'// bits 6,7 are name type
%EQUATE `DNSSEC_KEY_FLAG_USER = &H0000
%EQUATE `DNSSEC_KEY_FLAG_ZONE = &H0040
%EQUATE `DNSSEC_KEY_FLAG_HOST = &H0080
%EQUATE `DNSSEC_KEY_FLAG_NTPE3 = &H00c0
'// bits 8-11 are reserved for future use
%EQUATE `DNSSEC_KEY_FLAG_FLAG8 = &H0100
%EQUATE `DNSSEC_KEY_FLAG_FLAG9 = &H0200
%EQUATE `DNSSEC_KEY_FLAG_FLAG10 = &H0400
%EQUATE `DNSSEC_KEY_FLAG_FLAG11 = &H0800
'// bits 12-15 are sig field
%EQUATE `DNSSEC_KEY_FLAG_SIG0 = &H0000
%EQUATE `DNSSEC_KEY_FLAG_SIG1 = &H1000
%EQUATE `DNSSEC_KEY_FLAG_SIG2 = &H2000
%EQUATE `DNSSEC_KEY_FLAG_SIG3 = &H3000
%EQUATE `DNSSEC_KEY_FLAG_SIG4 = &H4000
%EQUATE `DNSSEC_KEY_FLAG_SIG5 = &H5000
%EQUATE `DNSSEC_KEY_FLAG_SIG6 = &H6000
%EQUATE `DNSSEC_KEY_FLAG_SIG7 = &H7000
%EQUATE `DNSSEC_KEY_FLAG_SIG8 = &H8000
%EQUATE `DNSSEC_KEY_FLAG_SIG9 = &H9000
%EQUATE `DNSSEC_KEY_FLAG_SIG10 = &Ha000
%EQUATE `DNSSEC_KEY_FLAG_SIG11 = &Hb000
%EQUATE `DNSSEC_KEY_FLAG_SIG12 = &Hc000
%EQUATE `DNSSEC_KEY_FLAG_SIG13 = &Hd000
%EQUATE `DNSSEC_KEY_FLAG_SIG14 = &He000
%EQUATE `DNSSEC_KEY_FLAG_SIG15 = &Hf000
'//
'// TKEY modes
'//
%EQUATE `DNS_TKEY_MODE_SERVER_ASSIGN = 1
%EQUATE `DNS_TKEY_MODE_DIFFIE_HELLMAN = 2
%EQUATE `DNS_TKEY_MODE_GSS = 3
%EQUATE `DNS_TKEY_MODE_RESOLVER_ASSIGN = 4
'//
'// WINS + NBSTAT flag field
'//
%EQUATE `DNS_WINS_FLAG_SCOPE = &H80000000
%EQUATE `DNS_WINS_FLAG_LOCAL = &H00010000
'//
'// Helpful checks
'//
'#define IS_WORD_ALIGNED(p) ( !((UINT_PTR)(p) & (UINT_PTR)1) )
'#define IS_DWORD_ALIGNED(p) ( !((UINT_PTR)(p) & (UINT_PTR)3) )
'#define IS_QWORD_ALIGNED(p) ( !((UINT_PTR)(p) & (UINT_PTR)7) )
MACRO IS_WORD_ALIGNED(p) = NOT (p AND 1)
MACRO IS_DWORD_ALIGNED(p) = NOT (p AND 3)
MACRO IS_QWORD_ALIGNED(p) = NOT (p AND 7)
'//
'// DNS config API
'//
'//
'// Types of DNS configuration info
'//
'typedef enum
'{
' // In Win2K
' DnsConfigPrimaryDomainName_W,
' DnsConfigPrimaryDomainName_A,
' DnsConfigPrimaryDomainName_UTF8,
' // Not available yet
' DnsConfigAdapterDomainName_W,
' DnsConfigAdapterDomainName_A,
' DnsConfigAdapterDomainName_UTF8,
' // In Win2K
' DnsConfigDnsServerList,
' // Not available yet
' DnsConfigSearchList,
' DnsConfigAdapterInfo,
' // In Win2K
' DnsConfigPrimaryHostNameRegistrationEnabled,
' DnsConfigAdapterHostNameRegistrationEnabled,
' DnsConfigAddressRegistrationMaxCount,
' // In WindowsXP
' DnsConfigHostName_W,
' DnsConfigHostName_A,
' DnsConfigHostName_UTF8,
' DnsConfigFullHostName_W,
' DnsConfigFullHostName_A,
' DnsConfigFullHostName_UTF8
' // In XP-SP1 (Server.net)
'}
'DNS_CONFIG_TYPE;
' DNS_CONFIG_TYPE enum
%EQUATE `DnsConfigPrimaryDomainName_W = 0
%EQUATE `DnsConfigPrimaryDomainName_A = 1
%EQUATE `DnsConfigPrimaryDomainName_UTF8 = 2
%EQUATE `DnsConfigAdapterDomainName_W = 3
%EQUATE `DnsConfigAdapterDomainName_A = 4
%EQUATE `DnsConfigAdapterDomainName_UTF8 = 5
%EQUATE `DnsConfigDnsServerList = 6
%EQUATE `DnsConfigSearchList = 7
%EQUATE `DnsConfigAdapterInfo = 8
%EQUATE `DnsConfigPrimaryHostNameRegistrationEnabled = 9
%EQUATE `DnsConfigAdapterHostNameRegistrationEnabled = 10
%EQUATE `DnsConfigAddressRegistrationMaxCount = 11
%EQUATE `DnsConfigHostName_W = 12
%EQUATE `DnsConfigHostName_A = 13
%EQUATE `DnsConfigHostName_UTF8 = 14
%EQUATE `DnsConfigFullHostName_W = 15
%EQUATE `DnsConfigFullHostName_A = 16
%EQUATE `DnsConfigFullHostName_UTF8 = 17
'//
'// Config API flags
'//
'//
'// DNS_CONFIG_FLAG_ALLOC -- Causes config info to be allocated.
'// Free with LocalFree().
'//
%EQUATE `DNS_CONFIG_FLAG_ALLOC = &H00000001
#IF %DEF(%USEPBDECL)
DECLARE FUNCTION DnsQueryConfig LIB "DnsApi.dll" ALIAS "DnsQueryConfig" ( BYVAL Config AS LONG, BYVAL Flag AS QUAD, pwsAdapterName AS WSTRINGZ, pReserved AS ANY,
 pBuffer AS ANY,
 pBufLen AS QUAD ) AS LONG
#ELSE
DECLARE FUNCTION DnsQueryConfig LIB "dnsapi.dll" ALIAS "DnsQueryConfig" ( BYVAL Config AS LONG , BYVAL Flag AS QUAD , BYREF pwsAdapterName AS WSTRINGZ , BYVAL pReserved AS QUAD , BYREF pBuffer AS ANY , BYREF pBufferLength AS QUAD ) AS LONG ' DNS_STATUS
#ENDIF
'//
'// DNS resource record structure
'//
'//
'// Record data for specific types
'//
' // Size = 4 bytes
TYPE DNS_A_DATA DWORD
 IpAddress AS DWORD ' IP4_ADDRESS
END TYPE
' // Size = 4 bytes
TYPE DNS_PTR_DATAW DWORD
 pNameHost AS WSTRINGZ PTR
END TYPE
' // Size = 4 bytes
TYPE DNS_PTR_DATAA DWORD
 pNameHost AS ASCIIZ PTR
END TYPE
#IF %DEF(%UNICODE)
 MACRO DNS_PTR_DATA = DNS_PTR_DATAW
#ELSE
 MACRO DNS_PTR_DATA = DNS_PTR_DATAA
#ENDIF
' // Size = 28 bytes
TYPE DNS_SOA_DATAW DWORD
 pNamePrimaryServer AS WSTRINGZ PTR
 pNameAdministrator AS WSTRINGZ PTR
 dwSerialNo AS DWORD
 dwRefresh AS DWORD
 dwRetry AS DWORD
 dwExpire AS DWORD
 dwDefaultTtl AS DWORD
END TYPE
' // Size = 28 bytes
TYPE DNS_SOA_DATAA DWORD
 pNamePrimaryServer AS ASCIIZ PTR
 pNameAdministrator AS ASCIIZ PTR
 dwSerialNo AS DWORD
 dwRefresh AS DWORD
 dwRetry AS DWORD
 dwExpire AS DWORD
 dwDefaultTtl AS DWORD
END TYPE
#IF %DEF(%UNICODE)
 MACRO DNS_SOA_DATA = DNS_SOA_DATAW
#ELSE
 MACRO DNS_SOA_DATA = DNS_SOA_DATAA
#ENDIF
' // Size = 8 bytes
TYPE DNS_MINFO_DATAW DWORD
 pNameMailbox AS WSTRINGZ PTR
 pNameErrorsMailbox AS WSTRINGZ PTR
END TYPE
' // Size = 8 bytes
TYPE DNS_MINFO_DATAA DWORD
 pNameMailbox AS ASCIIZ PTR
 pNameErrorsMailbox AS ASCIIZ PTR
END TYPE
#IF %DEF(%UNICODE)
 MACRO DNS_MINFO_DATA = DNS_MINFO_DATAW
#ELSE
 MACRO DNS_MINFO_DATA = DNS_MINFO_DATAA
#ENDIF
' // Size = 8 bytes
TYPE DNS_MX_DATAW WORD
 pNameExchange AS WSTRINGZ PTR
 wPreference AS WORD
 Pad AS WORD ' // keep ptrs DWORD aligned
END TYPE
' // Size = 8 bytes
TYPE DNS_MX_DATAA WORD
 pNameExchange AS ASCIIZ PTR
 wPreference AS WORD
 Pad AS WORD ' // keep ptrs DWORD aligned
END TYPE
#IF %DEF(%UNICODE)
 MACRO DNS_MX_DATA = DNS_MX_DATAW
#ELSE
 MACRO DNS_MX_DATA = DNS_MX_DATAA
#ENDIF
' // Size = 8 bytes
TYPE DNS_TXT_DATAW DWORD
 dwStringCount AS DWORD
 pStringArray(0) AS WSTRINGZ PTR
END TYPE
' // Size = 8 bytes
TYPE DNS_TXT_DATAA DWORD
 dwStringCount AS DWORD
 pStringArray(0) AS ASCIIZ PTR
END TYPE
#IF %DEF(%UNICODE)
 MACRO DNS_TXT_DATA = DNS_TXT_DATAW
#ELSE
 MACRO DNS_TXT_DATA = DNS_TXT_DATAA
#ENDIF
' // Size = 8 bytes
TYPE DNS_NULL_DATA DWORD
 dwByteCount AS DWORD
 Data(0) AS BYTE
END TYPE
' // Size = 8 bytes
TYPE DNS_WKS_DATA BYTE
 IpAddress AS DWORD ' IP4_ADDRESS
 chProtocol AS BYTE ' UCHAR
 BitMask(2) AS BYTE
 ' Note: We are using BitMask(2) instead of BitMask(0) to keep DWORD alignment
END TYPE
' // Size = 16 bytes
TYPE DNS_AAAA_DATA BYTE
 Ip6Address AS IP6_ADDRESS
END TYPE
' // Size = 28 bytes
TYPE DNS_SIG_DATAW BYTE
 pNameSigner AS WSTRINGZ PTR
 wTypeCovered AS WORD
 chAlgorithm AS BYTE
 chLabelCount AS BYTE
 dwOriginalTtl AS DWORD
 dwExpiration AS DWORD
 dwTimeSigned AS DWORD
 wKeyTag AS WORD
 Pad AS WORD ' // keep byte field aligned
 Signature(3) AS BYTE
 ' Note: We are using Signature(3) instead of Signature(0) to keep DWORD alignment
END TYPE
' // Size = 28 bytes
TYPE DNS_SIG_DATAA BYTE
 pNameSigner AS ASCIIZ PTR
 wTypeCovered AS WORD
 chAlgorithm AS BYTE
 chLabelCount AS BYTE
 dwOriginalTtl AS DWORD
 dwExpiration AS DWORD
 dwTimeSigned AS DWORD
 wKeyTag AS WORD
 Pad AS WORD ' // keep byte field aligned
 Signature(3) AS BYTE
 ' Note: We are using Signature(3) instead of Signature(0) to keep DWORD alignment
END TYPE
MACRO DNS_RRSIG_DATAW = DNS_SIG_DATAW
MACRO DNS_RRSIG_DATAA = DNS_SIG_DATAA
#IF %DEF(%UNICODE)
 MACRO DNS_SIG_DATA = DNS_SIG_DATAW
#ELSE
 MACRO DNS_SIG_DATA = DNS_SIG_DATAA
#ENDIF
' // Size = 10 bytes
TYPE DNS_KEY_DATA BYTE
 wFlags AS WORD
 chProtocol AS BYTE
 chAlgorithm AS BYTE
 wKeyLength AS WORD
 wPad AS WORD ' // keep byte field aligned
 Key(1) AS BYTE
 ' Note: We are using Key(1) instead of Key(0) to keep WORD alignment
END TYPE
MACRO DNS_DNSKEY_DATA = DNS_KEY_DATA
' // Size = 8 bytes
TYPE DNS_DHCID_DATA BYTE
 dwByteCount AS DWORD
 DHCID(3) AS BYTE ' BYTE[1]
 ' Note: We are using DHCID(3) instead of DHCID(0) to keep DWORD alignment
END TYPE
' // Size = 12 bytes
TYPE DNS_NSEC_DATAW BYTE
 pNextDomainName AS WSTRINGZ PTR
 wTypeBitMapsLength AS WORD ' WORD
 wPad AS WORD ' WORD // keep byte field aligned
 TypeBitMaps(3) AS BYTE ' BYTE[1]
 ' Note: We are using TypeBitMaps(3) instead of TypeBitMaps(0) to keep DWORD alignment
END TYPE
' // Size = 12 bytes
TYPE DNS_NSEC_DATAA BYTE
 pNextDomainName AS ASCIIZ PTR
 wTypeBitMapsLength AS WORD ' WORD
 wPad AS WORD ' WORD // keep byte field aligned
 TypeBitMaps(3) AS BYTE
 ' Note: We are using TypeBitMaps(3) instead of TypeBitMaps(0) to keep DWORD alignment
END TYPE
#IF %DEF(%UNICODE)
 MACRO DNS_NSEC_DATA = DNS_NSEC_DATAW
#ELSE
 MACRO DNS_NSEC_DATA = DNS_NSEC_DATAA
#ENDIF
' // Size = 10 bytes
TYPE DNS_DS_DATA BYTE
 wKeyTag AS WORD ' WORD
 chAlgorithm AS BYTE ' BYTE
 chDigestType AS BYTE ' BYTE
 wDigestLength AS WORD ' WORD
 wPad AS WORD ' WORD // keep byte field aligned
 Digest(1) AS BYTE ' BYTE[1]
 ' Note: We are using Digest(1) instead of Digest(0) to keep DWORD alignment
END TYPE
' // Size = 6 bytes
TYPE DNS_OPT_DATA
 wDataLength AS WORD ' WORD
 wPad AS WORD ' WORD // keep byte field aligned
 Data(1) AS BYTE ' BYTE[1]
 ' Note: We are using Data(1) instead of Data(0) to keep DWORD alignment
END TYPE
' // Size = 20 bytes
TYPE DNS_LOC_DATA DWORD FILL
 wVersion AS WORD
 wSize AS WORD
 wHorPrec AS WORD
 wVerPrec AS WORD
 dwLatitude AS DWORD
 dwLongitude AS DWORD
 dwAltitude AS DWORD
END TYPE
' // Size = 8 bytes
TYPE DNS_NXT_DATAW DWORD FILL
 pNameNext AS WSTRINGZ PTR
 wNumTypes AS WORD
 wTypes(0) AS WORD
END TYPE
' // Size = 8 bytes
TYPE DNS_NXT_DATAA DWORD FILL
 pNameNext AS ASCIIZ PTR
 wNumTypes AS WORD
 wTypes(0) AS WORD
END TYPE
#IF %DEF(%UNICODE)
 MACRO DNS_NXT_DATA = DNS_NXT_DATAW
#ELSE
 MACRO DNS_NXT_DATA = DNS_NXT_DATAA
#ENDIF
' // Size = 12 bytes
TYPE DNS_SRV_DATAW DWORD FILL
 pNameTarget AS WSTRINGZ PTR
 wPriority AS WORD
 wWeight AS WORD
 wPort AS WORD
 Pad AS WORD ' // keep ptrs DWORD aligned
END TYPE
' // Size = 12 bytes
TYPE DNS_SRV_DATAA DWORD FILL
 pNameTarget AS ASCIIZ PTR
 wPriority AS WORD
 wWeight AS WORD
 wPort AS WORD
 Pad AS WORD ' // keep ptrs DWORD aligned
END TYPE
#IF %DEF(%UNICODE)
 MACRO DNS_SRV_DATA = DNS_SRV_DATAW
#ELSE
 MACRO DNS_SRV_DATA = DNS_SRV_DATAA
#ENDIF
' // Size = 20 bytes
TYPE DNS_NAPTR_DATAW DWORD FILL
 wOrder AS WORD ' WORD
 wPreference AS WORD ' WORD
 pFlags AS WSTRINGZ PTR
 pService AS WSTRINGZ PTR
 pRegularExpression AS WSTRINGZ PTR
 pReplacement AS WSTRINGZ PTR
END TYPE
' // Size = 20 bytes
TYPE DNS_NAPTR_DATAA DWORD FILL
 wOrder AS WORD ' WORD
 wPreference AS WORD ' WORD
 pFlags AS ASCIIZ PTR
 pService AS ASCIIZ PTR
 pRegularExpression AS ASCIIZ PTR
 pReplacement AS ASCIIZ PTR
END TYPE
#IF %DEF(%UNICODE)
 MACRO DNS_NAPTR_DATA = DNS_NAPTR_DATAW
#ELSE
 MACRO DNS_NAPTR_DATA = DNS_NAPTR_DATAA
#ENDIF
' // Size = 21 bytes
TYPE DNS_ATMA_DATA BYTE
 AddressType AS BYTE
 Address(%DNS_ATMA_MAX_ADDR_LENGTH - 1) AS BYTE
 ' // E164 -- Null terminated string of less than
 ' // DNS_ATMA_MAX_ADDR_LENGTH
 ' //
 ' // For NSAP (AESA) BCD encoding of exactly
 ' // DNS_ATMA_AESA_ADDR_LENGTH
END TYPE
' // Size = 40 bytes
TYPE DNS_TKEY_DATAW DWORD FILL
 pNameAlgorithm AS WSTRINGZ PTR
 pAlgorithmPacket AS BYTE PTR
 pKey AS BYTE PTR
 pOtherData AS BYTE PTR
 dwCreateTime AS DWORD
 dwExpireTime AS DWORD
 wMode AS WORD
 wError AS WORD
 wKeyLength AS WORD
 wOtherLength AS WORD
 cAlgNameLength AS BYTE ' UCHAR
 bPacketPointers AS LONG
END TYPE
' // Size = 40 bytes
TYPE DNS_TKEY_DATAA DWORD FILL
 pNameAlgorithm AS ASCIIZ PTR
 pAlgorithmPacket AS BYTE PTR
 pKey AS BYTE PTR
 pOtherData AS BYTE PTR
 dwCreateTime AS DWORD
 dwExpireTime AS DWORD
 wMode AS WORD
 wError AS WORD
 wKeyLength AS WORD
 wOtherLength AS WORD
 cAlgNameLength AS BYTE ' UCHAR
 bPacketPointers AS LONG
END TYPE
#IF %DEF(%UNICODE)
 MACRO DNS_TKEY_DATA = DNS_TKEY_DATAW
#ELSE
 MACRO DNS_TKEY_DATA = DNS_TKEY_DATAA
#ENDIF
' // Size = 40 bytes
TYPE DNS_TSIG_DATAW DWORD FILL
 pNameAlgorithm AS WSTRINGZ PTR
 pAlgorithmPacket AS BYTE PTR
 pSignature AS BYTE PTR
 pOtherData AS BYTE PTR
 i64CreateTime AS QUAD ' LONGLONG
 wFudgeTime AS WORD ' WORD
 wOriginalXid AS WORD ' WORD
 wError AS WORD ' WORD
 wSigLength AS WORD ' WORD
 wOtherLength AS WORD ' WORD
 cAlgNameLength AS BYTE ' UCHAR
 bPacketPointers AS LONG
END TYPE
' // Size = 40 bytes
TYPE DNS_TSIG_DATAA DWORD FILL
 pNameAlgorithm AS ASCIIZ PTR
 pAlgorithmPacket AS BYTE PTR
 pSignature AS BYTE PTR
 pOtherData AS BYTE PTR
 i64CreateTime AS QUAD ' LONGLONG
 wFudgeTime AS WORD ' WORD
 wOriginalXid AS WORD ' WORD
 wError AS WORD ' WORD
 wSigLength AS WORD ' WORD
 wOtherLength AS WORD ' WORD
 cAlgNameLength AS BYTE ' UCHAR
 bPacketPointers AS LONG
END TYPE
#IF %DEF(%UNICODE)
 MACRO DNS_TSIG_DATA = DNS_TSIG_DATAW
#ELSE
 MACRO DNS_TSIG_DATA = DNS_TSIG_DATAA
#ENDIF
'//
'// MS only types -- only hit the wire in MS-MS zone transfer
'//
' // Size = 20 bytes
TYPE DNS_WINS_DATA DWORD
 dwMappingFlag AS DWORD
 dwLookupTimeout AS DWORD
 dwCacheTimeout AS DWORD
 cWinsServerCount AS DWORD
 WinsServers(0) AS DWORD ' IP4_ADDRESS
END TYPE
' // Size = 16 bytes
TYPE DNS_WINSR_DATAW DWORD
 dwMappingFlag AS DWORD
 dwLookupTimeout AS DWORD
 dwCacheTimeout AS DWORD
 pNameResultDomain AS WSTRINGZ PTR
END TYPE
' // Size = 16 bytes
TYPE DNS_WINSR_DATAA DWORD
 dwMappingFlag AS DWORD
 dwLookupTimeout AS DWORD
 dwCacheTimeout AS DWORD
 pNameResultDomain AS ASCIIZ PTR
END TYPE
#IF %DEF(%UNICODE)
 MACRO DNS_WINSR_DATA = DNS_WINSR_DATAW
#ELSE
 MACRO DNS_WINSR_DATA = DNS_WINSR_DATAA
#ENDIF
'//
'// Length of non-fixed-length data types
'//
'#define DNS_TEXT_RECORD_LENGTH(StringCount) \
' (FIELD_OFFSET(DNS_TXT_DATA, pStringArray) + ((StringCount) * sizeof(PCHAR)))
'#define DNS_NULL_RECORD_LENGTH(ByteCount) \
' (FIELD_OFFSET(DNS_NULL_DATA, Data) + (ByteCount))
'#define DNS_WKS_RECORD_LENGTH(ByteCount) \
' (FIELD_OFFSET(DNS_WKS_DATA, BitMask) + (ByteCount))
'#define DNS_WINS_RECORD_LENGTH(IpCount) \
' (FIELD_OFFSET(DNS_WINS_DATA, WinsServers) + ((IpCount) * sizeof(IP4_ADDRESS)))
'#define DNS_KEY_RECORD_LENGTH(ByteCount) \
' (FIELD_OFFSET(DNS_KEY_DATA, Key) + (ByteCount))
'#define DNS_SIG_RECORD_LENGTH(ByteCount) \
' (FIELD_OFFSET(DNS_SIG_DATA, Signature) + (ByteCount))
'#define DNS_NSEC_RECORD_LENGTH(ByteCount) \
' (FIELD_OFFSET(DNS_NSEC_DATA, TypeBitMaps) + (ByteCount))
'#define DNS_DS_RECORD_LENGTH(ByteCount) \
' (FIELD_OFFSET(DNS_DS_DATA, Digest) + (ByteCount))
'#define DNS_OPT_RECORD_LENGTH(ByteCount) \
' (FIELD_OFFSET(DNS_OPT_DATA, Data) + (ByteCount))
'#define DNS_DHCID_RECORD_LENGTH(ByteCount) \
' (FIELD_OFFSET(DNS_DHCID_DATA, DHCID) + (ByteCount))
'//
'// Record flags
'//
' // Size = 4 bytes
TYPE DNS_RECORD_FLAGS DWORD
 Section AS BIT * 2 IN DWORD
 Delete AS BIT * 1
 CharSet AS BIT * 2
 Unused AS BIT * 3
 Reserved AS BIT * 24
END TYPE
'//
'// Wire Record Sections
'//
'// Useable both in record flags "Section" and as index into
'// wire message header section counts.
'//
' enum DNS_SECTION
%EQUATE `DnsSectionQuestion = 0
%EQUATE `DnsSectionAnswer = 1
%EQUATE `DnsSectionAuthority = 2
%EQUATE `DnsSectionAddtional = 3
'// Update message section names
%EQUATE `DnsSectionZone = %DnsSectionQuestion
%EQUATE `DnsSectionPrereq = %DnsSectionAnswer
%EQUATE `DnsSectionUpdate = %DnsSectionAuthority
'//
'// Record flags as bit flags
'// These may be or'd together to set the fields
'//
'// RR Section in packet
%EQUATE `DNSREC_SECTION = &H00000003
%EQUATE `DNSREC_QUESTION = &H00000000
%EQUATE `DNSREC_ANSWER = &H00000001
%EQUATE `DNSREC_AUTHORITY = &H00000002
%EQUATE `DNSREC_ADDITIONAL = &H00000003
'// RR Section in packet (update)
%EQUATE `DNSREC_ZONE = &H00000000
%EQUATE `DNSREC_PREREQ = &H00000001
%EQUATE `DNSREC_UPDATE = &H00000002
'// Delete RR (update or No-exist (prerequisite)
%EQUATE `DNSREC_DELETE = &H00000004
%EQUATE `DNSREC_NOEXIST = &H00000004
'//
'// Record \ RR set structure
'//
'// Note: The dwReserved flag serves to insure that the substructures
'// start on 64-bit boundaries. Do NOT pack this structure, as the
'// substructures may contain pointers or int64 values which are
'// properly aligned unpacked.
'//
'#ifdef MIDL_PASS
'#define PDNS_RECORD PVOID
'#else
' // Size = 4 bytes
UNION DNS_RECORD_UNION_Flags DWORD
 DW AS DWORD ' // flags as DWORD
 S AS DNS_RECORD_FLAGS ' // flags as structure
END UNION
' // Size = 40 bytes
UNION DNS_RECORDW_UNION_Data DWORD
 A AS DNS_A_DATA
 Soa AS DNS_SOA_DATAW
 Ptr AS DNS_PTR_DATAW
 Ns AS DNS_PTR_DATAW
 Cname AS DNS_PTR_DATAW
 Dname AS DNS_PTR_DATAW
 Mb AS DNS_PTR_DATAW
 Md AS DNS_PTR_DATAW
 Mf AS DNS_PTR_DATAW
 Mg AS DNS_PTR_DATAW
 Mr AS DNS_PTR_DATAW
 Minfo AS DNS_MINFO_DATAW
 Rp AS DNS_MINFO_DATAW
 Mx AS DNS_MX_DATAW
 Afsdb AS DNS_MX_DATAW
 Rt AS DNS_MX_DATAW
 Hinfo AS DNS_TXT_DATAW
 Isdn AS DNS_TXT_DATAW
 Txt AS DNS_TXT_DATAW
 X25 AS DNS_TXT_DATAW
 Null AS DNS_NULL_DATA
 Wks AS DNS_WKS_DATA
 AAAA AS DNS_AAAA_DATA
 Key AS DNS_KEY_DATA
 Sig AS DNS_SIG_DATAW
 Atma AS DNS_ATMA_DATA
 Nxt AS DNS_NXT_DATAW
 Srv AS DNS_SRV_DATAW
 Naptr AS DNS_NAPTR_DATAW
 Opt AS DNS_OPT_DATA
 Ds AS DNS_DS_DATA
 Rrsig AS DNS_RRSIG_DATAW
 Nsec AS DNS_NSEC_DATAW
 Dnskey AS DNS_DNSKEY_DATA
 Tkey AS DNS_TKEY_DATAW
 Tsig AS DNS_TSIG_DATAW
 Wins AS DNS_WINS_DATA
 WinsR AS DNS_WINSR_DATAW
 Nbstat AS DNS_WINSR_DATAW
 DHCID AS DNS_DHCID_DATA
END UNION
' // Size = 64 bytes
TYPE DNS_RECORDW DWORD FILL
 pNext AS DNS_RECORDW PTR ' struct _DnsRecordW *
 pName AS WSTRINGZ PTR
 wType AS WORD ' WORD
 wDataLength AS WORD ' WORD // Not referenced for DNS record types defined above.
 Flags AS DNS_RECORD_UNION_Flags
 dwTtl AS DWORD
 dwReserved AS DWORD
 ' // Record Data
 Data AS DNS_RECORDW_UNION_Data
END TYPE
' // Size = 4 bytes
UNION DNS_RECORD_OPTW_UNION_Flags
 DW AS DWORD ' DWORD // flags as DWORD
 S AS DNS_RECORD_FLAGS ' DNS_RECORD_FLAGS // flags as structure
END UNION
' // Size = 6 bytes
UNION DNS_RECORD_OPTW_UNION_Data
 Opt AS DNS_OPT_DATA
END UNION
' // Size = 32 bytes
TYPE DNS_RECORD_OPTW
 pNext AS DNS_RECORDW PTR ' struct _DnsRecordW *
 pName AS WSTRINGZ PTR
 wType AS WORD ' WORD
 wDataLength AS WORD ' WORD // Not referenced for DNS record types defined above.
 DNS_RECORD_OPTW_UNION_Flags
 ExtHeader AS DNS_HEADER_EXT ' DNS_HEADER_EXT // TTL
 wPayloadSize AS WORD ' WORD // dwReserved;
 wReserved AS WORD ' WORD
 ' // Record Data
 DNS_RECORD_OPTW_UNION_Data
 alignment__ AS WORD ' // To keep DWORD alignment
END TYPE
' // Size = 40 bytes
UNION DNS_RECORDA_UNION_Data DWORD
 A AS DNS_A_DATA
 Soa AS DNS_SOA_DATAA
 Ptr AS DNS_PTR_DATAA
 Ns AS DNS_PTR_DATAA
 Cname AS DNS_PTR_DATAA
 Dname AS DNS_PTR_DATAA
 Mb AS DNS_PTR_DATAA
 Md AS DNS_PTR_DATAA
 Mf AS DNS_PTR_DATAA
 Mg AS DNS_PTR_DATAA
 Mr AS DNS_PTR_DATAA
 Minfo AS DNS_MINFO_DATAA
 Rp AS DNS_MINFO_DATAA
 Mx AS DNS_MX_DATAA
 Afsdb AS DNS_MX_DATAA
 Rt AS DNS_MX_DATAA
 Hinfo AS DNS_TXT_DATAA
 Isdn AS DNS_TXT_DATAA
 Txt AS DNS_TXT_DATAA
 X25 AS DNS_TXT_DATAA
 Null AS DNS_NULL_DATA
 Wks AS DNS_WKS_DATA
 AAAA AS DNS_AAAA_DATA
 Key AS DNS_KEY_DATA
 Sig AS DNS_SIG_DATAA
 Atma AS DNS_ATMA_DATA
 Nxt AS DNS_NXT_DATAA
 Srv AS DNS_SRV_DATAA
 Naptr AS DNS_NAPTR_DATAA
 Opt AS DNS_OPT_DATA
 Ds AS DNS_DS_DATA
 Rrsig AS DNS_RRSIG_DATAA
 Nsec AS DNS_NSEC_DATAA
 Dnskey AS DNS_DNSKEY_DATA
 Tkey AS DNS_TKEY_DATAA
 Tsig AS DNS_TSIG_DATAA
 Wins AS DNS_WINS_DATA
 WinsR AS DNS_WINSR_DATAA
 Nbstat AS DNS_WINSR_DATAA
 DHCID AS DNS_DHCID_DATA
END UNION
' // Size = 64 bytes
TYPE DNS_RECORDA DWORD FILL
 pNext AS DNS_RECORDA PTR ' struct _DnsRecordA *
 pName AS ASCIIZ PTR
 wType AS WORD ' WORD
 wDataLength AS WORD ' WORD // Not referenced for DNS record types
 ' // defined above.
 Flags AS DNS_RECORD_UNION_Flags
 dwTtl AS DWORD
 dwReserved AS DWORD
 ' // Record Data
 Data AS DNS_RECORDA_UNION_Data
END TYPE
' // Size = 4 bytes
UNION DNS_RECORD_OPTA_UNION_Flags
 DW AS DWORD ' DWORD // flags as DWORD
 S AS DNS_RECORD_FLAGS ' DNS_RECORD_FLAGS // flags as structure
END UNION
' // Size = 6 bytes
UNION DNS_RECORD_OPTA_UNION_Data
 Opt AS DNS_OPT_DATA
END UNION
' // Size = 32 bytes
TYPE DNS_RECORD_OPTA
 pNext AS DNS_RECORDA PTR ' struct _DnsRecordA *
 pName AS ASCIIZ PTR
 wType AS WORD ' WORD
 wDataLength AS WORD ' WORD // Not referenced for DNS record types defined above.
 DNS_RECORD_OPTA_UNION_Flags
 ExtHeader AS DNS_HEADER_EXT ' DNS_HEADER_EXT // TTL
 wPayloadSize AS WORD ' WORD // dwReserved;
 wReserved AS WORD ' WORD
 ' // Record Data
 DNS_RECORD_OPTA_UNION_Data
 alignment__ AS WORD ' // To keep DWORD alignment
END TYPE
#IF %DEF(%UNICODE)
 MACRO DNS_RECORD_OPT = DNS_RECORD_OPTW
 MACRO DNS_RECORD = DNS_RECORDW
#ELSE
 MACRO DNS_RECORD_OPT = DNS_RECORD_OPTA
 MACRO DNS_RECORD = DNS_RECORDA
#ENDIF
'//
'// Header or fixed size of DNS_RECORD
'//
'#define DNS_RECORD_FIXED_SIZE FIELD_OFFSET( DNS_RECORD, Data )
'#define SIZEOF_DNS_RECORD_HEADER DNS_RECORD_FIXED_SIZE
'//
'// Resource record set building
'//
'// pFirst points to first record in list.
'// pLast points to last record in list.
'//
' // Size = 8 bytes
TYPE DNS_RRSET DWORD
 pFirstRR AS DNS_RECORD PTR ' PDNS_RECORD
 pLastRR AS DNS_RECORD PTR ' PDNS_RECORD
END TYPE
'//
'// To init pFirst is NULL.
'// But pLast points at the location of the pFirst pointer -- essentially
'// treating the pFirst ptr as a DNS_RECORD. (It is a DNS_RECORD with
'// only a pNext field, but that's the only part we use.)
'//
'// Then when the first record is added to the list, the pNext field of
'// this dummy record (which corresponds to pFirst's value) is set to
'// point at the first record. So pFirst then properly points at the
'// first record.
'//
'// (This works only because pNext is the first field in a
'// DNS_RECORD structure and hence casting a PDNS_RECORD ptr to
'// PDNS_RECORD* and dereferencing yields its pNext field)
'//
'// Use TERMINATE when have built RR set by grabbing records out of
'// existing set. This makes sure that at the end, the last RR is
'// properly NULL terminated.
'//
'#define DNS_RRSET_INIT( rrset ) \
' { \
' PDNS_RRSET _prrset = &(rrset); \
' _prrset->pFirstRR = NULL; \
' _prrset->pLastRR = (PDNS_RECORD) &_prrset->pFirstRR; \
' }
'#define DNS_RRSET_ADD( rrset, pnewRR ) \
' { \
' PDNS_RRSET _prrset = &(rrset); \
' PDNS_RECORD _prrnew = (pnewRR); \
' _prrset->pLastRR->pNext = _prrnew; \
' _prrset->pLastRR = _prrnew; \
' }
'#define DNS_RRSET_TERMINATE( rrset ) \
' { \
' PDNS_RRSET _prrset = &(rrset); \
' _prrset->pLastRR->pNext = NULL; \
' }
'typedef
'(WINAPI *DNS_PROXY_COMPLETION_ROUTINE) (
'SUB DNS_PROXY_COMPLETION_ROUTINE ( ' BYVAL completionContext AS DWORD
' , BYVAL status AS LONG
' )
' enum DNS_PROXY_INFORMATION_TYPE
%EQUATE `DNS_PROXY_INFORMATION_DIRECT = 0
%EQUATE `DNS_PROXY_INFORMATION_DEFAULT_SETTINGS = 1
%EQUATE `DNS_PROXY_INFORMATION_PROXY_NAME = 2
%EQUATE `DNS_PROXY_INFORMATION_DOES_NOT_EXIST = 3
' // Size = 12 bytes
TYPE DNS_PROXY_INFORMATION DWORD
 version AS DWORD
 proxyInformationType AS LONG
 proxyName AS WSTRINGZ PTR
END TYPE
'//
'// Record set manipulation
'//
'//
'// Record Copy
'// Record copy functions also do conversion between character sets.
'//
'// Note, it might be advisable to directly expose non-Ex copy
'// functions _W, _A for record and set, to avoid exposing the
'// conversion enum.
'//
' enum DNS_CHARSET
%EQUATE `DnsCharSetUnknown = 0
%EQUATE `DnsCharSetUnicode = 1
%EQUATE `DnsCharSetUtf8 = 2
%EQUATE `DnsCharSetAnsi = 3
' PDNS_RECORD declared AS ANY to allow to pass a DNS_RECORDA or DNS_RECORDW structure
DECLARE FUNCTION DnsRecordCopyEx LIB "dnsapi.dll" ALIAS "DnsRecordCopyEx" ( BYREF pRecord AS ANY , BYVAL CharSetIn AS LONG , BYVAL CharSetOut AS LONG ) AS QUAD ' PDNS_RECORD
' PDNS_RECORD declared AS ANY to allow to pass a DNS_RECORDA or DNS_RECORDW structure
#IF %DEF(%USEPBDECL)
DECLARE FUNCTION DnsRecordSetCopyEx LIB "DnsApi.dll" ALIAS "DnsRecordSetCopyEx" ( BYVAL pRecordSet AS DNS_RECORD PTR, BYVAL CharSetIn AS LONG, BYVAL CharSetOut AS LONG ) AS QUAD ' DNS_RECORD PTR
#ELSE
DECLARE FUNCTION DnsRecordSetCopyEx LIB "dnsapi.dll" ALIAS "DnsRecordSetCopyEx" ( BYREF pRecordSet AS ANY , BYVAL CharSetIn AS LONG , BYVAL CharSetOut AS LONG ) AS QUAD ' PDNS_RECORD
#ENDIF
'#ifdef UNICODE
'#define DnsRecordCopy(pRR) \
' DnsRecordCopyEx( (pRR), DnsCharSetUnicode, DnsCharSetUnicode )
'#define DnsRecordSetCopy(pRR) \
' DnsRecordSetCopyEx( (pRR), DnsCharSetUnicode, DnsCharSetUnicode )
'#else
'#define DnsRecordCopy(pRR) \
' DnsRecordCopyEx( (pRR), DnsCharSetAnsi, DnsCharSetAnsi )
'#define DnsRecordSetCopy(pRR) \
' DnsRecordSetCopyEx( (pRR), DnsCharSetAnsi, DnsCharSetAnsi )
'#endif
#IF %DEF(%USEPBDECL)
#IF %DEF(%UNICODE)
MACRO DnsRecordCopy(pRR)=DnsRecordCopyEx((pRR), DnsCharSetUnicode, DnsCharSetUnicode)
MACRO DnsRecordSetCopy(pRR)=DnsRecordSetCopyEx((pRR), DnsCharSetUnicode, DnsCharSetUnicode)
#ELSE
MACRO DnsRecordCopy(pRR)=DnsRecordCopyEx((pRR), DnsCharSetAnsi, DnsCharSetAnsi)
MACRO DnsRecordSetCopy(pRR)=DnsRecordSetCopyEx((pRR), DnsCharSetAnsi, DnsCharSetAnsi)
#ENDIF
#ELSE
FUNCTION DnsRecordCopyW (BYREF pRR AS DNS_RECORDW) AS DWORD
 FUNCTION = DnsRecordCopyEx(pRR, %DnsCharSetUnicode, %DnsCharSetUnicode)
END FUNCTION
FUNCTION DnsRecordCopyA (BYREF pRR AS DNS_RECORDA) AS DWORD
 FUNCTION = DnsRecordCopyEx(pRR, %DnsCharSetAnsi, %DnsCharSetAnsi)
END FUNCTION
FUNCTION DnsRecordSetCopyW (BYREF pRR AS DNS_RECORDW) AS DWORD
 FUNCTION = DnsRecordSetCopyEx(pRR, %DnsCharSetUnicode, %DnsCharSetUnicode)
END FUNCTION
FUNCTION DnsRecordSetCopyA (BYREF pRR AS DNS_RECORDA) AS DWORD
 FUNCTION = DnsRecordSetCopyEx(pRR, %DnsCharSetAnsi, %DnsCharSetAnsi)
END FUNCTION
#IF %DEF(%UNICODE)
 MACRO DnsRecordCopy = DnsRecordCopyW
 MACRO DnsRecordSetCopy = DnsRecordSetCopyW
#ELSE
 MACRO DnsRecordCopy = DnsRecordCopyA
 MACRO DnsRecordSetCopy = DnsRecordSetCopyA
#ENDIF
#ENDIF
'//
'// Record Compare
'//
'// Note: these routines only compare records of the SAME character set.
'// (ANSI, unicode or UTF8). Furthermore the routines assume the character
'// set is indicated within the record. If compare of user created, rather
'// than DNS API created record lists is desired, then caller should use
'// DnsRecordCopy API and compare copies.
'//
' PDNS_RECORD declared AS ANY to allow to pass a DNS_RECORDA or DNS_RECORDW structure
DECLARE FUNCTION DnsRecordCompare LIB "dnsapi.dll" ALIAS "DnsRecordCompare" ( BYREF pRecord1 AS ANY , BYREF pRecord2 AS ANY ) AS LONG
' PDNS_RECORD declared AS ANY to allow to pass a DNS_RECORDA or DNS_RECORDW structure
DECLARE FUNCTION DnsRecordSetCompare LIB "dnsapi.dll" ALIAS "DnsRecordSetCompare" ( BYREF pRR1 AS ANY , BYREF pRR2 AS ANY , BYREF ppDiff1 AS ANY , BYREF ppDiff2 AS ANY ) AS LONG
'//
'// Detach next record set from record list
'//
' PDNS_RECORD declared AS ANY to allow to pass a DNS_RECORDA or DNS_RECORDW structure
DECLARE FUNCTION DnsRecordSetDetach LIB "dnsapi.dll" ALIAS "DnsRecordSetDetach" ( BYREF pRecordList AS ANY ) AS QUAD ' PDNS_RECORD
'//
'// Free structures returned from dnsapi.dll
'//
'// Currently supported free structures:
'// Flat -- flat structure, including those allocated by DnsQueryConfig()
'// RecordList -- deep record list free, including sub-fields of DNS_RECORD;
'// includes those returned by DnsQuery() or DnsRecordSetCopy()
'//
' enum DNS_FREE_TYPE
%EQUATE `DnsFreeFlat = 0
%EQUATE `DnsFreeRecordList = 1
%EQUATE `DnsFreeParsedMessageFields = 2
#IF %DEF(%USEPBDECL)
DECLARE SUB DnsFree LIB "DnsApi.dll" ALIAS "DnsFree" ( pData AS ANY,
 FreeType AS LONG )
#ELSE
DECLARE SUB DnsFree LIB "dnsapi.dll" ALIAS "DnsFree" ( BYVAL pData AS QUAD , BYVAL FreeType AS LONG )
#ENDIF
'//
'// Backward compatibility with Win2K, do not use for XP+ applications
'//
'// To free record lists, code
'// DnsFree( pRecordList, DnsFreeRecordList );
'//
'#define DnsFreeRecordListDeep DnsFreeRecordList
' PDNS_RECORD declared AS ANY to allow to pass a DNS_RECORDA or DNS_RECORDW structure
'#if(_WIN32_WINNT >= 0x0501)
'#define DnsRecordListFree(p,t) DnsFree(p,DnsFreeRecordList)
'#else
#IF %DEF(%USEPBDECL)
DECLARE SUB DnsRecordListFree LIB "DnsApi.dll" ALIAS "DnsRecordListFree" ( pRecordList AS DNS_RECORD, FreeType AS LONG )
#ELSE
DECLARE SUB DnsRecordListFree LIB "dnsapi.dll" ALIAS "DnsRecordListFree" ( BYREF pRecordList AS ANY , BYVAL FreeType AS LONG )
#ENDIF
'#endif /* _WIN32_WINNT >= 0x0501 */
'//
'// DNS Query API
'//
'//
'// Options for DnsQuery
'//
%EQUATE `DNS_QUERY_STANDARD = &H00000000
%EQUATE `DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE = &H00000001
%EQUATE `DNS_QUERY_USE_TCP_ONLY = &H00000002
%EQUATE `DNS_QUERY_NO_RECURSION = &H00000004
%EQUATE `DNS_QUERY_BYPASS_CACHE = &H00000008
%EQUATE `DNS_QUERY_NO_WIRE_QUERY = &H00000010
%EQUATE `DNS_QUERY_NO_LOCAL_NAME = &H00000020
%EQUATE `DNS_QUERY_NO_HOSTS_FILE = &H00000040
%EQUATE `DNS_QUERY_NO_NETBT = &H00000080
%EQUATE `DNS_QUERY_WIRE_ONLY = &H00000100
%EQUATE `DNS_QUERY_RETURN_MESSAGE = &H00000200
%EQUATE `DNS_QUERY_MULTICAST_ONLY = &H00000400
%EQUATE `DNS_QUERY_NO_MULTICAST = &H00000800
%EQUATE `DNS_QUERY_TREAT_AS_FQDN = &H00001000
%EQUATE `DNS_QUERY_APPEND_MULTILABEL = &H00800000
%EQUATE `DNS_QUERY_DONT_RESET_TTL_VALUES = &H00100000
%EQUATE `DNS_QUERY_RESERVED = &Hf0000000
'// Backward compatibility with Win2K
'// Do not use
%EQUATE `DNS_QUERY_CACHE_ONLY = %DNS_QUERY_NO_WIRE_QUERY
#IF %DEF(%USEPBDECL)
DECLARE FUNCTION DnsQuery_A LIB "DnsApi.dll" ALIAS "DnsQuery_A" ( pszName AS ASCIIZ, BYVAL wType AS WORD, BYVAL Options AS QUAD, pExtra AS ANY,
 ppQueryResults AS ANY, ' DNS_RECORD PTR PTR
 pReserved AS ANY ' PVOID *
 ) AS LONG
#ELSE
DECLARE FUNCTION DnsQuery_A LIB "dnsapi.dll" ALIAS "DnsQuery_A" ( BYREF pszName AS ASCIIZ , BYVAL wType AS WORD , BYVAL Options AS QUAD , BYREF aipServers AS IP4_ARRAY , BYREF ppQueryResults AS ANY , BYREF pReserved AS ANY ) AS LONG ' DNS_STATUS
#ENDIF
#IF %DEF(%USEPBDECL)
DECLARE FUNCTION DnsQuery_W LIB "DnsApi.dll" ALIAS "DnsQuery_W" ( pszName AS WSTRINGZ, BYVAL wType AS WORD, BYVAL Options AS QUAD, pExtra AS ANY,
 ppQueryResults AS ANY, ' DNS_RECORD PTR PTR
 pReserved AS ANY ' PVOID *
 ) AS LONG
#ELSE
DECLARE FUNCTION DnsQuery_W LIB "dnsapi.dll" ALIAS "DnsQuery_W" ( BYREF pszName AS WSTRINGZ , BYVAL wType AS WORD , BYVAL Options AS QUAD , BYREF aipServers AS IP4_ARRAY , BYREF ppQueryResults AS ANY , BYREF pReserved AS ANY ) AS LONG ' DNS_STATUS
#ENDIF
#IF %DEF(%UNICODE)
 MACRO DnsQuery = DnsQuery_W
#ELSE
 MACRO DnsQuery = DnsQuery_A
#ENDIF
#IF %DEF(%USEPBDECL)
DECLARE FUNCTION DnsQuery_UTF8 LIB "DnsApi.dll" ALIAS "DnsQuery_UTF8" ( pszName AS ASCIIZ, BYVAL wType AS WORD, BYVAL Options AS QUAD, pExtra AS ANY,
 ppQueryResults AS ANY, ' DNS_RECORD PTR PTR
 pReserved AS ANY ' PVOID *
 ) AS LONG
#ELSE
DECLARE FUNCTION DnsQuery_UTF8 LIB "dnsapi.dll" ALIAS "DnsQuery_UTF8" ( BYREF pszName AS ASCIIZ , BYVAL wType AS WORD , BYVAL Options AS QUAD , BYREF aipServers AS IP4_ARRAY , BYREF ppQueryResults AS ANY , BYREF pReserved AS ANY ) AS LONG ' DNS_STATUS
#ENDIF
'//
'// DNS Update API
'//
'// DnsAcquireContextHandle
'// DnsReleaseContextHandle
'// DnsModifyRecordsInSet
'// DnsReplaceRecordSet
'//
'//
'// Update flags
'//
%EQUATE `DNS_UPDATE_SECURITY_USE_DEFAULT = &H00000000
%EQUATE `DNS_UPDATE_SECURITY_OFF = &H00000010
%EQUATE `DNS_UPDATE_SECURITY_ON = &H00000020
%EQUATE `DNS_UPDATE_SECURITY_ONLY = &H00000100
%EQUATE `DNS_UPDATE_CACHE_SECURITY_CONTEXT = &H00000200
%EQUATE `DNS_UPDATE_TEST_USE_LOCAL_SYS_ACCT = &H00000400
%EQUATE `DNS_UPDATE_FORCE_SECURITY_NEGO = &H00000800
%EQUATE `DNS_UPDATE_TRY_ALL_MASTER_SERVERS = &H00001000
%EQUATE `DNS_UPDATE_SKIP_NO_UPDATE_ADAPTERS = &H00002000
%EQUATE `DNS_UPDATE_REMOTE_SERVER = &H00004000
%EQUATE `DNS_UPDATE_RESERVED = &Hffff0000
'//
'// Note: pCredentials paramater is currently respectively
'// PSEC_WINNT_AUTH_IDENTITY_W or PSEC_WINNT_AUTH_IDENTITY_A.
'// Using PVOID to obviate the need for including rpcdce.h
'// in order to include this file and to leave open the
'// possibility of alternative credential specifications in
'// the future.
'//
DECLARE FUNCTION DnsAcquireContextHandleW LIB "dnsapi.dll" ALIAS "DnsAcquireContextHandle_W" ( BYVAL CredentialFlags AS QUAD , BYREF pCredentials AS ANY , BYREF pContextHandle AS QUAD ) AS LONG ' DNS_STATUS
DECLARE FUNCTION DnsAcquireContextHandleA LIB "dnsapi.dll" ALIAS "DnsAcquireContextHandle_A" ( BYVAL CredentialFlags AS QUAD , BYREF pCredentials AS ANY , BYREF pContextHandle AS QUAD ) AS LONG ' DNS_STATUS
#IF %DEF(%UNICODE)
 MACRO DnsAcquireContextHandle = DnsAcquireContextHandleW
#ELSE
 MACRO DnsAcquireContextHandle = DnsAcquireContextHandleA
#ENDIF
DECLARE SUB DnsReleaseContextHandle LIB "dnsapi.dll" ALIAS "DnsReleaseContextHandle" ( BYVAL hContext AS QUAD )
'//
'// Dynamic Update API
'//
#IF %DEF(%USEPBDECL)
DECLARE FUNCTION DnsModifyRecordsInSet_W LIB "DnsApi.dll" ALIAS "DnsModifyRecordsInSet_W" ( pAddRecords AS DNS_RECORD, pDeleteRecords AS DNS_RECORD, BYVAL Options AS QUAD, BYVAL hCredentials AS QUAD,
 pExtraList AS ANY,
 pReserved AS ANY
 ) AS LONG
#ELSE
DECLARE FUNCTION DnsModifyRecordsInSet_W LIB "dnsapi.dll" ALIAS "DnsModifyRecordsInSet_W" ( BYREF pAddRecords AS ANY , BYREF pDeleteRecords AS ANY , BYVAL Options AS QUAD , BYVAL hContext AS QUAD , BYREF pServerList AS IP4_ARRAY , BYVAL pReserved AS QUAD ) AS LONG ' DNS_STATUS
#ENDIF
#IF %DEF(%USEPBDECL)
DECLARE FUNCTION DnsModifyRecordsInSet_A LIB "DnsApi.dll" ALIAS "DnsModifyRecordsInSet_A" ( pAddRecords AS DNS_RECORD, pDeleteRecords AS DNS_RECORD, BYVAL Options AS QUAD, BYVAL hCredentials AS QUAD,
 pExtraList AS ANY,
 pReserved AS ANY
 ) AS LONG
#ELSE
DECLARE FUNCTION DnsModifyRecordsInSet_A LIB "dnsapi.dll" ALIAS "DnsModifyRecordsInSet_A" ( BYREF pAddRecords AS ANY , BYREF pDeleteRecords AS ANY , BYVAL Options AS QUAD , BYVAL hContext AS QUAD , BYREF pServerList AS IP4_ARRAY , BYVAL pReserved AS QUAD ) AS LONG ' DNS_STATUS
#ENDIF
#IF %DEF(%UNICODE)
 MACRO DnsModifyRecordsInSet = DnsModifyRecordsInSet_W
#ELSE
 MACRO DnsModifyRecordsInSet = DnsModifyRecordsInSet_A
#ENDIF
#IF %DEF(%USEPBDECL)
DECLARE FUNCTION DnsModifyRecordsInSet_UTF8 LIB "DnsApi.dll" ALIAS "DnsModifyRecordsInSet_UTF8" ( pAddRecords AS DNS_RECORD, pDeleteRecords AS DNS_RECORD, BYVAL Options AS QUAD, BYVAL hCredentials AS QUAD,
 pExtraList AS ANY,
 pReserved AS ANY
 ) AS LONG
#ELSE
DECLARE FUNCTION DnsModifyRecordsInSet_UTF8 LIB "dnsapi.dll" ALIAS "DnsModifyRecordsInSet_UTF8" ( BYREF pAddRecords AS ANY , BYREF pDeleteRecords AS ANY , BYVAL Options AS QUAD , BYVAL hContext AS QUAD , BYREF pServerList AS IP4_ARRAY , BYVAL pReserved AS QUAD ) AS LONG ' DNS_STATUS
#ENDIF
#IF %DEF(%USEPBDECL)
DECLARE FUNCTION DnsReplaceRecordSetW LIB "DnsApi.dll" ALIAS "DnsReplaceRecordSetW" ( pReplaceSet AS DNS_RECORD, BYVAL Options AS QUAD, BYVAL hContext AS QUAD,
 pExtraInfo AS ANY,
 pReserved AS ANY
 ) AS LONG
#ELSE
DECLARE FUNCTION DnsReplaceRecordSetW LIB "dnsapi.dll" ALIAS "DnsReplaceRecordSetW" ( BYREF pNewSet AS ANY , BYVAL Options AS QUAD , BYVAL hContext AS QUAD , BYREF pServerList AS IP4_ARRAY , BYVAL pReserved AS QUAD ) AS LONG ' DNS_STATUS
#ENDIF
#IF %DEF(%USEPBDECL)
DECLARE FUNCTION DnsReplaceRecordSetA LIB "DnsApi.dll" ALIAS "DnsReplaceRecordSetA" ( pReplaceSet AS DNS_RECORD, BYVAL Options AS QUAD, BYVAL hContext AS QUAD,
 pExtraInfo AS ANY,
 pReserved AS ANY
 ) AS LONG
#ELSE
DECLARE FUNCTION DnsReplaceRecordSetA LIB "dnsapi.dll" ALIAS "DnsReplaceRecordSetA" ( BYREF pNewSet AS ANY , BYVAL Options AS QUAD , BYVAL hContext AS QUAD , BYREF pServerList AS IP4_ARRAY , BYVAL pReserved AS QUAD ) AS LONG ' DNS_STATUS
#ENDIF
#IF %DEF(%UNICODE)
 MACRO DnsReplaceRecordSet = DnsReplaceRecordSetW
#ELSE
 MACRO DnsReplaceRecordSet = DnsReplaceRecordSetA
#ENDIF
#IF %DEF(%USEPBDECL)
DECLARE FUNCTION DnsReplaceRecordSetUTF8 LIB "DnsApi.dll" ALIAS "DnsReplaceRecordSetUTF8" ( pReplaceSet AS DNS_RECORD, BYVAL Options AS QUAD, BYVAL hContext AS QUAD,
 pExtraInfo AS ANY,
 pReserved AS ANY
 ) AS LONG
#ELSE
DECLARE FUNCTION DnsReplaceRecordSetUTF8 LIB "dnsapi.dll" ALIAS "DnsReplaceRecordSetUTF8" ( BYREF pNewSet AS ANY , BYVAL Options AS QUAD , BYVAL hContext AS QUAD , BYREF pServerList AS IP4_ARRAY , BYVAL pReserved AS QUAD ) AS LONG ' DNS_STATUS
#ENDIF
'//
'// DNS name validation
'//
' enum DNS_NAME_FORMAT
%EQUATE `DnsNameDomain = 0
%EQUATE `DnsNameDomainLabel = 1
%EQUATE `DnsNameHostnameFull = 2
%EQUATE `DnsNameHostnameLabel = 3
%EQUATE `DnsNameWildcard = 4
%EQUATE `DnsNameSrvRecord = 5
%EQUATE `DnsNameValidateTld = 6
DECLARE FUNCTION DnsValidateNameW LIB "dnsapi.dll" ALIAS "DnsValidateName_W" ( BYREF pszName AS WSTRINGZ , BYVAL Format AS LONG ) AS LONG ' DNS_STATUS
DECLARE FUNCTION DnsValidateNameA LIB "dnsapi.dll" ALIAS "DnsValidateName_A" ( BYREF pszName AS ASCIIZ , BYVAL Format AS LONG ) AS LONG ' DNS_STATUS
#IF %DEF(%UNICODE)
 MACRO DnsValidateName = DnsValidateNameW
#ELSE
 MACRO DnsValidateName = DnsValidateNameA
#ENDIF
#IF %DEF(%USEPBDECL)
DECLARE FUNCTION DnsValidateName_UTF8 LIB "DnsApi.dll" ALIAS "DnsValidateName_UTF8" ( pszName AS ASCIIZ, Format AS LONG ) AS LONG
#ELSE
DECLARE FUNCTION DnsValidateName_UTF8 LIB "dnsapi.dll" ALIAS "DnsValidateName_UTF8" ( BYREF pszName AS ASCIIZ , BYVAL Format AS LONG ) AS LONG ' DNS_STATUS
#ENDIF
'//
'// DNS server validation
'//
'// DNS server validation error codes
%EQUATE `DNS_VALSVR_ERROR_INVALID_ADDR = &H01
%EQUATE `DNS_VALSVR_ERROR_INVALID_NAME = &H02
%EQUATE `DNS_VALSVR_ERROR_UNREACHABLE = &H03
%EQUATE `DNS_VALSVR_ERROR_NO_RESPONSE = &H04
%EQUATE `DNS_VALSVR_ERROR_NO_AUTH = &H05
%EQUATE `DNS_VALSVR_ERROR_REFUSED = &H06
%EQUATE `DNS_VALSVR_ERROR_NO_TCP = &H10
%EQUATE `DNS_VALSVR_ERROR_UNKNOWN = &HFF
'// Winsock2.h must be included before windns.h to use the validate server function
#IF %DEF(%WINSOCK2_INC)
DECLARE FUNCTION DnsValidateServerStatus LIB "dnsapi.dll" ALIAS "DnsValidateServerStatus" ( BYREF server AS SOCKADDR , BYREF queryName AS WSTRINGZ , BYREF serverStatus AS QUAD ) AS LONG ' DNS_STATUS
#ENDIF
'//
'// DNS name comparison
'//
DECLARE FUNCTION DnsNameCompareA LIB "dnsapi.dll" ALIAS "DnsNameCompare_A" ( BYREF pName1 AS ASCIIZ , BYREF pName2 AS ASCIIZ ) AS LONG
DECLARE FUNCTION DnsNameCompareW LIB "dnsapi.dll" ALIAS "DnsNameCompare_W" ( BYREF pName1 AS WSTRINGZ
 , BYREF pName2 AS WSTRINGZ
 ) AS LONG
#IF %DEF(%UNICODE)
 MACRO DnsNameCompare = DnsNameCompareW
#ELSE
 MACRO DnsNameCompare = DnsNameCompareA
#ENDIF
'//
'// DNS message "roll-your-own" routines
'//
' // Size = 8 bytes
TYPE DNS_MESSAGE_BUFFER BYTE
 MessageHead AS DNS_HEADER ' DNS_HEADER
 MessageBody(0) AS BYTE ' CHAR
END TYPE
#IF %DEF(%USEPBDECL)
DECLARE FUNCTION DnsWriteQuestionToBuffer_W LIB "DnsApi.dll" ALIAS "DnsWriteQuestionToBuffer_W" ( BYVAL pDnsBuffer AS DNS_MESSAGE_BUFFER PTR, pdwBufferSize AS QUAD, pszName AS WSTRINGZ, BYVAL wType AS WORD, BYVAL Xid AS WORD, BYVAL fRecursionDesired AS LONG
 ) AS LONG
#ELSE
DECLARE FUNCTION DnsWriteQuestionToBuffer_W LIB "dnsapi.dll" ALIAS "DnsWriteQuestionToBuffer_W" ( BYREF pDnsBuffer AS DNS_MESSAGE_BUFFER , BYREF pdwBufferSize AS QUAD , BYREF pszName AS WSTRINGZ , BYVAL wType AS WORD , BYVAL Xid AS WORD , BYVAL fRecursionDesired AS LONG ) AS LONG
#ENDIF
MACRO DnsWriteQuestionToBuffer = DnsWriteQuestionToBuffer_W
#IF %DEF(%USEPBDECL)
DECLARE FUNCTION DnsWriteQuestionToBuffer_UTF8 LIB "DnsApi.dll" ALIAS "DnsWriteQuestionToBuffer_UTF8" ( BYVAL pDnsBuffer AS DNS_MESSAGE_BUFFER PTR, pdwBufferSize AS QUAD, pszName AS ASCIIZ, BYVAL wType AS WORD, BYVAL Xid AS WORD, BYVAL fRecursionDesired AS LONG
 ) AS LONG
#ELSE
DECLARE FUNCTION DnsWriteQuestionToBuffer_UTF8 LIB "dnsapi.dll" ALIAS "DnsWriteQuestionToBuffer_UTF8" ( BYREF pDnsBuffer AS DNS_MESSAGE_BUFFER , BYREF pdwBufferSize AS QUAD , BYREF pszName AS ASCIIZ , BYVAL wType AS WORD , BYVAL Xid AS WORD , BYVAL fRecursionDesired AS LONG ) AS LONG
#ENDIF
#IF %DEF(%USEPBDECL)
DECLARE FUNCTION DnsExtractRecordsFromMessage_W LIB "DnsApi.dll" ALIAS "DnsExtractRecordsFromMessage_W" ( BYVAL pDnsBuffer AS DNS_MESSAGE_BUFFER PTR, BYVAL wMessageLength AS WORD, ppRecord AS ANY ) AS LONG ' PDNS_RECORD *
#ELSE
DECLARE FUNCTION DnsExtractRecordsFromMessage_W LIB "dnsapi.dll" ALIAS "DnsExtractRecordsFromMessage_W" ( BYREF pDnsBuffer AS DNS_MESSAGE_BUFFER , BYVAL wMessageLength AS WORD , BYREF ppRecord AS ANY ) AS LONG
#ENDIF
MACRO DnsExtractRecordsFromMessage = DnsExtractRecordsFromMessage_W
#IF %DEF(%USEPBDECL)
DECLARE FUNCTION DnsExtractRecordsFromMessage_UTF8 LIB "DnsApi.dll" ALIAS "DnsExtractRecordsFromMessage_UTF8" ( BYVAL pDnsBuffer AS DNS_MESSAGE_BUFFER PTR, BYVAL wMessageLength AS WORD, ppRecord AS ANY ) AS LONG ' PDNS_RECORD *
#ELSE
DECLARE FUNCTION DnsExtractRecordsFromMessage_UTF8 LIB "dnsapi.dll" ALIAS "DnsExtractRecordsFromMessage_UTF8" ( BYREF pDnsBuffer AS DNS_MESSAGE_BUFFER , BYVAL wMessageLength AS WORD , BYREF ppRecord AS ANY ) AS LONG
#ENDIF
#IF %DEF(%USEPBDECL)
DECLARE FUNCTION DnsGetProxyInformation LIB "DnsApi.dll" ALIAS "DnsGetProxyInformation" ( hostName AS WSTRINGZ, proxyInformation AS DNS_PROXY_INFORMATION, defaultProxyInformation AS DNS_PROXY_INFORMATION, BYVAL completionRoutine AS QUAD, ' DNS_PROXY_COMPLETION_ROUTINE
 completionContext AS ANY ' void *
 ) AS DWORD
#ELSE
DECLARE FUNCTION DnsGetProxyInformation LIB "dnsapi.dll" ALIAS "DnsGetProxyInformation" ( BYREF hostName AS WSTRINGZ , BYVAL proxyInformation AS LONG , OPTIONAL BYREF defaultProxyInformation AS LONG , OPTIONAL BYVAL completionRoutine AS QUAD , OPTIONAL BYVAL completionContext AS QUAD ) AS QUAD
#ENDIF
#IF %DEF(%USEPBDECL)
DECLARE SUB DnsFreeProxyName LIB "DnsApi.dll" ALIAS "DnsFreeProxyName" ( proxyName AS WSTRINGZ)
#ELSE
DECLARE SUB DnsFreeProxyName LIB "dnsapi.dll" ALIAS "DnsFreeProxyName" ( BYVAL proxyName AS WSTRINGZ PTR )
#ENDIF
#ENDIF
