// DnsMessageWB.cpp : implementation file
//

#include "stdafx.h"
#include "dnsfirewall_public.h"
#include "WS2InterceptDLL.h"
#include "DnsMessageWB.h"
#include "DnsResorceRecord.h"
#include "Trace.h"
#include "DnsMessageWB.tmh"


// CDnsMessageWB

CDnsMessageWB::CDnsMessageWB()
: m_pFirstDnsRRecord(NULL)
, m_pLastDnsRRecord(NULL)
, m_nAnswerCount(0)
, m_nNameServerCount(0)
, m_nAdditionalCount(0)
, m_pParsedMessage(NULL)
, m_nParsedMessageLength(0)
, m_nQuestionCount(0)
, m_pSavedQueryMessage(NULL)
, m_sDnsQuestionTypeName(_T(""))
, m_nCookiesValue(721721721)
{
    RtlZeroMemory(&m_stDnsHeader, sizeof(m_stDnsHeader));
}

CDnsMessageWB::~CDnsMessageWB()
{
    CDnsResorceRecord*  pRemovedRR;
    if (721721721 != m_nCookiesValue)
    {
        TraceEvents(
            TRACE_LEVEL_ERROR,
            TRACE_DNS_MESSAGE_WB,
            "%!FUNC! line:%!LINE! %!LEVEL! Exception #1 (721721721 != m_nCookiesValue)"
            );
        throw int(1);
    }
    m_stDnsQuestionRecord.ClearName();
    if (NULL != m_pSavedQueryMessage)
    {
        delete m_pSavedQueryMessage;
        m_pSavedQueryMessage = NULL;
    }
    while ((pRemovedRR = RemoveFromTail()) != NULL)
    {
        delete pRemovedRR;
    }
    if (721721721 != m_nCookiesValue)
    {
        TraceEvents(
            TRACE_LEVEL_ERROR,
            TRACE_DNS_MESSAGE_WB,
            "%!FUNC! line:%!LINE! %!LEVEL! Exception #2 (721721721 != m_nCookiesValue)"
            );
        throw int(2);
    }
}


// CDnsMessageWB member functions


bool CDnsMessageWB::ParseDnsMessageBuffer(
    PDNS_MESSAGE_BUFFER pDnsMessageBufer,
    WORD wMessageLength
    )
{
    WORD    nSectionsNumber = 0;
    PCHAR   pCurrentBufferPoint;
    PDNS_WIRE_QUESTION  pSourceDnsWireQuestion;
    CDnsResorceRecord*  pDnsRecord;
    WORD    wSI;
    CString sQuestionName;
    m_pParsedMessage = (PCHAR) pDnsMessageBufer;
    m_nParsedMessageLength = (int)wMessageLength;
    RtlCopyMemory(
        &m_stDnsHeader,
        &pDnsMessageBufer->MessageHead,
        sizeof(m_stDnsHeader)
        );
    DNS_BYTE_FLIP_HEADER_COUNTS(&m_stDnsHeader);
    //DumpDnsHeader();
    //if (DNS_OPCODE_IQUERY == m_stDnsHeader.Opcode)
    //{
    //    TraceEvents(
    //        TRACE_LEVEL_WARNING,
    //        TRACE_DNS_MESSAGE_WB,
    //        "%!FUNC! line:%!LINE! %!LEVEL! Exit (DNS_OPCODE_IQUERY == m_stDnsHeader.Opcode)"
    //        );
    //    return false;
    //}
    m_nQuestionCount = m_stDnsHeader.QuestionCount;
    nSectionsNumber = m_stDnsHeader.AnswerCount + m_stDnsHeader.NameServerCount + m_stDnsHeader.AdditionalCount;
    pCurrentBufferPoint = DNS_QUESTION_NAME_FROM_HEADER(&pDnsMessageBufer->MessageHead);
    m_stDnsQuestionRecord.ClearName();
    sQuestionName = L"";
    m_stDnsQuestionRecord.SetQNAME(GetDomainName(
        sQuestionName,
        pCurrentBufferPoint
        ));
    pSourceDnsWireQuestion = (PDNS_WIRE_QUESTION)pCurrentBufferPoint;
    pCurrentBufferPoint += sizeof(DNS_WIRE_QUESTION);
    INLINE_HTONS(m_stDnsQuestionRecord.stDnsWireQuestion.QuestionType,pSourceDnsWireQuestion->QuestionType);
    INLINE_HTONS(m_stDnsQuestionRecord.stDnsWireQuestion.QuestionClass,pSourceDnsWireQuestion->QuestionClass);
    if((m_stDnsHeader.ResponseCode != 0) || (nSectionsNumber == 0))
    {
        TraceEvents(
            TRACE_LEVEL_WARNING,
            TRACE_DNS_MESSAGE_WB,
            "%!FUNC! line:%!LINE! %!LEVEL! Exit ((m_stDnsHeader.ResponseCode != 0) || (nSectionsNumber == 0))"
            );
        return false;
    }
    for(wSI=0;wSI<m_stDnsHeader.AnswerCount;wSI++)
    {
        pDnsRecord = new CDnsResorceRecord;
        pDnsRecord->m_unDnsRecordFlags.S.Section = DnsSectionAnswer;
        if (!pDnsRecord->FillFromBuffer(pCurrentBufferPoint, *this))
        {
            TraceEvents(
                TRACE_LEVEL_WARNING,
                TRACE_DNS_MESSAGE_WB,
                "%!FUNC! line:%!LINE! %!LEVEL! Exit (!pDnsRecord->FillFromBuffer(pCurrentBufferPoint, *this))"
                );
            return false;
        }
        AddRRToTail(pDnsRecord);
    }
    for(wSI=0;wSI<m_stDnsHeader.NameServerCount;wSI++)
    {
        pDnsRecord = new CDnsResorceRecord;
        pDnsRecord->m_unDnsRecordFlags.S.Section = DnsSectionAuthority;
        if (!pDnsRecord->FillFromBuffer(pCurrentBufferPoint, *this))
        {
            TraceEvents(
                TRACE_LEVEL_WARNING,
                TRACE_DNS_MESSAGE_WB,
                "%!FUNC! line:%!LINE! %!LEVEL! Exit (!pDnsRecord->FillFromBuffer(pCurrentBufferPoint, *this))"
                );
            return false;
        }
        AddRRToTail(pDnsRecord);
    }
    for(wSI=0;wSI<m_stDnsHeader.AdditionalCount;wSI++)
    {
        pDnsRecord = new CDnsResorceRecord;
        pDnsRecord->m_unDnsRecordFlags.S.Section = DnsSectionAddtional;
        if (!pDnsRecord->FillFromBuffer(pCurrentBufferPoint, *this))
        {
            TraceEvents(
                TRACE_LEVEL_WARNING,
                TRACE_DNS_MESSAGE_WB,
                "%!FUNC! line:%!LINE! %!LEVEL! Exit (!pDnsRecord->FillFromBuffer(pCurrentBufferPoint, *this))"
                );
            return false;
        }
        AddRRToTail(pDnsRecord);
    }
    return true;
}


CString& CDnsMessageWB::GetDomainName(CString& sCurrentQNAME, PCHAR& pCurrentBufferPoint)
{
    WCHAR   sNamePartition[64];
    int     nConvertedChars;
    bool    bOutBufer;
    int     nStingLength = (int)((BYTE)*pCurrentBufferPoint);
    if (nStingLength == 0)
    {
        pCurrentBufferPoint++;
        sCurrentQNAME += _T('.');
        return sCurrentQNAME;
    }
    if((nStingLength&0xC0) != 0)
    {
        WORD    wQNAMEPos = *((PWORD)pCurrentBufferPoint);
        PCHAR   pQNAMEPos;
        CString sPrevQNAME;
        int     nDelta;
        INLINE_HTONS(wQNAMEPos,wQNAMEPos);
        wQNAMEPos &= ~0xC000;
        pQNAMEPos = m_pParsedMessage + wQNAMEPos;
        nDelta =  (int)(pCurrentBufferPoint - pQNAMEPos);
        pCurrentBufferPoint += 2;
        if(!sCurrentQNAME.IsEmpty())
        {
            sCurrentQNAME += _T('.');
        }
        sCurrentQNAME += GetDomainName(sPrevQNAME, pQNAMEPos);
        return sCurrentQNAME;
    }
    bOutBufer = (m_nParsedMessageLength - (int)((pCurrentBufferPoint + *pCurrentBufferPoint + 1) - m_pParsedMessage) < 0);
    nConvertedChars = MultiByteToWideChar(
        CP_UTF8,
        0,
        pCurrentBufferPoint + 1,
        nStingLength,
        sNamePartition,
        64
        );
    assert(nConvertedChars > 0);
    sNamePartition[nConvertedChars] = 0;
    if(!sCurrentQNAME.IsEmpty())
    {
        sCurrentQNAME += _T('.');
    }
    sCurrentQNAME += sNamePartition;
    pCurrentBufferPoint += nStingLength + 1;
    return GetDomainName(sCurrentQNAME, pCurrentBufferPoint);
}


CString CDnsMessageWB::GetCharSTRING(CString& sCurrentCharSTRING, PCHAR& pCurrentBufferPoint)
{
    WCHAR   wsUnicodeString[256];
    int     nConvertedChars;
    bool    bOutBufer;
    int     nStingLength = (int)((BYTE)*pCurrentBufferPoint);
    sCurrentCharSTRING = CString();
    if(nStingLength == 0)
    {
        return sCurrentCharSTRING;
    }
    bOutBufer = (m_nParsedMessageLength - (int)((pCurrentBufferPoint + *pCurrentBufferPoint + 1) - m_pParsedMessage) < 0);
    if(bOutBufer)
    {
        nStingLength = m_nParsedMessageLength - (int)((pCurrentBufferPoint + 1) - m_pParsedMessage);
    }
    if(nStingLength > 0)
    {
        nConvertedChars = MultiByteToWideChar(
            CP_UTF8,
            0,
            pCurrentBufferPoint + 1,
            nStingLength,
            wsUnicodeString,
            256
            );
        wsUnicodeString[nConvertedChars] = 0;
        sCurrentCharSTRING = wsUnicodeString;
    }
    pCurrentBufferPoint += nStingLength + 1;
    return sCurrentCharSTRING;
}


CDnsResorceRecord* CDnsMessageWB::RemoveFromTail(void)
{
    CDnsResorceRecord*  pPrevRR = m_pFirstDnsRRecord;
    CDnsResorceRecord*  pRemovedRR = m_pLastDnsRRecord;
    if (NULL == pRemovedRR)
    {
        return pRemovedRR;
    }
    if (pPrevRR == pRemovedRR)
    {
        m_pFirstDnsRRecord = NULL;
        m_pLastDnsRRecord  = NULL;
    }
    else
    {
        while(pPrevRR->m_pNext != pRemovedRR)
        {
            pPrevRR = pPrevRR->m_pNext;
        }
        pPrevRR->m_pNext = NULL;
        m_pLastDnsRRecord = pPrevRR;
    }
    if(NULL != pRemovedRR)
    {
        switch(pRemovedRR->m_unDnsRecordFlags.S.Section)
        {
        case DnsSectionQuestion:
            m_nQuestionCount--;
            break;
        case DnsSectionAnswer:
            m_nAnswerCount--;
            break;
        case DnsSectionAuthority:
            m_nNameServerCount--;
            break;
        case DnsSectionAddtional:
            m_nAdditionalCount--;
            break;
        }
    }
    return pRemovedRR;
}


void CDnsMessageWB::AddRRToTail(CDnsResorceRecord* pDnsResorceRecord)
{
    if (NULL == m_pFirstDnsRRecord)
    {
        m_pFirstDnsRRecord = pDnsResorceRecord;
        m_pLastDnsRRecord  = pDnsResorceRecord;
    }
    else
    {
        m_pLastDnsRRecord->m_pNext = pDnsResorceRecord;
        m_pLastDnsRRecord  = pDnsResorceRecord;
    }
    pDnsResorceRecord->m_pNext = NULL;
    switch(pDnsResorceRecord->m_unDnsRecordFlags.S.Section)
    {
    case DnsSectionQuestion:
        m_nQuestionCount++;
        break;
    case DnsSectionAnswer:
        m_nAnswerCount++;
        break;
    case DnsSectionAuthority:
        m_nNameServerCount++;
        break;
    case DnsSectionAddtional:
        m_nAdditionalCount++;
        break;
    }
}


CDnsResorceRecord* CDnsMessageWB::RemoveFromHeader(void)
{
    CDnsResorceRecord*  pRemovedRR = m_pFirstDnsRRecord;
    if (NULL == pRemovedRR)
    {
        return NULL;
    }
    m_pFirstDnsRRecord = pRemovedRR->m_pNext;
    if(NULL == m_pFirstDnsRRecord)
    {
        m_pLastDnsRRecord = NULL;
    }
    switch(pRemovedRR->m_unDnsRecordFlags.S.Section)
    {
    case DnsSectionQuestion:
        m_nQuestionCount--;
        break;
    case DnsSectionAnswer:
        m_nAnswerCount--;
        break;
    case DnsSectionAuthority:
        m_nNameServerCount--;
        break;
    case DnsSectionAddtional:
        m_nAdditionalCount--;
        break;
    }
    return pRemovedRR;
}


void CDnsMessageWB::RemoveRRAt(CDnsResorceRecord* pRemovedRR)
{
    if(NULL == pRemovedRR)
    {
        TraceEvents(
            TRACE_LEVEL_FATAL,
            TRACE_DNS_MESSAGE_WB,
            "%!FUNC! line:%!LINE! %!LEVEL! Exit (NULL == pRemovedRR)"
            );
        return;
    }
    CDnsResorceRecord*  pPrevRR = m_pFirstDnsRRecord;
    CDnsResorceRecord*  pNextRR = pRemovedRR->m_pNext;
    if(pPrevRR == pRemovedRR)
    {
        m_pFirstDnsRRecord = pNextRR;
        if(NULL == pNextRR)
        {
            m_pLastDnsRRecord  = NULL;
        }
    }
    else
    {
        while((NULL != pPrevRR)&&(pPrevRR->m_pNext != pRemovedRR))
        {
            pPrevRR = pPrevRR->m_pNext;
        }
        if(NULL == pPrevRR)
        {
            TraceEvents(
                TRACE_LEVEL_FATAL,
                TRACE_DNS_MESSAGE_WB,
                "%!FUNC! line:%!LINE! %!LEVEL! Exit (NULL == pPrevRR)"
                );
            return;
        }
        pPrevRR->m_pNext = pNextRR;
        if(NULL == pNextRR)
        {
            m_pLastDnsRRecord = pPrevRR;
        }
    }
    switch(pRemovedRR->m_unDnsRecordFlags.S.Section)
    {
    case DnsSectionQuestion:
        m_nQuestionCount--;
        break;
    case DnsSectionAnswer:
        m_nAnswerCount--;
        break;
    case DnsSectionAuthority:
        m_nNameServerCount--;
        break;
    case DnsSectionAddtional:
        m_nAdditionalCount--;
        break;
    }
}


void CDnsMessageWB::PerformQuerySection(PBYTE& rCurrentBufferPosition)
{
    CString sQNAME(m_stDnsQuestionRecord.sQNAME);
    int     nConvertedChars, nDotPosition;
    do
    {
        nDotPosition = sQNAME.Find(_T('.'));
        if(nDotPosition < 0)
        {
            *rCurrentBufferPosition = 0;
            rCurrentBufferPosition++;
            break;
        }
        nConvertedChars = WideCharToMultiByte(
            CP_UTF8,
            0,
            (LPCWSTR)sQNAME,
            nDotPosition,
            (LPSTR)(rCurrentBufferPosition + 1),
            64,
            NULL,
            NULL
            );
        *rCurrentBufferPosition = (BYTE)nConvertedChars;
        rCurrentBufferPosition += nConvertedChars + 1;
        sQNAME = sQNAME.Mid(nDotPosition + 1);
    }
    while(true);
    INLINE_HTONS(*((PWORD)rCurrentBufferPosition),m_stDnsQuestionRecord.stDnsWireQuestion.QuestionType);
    rCurrentBufferPosition += 2;
    INLINE_HTONS(*((PWORD)rCurrentBufferPosition),m_stDnsQuestionRecord.stDnsWireQuestion.QuestionClass);
    rCurrentBufferPosition += 2;
}


CDnsMessageWB::CDnsMessageWB(
    CDnsMessageWB* pSourceDnsMessage,
    CDnsResorceRecord* pDnsResorceRecord
    )
: m_pFirstDnsRRecord(NULL)
, m_pLastDnsRRecord(NULL)
, m_nAnswerCount(0)
, m_nNameServerCount(0)
, m_nAdditionalCount(0)
, m_pParsedMessage(NULL)
, m_nParsedMessageLength(0)
, m_nQuestionCount(0)
, m_pSavedQueryMessage(NULL)
, m_sDnsQuestionTypeName(_T(""))
, m_nCookiesValue(721721721)
{
    RtlCopyMemory(
        &m_stDnsHeader,
        &pSourceDnsMessage->m_stDnsHeader,
        sizeof(m_stDnsHeader)
        );
    m_stDnsQuestionRecord.SetQNAME(pSourceDnsMessage->m_stDnsQuestionRecord.sQNAME);
    RtlCopyMemory(
        &m_stDnsQuestionRecord.stDnsWireQuestion,
        &pSourceDnsMessage->m_stDnsQuestionRecord.stDnsWireQuestion,
        sizeof(DNS_WIRE_QUESTION)
        );
    AddRRToTail(pDnsResorceRecord);
    //TraceEvents(
    //    TRACE_LEVEL_INFORMATION,
    //    FILE_TRACE,
    //    "%!FUNC! line:%!LINE! %!LEVEL! Object \'CDnsMessageWB\' (%p) was created",
    //    this
    //    );
}


UINT32 CDnsMessageWB::PerformDnsMessageBuffer(
    PBYTE pMessageBuffer,
    UINT32 nBufferLength
    )
{
    BYTE    baBufferInStack[0x20000];
    PDNS_HEADER pDnsHeader = (PDNS_HEADER)baBufferInStack;
    int     nCurrentPosition = (int)sizeof(DNS_HEADER);
    PBYTE   pCurrentBufferPosition = &baBufferInStack[nCurrentPosition];
    CDnsResorceRecord*  pCurrentRR = m_pFirstDnsRRecord;
    CDnsResorceRecord*  pNextRR;
    UINT32  nResultMessageLength;
    RtlCopyMemory(
        pDnsHeader,
        &m_stDnsHeader,
        sizeof(DNS_HEADER)
        );
    pDnsHeader->AnswerCount = m_nAnswerCount;
    pDnsHeader->NameServerCount = m_nNameServerCount;
    pDnsHeader->AdditionalCount = m_nAdditionalCount;
    PerformQuerySection(pCurrentBufferPosition);
    nCurrentPosition = (int) (pCurrentBufferPosition - baBufferInStack);
    while(NULL != pCurrentRR)
    {
        WORD    wDataLength = 0;
        PWORD   pwRDataLength;
        int     nRDataPosition;
        PDNS_DATA   pDnsRecordData;
        pNextRR = pCurrentRR->m_pNext;
        pCurrentRR->m_nStartPositionIndex = nCurrentPosition;
        PerformDomanName(
            pCurrentRR->m_sName,
            baBufferInStack,
            pCurrentRR,
            nCurrentPosition
            );
        INLINE_HTONS(*(PWORD)&baBufferInStack[nCurrentPosition],pCurrentRR->m_wType);
        nCurrentPosition += 2;
        INLINE_HTONS(*(PWORD)&baBufferInStack[nCurrentPosition],pCurrentRR->m_wClass);
        nCurrentPosition += 2;
        INLINE_HTONL(*(PDWORD)&baBufferInStack[nCurrentPosition],pCurrentRR->m_dwTtl);
        nCurrentPosition += 4;
        pwRDataLength = (PWORD)&baBufferInStack[nCurrentPosition];
        nCurrentPosition += 2;
        nRDataPosition = nCurrentPosition;
        pDnsRecordData = pCurrentRR->m_pDnsRecordData;
        switch(pCurrentRR->m_wType)
        {
        case DNS_TYPE_SOA:
            {
                PDNS_SOA_DATA   pSoaData = &pDnsRecordData->SOA;
                PerformDomanName(
                    CString(pSoaData->pNamePrimaryServer),
                    baBufferInStack,
                    pCurrentRR,
                    nCurrentPosition
                    );
                PerformDomanName(
                    CString(pSoaData->pNameAdministrator),
                    baBufferInStack,
                    pCurrentRR,
                    nCurrentPosition
                    );
                INLINE_HTONL(*(PDWORD)&baBufferInStack[nCurrentPosition],pSoaData->dwSerialNo);
                nCurrentPosition += 4;
                INLINE_HTONL(*(PDWORD)&baBufferInStack[nCurrentPosition],pSoaData->dwRefresh);
                nCurrentPosition += 4;
                INLINE_HTONL(*(PDWORD)&baBufferInStack[nCurrentPosition],pSoaData->dwRetry);
                nCurrentPosition += 4;
                INLINE_HTONL(*(PDWORD)&baBufferInStack[nCurrentPosition],pSoaData->dwExpire);
                nCurrentPosition += 4;
                INLINE_HTONL(*(PDWORD)&baBufferInStack[nCurrentPosition],pSoaData->dwDefaultTtl);
                nCurrentPosition += 4;
            }
            break;
        case DNS_TYPE_PTR:
        case DNS_TYPE_NS:
        case DNS_TYPE_MD:
        case DNS_TYPE_MF:
        case DNS_TYPE_CNAME:
        case DNS_TYPE_MB:
        case DNS_TYPE_MG:
        case DNS_TYPE_MR:
        case DNS_TYPE_DNAME:
            {
                PDNS_PTR_DATA   pDnsPtrData = &pDnsRecordData->PTR;
                PerformDomanName(
                    CString(pDnsPtrData->pNameHost),
                    baBufferInStack,
                    pCurrentRR,
                    nCurrentPosition
                    );
            }
            break;
        case DNS_TYPE_NULL:
            {
                PDNS_NULL_DATA  pDnsNullData = &pDnsRecordData->Null;
                RtlCopyMemory(
                    &baBufferInStack[nCurrentPosition],
                    pDnsNullData->Data,
                    pDnsNullData->dwByteCount
                    );
                nCurrentPosition += (int)pDnsNullData->dwByteCount;
            }
            break;
        case DNS_TYPE_MINFO:
        case DNS_TYPE_RP:
            {
                PDNS_MINFO_DATA pDnsMinfoData = &pDnsRecordData->MINFO;
                PerformDomanName(
                    CString(pDnsMinfoData->pNameMailbox),
                    baBufferInStack,
                    pCurrentRR,
                    nCurrentPosition
                    );
                PerformDomanName(
                    CString(pDnsMinfoData->pNameErrorsMailbox),
                    baBufferInStack,
                    pCurrentRR,
                    nCurrentPosition
                    );
            }
            break;
        case DNS_TYPE_MX:
        case DNS_TYPE_AFSDB:
        case DNS_TYPE_RT:
        case DNS_TYPE_KX:
        {
                PDNS_MX_DATA pDnsMxData = &pDnsRecordData->MX;
                INLINE_HTONS(*(PWORD)&baBufferInStack[nCurrentPosition],pDnsMxData->wPreference);
                nCurrentPosition += 2;
                PerformDomanName(
                    CString(pDnsMxData->pNameExchange),
                    baBufferInStack,
                    pCurrentRR,
                    nCurrentPosition
                    );
            }
            break;
        case DNS_TYPE_KEY:
        case DNS_TYPE_DNSKEY:
            {
                PDNS_KEY_DATA   pDnsKeyData = &pDnsRecordData->KEY;
                INLINE_HTONS(*(PWORD)&baBufferInStack[nCurrentPosition],pDnsKeyData->wFlags);
                nCurrentPosition += 2;
                baBufferInStack[nCurrentPosition] = pDnsKeyData->chProtocol;
                nCurrentPosition++;
                baBufferInStack[nCurrentPosition] = pDnsKeyData->chAlgorithm;
                nCurrentPosition++;
                RtlCopyMemory(
                    &baBufferInStack[nCurrentPosition],
                    pDnsKeyData->Key,
                    pDnsKeyData->wKeyLength
                    );
                nCurrentPosition += pDnsKeyData->wKeyLength;
            }
            break;
        case DNS_TYPE_SIG:
        case DNS_TYPE_RRSIG:
            {
                PDNS_SIG_DATA   pDnsSigData = &pDnsRecordData->SIG;
                int     nSignatureLength = (int)pCurrentRR->m_wDataLength - offsetof(DNS_SIG_DATA,Signature);
                INLINE_HTONS(*(PWORD)&baBufferInStack[nCurrentPosition],pDnsSigData->wTypeCovered);
                nCurrentPosition += 2;
                baBufferInStack[nCurrentPosition] = pDnsSigData->chAlgorithm;
                nCurrentPosition++;
                baBufferInStack[nCurrentPosition] = pDnsSigData->chLabelCount;
                nCurrentPosition++;
                INLINE_HTONL(*(PDWORD)&baBufferInStack[nCurrentPosition],pDnsSigData->dwOriginalTtl);
                nCurrentPosition += 4;
                INLINE_HTONL(*(PDWORD)&baBufferInStack[nCurrentPosition],pDnsSigData->dwExpiration);
                nCurrentPosition += 4;
                INLINE_HTONL(*(PDWORD)&baBufferInStack[nCurrentPosition],pDnsSigData->dwTimeSigned);
                nCurrentPosition += 4;
                INLINE_HTONS(*(PWORD)&baBufferInStack[nCurrentPosition],pDnsSigData->wKeyTag);
                nCurrentPosition += 2;
                PerformDomanName(
                    CString(pDnsSigData->pNameSigner),
                    baBufferInStack,
                    pCurrentRR,
                    nCurrentPosition
                    );
                RtlCopyMemory(
                    &baBufferInStack[nCurrentPosition],
                    pDnsSigData->Signature,
                    nSignatureLength
                    );
                nCurrentPosition += nSignatureLength;
            }
            break;
        case DNS_TYPE_NXT:
        case DNS_TYPE_NSEC:
            {
                PDNS_NSEC_DATA  pDnsNsecData = &pDnsRecordData->NSEC;
                PerformUnpackDomanName(
                    CString(pDnsNsecData->pNextDomainName),
                    baBufferInStack,
                    pCurrentRR,
                    nCurrentPosition
                    );
                RtlCopyMemory(
                    &baBufferInStack[nCurrentPosition],
                    pDnsNsecData->TypeBitMaps,
                    pDnsNsecData->wTypeBitMapsLength
                    );
                nCurrentPosition += (int)pDnsNsecData->wTypeBitMapsLength;
            }
            break;
        case DNS_TYPE_SRV:
            {
                PDNS_SRV_DATA   pDnsSrvData = &pDnsRecordData->SRV;
                INLINE_HTONS(*(PWORD)&baBufferInStack[nCurrentPosition],pDnsSrvData->wPriority);
                nCurrentPosition += 2;
                INLINE_HTONS(*(PWORD)&baBufferInStack[nCurrentPosition],pDnsSrvData->wWeight);
                nCurrentPosition += 2;
                INLINE_HTONS(*(PWORD)&baBufferInStack[nCurrentPosition],pDnsSrvData->wPort);
                nCurrentPosition += 2;
                PerformDomanName(
                    CString(pDnsSrvData->pNameTarget),
                    baBufferInStack,
                    pCurrentRR,
                    nCurrentPosition
                    );
            }
            break;
        case DNS_TYPE_NAPTR:
            {
                PDNS_NAPTR_DATA pDnsNaptrData = &pDnsRecordData->NAPTR;
                INLINE_HTONS(*(PWORD)&baBufferInStack[nCurrentPosition],pDnsNaptrData->wOrder);
                nCurrentPosition += 2;
                INLINE_HTONS(*(PWORD)&baBufferInStack[nCurrentPosition],pDnsNaptrData->wPreference);
                nCurrentPosition += 2;
                PerformCharString(
                    pDnsNaptrData->pFlags,
                    baBufferInStack,
                    nCurrentPosition
                    );
                PerformCharString(
                    pDnsNaptrData->pService,
                    baBufferInStack,
                    nCurrentPosition
                    );
                PerformCharString(
                    pDnsNaptrData->pRegularExpression,
                    baBufferInStack,
                    nCurrentPosition
                    );
                PerformDomanName(
                    CString(pDnsNaptrData->pReplacement),
                    baBufferInStack,
                    pCurrentRR,
                    nCurrentPosition
                    );
            }
            break;
        case DNS_TYPE_OPT:
            {
                PDNS_OPTD_DATA  pDnsOptdData = &pDnsRecordData->OPT;
                INLINE_HTONS(*(PWORD)&baBufferInStack[nCurrentPosition],pDnsOptdData->wOptionCode);
                nCurrentPosition += 2;
                INLINE_HTONS(*(PWORD)&baBufferInStack[nCurrentPosition],pDnsOptdData->wDataLength);
                nCurrentPosition += 2;
                RtlCopyMemory(
                    &baBufferInStack[nCurrentPosition],
                    pDnsOptdData->Data,
                    pDnsOptdData->wDataLength
                    );
                nCurrentPosition += (int)pDnsOptdData->wDataLength;
            }
            break;
        case DNS_TYPE_TEXT:
        case DNS_TYPE_HINFO:
        case DNS_TYPE_ISDN:
        case DNS_TYPE_X25:
            {
                PDNS_TXT_DATA   pDnsTxtData = &pDnsRecordData->TXT;
                DWORD   i;
                for(i=0;i<pDnsTxtData->dwStringCount;i++)
                {
                    PerformCharString(
                        pDnsTxtData->pStringArray[i],
                        baBufferInStack,
                        nCurrentPosition
                        );
                }
            }
            break;
        case DNS_TYPE_DS:
            {
                PDNS_DS_DATA    pDnsDsData = &pDnsRecordData->DS;
                INLINE_HTONS(*(PWORD)&baBufferInStack[nCurrentPosition],pDnsDsData->wKeyTag);
                nCurrentPosition += 2;
                baBufferInStack[nCurrentPosition] = pDnsDsData->chAlgorithm;
                nCurrentPosition++;
                baBufferInStack[nCurrentPosition] = pDnsDsData->chDigestType;
                nCurrentPosition++;
                RtlCopyMemory(
                    &baBufferInStack[nCurrentPosition],
                    pDnsDsData->Digest,
                    pDnsDsData->wDigestLength
                    );
                nCurrentPosition += (int)pDnsDsData->wDigestLength;
            }
            break;
        case DNS_TYPE_TKEY:
            {
                PDNS_TKEY_DATA  pDnsTkeyData = &pDnsRecordData->TKEY;
                PerformDomanName(
                    CString(pDnsTkeyData->pNameAlgorithm),
                    baBufferInStack,
                    pCurrentRR,
                    nCurrentPosition
                    );
                INLINE_HTONL(*(PDWORD)&baBufferInStack[nCurrentPosition],pDnsTkeyData->dwCreateTime);
                nCurrentPosition += 4;
                INLINE_HTONL(*(PDWORD)&baBufferInStack[nCurrentPosition],pDnsTkeyData->dwExpireTime);
                nCurrentPosition += 4;
                INLINE_HTONS(*(PWORD)&baBufferInStack[nCurrentPosition],pDnsTkeyData->wMode);
                nCurrentPosition += 2;
                INLINE_HTONS(*(PWORD)&baBufferInStack[nCurrentPosition],pDnsTkeyData->wError);
                nCurrentPosition += 2;
                INLINE_HTONS(*(PWORD)&baBufferInStack[nCurrentPosition],pDnsTkeyData->wKeyLength);
                nCurrentPosition += 2;
                RtlCopyMemory(
                    &baBufferInStack[nCurrentPosition],
                    pDnsTkeyData->pKey,
                    pDnsTkeyData->wKeyLength
                    );
                nCurrentPosition += (int)pDnsTkeyData->wKeyLength;
                INLINE_HTONS(*(PWORD)&baBufferInStack[nCurrentPosition],pDnsTkeyData->wOtherLength);
                nCurrentPosition += 2;
                RtlCopyMemory(
                    &baBufferInStack[nCurrentPosition],
                    pDnsTkeyData->pOtherData,
                    pDnsTkeyData->wOtherLength
                    );
                nCurrentPosition += (int)pDnsTkeyData->wOtherLength;
            }
            break;
        case DNS_TYPE_TSIG:
            {
                PDNS_TSIG_DATA  pDnsTsigData = &pDnsRecordData->TSIG;
                PerformDomanName(
                    CString(pDnsTsigData->pNameAlgorithm),
                    baBufferInStack,
                    pCurrentRR,
                    nCurrentPosition
                    );
                INLINE_HTONQ(*(PQWORD)&baBufferInStack[nCurrentPosition],pDnsTsigData->i64CreateTime);
                nCurrentPosition += 6;
                INLINE_HTONS(*(PWORD)&baBufferInStack[nCurrentPosition],pDnsTsigData->wFudgeTime);
                nCurrentPosition += 2;
                INLINE_HTONS(*(PWORD)&baBufferInStack[nCurrentPosition],pDnsTsigData->wSigLength);
                nCurrentPosition += 2;
                RtlCopyMemory(
                    &baBufferInStack[nCurrentPosition],
                    pDnsTsigData->pSignature,
                    pDnsTsigData->wSigLength
                    );
                nCurrentPosition += (int)pDnsTsigData->wSigLength;
                INLINE_HTONS(*(PWORD)&baBufferInStack[nCurrentPosition],pDnsTsigData->wOtherLength);
                nCurrentPosition += 2;
                RtlCopyMemory(
                    &baBufferInStack[nCurrentPosition],
                    pDnsTsigData->pOtherData,
                    pDnsTsigData->wOtherLength
                    );
                nCurrentPosition += (int)pDnsTsigData->wOtherLength;
            }
            break;
        case DNS_TYPE_WINS:
            {
                PDNS_WINS_DATA  pDnsWinsData = &pDnsRecordData->WINS;
                DWORD   i;
                INLINE_HTONL(*(PDWORD)&baBufferInStack[nCurrentPosition],pDnsWinsData->dwMappingFlag);
                nCurrentPosition += 4;
                INLINE_HTONL(*(PDWORD)&baBufferInStack[nCurrentPosition],pDnsWinsData->dwLookupTimeout);
                nCurrentPosition += 4;
                INLINE_HTONL(*(PDWORD)&baBufferInStack[nCurrentPosition],pDnsWinsData->dwCacheTimeout);
                nCurrentPosition += 4;
                INLINE_HTONL(*(PDWORD)&baBufferInStack[nCurrentPosition],pDnsWinsData->cWinsServerCount);
                nCurrentPosition += 4;
                for(i=0;i<pDnsWinsData->cWinsServerCount;i++)
                {
                    *(PDWORD)&baBufferInStack[nCurrentPosition] = pDnsWinsData->WinsServers[i];
                    nCurrentPosition += 4;
                }
            }
            break;
        case DNS_TYPE_WINSR:
            {
                PDNS_WINSR_DATA pDnsWinsrData = &pDnsRecordData->WINSR;
                CString sDomainName;
                INLINE_HTONL(*(PDWORD)&baBufferInStack[nCurrentPosition],pDnsWinsrData->dwMappingFlag);
                nCurrentPosition += 4;
                INLINE_HTONL(*(PDWORD)&baBufferInStack[nCurrentPosition],pDnsWinsrData->dwLookupTimeout);
                nCurrentPosition += 4;
                INLINE_HTONL(*(PDWORD)&baBufferInStack[nCurrentPosition],pDnsWinsrData->dwCacheTimeout);
                nCurrentPosition += 4;
                sDomainName = pDnsWinsrData->pNameResultDomain;
                //if(sDomainName == _T("."))
                //{
                //    CString sMsg;
                //    sMsg.Format(
                //        _T("Информация: фрагмент DNS-имени нулевой длины!\n"),
                //        (LPCTSTR)sDomainName
                //        );
                //    LPCTSTR pStrings[] = { (LPCTSTR)sMsg };
                //    theApp.ReportEventInvoke(
                //        EVENTLOG_INFORMATION_TYPE,
                //        MSG_INFORMATIONAL_EVENT_TEXT,
                //        1,
                //        pStrings
                //        );
                //}
                PerformDomanName(
                    sDomainName,
                    baBufferInStack,
                    pCurrentRR,
                    nCurrentPosition
                    );
            }
            break;
        case DNS_TYPE_DHCID:
            {
                PDNS_DHCID_DATA pDnsDhcidData = &pDnsRecordData->DHCID;
                RtlCopyMemory(
                    &baBufferInStack[nCurrentPosition],
                    pDnsDhcidData->DHCID,
                    pDnsDhcidData->dwByteCount
                    );
                nCurrentPosition += (int)pDnsDhcidData->dwByteCount;
            }
            break;
        case DNS_TYPE_LOC:
            {
                PDNS_LOC_DATA   pDnsLocData = &pDnsRecordData->LOC;
                baBufferInStack[nCurrentPosition] = (BYTE)pDnsLocData->wVersion;
                nCurrentPosition++;
                baBufferInStack[nCurrentPosition] = (BYTE)pDnsLocData->wSize;
                nCurrentPosition++;
                baBufferInStack[nCurrentPosition] = (BYTE)pDnsLocData->wHorPrec;
                nCurrentPosition++;
                baBufferInStack[nCurrentPosition] = (BYTE)pDnsLocData->wVerPrec;
                nCurrentPosition++;
                INLINE_HTONL(*(PDWORD)&baBufferInStack[nCurrentPosition],pDnsLocData->dwLatitude);
                nCurrentPosition += 4;
                INLINE_HTONL(*(PDWORD)&baBufferInStack[nCurrentPosition],pDnsLocData->dwLongitude);
                nCurrentPosition += 4;
                INLINE_HTONL(*(PDWORD)&baBufferInStack[nCurrentPosition],pDnsLocData->dwAltitude);
                nCurrentPosition += 4;
            }
            break;
        default:
            RtlCopyMemory(
                &baBufferInStack[nCurrentPosition],
                pDnsRecordData,
                pCurrentRR->m_wDataLength
                );
            nCurrentPosition += (int)pCurrentRR->m_wDataLength;
        }
        wDataLength = (WORD)(nCurrentPosition - nRDataPosition);
        INLINE_HTONS(*pwRDataLength,wDataLength);
        pCurrentRR = pNextRR;
    }
    nResultMessageLength = (UINT32)nCurrentPosition;
    if(nResultMessageLength > nBufferLength)
    {
        nResultMessageLength = nBufferLength;
        pDnsHeader->Truncation = 1;
        TraceEvents(
            TRACE_LEVEL_WARNING,
            TRACE_DNS_MESSAGE_WB,
            "%!FUNC! line:%!LINE! %!LEVEL! (nResultMessageLength = %d > nBufferLength = %d)",
            nResultMessageLength,
            nBufferLength
            );
    }
    DNS_BYTE_FLIP_HEADER_COUNTS(pDnsHeader);
    RtlCopyMemory(
        pMessageBuffer,
        baBufferInStack,
        nResultMessageLength
        );
    return nResultMessageLength;
}


void CDnsMessageWB::DnsReParseResponceMessage(
    DNS_APPROVAL_CONFIG& rApprovalConfig,
    PBYTE pOutputBuffer,
    size_t nOutputBufferLength
    )
{
    CDnsResorceRecord*  pCurrentRR = m_pFirstDnsRRecord;
    CDnsResorceRecord*  pNextRR;
    int     nA4Count = 0;
    int     nA4PrivateCount = 0;
    int     nA6Count = 0;
    int     nA6PrivateCount = 0;
    bool    bPrivateAll = false;
    bool    bModify = false;
    rApprovalConfig; pOutputBuffer; nOutputBufferLength;
    if (NULL == pCurrentRR)
    {
        TraceEvents(
            TRACE_LEVEL_FATAL,
            TRACE_DNS_MESSAGE_WB,
            "%!FUNC! line:%!LINE! %!LEVEL! Exit (NULL == pCurrentRR)"
            );
        return;
    }
    // исключение приватных адресов
    while(NULL != pCurrentRR)
    {
        pNextRR = pCurrentRR->m_pNext;
        if(DNS_TYPE_A == pCurrentRR->m_wType)
        {
            int     i;
            UINT32  nHostAddress = 0;
            bool    bPrivate = false;
            INLINE_NTOHL(
                nHostAddress,
                pCurrentRR->m_pDnsRecordData->A.IpAddress
                );
            nA4Count++;
            if(!bPrivate)
            {
                for(i=0;i<theApp.m_nPrivateIpCount;i++)
                {
                    bPrivate = (nHostAddress == theApp.m_pPrivateIpArray[i]);
                    if(bPrivate)
                    {
                        break;
                    }
                }
            }
            if(!bPrivate)
            {
                for(i=0;i<theApp.m_nPrivateRangeCount;i++)
                {
                    bPrivate = (nHostAddress <= theApp.m_pPrivateRangeArray[i].valueHigh.uint32)
                        && (nHostAddress >= theApp.m_pPrivateRangeArray[i].valueLow.uint32);
                    if(bPrivate)
                    {
                        break;
                    }
                }
            }
            if(!bPrivate)
            {
                for(i=0;i<theApp.m_nPrivateSubnetCount;i++)
                {
                    bPrivate = ((nHostAddress & theApp.m_pPrivateSubnetArray[i].mask)
                        == theApp.m_pPrivateSubnetArray[i].addr);
                    if(bPrivate)
                    {
                        break;
                    }
                }
            }
            if(bPrivate)
            {
                nA4PrivateCount++;
                RemoveRRAt(pCurrentRR);
                delete pCurrentRR;
                bModify = true;
            }
        }
        else
        if(DNS_TYPE_AAAA == pCurrentRR->m_wType)
        {
            IN6_ADDR    stIPv6Address;
            BOOLEAN     bPrivate = FALSE;
            int         i;
            IPv6CopyAddress(
                &stIPv6Address,
                &pCurrentRR->m_pDnsRecordData->AAAA.Ip6Address
                );
            nA6Count++;
            bPrivate = !bfIPv6AddressInIPv6Subnet(
                &stIPv6Address,
                c_pGlobalIPv6Subnet
                );
            if (!bPrivate)
            {
                for (i = 0; i<theApp.m_nPrivateIPV6AddrCount; i++)
                {
                    bPrivate = bfIPv6AddressInIPv6Subnet(
                        &stIPv6Address,
                        &theApp.m_pPrivateIPV6AddrArray[i]
                        );
                    if (bPrivate)
                    {
                        break;
                    }
                }
            }
            if (bPrivate)
            {
                BOOLEAN bPublic = FALSE;
                for (i = 0; i < theApp.m_nPublicIPV6AddrCount; i++)
                {
                    bPublic = bfIPv6AddressInIPv6Subnet(
                        &stIPv6Address,
                        &theApp.m_pPublicIPV6AddrArray[i]
                        );
                    if (bPublic)
                    {
                        break;
                    }
                }
                if (!bPublic)
                {
                    nA6PrivateCount++;
                    RemoveRRAt(pCurrentRR);
                    delete pCurrentRR;
                    bModify = true;
                }
            }
        }
        pCurrentRR = pNextRR;
    }
    if(bModify)
    {
        UINT32  nNewBufferLength;
        rApprovalConfig.m_bDataModify = TRUE;
        bPrivateAll = IsPrivate(
            nA4Count,
            nA4PrivateCount,
            nA6Count,
            nA6PrivateCount
            );
        if(bPrivateAll)
        {
            while(NULL != m_pLastDnsRRecord)
            {
                pCurrentRR = RemoveFromTail();
                delete pCurrentRR;
            }
            AddRRToTail(new CDnsResorceRecord(*theApp.m_pDnsZoneRecord));
            m_stDnsHeader.ResponseCode = DNS_RCODE_NXDOMAIN;
        }
        nNewBufferLength = PerformDnsMessageBuffer(
            pOutputBuffer,
            (UINT32) nOutputBufferLength
            );
        if(nNewBufferLength > (UINT32)nOutputBufferLength)
        {
            rApprovalConfig.m_nDataSize = (UINT32)nOutputBufferLength;
        }
        else
        {
            rApprovalConfig.m_nDataSize = nNewBufferLength;
        }
    }
}


bool CDnsMessageWB::DnsQueryParse(
    PDNS_MESSAGE_BUFFER pDnsBuffer,
    WORD wMessageLength,
    DNS_APPROVAL_CONFIG& rApprovalConfig,
    PBYTE pOutputBuffer,
    size_t nOutputBufferLength
    )
{
    PCHAR               pCurrentBuffer;
    BOOL                bRet;
    DWORD               dwBufferSize;
    BYTE                baInStackBuffer[4096];
    m_pParsedMessage = (PCHAR) pDnsBuffer;
    m_nParsedMessageLength = (int)wMessageLength;
    RtlCopyMemory(
        &m_stDnsHeader,
        pDnsBuffer,
        sizeof(DNS_HEADER)
        );
    DNS_BYTE_FLIP_HEADER_COUNTS(&m_stDnsHeader);
    //DumpDnsHeader();
    switch (m_stDnsHeader.Opcode)
    {
    case DNS_OPCODE_QUERY:
        break;
    case DNS_OPCODE_IQUERY:
        break;
    case DNS_OPCODE_NOTIFY:
        //TraceEvents(
        //    TRACE_LEVEL_INFORMATION,
        //    TRACE_DNS_MESSAGE_WB,
        //    "%!FUNC! line:%!LINE! %!LEVEL! This is NOTIFY Query."
        //    );
        break;
    default:
        m_pSavedQueryMessage = (DNS_MESSAGE_BUFFER *) new BYTE[m_nParsedMessageLength];
        RtlCopyMemory(
            m_pSavedQueryMessage,
            pDnsBuffer,
            m_nParsedMessageLength
            );
        dwBufferSize = sizeof(baInStackBuffer);
        bRet = DnsWriteQuestionToBuffer_W(
            (PDNS_MESSAGE_BUFFER)baInStackBuffer,
            &dwBufferSize,
            theApp.m_sDnsZoneName,
            DNS_TYPE_SOA,
            m_stDnsHeader.Xid,
            TRUE
            );
        if (dwBufferSize > (DWORD) nOutputBufferLength)
        {
            TraceEvents(
                TRACE_LEVEL_ERROR,
                TRACE_DNS_MESSAGE_WB,
                "%!FUNC! line:%!LINE! %!LEVEL! dwBufferSize (%u) > nOutputBufferLength (%u)",
                dwBufferSize,
                DWORD(nOutputBufferLength)
                );
            throw int(3);
        }
        rApprovalConfig.m_bDataModify = TRUE;
        rApprovalConfig.m_nDataSize = dwBufferSize;
        RtlCopyMemory(
            pOutputBuffer,
            baInStackBuffer,
            dwBufferSize
            );
        TraceEvents(
            TRACE_LEVEL_WARNING,
            TRACE_DNS_MESSAGE_WB,
            "%!FUNC! line:%!LINE! %!LEVEL! Exit ((Opcode = %u) != DNS_OPCODE_QUERY)",
            m_stDnsHeader.Opcode
            );
        return false;
    }
    pCurrentBuffer = (PCHAR) pDnsBuffer->MessageBody;
    try
    {
        ParseQuestionSection(
            pCurrentBuffer,
            wMessageLength
            );
    }
    catch (int nError)
    {
        TraceEvents(
            TRACE_LEVEL_ERROR,
            TRACE_DNS_MESSAGE_WB,
            "%!FUNC! line:%!LINE! %!LEVEL! Exception on \"ParseQuestionSection\". nError = %d;",
            nError
            );
        throw int(1);
    }
    switch (m_stDnsQuestionRecord.stDnsWireQuestion.QuestionType)
    {
    case DNS_TYPE_IXFR:
    case DNS_TYPE_WINS:
    case DNS_TYPE_WINSR:
        dwBufferSize = sizeof(baInStackBuffer);
        bRet = DnsWriteQuestionToBuffer_W(
            (PDNS_MESSAGE_BUFFER)baInStackBuffer,
            &dwBufferSize,
            theApp.m_sDnsZoneName,
            DNS_TYPE_SOA,
            m_stDnsHeader.Xid,
            TRUE
            );
        if (dwBufferSize > (DWORD) nOutputBufferLength)
        {
            TraceEvents(
                TRACE_LEVEL_ERROR,
                TRACE_DNS_MESSAGE_WB,
                "%!FUNC! line:%!LINE! %!LEVEL! dwBufferSize (%u) > nOutputBufferLength (%u)",
                dwBufferSize,
                DWORD(nOutputBufferLength)
                );
            throw int(2);
        }
        rApprovalConfig.m_bDataModify = TRUE;
        rApprovalConfig.m_nDataSize = dwBufferSize;
        RtlCopyMemory(
            pOutputBuffer,
            baInStackBuffer,
            dwBufferSize
            );
        break;
    }
    return true;
}


void CDnsMessageWB::ParseQuestionSection(
    PCHAR &rCurrentBuffer,
    WORD wBufferLengt
    )
{
    WORD    wCurrentPos = 0;
    BYTE    bLabelLength, i;
    wchar_t szUnicodeString[256];
    char    szMultibyteString[256], *pC;
    int     nOutChars;
    PCHAR   pQuestionSectionData = rCurrentBuffer;
    CString sQuestionName;
    m_stDnsQuestionRecord.ClearName();
    while(0 != pQuestionSectionData[wCurrentPos])
    {
        bLabelLength = pQuestionSectionData[wCurrentPos];
        pC = (char*)&pQuestionSectionData[wCurrentPos+1];
        for(i=0;i<bLabelLength;i++)
        {
            szMultibyteString[i] = *pC;
            pC++;
        }
        nOutChars = MultiByteToWideChar(
            CP_UTF8,
            0,
            szMultibyteString,
            (int)bLabelLength,
            szUnicodeString,
            256
            );
        if (nOutChars < 1)
        {
            TraceEvents(
                TRACE_LEVEL_ERROR,
                TRACE_DNS_MESSAGE_WB,
                "%!FUNC! line:%!LINE! %!LEVEL! Illegal string length = %d.",
                nOutChars
                );
            throw int(1);
        }
        szUnicodeString[nOutChars] = 0;
        sQuestionName += szUnicodeString;
        sQuestionName += _T('.');
        wCurrentPos += (WORD)bLabelLength + 1;
        if (wCurrentPos >= wBufferLengt)
        {
            TraceEvents(
                TRACE_LEVEL_ERROR,
                TRACE_DNS_MESSAGE_WB,
                "%!FUNC! line:%!LINE! %!LEVEL! wCurrentPos (%hu) >= wBufferLengt (%hu).",
                wCurrentPos,
                wBufferLengt
                );
            throw int(2);
        }
    }
    m_stDnsQuestionRecord.SetQNAME(sQuestionName);
    wCurrentPos++;
    if (wCurrentPos >= wBufferLengt)
    {
        TraceEvents(
            TRACE_LEVEL_ERROR,
            TRACE_DNS_MESSAGE_WB,
            "%!FUNC! line:%!LINE! %!LEVEL! wCurrentPos (%hu) >= wBufferLengt (%hu).",
            wCurrentPos,
            wBufferLengt
            );
        throw int(3);
    }
    INLINE_WORD_FLIP(m_stDnsQuestionRecord.stDnsWireQuestion.QuestionType, *((PWORD) &pQuestionSectionData[wCurrentPos]));
    wCurrentPos += 2;
    if (wCurrentPos >= wBufferLengt)
    {
        TraceEvents(
            TRACE_LEVEL_ERROR,
            TRACE_DNS_MESSAGE_WB,
            "%!FUNC! line:%!LINE! %!LEVEL! wCurrentPos (%hu) >= wBufferLengt (%hu).",
            wCurrentPos,
            wBufferLengt
            );
        throw int(4);
    }
    INLINE_WORD_FLIP(m_stDnsQuestionRecord.stDnsWireQuestion.QuestionClass, *((PWORD) &pQuestionSectionData[wCurrentPos]));
    wCurrentPos += 2;
    if (wCurrentPos > wBufferLengt)
    {
        TraceEvents(
            TRACE_LEVEL_ERROR,
            TRACE_DNS_MESSAGE_WB,
            "%!FUNC! line:%!LINE! %!LEVEL! wCurrentPos (%hu) > wBufferLengt (%hu).",
            wCurrentPos,
            wBufferLengt
            );
        throw int(5);
    }
    rCurrentBuffer += wCurrentPos;
    m_sDnsQuestionTypeName = GetRRTypeName(m_stDnsQuestionRecord.stDnsWireQuestion.QuestionType);
    //TraceEvents(
    //    TRACE_LEVEL_INFORMATION,
    //    TRACE_DNS_RECORD_DUMP,
    //    "%!FUNC! DnsQuestionRecord:"
    //    );
    //TraceEvents(
    //    TRACE_LEVEL_INFORMATION,
    //    TRACE_DNS_RECORD_DUMP,
    //    "%!FUNC!     sQNAME = \"%ws\"",
    //    m_stDnsQuestionRecord.sQNAME
    //    );
    //TraceEvents(
    //    TRACE_LEVEL_INFORMATION,
    //    TRACE_DNS_RECORD_DUMP,
    //    "%!FUNC!     QuestionType = %ws",
    //    (LPCTSTR) m_sDnsQuestionTypeName
    //    );
}


void CDnsMessageWB::PerformDomanName(
    CString sDomainName,
    PBYTE pMessageBuffer,
    CDnsResorceRecord* pCurrentRR,
    int& rCurrentMessagePosition
    )
{
    CString sAuxString = sDomainName;
    while (sAuxString.GetLength() > 0)
    {
        int     nNamePosition;
        int     nPos1;
        int     nConvertedChars;
        nNamePosition = FindDomanName(
            sAuxString,
            pMessageBuffer,
            pCurrentRR,
            rCurrentMessagePosition
            );
        if(nNamePosition > 0)
        {
            PWORD   pwNamePosition = (PWORD)&pMessageBuffer[rCurrentMessagePosition];
            *pwNamePosition = (WORD)nNamePosition | 0xC000;
            INLINE_HTONS(*pwNamePosition,*pwNamePosition);
            rCurrentMessagePosition += 2;
            return;
        }
        nPos1 = sAuxString.Find(_T('.'));
        if(nPos1 > 0)
        {
            nConvertedChars = WideCharToMultiByte(
                CP_UTF8,
                0,
                (LPCWSTR)sAuxString,
                nPos1,
                (LPSTR)&pMessageBuffer[rCurrentMessagePosition + 1],
                64,
                NULL,
                NULL
                );
            pMessageBuffer[rCurrentMessagePosition] = (BYTE)nConvertedChars;
            rCurrentMessagePosition += nConvertedChars + 1;
        }
        else if(nPos1 < 0)
        {
            TraceEvents(
                TRACE_LEVEL_WARNING,
                TRACE_DNS_MESSAGE_WB,
                "%!FUNC! line:%!LINE! %!LEVEL! The final point of the portion of the DNS name not found. Point position = %d;",
                nPos1
                );
            break;
        }
        else
        {
            pMessageBuffer[rCurrentMessagePosition] = (BYTE)0;
            rCurrentMessagePosition += 1;
			return;
        }
        sAuxString = sAuxString.Mid(nPos1 + 1);
    }
    pMessageBuffer[rCurrentMessagePosition] = 0;
    rCurrentMessagePosition++;
}


int CDnsMessageWB::FindDomanName(
    CString sDomainName,
    PBYTE pMessageBuffer,
    CDnsResorceRecord* pCurrentRR,
    int nCurrentMessagePosition
    )
{
    int     nFindedPosition = -1;
    CString sFindedName = sDomainName.MakeLower();
    CString sComparedName = CString(m_stDnsQuestionRecord.sQNAME).MakeLower();
    int     nPos1, nPos2;
    CDnsResorceRecord*  pFindingRR = m_pFirstDnsRRecord;
    CDnsResorceRecord*  pNextRR;
	BYTE	bCurrentLen;
	WORD	wCurrentRef;
    if (sComparedName == sFindedName)
    {
        return (int)sizeof(DNS_HEADER);
    }
    nPos1 = sComparedName.Find(sFindedName);
    if((nPos1 > 0)
        && (sComparedName.Mid(nPos1) == sFindedName)
        && (sComparedName[nPos1 - 1] == _T('.'))
        )
    {
        nFindedPosition = (int)sizeof(DNS_HEADER);
        do
        {
			bCurrentLen = pMessageBuffer[nFindedPosition];
			while((bCurrentLen & 0xc0) != 0)
			{
				wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
				INLINE_NTOHS(wCurrentRef, wCurrentRef);
				wCurrentRef &= 0xC000;
                nFindedPosition = (int)wCurrentRef;
                bCurrentLen = pMessageBuffer[nFindedPosition];
			}
            nPos2 = sComparedName.Find(_T('.'));
            if(0 >= nPos2)
            {
                TraceEvents(
                    TRACE_LEVEL_WARNING,
                    TRACE_DNS_MESSAGE_WB,
                    "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                    );
                return -1;
            }
            nFindedPosition += (int)bCurrentLen + 1;
            sComparedName = sComparedName.Mid(nPos2 + 1);
            if(0 == sComparedName.GetLength())
            {
                TraceEvents(
                    TRACE_LEVEL_WARNING,
                    TRACE_DNS_MESSAGE_WB,
                    "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                    );
                return -1;
            }
            if(sComparedName == sFindedName)
            {
                return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
            }
        }
        while(true);
    }
    while(pFindingRR != pCurrentRR)
    {
        pNextRR = pFindingRR->m_pNext;
        sComparedName = pFindingRR->m_sName.MakeLower();
        if(sComparedName == sFindedName)
        {
            nFindedPosition = pFindingRR->m_nStartPositionIndex;
            return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
        }
        nPos1 = sComparedName.Find(sFindedName);
        if((nPos1 > 0)
            && (sComparedName.Mid(nPos1) == sFindedName)
            && (sComparedName[nPos1 - 1] == _T('.'))
            )
        {
            nFindedPosition = pFindingRR->m_nStartPositionIndex;
            do
            {
				bCurrentLen = pMessageBuffer[nFindedPosition];
				while((bCurrentLen & 0xc0) != 0)
				{
					wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
					INLINE_NTOHS(wCurrentRef, wCurrentRef);
					wCurrentRef &= 0xC000;
                    nFindedPosition = (int)wCurrentRef;
                    bCurrentLen = pMessageBuffer[nFindedPosition];
				}
                nPos2 = sComparedName.Find(_T('.'));
                if(0 >= nPos2)
                {
                    TraceEvents(
                        TRACE_LEVEL_WARNING,
                        TRACE_DNS_MESSAGE_WB,
                        "%!FUNC! line:%!LINE! %!LEVEL! Exit (sComparedName == sFindedName)"
                        );
                    return -1;
                }
                nFindedPosition += (int)bCurrentLen + 1;
                sComparedName = sComparedName.Mid(nPos2 + 1);
                if(0 == sComparedName.GetLength())
                {
                    TraceEvents(
                        TRACE_LEVEL_WARNING,
                        TRACE_DNS_MESSAGE_WB,
                        "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                        );
                    return -1;
                }
                if(sComparedName == sFindedName)
                {
                    return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                }
            }
            while(true);
        }
        nFindedPosition = pFindingRR->m_nStartPositionIndex;
        sComparedName = pFindingRR->m_sName.MakeLower();
        do
        {
            if((pMessageBuffer[nFindedPosition] & 0xC0) != 0)
            {
                nFindedPosition += 2;
                break;
            }
            if(pMessageBuffer[nFindedPosition] == 0)
            {
                nFindedPosition++;
                break;
            }
            nPos2 = sComparedName.Find(_T('.'));
            nFindedPosition += (int)pMessageBuffer[nFindedPosition] + 1;
            sComparedName = sComparedName.Mid(nPos2 + 1);
        }
        while(true);
        nFindedPosition += 10;
        switch(pFindingRR->m_wType)
        {
        case DNS_TYPE_SOA:
            {
                PDNS_SOA_DATA   pSoaData = &pFindingRR->m_pDnsRecordData->SOA;
                sComparedName = pSoaData->pNamePrimaryServer;
                sComparedName = sComparedName.MakeLower();
                if(sComparedName == sFindedName)
                {
                    return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                }
                nPos1 = sComparedName.Find(sFindedName);
                if((nPos1 > 0)
                    && (sComparedName.Mid(nPos1) == sFindedName)
                    && (sComparedName[nPos1 - 1] == _T('.'))
                    )
                {
                    do
                    {
				        bCurrentLen = pMessageBuffer[nFindedPosition];
				        while((bCurrentLen & 0xc0) != 0)
				        {
					        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
					        INLINE_NTOHS(wCurrentRef, wCurrentRef);
					        wCurrentRef &= 0xC000;
                            nFindedPosition = (int)wCurrentRef;
                            bCurrentLen = pMessageBuffer[nFindedPosition];
				        }
                        nPos2 = sComparedName.Find(_T('.'));
                        if(0 >= nPos2)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (sComparedName == sFindedName)"
                                );
                            return -1;
                        }
                        nFindedPosition += (int)bCurrentLen + 1;
                        sComparedName = sComparedName.Mid(nPos2 + 1);
                        if(0 == sComparedName.GetLength())
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                                );
                            return -1;
                        }
                        if(sComparedName == sFindedName)
                        {
                            return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                        }
                    }
                    while(true);
                }
                do
                {
                    if((pMessageBuffer[nFindedPosition] & 0xC0) != 0)
                    {
                        nFindedPosition += 2;
                        break;
                    }
                    if(pMessageBuffer[nFindedPosition] == 0)
                    {
                        nFindedPosition++;
                        break;
                    }
                    nPos2 = sComparedName.Find(_T('.'));
                    nFindedPosition += (int)pMessageBuffer[nFindedPosition] + 1;
                    sComparedName = sComparedName.Mid(nPos2 + 1);
                }
                while(true);
                sComparedName = pSoaData->pNameAdministrator;
                sComparedName = sComparedName.MakeLower();
                if(sComparedName == sFindedName)
                {
                    return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                }
                nPos1 = sComparedName.Find(sFindedName);
                if((nPos1 > 0)
                    && (sComparedName.Mid(nPos1) == sFindedName)
                    && (sComparedName[nPos1 - 1] == _T('.'))
                    )
                {
                    do
                    {
				        bCurrentLen = pMessageBuffer[nFindedPosition];
				        while((bCurrentLen & 0xc0) != 0)
				        {
					        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
					        INLINE_NTOHS(wCurrentRef, wCurrentRef);
					        wCurrentRef &= 0xC000;
                            nFindedPosition = (int)wCurrentRef;
                            bCurrentLen = pMessageBuffer[nFindedPosition];
				        }
                        nPos2 = sComparedName.Find(_T('.'));
                        if(0 >= nPos2)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                                );
                            return -1;
                        }
                        nFindedPosition += (int)bCurrentLen + 1;
                        sComparedName = sComparedName.Mid(nPos2 + 1);
                        if(0 == sComparedName.GetLength())
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                                );
                            return -1;
                        }
                        if(sComparedName == sFindedName)
                        {
                            return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                        }
                    }
                    while(true);
                }
            }
            break;
        case DNS_TYPE_PTR:
        case DNS_TYPE_NS:
        case DNS_TYPE_MD:
        case DNS_TYPE_MF:
        case DNS_TYPE_CNAME:
        case DNS_TYPE_MB:
        case DNS_TYPE_MG:
        case DNS_TYPE_MR:
        case DNS_TYPE_DNAME:
            {
                PDNS_PTR_DATA   pDnsPtrData = &pFindingRR->m_pDnsRecordData->PTR;
                sComparedName = pDnsPtrData->pNameHost;
                sComparedName = sComparedName.MakeLower();
                if(sComparedName == sFindedName)
                {
                    return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                }
                nPos1 = sComparedName.Find(sFindedName);
                if((nPos1 > 0)
                    && (sComparedName.Mid(nPos1) == sFindedName)
                    && (sComparedName[nPos1 - 1] == _T('.'))
                    )
                {
                    do
                    {
				        bCurrentLen = pMessageBuffer[nFindedPosition];
				        while((bCurrentLen & 0xc0) != 0)
				        {
					        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
					        INLINE_NTOHS(wCurrentRef, wCurrentRef);
					        wCurrentRef &= 0xC000;
                            nFindedPosition = (int)wCurrentRef;
                            bCurrentLen = pMessageBuffer[nFindedPosition];
				        }
                        nPos2 = sComparedName.Find(_T('.'));
                        if(0 >= nPos2)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                                );
                            return -1;
                        }
                        nFindedPosition += (int)bCurrentLen + 1;
                        sComparedName = sComparedName.Mid(nPos2 + 1);
                        if(0 == sComparedName.GetLength())
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                                );
                            return -1;
                        }
                        if(sComparedName == sFindedName)
                        {
                            return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                        }
                    }
                    while(true);
                }
            }
            break;
        case DNS_TYPE_MINFO:
        case DNS_TYPE_RP:
            {
                PDNS_MINFO_DATA pDnsMinfoData = &pFindingRR->m_pDnsRecordData->MINFO;
                sComparedName = pDnsMinfoData->pNameMailbox;
                sComparedName = sComparedName.MakeLower();
                if(sComparedName == sFindedName)
                {
                    return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                }
                nPos1 = sComparedName.Find(sFindedName);
                if((nPos1 > 0)
                    && (sComparedName.Mid(nPos1) == sFindedName)
                    && (sComparedName[nPos1 - 1] == _T('.'))
                    )
                {
                    do
                    {
				        bCurrentLen = pMessageBuffer[nFindedPosition];
				        while((bCurrentLen & 0xc0) != 0)
				        {
					        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
					        INLINE_NTOHS(wCurrentRef, wCurrentRef);
					        wCurrentRef &= 0xC000;
                            nFindedPosition = (int)wCurrentRef;
                            bCurrentLen = pMessageBuffer[nFindedPosition];
				        }
                        nPos2 = sComparedName.Find(_T('.'));
                        if(0 >= nPos2)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                                );
                            return -1;
                        }
                        nFindedPosition += (int)bCurrentLen + 1;
                        sComparedName = sComparedName.Mid(nPos2 + 1);
                        if(0 == sComparedName.GetLength())
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                                );
                            return -1;
                        }
                        if(sComparedName == sFindedName)
                        {
                            return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                        }
                    }
                    while(true);
                }
                do
                {
                    if((pMessageBuffer[nFindedPosition] & 0xC0) != 0)
                    {
                        nFindedPosition += 2;
                        break;
                    }
                    if(pMessageBuffer[nFindedPosition] == 0)
                    {
                        nFindedPosition++;
                        break;
                    }
                    nPos2 = sComparedName.Find(_T('.'));
                    nFindedPosition += (int)pMessageBuffer[nFindedPosition] + 1;
                    sComparedName = sComparedName.Mid(nPos2 + 1);
                }
                while(true);
                sComparedName = pDnsMinfoData->pNameErrorsMailbox;
                sComparedName = sComparedName.MakeLower();
                if(sComparedName == sFindedName)
                {
                    return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                }
                nPos1 = sComparedName.Find(sFindedName);
                if((nPos1 > 0)
                    && (sComparedName.Mid(nPos1) == sFindedName)
                    && (sComparedName[nPos1 - 1] == _T('.'))
                    )
                {
                    do
                    {
				        bCurrentLen = pMessageBuffer[nFindedPosition];
				        while((bCurrentLen & 0xc0) != 0)
				        {
					        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
					        INLINE_NTOHS(wCurrentRef, wCurrentRef);
					        wCurrentRef &= 0xC000;
                            nFindedPosition = (int)wCurrentRef;
                            bCurrentLen = pMessageBuffer[nFindedPosition];
				        }
                        nPos2 = sComparedName.Find(_T('.'));
                        if(0 >= nPos2)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                                );
                            return -1;
                        }
                        nFindedPosition += (int)bCurrentLen + 1;
                        sComparedName = sComparedName.Mid(nPos2 + 1);
                        if(0 == sComparedName.GetLength())
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                                );
                            return -1;
                        }
                        if(sComparedName == sFindedName)
                        {
                            return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                        }
                    }
                    while(true);
                }
            }
            break;
        case DNS_TYPE_MX:
        case DNS_TYPE_AFSDB:
        case DNS_TYPE_RT:
            {
                PDNS_MX_DATA pDnsMxData = &pFindingRR->m_pDnsRecordData->MX;
                nFindedPosition += 2;
                sComparedName = pDnsMxData->pNameExchange;
                sComparedName = sComparedName.MakeLower();
                if(sComparedName == sFindedName)
                {
                    return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                }
                nPos1 = sComparedName.Find(sFindedName);
                if((nPos1 > 0)
                    && (sComparedName.Mid(nPos1) == sFindedName)
                    && (sComparedName[nPos1 - 1] == _T('.'))
                    )
                {
                    do
                    {
				        bCurrentLen = pMessageBuffer[nFindedPosition];
				        while((bCurrentLen & 0xc0) != 0)
				        {
					        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
					        INLINE_NTOHS(wCurrentRef, wCurrentRef);
					        wCurrentRef &= 0xC000;
                            nFindedPosition = (int)wCurrentRef;
                            bCurrentLen = pMessageBuffer[nFindedPosition];
				        }
                        nPos2 = sComparedName.Find(_T('.'));
                        if(0 >= nPos2)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                                );
                            return -1;
                        }
                        nFindedPosition += (int)bCurrentLen + 1;
                        sComparedName = sComparedName.Mid(nPos2 + 1);
                        if(0 == sComparedName.GetLength())
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                                );
                            return -1;
                        }
                        if(sComparedName == sFindedName)
                        {
                            return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                        }
                    }
                    while(true);
                }
            }
            break;
        case DNS_TYPE_SIG:
        case DNS_TYPE_RRSIG:
            {
                PDNS_SIG_DATA   pDnsSigData = &pFindingRR->m_pDnsRecordData->SIG;
                nFindedPosition += 18;
                sComparedName = pDnsSigData->pNameSigner;
                sComparedName = sComparedName.MakeLower();
                if(sComparedName == sFindedName)
                {
                    return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                }
                nPos1 = sComparedName.Find(sFindedName);
                if((nPos1 > 0)
                    && (sComparedName.Mid(nPos1) == sFindedName)
                    && (sComparedName[nPos1 - 1] == _T('.'))
                    )
                {
                    do
                    {
				        bCurrentLen = pMessageBuffer[nFindedPosition];
				        while((bCurrentLen & 0xc0) != 0)
				        {
					        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
					        INLINE_NTOHS(wCurrentRef, wCurrentRef);
					        wCurrentRef &= 0xC000;
                            nFindedPosition = (int)wCurrentRef;
                            bCurrentLen = pMessageBuffer[nFindedPosition];
				        }
                        nPos2 = sComparedName.Find(_T('.'));
                        if(0 >= nPos2)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                                );
                            return -1;
                        }
                        nFindedPosition += (int)bCurrentLen + 1;
                        sComparedName = sComparedName.Mid(nPos2 + 1);
                        if(0 == sComparedName.GetLength())
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                                );
                            return -1;
                        }
                        if(sComparedName == sFindedName)
                        {
                            return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                        }
                    }
                    while(true);
                }
            }
            break;
        case DNS_TYPE_NXT:
        case DNS_TYPE_NSEC:
            {
                PDNS_NSEC_DATA  pDnsNsecData = &pFindingRR->m_pDnsRecordData->NSEC;
                sComparedName = pDnsNsecData->pNextDomainName;
                sComparedName = sComparedName.MakeLower();
                if(sComparedName == sFindedName)
                {
                    return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                }
                nPos1 = sComparedName.Find(sFindedName);
                if((nPos1 > 0)
                    && (sComparedName.Mid(nPos1) == sFindedName)
                    && (sComparedName[nPos1 - 1] == _T('.'))
                    )
                {
                    do
                    {
				        bCurrentLen = pMessageBuffer[nFindedPosition];
				        while((bCurrentLen & 0xc0) != 0)
				        {
					        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
					        INLINE_NTOHS(wCurrentRef, wCurrentRef);
					        wCurrentRef &= 0xC000;
                            nFindedPosition = (int)wCurrentRef;
                            bCurrentLen = pMessageBuffer[nFindedPosition];
				        }
                        nPos2 = sComparedName.Find(_T('.'));
                        if(0 >= nPos2)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                                );
                            return -1;
                        }
                        nFindedPosition += (int)bCurrentLen + 1;
                        sComparedName = sComparedName.Mid(nPos2 + 1);
                        if(0 == sComparedName.GetLength())
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                                );
                            return -1;
                        }
                        if(sComparedName == sFindedName)
                        {
                            return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                        }
                    }
                    while(true);
                }
            }
            break;
        case DNS_TYPE_SRV:
            {
                PDNS_SRV_DATA   pDnsSrvData = &pFindingRR->m_pDnsRecordData->SRV;
                nFindedPosition += 6;
                sComparedName = pDnsSrvData->pNameTarget;
                sComparedName = sComparedName.MakeLower();
                if(sComparedName == sFindedName)
                {
                    return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                }
                nPos1 = sComparedName.Find(sFindedName);
                if((nPos1 > 0)
                    && (sComparedName.Mid(nPos1) == sFindedName)
                    && (sComparedName[nPos1 - 1] == _T('.'))
                    )
                {
                    do
                    {
				        bCurrentLen = pMessageBuffer[nFindedPosition];
				        while((bCurrentLen & 0xc0) != 0)
				        {
					        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
					        INLINE_NTOHS(wCurrentRef, wCurrentRef);
					        wCurrentRef &= 0xC000;
                            nFindedPosition = (int)wCurrentRef;
                            bCurrentLen = pMessageBuffer[nFindedPosition];
				        }
                        nPos2 = sComparedName.Find(_T('.'));
                        if(0 >= nPos2)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                                );
                            return -1;
                        }
                        nFindedPosition += (int)bCurrentLen + 1;
                        sComparedName = sComparedName.Mid(nPos2 + 1);
                        if(0 == sComparedName.GetLength())
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                                );
                            return -1;
                        }
                        if(sComparedName == sFindedName)
                        {
                            return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                        }
                    }
                    while(true);
                }
            }
            break;
        case DNS_TYPE_NAPTR:
            {
                PDNS_NAPTR_DATA pDnsNaptrData = &pFindingRR->m_pDnsRecordData->NAPTR;
                nFindedPosition += 4;
                nFindedPosition += (int)pMessageBuffer[nFindedPosition] + 1;
                nFindedPosition += (int)pMessageBuffer[nFindedPosition] + 1;
                nFindedPosition += (int)pMessageBuffer[nFindedPosition] + 1;
                sComparedName = pDnsNaptrData->pReplacement;
                sComparedName = sComparedName.MakeLower();
                if(sComparedName == sFindedName)
                {
                    return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                }
                nPos1 = sComparedName.Find(sFindedName);
                if((nPos1 > 0)
                    && (sComparedName.Mid(nPos1) == sFindedName)
                    && (sComparedName[nPos1 - 1] == _T('.'))
                    )
                {
                    do
                    {
				        bCurrentLen = pMessageBuffer[nFindedPosition];
				        while((bCurrentLen & 0xc0) != 0)
				        {
					        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
					        INLINE_NTOHS(wCurrentRef, wCurrentRef);
					        wCurrentRef &= 0xC000;
                            nFindedPosition = (int)wCurrentRef;
                            bCurrentLen = pMessageBuffer[nFindedPosition];
				        }
                        nPos2 = sComparedName.Find(_T('.'));
                        if(0 >= nPos2)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                                );
                            return -1;
                        }
                        nFindedPosition += (int)bCurrentLen + 1;
                        sComparedName = sComparedName.Mid(nPos2 + 1);
                        if(0 == sComparedName.GetLength())
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                                );
                            return -1;
                        }
                        if(sComparedName == sFindedName)
                        {
                            return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                        }
                    }
                    while(true);
                }
            }
            break;
        case DNS_TYPE_TKEY:
            {
                PDNS_TKEY_DATA  pDnsTkeyData = &pFindingRR->m_pDnsRecordData->TKEY;
                sComparedName = pDnsTkeyData->pNameAlgorithm;
                sComparedName = sComparedName.MakeLower();
                if(sComparedName == sFindedName)
                {
                    return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                }
                nPos1 = sComparedName.Find(sFindedName);
                if((nPos1 > 0)
                    && (sComparedName.Mid(nPos1) == sFindedName)
                    && (sComparedName[nPos1 - 1] == _T('.'))
                    )
                {
                    do
                    {
				        bCurrentLen = pMessageBuffer[nFindedPosition];
				        while((bCurrentLen & 0xc0) != 0)
				        {
					        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
					        INLINE_NTOHS(wCurrentRef, wCurrentRef);
					        wCurrentRef &= 0xC000;
                            nFindedPosition = (int)wCurrentRef;
                            bCurrentLen = pMessageBuffer[nFindedPosition];
				        }
                        nPos2 = sComparedName.Find(_T('.'));
                        if(0 >= nPos2)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                                );
                            return -1;
                        }
                        nFindedPosition += (int)bCurrentLen + 1;
                        sComparedName = sComparedName.Mid(nPos2 + 1);
                        if(0 == sComparedName.GetLength())
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                                );
                            return -1;
                        }
                        if(sComparedName == sFindedName)
                        {
                            return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                        }
                    }
                    while(true);
                }
            }
            break;
        case DNS_TYPE_TSIG:
            {
                PDNS_TSIG_DATA  pDnsTsigData = &pFindingRR->m_pDnsRecordData->TSIG;
                sComparedName = pDnsTsigData->pNameAlgorithm;
                sComparedName = sComparedName.MakeLower();
                if(sComparedName == sFindedName)
                {
                    return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                }
                nPos1 = sComparedName.Find(sFindedName);
                if((nPos1 > 0)
                    && (sComparedName.Mid(nPos1) == sFindedName)
                    && (sComparedName[nPos1 - 1] == _T('.'))
                    )
                {
                    do
                    {
				        bCurrentLen = pMessageBuffer[nFindedPosition];
				        while((bCurrentLen & 0xc0) != 0)
				        {
					        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
					        INLINE_NTOHS(wCurrentRef, wCurrentRef);
					        wCurrentRef &= 0xC000;
                            nFindedPosition = (int)wCurrentRef;
                            bCurrentLen = pMessageBuffer[nFindedPosition];
				        }
                        nPos2 = sComparedName.Find(_T('.'));
                        if(0 >= nPos2)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                                );
                            return -1;
                        }
                        nFindedPosition += (int)bCurrentLen + 1;
                        sComparedName = sComparedName.Mid(nPos2 + 1);
                        if(0 == sComparedName.GetLength())
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                                );
                            return -1;
                        }
                        if(sComparedName == sFindedName)
                        {
                            return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                        }
                    }
                    while(true);
                }
            }
            break;
        case DNS_TYPE_WINSR:
            {
                PDNS_WINSR_DATA pDnsWinsrData = &pFindingRR->m_pDnsRecordData->WINSR;
                nFindedPosition += 12;
                sComparedName = pDnsWinsrData->pNameResultDomain;
                sComparedName = sComparedName.MakeLower();
                if(sComparedName == sFindedName)
                {
                    return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                }
                nPos1 = sComparedName.Find(sFindedName);
                if((nPos1 > 0)
                    && (sComparedName.Mid(nPos1) == sFindedName)
                    && (sComparedName[nPos1 - 1] == _T('.'))
                    )
                {
                    do
                    {
				        bCurrentLen = pMessageBuffer[nFindedPosition];
				        while((bCurrentLen & 0xc0) != 0)
				        {
					        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
					        INLINE_NTOHS(wCurrentRef, wCurrentRef);
					        wCurrentRef &= 0xC000;
                            nFindedPosition = (int)wCurrentRef;
                            bCurrentLen = pMessageBuffer[nFindedPosition];
				        }
                        nPos2 = sComparedName.Find(_T('.'));
                        if(0 >= nPos2)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                                );
                            return -1;
                        }
                        nFindedPosition += (int)bCurrentLen + 1;
                        sComparedName = sComparedName.Mid(nPos2 + 1);
                        if(0 == sComparedName.GetLength())
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                                );
                            return -1;
                        }
                        if(sComparedName == sFindedName)
                        {
                            return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                        }
                    }
                    while(true);
                }
            }
            break;
        }
        pFindingRR = pNextRR;
    }
    sComparedName = pFindingRR->m_sName.MakeLower();
    if(sComparedName == sFindedName)
    {
        nFindedPosition = pFindingRR->m_nStartPositionIndex;
        if(nFindedPosition == nCurrentMessagePosition)
        {
            return -1;
        }
        return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
    }
    nPos1 = sComparedName.Find(sFindedName);
    if((nPos1 > 0)
        && (sComparedName.Mid(nPos1) == sFindedName)
        && (sComparedName[nPos1 - 1] == _T('.'))
        )
    {
        nFindedPosition = pFindingRR->m_nStartPositionIndex;
        do
        {
			bCurrentLen = pMessageBuffer[nFindedPosition];
			while((bCurrentLen & 0xc0) != 0)
			{
				wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
				INLINE_NTOHS(wCurrentRef, wCurrentRef);
				wCurrentRef &= 0xC000;
                nFindedPosition = (int)wCurrentRef;
                bCurrentLen = pMessageBuffer[nFindedPosition];
			}
            nPos2 = sComparedName.Find(_T('.'));
            if(0 >= nPos2)
            {
                TraceEvents(
                    TRACE_LEVEL_WARNING,
                    TRACE_DNS_MESSAGE_WB,
                    "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                    );
                return -1;
            }
            nFindedPosition += (int)bCurrentLen + 1;
            sComparedName = sComparedName.Mid(nPos2 + 1);
            if(0 == sComparedName.GetLength())
            {
                TraceEvents(
                    TRACE_LEVEL_WARNING,
                    TRACE_DNS_MESSAGE_WB,
                    "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                    );
                return -1;
            }
            if(sComparedName == sFindedName)
            {
                if(nFindedPosition == nCurrentMessagePosition)
                {
                    //TraceEvents(
                    //    TRACE_LEVEL_WARNING,
                    //    TRACE_DNS_MESSAGE_WB,
                    //    "%!FUNC! line:%!LINE! %!LEVEL! Exit (nFindedPosition == nCurrentMessagePosition)"
                    //    );
                    return -1;
                }
                return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
            }
        }
        while(true);
    }
    nFindedPosition = pFindingRR->m_nStartPositionIndex;
    sComparedName = pFindingRR->m_sName.MakeLower();
    do
    {
        if((pMessageBuffer[nFindedPosition] & 0xC0) != 0)
        {
            nFindedPosition += 2;
            break;
        }
        if(pMessageBuffer[nFindedPosition] == 0)
        {
            nFindedPosition++;
            break;
        }
        nPos2 = sComparedName.Find(_T('.'));
        nFindedPosition += (int)pMessageBuffer[nFindedPosition] + 1;
        sComparedName = sComparedName.Mid(nPos2 + 1);
    }
    while(true);
    nFindedPosition += 10;
    switch(pFindingRR->m_wType)
    {
    case DNS_TYPE_SOA:
        {
            PDNS_SOA_DATA   pSoaData = &pFindingRR->m_pDnsRecordData->SOA;
            sComparedName = pSoaData->pNamePrimaryServer;
            sComparedName = sComparedName.MakeLower();
            if(sComparedName == sFindedName)
            {
                if(nFindedPosition == nCurrentMessagePosition)
                {
                    return -1;
                }
                return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
            }
            nPos1 = sComparedName.Find(sFindedName);
            if((nPos1 > 0)
                && (sComparedName.Mid(nPos1) == sFindedName)
                && (sComparedName[nPos1 - 1] == _T('.'))
                )
            {
                do
                {
			        bCurrentLen = pMessageBuffer[nFindedPosition];
			        while((bCurrentLen & 0xc0) != 0)
			        {
				        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
				        INLINE_NTOHS(wCurrentRef, wCurrentRef);
				        wCurrentRef &= 0xC000;
                        nFindedPosition = (int)wCurrentRef;
                        bCurrentLen = pMessageBuffer[nFindedPosition];
			        }
                    nPos2 = sComparedName.Find(_T('.'));
                    if(0 >= nPos2)
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                            );
                        return -1;
                    }
                    nFindedPosition += (int)bCurrentLen + 1;
                    sComparedName = sComparedName.Mid(nPos2 + 1);
                    if(0 == sComparedName.GetLength())
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                            );
                        return -1;
                    }
                    if(sComparedName == sFindedName)
                    {
                        if(nFindedPosition == nCurrentMessagePosition)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (nFindedPosition == nCurrentMessagePosition)"
                                );
                            return -1;
                        }
                        return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                    }
                }
                while(true);
            }
            do
            {
                if((pMessageBuffer[nFindedPosition] & 0xC0) != 0)
                {
                    nFindedPosition += 2;
                    break;
                }
                if(pMessageBuffer[nFindedPosition] == 0)
                {
                    nFindedPosition++;
                    break;
                }
                nPos2 = sComparedName.Find(_T('.'));
                nFindedPosition += (int)pMessageBuffer[nFindedPosition] + 1;
                sComparedName = sComparedName.Mid(nPos2 + 1);
            }
            while(true);
            sComparedName = pSoaData->pNameAdministrator;
            sComparedName = sComparedName.MakeLower();
            if(sComparedName == sFindedName)
            {
                if(nFindedPosition == nCurrentMessagePosition)
                {
                    return -1;
                }
                return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
            }
            nPos1 = sComparedName.Find(sFindedName);
            if((nPos1 > 0)
                && (sComparedName.Mid(nPos1) == sFindedName)
                && (sComparedName[nPos1 - 1] == _T('.'))
                )
            {
                do
                {
			        bCurrentLen = pMessageBuffer[nFindedPosition];
			        while((bCurrentLen & 0xc0) != 0)
			        {
				        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
				        INLINE_NTOHS(wCurrentRef, wCurrentRef);
				        wCurrentRef &= 0xC000;
                        nFindedPosition = (int)wCurrentRef;
                        bCurrentLen = pMessageBuffer[nFindedPosition];
			        }
                    nPos2 = sComparedName.Find(_T('.'));
                    if(0 >= nPos2)
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                            );
                        return -1;
                    }
                    nFindedPosition += (int)bCurrentLen + 1;
                    sComparedName = sComparedName.Mid(nPos2 + 1);
                    if(0 == sComparedName.GetLength())
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                            );
                        return -1;
                    }
                    if(sComparedName == sFindedName)
                    {
                        if(nFindedPosition == nCurrentMessagePosition)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (nFindedPosition == nCurrentMessagePosition)"
                                );
                            return -1;
                        }
                        return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                    }
                }
                while(true);
            }
        }
        break;
    case DNS_TYPE_PTR:
    case DNS_TYPE_NS:
    case DNS_TYPE_MD:
    case DNS_TYPE_MF:
    case DNS_TYPE_CNAME:
    case DNS_TYPE_MB:
    case DNS_TYPE_MG:
    case DNS_TYPE_MR:
    case DNS_TYPE_DNAME:
        {
            PDNS_PTR_DATA   pDnsPtrData = &pFindingRR->m_pDnsRecordData->PTR;
            sComparedName = pDnsPtrData->pNameHost;
            sComparedName = sComparedName.MakeLower();
            if(sComparedName == sFindedName)
            {
                if(nFindedPosition == nCurrentMessagePosition)
                {
                    return -1;
                }
                return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
            }
            nPos1 = sComparedName.Find(sFindedName);
            if((nPos1 > 0)
                && (sComparedName.Mid(nPos1) == sFindedName)
                && (sComparedName[nPos1 - 1] == _T('.'))
                )
            {
                do
                {
			        bCurrentLen = pMessageBuffer[nFindedPosition];
			        while((bCurrentLen & 0xc0) != 0)
			        {
				        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
				        INLINE_NTOHS(wCurrentRef, wCurrentRef);
				        wCurrentRef &= 0xC000;
                        nFindedPosition = (int)wCurrentRef;
                        bCurrentLen = pMessageBuffer[nFindedPosition];
			        }
                    nPos2 = sComparedName.Find(_T('.'));
                    if(0 >= nPos2)
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                            );
                        return -1;
                    }
                    nFindedPosition += (int)bCurrentLen + 1;
                    sComparedName = sComparedName.Mid(nPos2 + 1);
                    if(0 == sComparedName.GetLength())
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                            );
                        return -1;
                    }
                    if(sComparedName == sFindedName)
                    {
                        if(nFindedPosition == nCurrentMessagePosition)
                        {
                            return -1;
                        }
                        return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                    }
                }
                while(true);
            }
        }
        break;
    case DNS_TYPE_MINFO:
    case DNS_TYPE_RP:
        {
            PDNS_MINFO_DATA pDnsMinfoData = &pFindingRR->m_pDnsRecordData->MINFO;
            sComparedName = pDnsMinfoData->pNameMailbox;
            sComparedName = sComparedName.MakeLower();
            if(sComparedName == sFindedName)
            {
                if(nFindedPosition == nCurrentMessagePosition)
                {
                    TraceEvents(
                        TRACE_LEVEL_WARNING,
                        TRACE_DNS_MESSAGE_WB,
                        "%!FUNC! line:%!LINE! %!LEVEL! Exit (nFindedPosition == nCurrentMessagePosition)"
                        );
                    return -1;
                }
                return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
            }
            nPos1 = sComparedName.Find(sFindedName);
            if((nPos1 > 0)
                && (sComparedName.Mid(nPos1) == sFindedName)
                && (sComparedName[nPos1 - 1] == _T('.'))
                )
            {
                do
                {
			        bCurrentLen = pMessageBuffer[nFindedPosition];
			        while((bCurrentLen & 0xc0) != 0)
			        {
				        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
				        INLINE_NTOHS(wCurrentRef, wCurrentRef);
				        wCurrentRef &= 0xC000;
                        nFindedPosition = (int)wCurrentRef;
                        bCurrentLen = pMessageBuffer[nFindedPosition];
			        }
                    nPos2 = sComparedName.Find(_T('.'));
                    if(0 >= nPos2)
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                            );
                        return -1;
                    }
                    nFindedPosition += (int)bCurrentLen + 1;
                    sComparedName = sComparedName.Mid(nPos2 + 1);
                    if(0 == sComparedName.GetLength())
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                            );
                        return -1;
                    }
                    if(sComparedName == sFindedName)
                    {
                        if(nFindedPosition == nCurrentMessagePosition)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (nFindedPosition == nCurrentMessagePosition)"
                                );
                            return -1;
                        }
                        return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                    }
                }
                while(true);
            }
            do
            {
                if((pMessageBuffer[nFindedPosition] & 0xC0) != 0)
                {
                    nFindedPosition += 2;
                    break;
                }
                if(pMessageBuffer[nFindedPosition] == 0)
                {
                    nFindedPosition++;
                    break;
                }
                nPos2 = sComparedName.Find(_T('.'));
                nFindedPosition += (int)pMessageBuffer[nFindedPosition] + 1;
                sComparedName = sComparedName.Mid(nPos2 + 1);
            }
            while(true);
            sComparedName = pDnsMinfoData->pNameErrorsMailbox;
            sComparedName = sComparedName.MakeLower();
            if(sComparedName == sFindedName)
            {
                if(nFindedPosition == nCurrentMessagePosition)
                {
                    TraceEvents(
                        TRACE_LEVEL_WARNING,
                        TRACE_DNS_MESSAGE_WB,
                        "%!FUNC! line:%!LINE! %!LEVEL! Exit (nFindedPosition == nCurrentMessagePosition)"
                        );
                    return -1;
                }
                return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
            }
            nPos1 = sComparedName.Find(sFindedName);
            if((nPos1 > 0)
                && (sComparedName.Mid(nPos1) == sFindedName)
                && (sComparedName[nPos1 - 1] == _T('.'))
                )
            {
                do
                {
			        bCurrentLen = pMessageBuffer[nFindedPosition];
			        while((bCurrentLen & 0xc0) != 0)
			        {
				        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
				        INLINE_NTOHS(wCurrentRef, wCurrentRef);
				        wCurrentRef &= 0xC000;
                        nFindedPosition = (int)wCurrentRef;
                        bCurrentLen = pMessageBuffer[nFindedPosition];
			        }
                    nPos2 = sComparedName.Find(_T('.'));
                    if(0 >= nPos2)
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                            );
                        return -1;
                    }
                    nFindedPosition += (int)bCurrentLen + 1;
                    sComparedName = sComparedName.Mid(nPos2 + 1);
                    if(0 == sComparedName.GetLength())
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                            );
                        return -1;
                    }
                    if(sComparedName == sFindedName)
                    {
                        if(nFindedPosition == nCurrentMessagePosition)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (nFindedPosition == nCurrentMessagePosition)"
                                );
                            return -1;
                        }
                        return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                    }
                }
                while(true);
            }
        }
        break;
    case DNS_TYPE_MX:
    case DNS_TYPE_AFSDB:
    case DNS_TYPE_RT:
        {
            PDNS_MX_DATA pDnsMxData = &pFindingRR->m_pDnsRecordData->MX;
            nFindedPosition += 2;
            sComparedName = pDnsMxData->pNameExchange;
            sComparedName = sComparedName.MakeLower();
            if(sComparedName == sFindedName)
            {
                if(nFindedPosition == nCurrentMessagePosition)
                {
                    TraceEvents(
                        TRACE_LEVEL_WARNING,
                        TRACE_DNS_MESSAGE_WB,
                        "%!FUNC! line:%!LINE! %!LEVEL! Exit (nFindedPosition == nCurrentMessagePosition)"
                        );
                    return -1;
                }
                return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
            }
            nPos1 = sComparedName.Find(sFindedName);
            if((nPos1 > 0)
                && (sComparedName.Mid(nPos1) == sFindedName)
                && (sComparedName[nPos1 - 1] == _T('.'))
                )
            {
                do
                {
			        bCurrentLen = pMessageBuffer[nFindedPosition];
			        while((bCurrentLen & 0xc0) != 0)
			        {
				        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
				        INLINE_NTOHS(wCurrentRef, wCurrentRef);
				        wCurrentRef &= 0xC000;
                        nFindedPosition = (int)wCurrentRef;
                        bCurrentLen = pMessageBuffer[nFindedPosition];
			        }
                    nPos2 = sComparedName.Find(_T('.'));
                    if(0 >= nPos2)
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                            );
                        return -1;
                    }
                    nFindedPosition += (int)bCurrentLen + 1;
                    sComparedName = sComparedName.Mid(nPos2 + 1);
                    if(0 == sComparedName.GetLength())
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                            );
                        return -1;
                    }
                    if(sComparedName == sFindedName)
                    {
                        if(nFindedPosition == nCurrentMessagePosition)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (nFindedPosition == nCurrentMessagePosition)"
                                );
                            return -1;
                        }
                        return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                    }
                }
                while(true);
            }
        }
        break;
    case DNS_TYPE_SIG:
    case DNS_TYPE_RRSIG:
        {
            PDNS_SIG_DATA   pDnsSigData = &pFindingRR->m_pDnsRecordData->SIG;
            nFindedPosition += 18;
            sComparedName = pDnsSigData->pNameSigner;
            sComparedName = sComparedName.MakeLower();
            if(sComparedName == sFindedName)
            {
                if(nFindedPosition == nCurrentMessagePosition)
                {
                    TraceEvents(
                        TRACE_LEVEL_WARNING,
                        TRACE_DNS_MESSAGE_WB,
                        "%!FUNC! line:%!LINE! %!LEVEL! Exit (nFindedPosition == nCurrentMessagePosition)"
                        );
                    return -1;
                }
                return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
            }
            nPos1 = sComparedName.Find(sFindedName);
            if((nPos1 > 0)
                && (sComparedName.Mid(nPos1) == sFindedName)
                && (sComparedName[nPos1 - 1] == _T('.'))
                )
            {
                do
                {
			        bCurrentLen = pMessageBuffer[nFindedPosition];
			        while((bCurrentLen & 0xc0) != 0)
			        {
				        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
				        INLINE_NTOHS(wCurrentRef, wCurrentRef);
				        wCurrentRef &= 0xC000;
                        nFindedPosition = (int)wCurrentRef;
                        bCurrentLen = pMessageBuffer[nFindedPosition];
			        }
                    nPos2 = sComparedName.Find(_T('.'));
                    if(0 >= nPos2)
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                            );
                        return -1;
                    }
                    nFindedPosition += (int)bCurrentLen + 1;
                    sComparedName = sComparedName.Mid(nPos2 + 1);
                    if(0 == sComparedName.GetLength())
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                            );
                        return -1;
                    }
                    if(sComparedName == sFindedName)
                    {
                        if(nFindedPosition == nCurrentMessagePosition)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (nFindedPosition == nCurrentMessagePosition)"
                                );
                            return -1;
                        }
                        return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                    }
                }
                while(true);
            }
        }
        break;
    case DNS_TYPE_NXT:
    case DNS_TYPE_NSEC:
        {
            PDNS_NSEC_DATA  pDnsNsecData = &pFindingRR->m_pDnsRecordData->NSEC;
            sComparedName = pDnsNsecData->pNextDomainName;
            sComparedName = sComparedName.MakeLower();
            if (sComparedName == sFindedName)
            {
                if (nFindedPosition == nCurrentMessagePosition)
                {
                    TraceEvents(
                        TRACE_LEVEL_WARNING,
                        TRACE_DNS_MESSAGE_WB,
                        "%!FUNC! line:%!LINE! %!LEVEL! Exit (nFindedPosition == nCurrentMessagePosition)"
                        );
                    return -1;
                }
                return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
            }
            nPos1 = sComparedName.Find(sFindedName);
            if((nPos1 > 0)
                && (sComparedName.Mid(nPos1) == sFindedName)
                && (sComparedName[nPos1 - 1] == _T('.'))
                )
            {
                do
                {
			        bCurrentLen = pMessageBuffer[nFindedPosition];
			        while((bCurrentLen & 0xc0) != 0)
			        {
				        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
				        INLINE_NTOHS(wCurrentRef, wCurrentRef);
				        wCurrentRef &= 0xC000;
                        nFindedPosition = (int)wCurrentRef;
                        bCurrentLen = pMessageBuffer[nFindedPosition];
			        }
                    nPos2 = sComparedName.Find(_T('.'));
                    if(0 >= nPos2)
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                            );
                        return -1;
                    }
                    nFindedPosition += (int)bCurrentLen + 1;
                    sComparedName = sComparedName.Mid(nPos2 + 1);
                    if(0 == sComparedName.GetLength())
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                            );
                        return -1;
                    }
                    if (sComparedName == sFindedName)
                    {
                        if (nFindedPosition == nCurrentMessagePosition)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (nFindedPosition == nCurrentMessagePosition)"
                                );
                            return -1;
                        }
                        return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                    }
                }
                while(true);
            }
        }
        break;
    case DNS_TYPE_SRV:
        {
            PDNS_SRV_DATA   pDnsSrvData = &pFindingRR->m_pDnsRecordData->SRV;
            nFindedPosition += 6;
            sComparedName = pDnsSrvData->pNameTarget;
            sComparedName = sComparedName.MakeLower();
            if (sComparedName == sFindedName)
            {
                if (nFindedPosition == nCurrentMessagePosition)
                {
                    //TraceEvents(
                    //    TRACE_LEVEL_WARNING,
                    //    TRACE_DNS_MESSAGE_WB,
                    //    "%!FUNC! line:%!LINE! %!LEVEL! Exit (nFindedPosition == nCurrentMessagePosition)"
                    //    );
                    return -1;
                }
                return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
            }
            nPos1 = sComparedName.Find(sFindedName);
            if((nPos1 > 0)
                && (sComparedName.Mid(nPos1) == sFindedName)
                && (sComparedName[nPos1 - 1] == _T('.'))
                )
            {
                do
                {
			        bCurrentLen = pMessageBuffer[nFindedPosition];
			        while((bCurrentLen & 0xc0) != 0)
			        {
				        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
				        INLINE_NTOHS(wCurrentRef, wCurrentRef);
				        wCurrentRef &= 0xC000;
                        nFindedPosition = (int)wCurrentRef;
                        bCurrentLen = pMessageBuffer[nFindedPosition];
			        }
                    nPos2 = sComparedName.Find(_T('.'));
                    if(0 >= nPos2)
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                            );
                        return -1;
                    }
                    nFindedPosition += (int)bCurrentLen + 1;
                    sComparedName = sComparedName.Mid(nPos2 + 1);
                    if(0 == sComparedName.GetLength())
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                            );
                        return -1;
                    }
                    if (sComparedName == sFindedName)
                    {
                        if (nFindedPosition == nCurrentMessagePosition)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (nFindedPosition == nCurrentMessagePosition)"
                                );
                            return -1;
                        }
                        return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                    }
                }
                while(true);
            }
        }
        break;
    case DNS_TYPE_NAPTR:
        {
            PDNS_NAPTR_DATA pDnsNaptrData = &pFindingRR->m_pDnsRecordData->NAPTR;
            nFindedPosition += 4;
            nFindedPosition += (int)pMessageBuffer[nFindedPosition] + 1;
            nFindedPosition += (int)pMessageBuffer[nFindedPosition] + 1;
            nFindedPosition += (int)pMessageBuffer[nFindedPosition] + 1;
            sComparedName = pDnsNaptrData->pReplacement;
            sComparedName = sComparedName.MakeLower();
            if (sComparedName == sFindedName)
            {
                if (nFindedPosition == nCurrentMessagePosition)
                {
                    TraceEvents(
                        TRACE_LEVEL_WARNING,
                        TRACE_DNS_MESSAGE_WB,
                        "%!FUNC! line:%!LINE! %!LEVEL! Exit (nFindedPosition == nCurrentMessagePosition)"
                        );
                    return -1;
                }
                return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
            }
            nPos1 = sComparedName.Find(sFindedName);
            if((nPos1 > 0)
                && (sComparedName.Mid(nPos1) == sFindedName)
                && (sComparedName[nPos1 - 1] == _T('.'))
                )
            {
                do
                {
			        bCurrentLen = pMessageBuffer[nFindedPosition];
			        while((bCurrentLen & 0xc0) != 0)
			        {
				        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
				        INLINE_NTOHS(wCurrentRef, wCurrentRef);
				        wCurrentRef &= 0xC000;
                        nFindedPosition = (int)wCurrentRef;
                        bCurrentLen = pMessageBuffer[nFindedPosition];
			        }
                    nPos2 = sComparedName.Find(_T('.'));
                    if(0 >= nPos2)
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                            );
                        return -1;
                    }
                    nFindedPosition += (int)bCurrentLen + 1;
                    sComparedName = sComparedName.Mid(nPos2 + 1);
                    if(0 == sComparedName.GetLength())
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                            );
                        return -1;
                    }
                    if (sComparedName == sFindedName)
                    {
                        if (nFindedPosition == nCurrentMessagePosition)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (nFindedPosition == nCurrentMessagePosition)"
                                );
                            return -1;
                        }
                        return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                    }
                }
                while(true);
            }
        }
        break;
    case DNS_TYPE_TKEY:
        {
            PDNS_TKEY_DATA  pDnsTkeyData = &pFindingRR->m_pDnsRecordData->TKEY;
            sComparedName = pDnsTkeyData->pNameAlgorithm;
            sComparedName = sComparedName.MakeLower();
            if (sComparedName == sFindedName)
            {
                if (nFindedPosition == nCurrentMessagePosition)
                {
                    TraceEvents(
                        TRACE_LEVEL_WARNING,
                        TRACE_DNS_MESSAGE_WB,
                        "%!FUNC! line:%!LINE! %!LEVEL! Exit (nFindedPosition == nCurrentMessagePosition)"
                        );
                    return -1;
                }
                return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
            }
            nPos1 = sComparedName.Find(sFindedName);
            if((nPos1 > 0)
                && (sComparedName.Mid(nPos1) == sFindedName)
                && (sComparedName[nPos1 - 1] == _T('.'))
                )
            {
                do
                {
			        bCurrentLen = pMessageBuffer[nFindedPosition];
			        while((bCurrentLen & 0xc0) != 0)
			        {
				        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
				        INLINE_NTOHS(wCurrentRef, wCurrentRef);
				        wCurrentRef &= 0xC000;
                        nFindedPosition = (int)wCurrentRef;
                        bCurrentLen = pMessageBuffer[nFindedPosition];
			        }
                    nPos2 = sComparedName.Find(_T('.'));
                    if(0 >= nPos2)
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                            );
                        return -1;
                    }
                    nFindedPosition += (int)bCurrentLen + 1;
                    sComparedName = sComparedName.Mid(nPos2 + 1);
                    if(0 == sComparedName.GetLength())
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                            );
                        return -1;
                    }
                    if (sComparedName == sFindedName)
                    {
                        if (nFindedPosition == nCurrentMessagePosition)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (nFindedPosition == nCurrentMessagePosition)"
                                );
                            return -1;
                        }
                        return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                    }
                }
                while(true);
            }
        }
        break;
    case DNS_TYPE_TSIG:
        {
            PDNS_TSIG_DATA  pDnsTsigData = &pFindingRR->m_pDnsRecordData->TSIG;
            sComparedName = pDnsTsigData->pNameAlgorithm;
            sComparedName = sComparedName.MakeLower();
            if (sComparedName == sFindedName)
            {
                if (nFindedPosition == nCurrentMessagePosition)
                {
                    TraceEvents(
                        TRACE_LEVEL_WARNING,
                        TRACE_DNS_MESSAGE_WB,
                        "%!FUNC! line:%!LINE! %!LEVEL! Exit (nFindedPosition == nCurrentMessagePosition)"
                        );
                    return -1;
                }
                return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
            }
            nPos1 = sComparedName.Find(sFindedName);
            if((nPos1 > 0)
                && (sComparedName.Mid(nPos1) == sFindedName)
                && (sComparedName[nPos1 - 1] == _T('.'))
                )
            {
                do
                {
			        bCurrentLen = pMessageBuffer[nFindedPosition];
			        while((bCurrentLen & 0xc0) != 0)
			        {
				        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
				        INLINE_NTOHS(wCurrentRef, wCurrentRef);
				        wCurrentRef &= 0xC000;
                        nFindedPosition = (int)wCurrentRef;
                        bCurrentLen = pMessageBuffer[nFindedPosition];
			        }
                    nPos2 = sComparedName.Find(_T('.'));
                    if(0 >= nPos2)
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                            );
                        return -1;
                    }
                    nFindedPosition += (int)bCurrentLen + 1;
                    sComparedName = sComparedName.Mid(nPos2 + 1);
                    if(0 == sComparedName.GetLength())
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                            );
                        return -1;
                    }
                    if (sComparedName == sFindedName)
                    {
                        if (nFindedPosition == nCurrentMessagePosition)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (nFindedPosition == nCurrentMessagePosition)"
                                );
                            return -1;
                        }
                        return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                    }
                }
                while(true);
            }
        }
        break;
    case DNS_TYPE_WINSR:
        {
            PDNS_WINSR_DATA pDnsWinsrData = &pFindingRR->m_pDnsRecordData->WINSR;
            nFindedPosition += 12;
            sComparedName = pDnsWinsrData->pNameResultDomain;
            sComparedName = sComparedName.MakeLower();
            if (sComparedName == sFindedName)
            {
                if (nFindedPosition == nCurrentMessagePosition)
                {
                    TraceEvents(
                        TRACE_LEVEL_WARNING,
                        TRACE_DNS_MESSAGE_WB,
                        "%!FUNC! line:%!LINE! %!LEVEL! Exit (nFindedPosition == nCurrentMessagePosition)"
                        );
                    return -1;
                }
                return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
            }
            nPos1 = sComparedName.Find(sFindedName);
            if((nPos1 > 0)
                && (sComparedName.Mid(nPos1) == sFindedName)
                && (sComparedName[nPos1 - 1] == _T('.'))
                )
            {
                do
                {
			        bCurrentLen = pMessageBuffer[nFindedPosition];
			        while((bCurrentLen & 0xc0) != 0)
			        {
				        wCurrentRef = *((PWORD)&pMessageBuffer[nFindedPosition]);
				        INLINE_NTOHS(wCurrentRef, wCurrentRef);
				        wCurrentRef &= 0xC000;
                        nFindedPosition = (int)wCurrentRef;
                        bCurrentLen = pMessageBuffer[nFindedPosition];
			        }
                    nPos2 = sComparedName.Find(_T('.'));
                    if(0 >= nPos2)
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 >= nPos2)"
                            );
                        return -1;
                    }
                    nFindedPosition += (int)bCurrentLen + 1;
                    sComparedName = sComparedName.Mid(nPos2 + 1);
                    if(0 == sComparedName.GetLength())
                    {
                        TraceEvents(
                            TRACE_LEVEL_WARNING,
                            TRACE_DNS_MESSAGE_WB,
                            "%!FUNC! line:%!LINE! %!LEVEL! Exit (0 == sComparedName.GetLength())"
                            );
                        return -1;
                    }
                    if (sComparedName == sFindedName)
                    {
                        if (nFindedPosition == nCurrentMessagePosition)
                        {
                            TraceEvents(
                                TRACE_LEVEL_WARNING,
                                TRACE_DNS_MESSAGE_WB,
                                "%!FUNC! line:%!LINE! %!LEVEL! Exit (nFindedPosition == nCurrentMessagePosition)"
                                );
                            return -1;
                        }
                        return (nFindedPosition > 0xBFFF) ? -1 : nFindedPosition;
                    }
                }
                while(true);
            }
        }
        break;
    }
    TraceEvents(
        TRACE_LEVEL_WARNING,
        TRACE_DNS_MESSAGE_WB,
        "%!FUNC! line:%!LINE! %!LEVEL! Exit (switch(pFindingRR->m_wType) break;)"
        );
    return -1;
}


void CDnsMessageWB::PerformCharString(
    CString sWCharString,
    PBYTE pMessageBuffer,
    int& rCurrentMessagePosition
    )
{
    int     nConvertedChars;
    int     nStringLength = sWCharString.GetLength();
    nConvertedChars = WideCharToMultiByte(
        CP_UTF8,
        0,
        (LPCWSTR)sWCharString,
        nStringLength,
        (LPSTR)&pMessageBuffer[rCurrentMessagePosition + 1],
        256,
        NULL,
        NULL
        );
    pMessageBuffer[rCurrentMessagePosition] = (BYTE)nConvertedChars;
    rCurrentMessagePosition += nConvertedChars + 1;
}


void CDnsMessageWB::PerformUnpackDomanName(
	CString sDomainName,
	PBYTE pMessageBuffer,
	CDnsResorceRecord* pCurrentRR,
	int& rCurrentMessagePosition
	)
{
    CString sAuxString = sDomainName;
    pCurrentRR;
    while (sAuxString.GetLength() > 0)
    {
        int     nPos1;
        int     nConvertedChars;
        nPos1 = sAuxString.Find(_T('.'));
        if(nPos1 > 0)
        {
            nConvertedChars = WideCharToMultiByte(
                CP_UTF8,
                0,
                (LPCWSTR)sAuxString,
                nPos1,
                (LPSTR)&pMessageBuffer[rCurrentMessagePosition + 1],
                64,
                NULL,
                NULL
                );
            pMessageBuffer[rCurrentMessagePosition] = (BYTE)nConvertedChars;
            rCurrentMessagePosition += nConvertedChars + 1;
        }
        else if(nPos1 < 0)
        {
            TraceEvents(
                TRACE_LEVEL_WARNING,
                TRACE_DNS_MESSAGE_WB,
                "%!FUNC! line:%!LINE! %!LEVEL! The final point of the portion of the DNS name not found. Point position = %d;",
                nPos1
                );
			break;
        }
        else
        {
            pMessageBuffer[rCurrentMessagePosition] = (BYTE)0;
            rCurrentMessagePosition += 1;
			return;
        }
        sAuxString = sAuxString.Mid(nPos1 + 1);
    }
    pMessageBuffer[rCurrentMessagePosition] = 0;
    rCurrentMessagePosition++;
}


CString CDnsMessageWB::GetRRTypeName(WORD wRRType)
{
    CString sRetString;
    switch (wRRType)
    {
    case DNS_TYPE_ZERO:
        sRetString = _T("DNS_TYPE_ZERO (0x0000)");
        break;
    case DNS_TYPE_A:
        sRetString = _T("DNS_TYPE_A (0x0001)");
        break;
    case DNS_TYPE_NS:
        sRetString = _T("DNS_TYPE_NS (0x0002)");
        break;
    case DNS_TYPE_MD:
        sRetString = _T("DNS_TYPE_MD (0x0003)");
        break;
    case DNS_TYPE_MF:
        sRetString = _T("DNS_TYPE_MF (0x0004)");
        break;
    case DNS_TYPE_CNAME:
        sRetString = _T("DNS_TYPE_CNAME (0x0005)");
        break;
    case DNS_TYPE_SOA:
        sRetString = _T("DNS_TYPE_SOA (0x0006)");
        break;
    case DNS_TYPE_MB:
        sRetString = _T("DNS_TYPE_MB (0x0007)");
        break;
    case DNS_TYPE_MG:
        sRetString = _T("DNS_TYPE_MG (0x0008)");
        break;
    case DNS_TYPE_MR:
        sRetString = _T("DNS_TYPE_MR (0x0009)");
        break;
    case DNS_TYPE_NULL:
        sRetString = _T("DNS_TYPE_NULL (0x000a)");
        break;
    case DNS_TYPE_WKS:
        sRetString = _T("DNS_TYPE_WKS (0x000b)");
        break;
    case DNS_TYPE_PTR:
        sRetString = _T("DNS_TYPE_PTR (0x000c)");
        break;
    case DNS_TYPE_HINFO:
        sRetString = _T("DNS_TYPE_HINFO (0x000d)");
        break;
    case DNS_TYPE_MINFO:
        sRetString = _T("DNS_TYPE_MINFO (0x000e)");
        break;
    case DNS_TYPE_MX:
        sRetString = _T("DNS_TYPE_MX (0x000f)");
        break;
    case DNS_TYPE_TEXT:
        sRetString = _T("DNS_TYPE_TEXT (0x0010)");
        break;
    case DNS_TYPE_RP:
        sRetString = _T("DNS_TYPE_RP (0x0011)");
        break;
    case DNS_TYPE_AFSDB:
        sRetString = _T("DNS_TYPE_AFSDB (0x0012)");
        break;
    case DNS_TYPE_X25:
        sRetString = _T("DNS_TYPE_X25 (0x0013)");
        break;
    case DNS_TYPE_ISDN:
        sRetString = _T("DNS_TYPE_ISDN (0x0014)");
        break;
    case DNS_TYPE_RT:
        sRetString = _T("DNS_TYPE_RT (0x0015)");
        break;
    case DNS_TYPE_NSAP:
        sRetString = _T("DNS_TYPE_NSAP (0x0016)");
        break;
    case DNS_TYPE_NSAPPTR:
        sRetString = _T("DNS_TYPE_NSAPPTR (0x0017)");
        break;
    case DNS_TYPE_SIG:
        sRetString = _T("DNS_TYPE_SIG (0x0018)");
        break;
    case DNS_TYPE_KEY:
        sRetString = _T("DNS_TYPE_KEY (0x0019)");
        break;
    case DNS_TYPE_PX:
        sRetString = _T("DNS_TYPE_PX (0x001a)");
        break;
    case DNS_TYPE_GPOS:
        sRetString = _T("DNS_TYPE_GPOS (0x001b)");
        break;
    case DNS_TYPE_AAAA:
        sRetString = _T("DNS_TYPE_AAAA (0x001c)");
        break;
    case DNS_TYPE_LOC:
        sRetString = _T("DNS_TYPE_LOC (0x001d)");
        break;
    case DNS_TYPE_NXT:
        sRetString = _T("DNS_TYPE_NXT (0x001e)");
        break;
    case DNS_TYPE_EID:
        sRetString = _T("DNS_TYPE_EID (0x001f)");
        break;
    case DNS_TYPE_NIMLOC:
        sRetString = _T("DNS_TYPE_NIMLOC (0x0020)");
        break;
    case DNS_TYPE_SRV:
        sRetString = _T("DNS_TYPE_SRV (0x0021)");
        break;
    case DNS_TYPE_ATMA:
        sRetString = _T("DNS_TYPE_ATMA (0x0022)");
        break;
    case DNS_TYPE_NAPTR:
        sRetString = _T("DNS_TYPE_NAPTR (0x0023)");
        break;
    case DNS_TYPE_KX:
        sRetString = _T("DNS_TYPE_KX (0x0024)");
        break;
    case DNS_TYPE_CERT:
        sRetString = _T("DNS_TYPE_CERT (0x0025)");
        break;
    case DNS_TYPE_A6:
        sRetString = _T("DNS_TYPE_A6 (0x0026)");
        break;
    case DNS_TYPE_DNAME:
        sRetString = _T("DNS_TYPE_DNAME (0x0027)");
        break;
    case DNS_TYPE_SINK:
        sRetString = _T("DNS_TYPE_SINK (0x0028)");
        break;
    case DNS_TYPE_OPT:
        sRetString = _T("DNS_TYPE_OPT (0x0029)");
        break;
    case DNS_TYPE_DS:
        sRetString = _T("DNS_TYPE_DS (0x002b)");
        break;
    case DNS_TYPE_RRSIG:
        sRetString = _T("DNS_TYPE_RRSIG (0x002e)");
        break;
    case DNS_TYPE_NSEC:
        sRetString = _T("DNS_TYPE_NSEC (0x002f)");
        break;
    case DNS_TYPE_DNSKEY:
        sRetString = _T("DNS_TYPE_DNSKEY (0x0030)");
        break;
    case DNS_TYPE_DHCID:
        sRetString = _T("DNS_TYPE_DHCID (0x0031)");
        break;
    case DNS_TYPE_NSEC3:
        sRetString = _T("DNS_TYPE_NSEC3 (0x0032)");
        break;
    case DNS_TYPE_NSEC3PARAM:
        sRetString = _T("DNS_TYPE_NSEC3PARAM (0x0033)");
        break;
    case DNS_TYPE_UINFO:
        sRetString = _T("DNS_TYPE_UINFO (0x0064)");
        break;
    case DNS_TYPE_UID:
        sRetString = _T("DNS_TYPE_UID (0x0065)");
        break;
    case DNS_TYPE_GID:
        sRetString = _T("DNS_TYPE_GID (0x0066)");
        break;
    case DNS_TYPE_UNSPEC:
        sRetString = _T("DNS_TYPE_UNSPEC (0x0067)");
        break;
    case DNS_TYPE_ADDRS:
        sRetString = _T("DNS_TYPE_ADDRS (0x00f8)");
        break;
    case DNS_TYPE_TKEY:
        sRetString = _T("DNS_TYPE_TKEY (0x00f9)");
        break;
    case DNS_TYPE_TSIG:
        sRetString = _T("DNS_TYPE_TSIG (0x00fa)");
        break;
    case DNS_TYPE_IXFR:
        sRetString = _T("DNS_TYPE_IXFR (0x00fb)");
        break;
    case DNS_TYPE_AXFR:
        sRetString = _T("DNS_TYPE_AXFR (0x00fc)");
        break;
    case DNS_TYPE_MAILB:
        sRetString = _T("DNS_TYPE_MAILB (0x00fd)");
        break;
    case DNS_TYPE_MAILA:
        sRetString = _T("DNS_TYPE_MAILA (0x00fe)");
        break;
    case DNS_TYPE_ALL:
        sRetString = _T("DNS_TYPE_ALL (0x00ff)");
        break;
    case DNS_TYPE_WINS:
        sRetString = _T("DNS_TYPE_WINS (0xff01)");
        break;
    case DNS_TYPE_WINSR:
        sRetString = _T("DNS_TYPE_WINSR (0xff02)");
        break;
    default:
        sRetString.Format(
            _T("unknown (0x%04hx)"),
            wRRType
            );
        break;
    }
    return sRetString;
}


void CDnsMessageWB::DumpDnsHeader()
{
    CString sOptcodeName;
    switch (m_stDnsHeader.Opcode)
    {
    case DNS_OPCODE_QUERY:
        sOptcodeName = L"DNS_OPCODE_QUERY (0)";
        break;
    case DNS_OPCODE_IQUERY:
        sOptcodeName = L"DNS_OPCODE_IQUERY (1)";
        break;
    case DNS_OPCODE_SERVER_STATUS:
        sOptcodeName = L"DNS_OPCODE_SERVER_STATUS (2)";
        break;
    case DNS_OPCODE_UNKNOWN:
        sOptcodeName = L"DNS_OPCODE_UNKNOWN (3)";
        break;
    case DNS_OPCODE_NOTIFY:
        sOptcodeName = L"DNS_OPCODE_NOTIFY (4)";
        break;
    case DNS_OPCODE_UPDATE:
        sOptcodeName = L"DNS_OPCODE_UPDATE (5)";
        break;
    default:
        sOptcodeName.Format(
            L"undefined (%u)",
            (DWORD) m_stDnsHeader.Opcode
            );
        break;
    }
    TraceEvents(
        TRACE_LEVEL_INFORMATION,
        TRACE_DNS_RECORD_DUMP,
        "DnsHeader:"
        );
    TraceEvents(
        TRACE_LEVEL_INFORMATION,
        TRACE_DNS_RECORD_DUMP,
        "     Xid = 0x%04hx",
        m_stDnsHeader.Xid
        );
    TraceEvents(
        TRACE_LEVEL_INFORMATION,
        TRACE_DNS_RECORD_DUMP,
        "     RecursionDesired = %!bool!",
        m_stDnsHeader.RecursionDesired
        );
    TraceEvents(
        TRACE_LEVEL_INFORMATION,
        TRACE_DNS_RECORD_DUMP,
        "     Truncation = %!bool!",
        m_stDnsHeader.Truncation
        );
    TraceEvents(
        TRACE_LEVEL_INFORMATION,
        TRACE_DNS_RECORD_DUMP,
        "     Authoritative = %!bool!",
        m_stDnsHeader.Authoritative
        );
    TraceEvents(
        TRACE_LEVEL_INFORMATION,
        TRACE_DNS_RECORD_DUMP,
        "     Opcode = %ws",
        (LPCTSTR) sOptcodeName
        );
    TraceEvents(
        TRACE_LEVEL_INFORMATION,
        TRACE_DNS_RECORD_DUMP,
        "     IsResponse = %!bool!",
        m_stDnsHeader.IsResponse
        );
    TraceEvents(
        TRACE_LEVEL_INFORMATION,
        TRACE_DNS_RECORD_DUMP,
        "     ResponseCode = %u",
        m_stDnsHeader.ResponseCode
        );
    TraceEvents(
        TRACE_LEVEL_INFORMATION,
        TRACE_DNS_RECORD_DUMP,
        "     CheckingDisabled = %!bool!",
        m_stDnsHeader.CheckingDisabled
        );
    TraceEvents(
        TRACE_LEVEL_INFORMATION,
        TRACE_DNS_RECORD_DUMP,
        "     AuthenticatedData = %!bool!",
        m_stDnsHeader.AuthenticatedData
        );
    TraceEvents(
        TRACE_LEVEL_INFORMATION,
        TRACE_DNS_RECORD_DUMP,
        "     Reserved = %!bool!",
        m_stDnsHeader.Reserved
        );
    TraceEvents(
        TRACE_LEVEL_INFORMATION,
        TRACE_DNS_RECORD_DUMP,
        "     RecursionAvailable = %!bool!",
        m_stDnsHeader.RecursionAvailable
        );
    TraceEvents(
        TRACE_LEVEL_INFORMATION,
        TRACE_DNS_RECORD_DUMP,
        "     QuestionCount = %u",
        m_stDnsHeader.QuestionCount
        );
    TraceEvents(
        TRACE_LEVEL_INFORMATION,
        TRACE_DNS_RECORD_DUMP,
        "     AnswerCount = %u",
        m_stDnsHeader.AnswerCount
        );
    TraceEvents(
        TRACE_LEVEL_INFORMATION,
        TRACE_DNS_RECORD_DUMP,
        "     NameServerCount = %u",
        m_stDnsHeader.NameServerCount
        );
    TraceEvents(
        TRACE_LEVEL_INFORMATION,
        TRACE_DNS_RECORD_DUMP,
        "     AdditionalCount = %u",
        m_stDnsHeader.AdditionalCount
        );
}


void CDnsMessageWB::Clear()
{
    CDnsResorceRecord*  pRemovedRR;
    while ((pRemovedRR = RemoveFromTail()) != NULL)
    {
        delete pRemovedRR;
    }
    m_stDnsQuestionRecord.ClearName();
    if (NULL != m_pSavedQueryMessage)
    {
        delete m_pSavedQueryMessage;
        m_pSavedQueryMessage = NULL;
    }
}
