#pragma once

#define INLINE_QWORD_FLIP(out, in)  \
        {                           \
            QWORD _in = (in);       \
            (out) =  (_in << 56)                       | \
                    ((_in << 40) & 0x00ff000000000000) | \
                    ((_in << 32) & 0x0000ff0000000000) | \
                    ((_in <<  8) & 0x000000ff00000000) | \
                    ((_in >>  8) & 0x00000000ff000000) | \
                    ((_in >> 32) & 0x0000000000ff0000) | \
                    ((_in >> 40) & 0x000000000000ff00) | \
                     (_in >> 56); \
        }
#define INLINE_NTOHQ(out, in) INLINE_QWORD_FLIP(out, in)
#define INLINE_HTONQ(out, in) INLINE_QWORD_FLIP(out, in)

//typedef struct
//{                                <-- пропущено поле OPTION-CODE (WORD)
//    WORD            wDataLength;
//    WORD            wPad;            // keep byte field aligned
//    BYTE            Data[1];
//}
//DNS_OPT_DATA, *PDNS_OPT_DATA;
typedef struct
{
    WORD            wOptionCode;
    WORD            wDataLength;
    BYTE            Data[1];
}
DNS_OPTD_DATA, *PDNS_OPTD_DATA;

#define DNS_OPTD_RECORD_LENGTH(ByteCount) \
            (FIELD_OFFSET(DNS_OPTD_DATA, Data) + (ByteCount))

typedef union _DNS_DATA
{
    DNS_A_DATA          A;
    DNS_SOA_DATAW       SOA, Soa;
    DNS_PTR_DATAW       PTR, Ptr,
                        NS, Ns,
                        CNAME, Cname,
                        DNAME, Dname,
                        MB, Mb,
                        MD, Md,
                        MF, Mf,
                        MG, Mg,
                        MR, Mr;
    DNS_MINFO_DATAW     MINFO, Minfo,
                        RP, Rp;
    DNS_MX_DATAW        MX, Mx,
                        AFSDB, Afsdb,
                        RT, Rt, KX;
    DNS_TXT_DATAW       HINFO, Hinfo,
                        ISDN, Isdn,
                        TXT, Txt,
                        X25;
    DNS_NULL_DATA       Null;
    DNS_WKS_DATA        WKS, Wks;
    DNS_AAAA_DATA       AAAA;
    DNS_KEY_DATA        KEY, Key;
    DNS_SIG_DATAW       SIG, Sig;
    DNS_ATMA_DATA       ATMA, Atma;
    DNS_NXT_DATAW       NXT, Nxt;
    DNS_SRV_DATAW       SRV, Srv;
    DNS_NAPTR_DATAW     NAPTR, Naptr;
    DNS_OPTD_DATA       OPT, Opt;
    DNS_DS_DATA         DS, Ds;
    DNS_RRSIG_DATAW     RRSIG, Rrsig;
    DNS_NSEC_DATAW      NSEC, Nsec;
    DNS_DNSKEY_DATA     DNSKEY, Dnskey;
    DNS_TKEY_DATAW      TKEY, Tkey;
    DNS_TSIG_DATAW      TSIG, Tsig;
    DNS_WINS_DATA       WINS, Wins;
    DNS_WINSR_DATAW     WINSR, WinsR, NBSTAT, Nbstat;
    DNS_DHCID_DATA      DHCID;
    DNS_LOC_DATA        LOC;
    DNS_NSEC3_DATA      NSEC3, Nsec3;
    DNS_NSEC3PARAM_DATA	NSEC3PARAM, Nsec3Param;
    PBYTE               pDataPtr;
} DNS_DATA, *PDNS_DATA;

typedef union _DNS_RECORD_FLAGS_UNION
{
    DWORD               DW;     // flags as DWORD
    DNS_RECORD_FLAGS    S;      // flags as structure
} DNS_RECORD_FLAGS_UNION;

class CDnsMessageWB;
class CDnsResorceRecord
{
public:
    CDnsResorceRecord(void);
    ~CDnsResorceRecord(void);
    CDnsResorceRecord(CDnsResorceRecord& rSourceRR);
    CDnsResorceRecord* m_pNext;
    int m_nStartPositionIndex;
    CString m_sName;
    unsigned short m_wType;
    unsigned short m_wClass;
    unsigned short m_wDataLength;
    DNS_RECORD_FLAGS_UNION m_unDnsRecordFlags;
    unsigned long m_dwTtl;
    unsigned long m_dwReserved;
    DNS_DATA* m_pDnsRecordData;
    bool FillFromBuffer(PCHAR& pCurrentBufferPoint, CDnsMessageWB& rOwner);
    CString m_sRRTypeName;
    void DumpResorceRecord();
};
