Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2928 lines
82 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1998 - 1999
//
// File: record.cpp
//
//--------------------------------------------------------------------------
#include "preDNSsn.h"
#include <SnapBase.h>
#include "resource.h"
#include "dnsutil.h"
#include "DNSSnap.h"
#include "snapdata.h"
#include "server.h"
#include "domain.h"
#include "record.h"
#include "zone.h"
#ifdef DEBUG_ALLOCATOR
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#endif
#define DNS_RECORD_CLASS_DEFAULT (0x1) // we support only class one records
#ifdef _USE_BLANK
#else
const WCHAR* g_szAtTheNodeInput = L"@"; // string to mark the "At the node RR"
#endif
extern COMBOBOX_TABLE_ENTRY g_Algorithms[];
extern COMBOBOX_TABLE_ENTRY g_Protocols[];
////////////////////////////////////////////////////////////////////////////
// CDNSRecord : base class for all the DNS record types
CDNSRecord::CDNSRecord()
{
m_wType = 0x0;
m_dwFlags = DNS_RPC_RECORD_FLAG_DEFAULT;
m_dwTtlSeconds = 60;
m_dwScavengeStart = 0;
}
////////////////////////////////////////////////////////////////////
//////////////// RPC SPECIFIC //////////////////////////////////////
//
// sizes of data sections for records: some of them have strings
// after the constant size part
//
#define SIZEOF_DNS_RPC_A_RECORD_DATA_HEADER (sizeof(IP_ADDRESS))
#define SIZEOF_DNS_RPC_ATMA_RECORD_DATA_HEADER (sizeof(UCHAR))
#define SIZEOF_DNS_RPC_AAAA_RECORD_DATA_HEADER (sizeof(IPV6_ADDRESS))
#define SIZEOF_DNS_RPC_SOA_RECORD_DATA_HEADER (5*sizeof(DWORD)) // then string
#define SIZEOF_DNS_RPC_MXAFSBD_RT_RECORD_DATA_HEADER (sizeof(WORD)) // thsn string
#define SIZEOF_DNS_RPC_WKS_RECORD_DATA_HEADER (sizeof(IP_ADDRESS)+sizeof(UCHAR))
#define SIZEOF_DNS_RPC_WINS_RECORD_DATA_HEADER (4*sizeof(DWORD))
#define SIZEOF_DNS_RPC_NBSTAT_RECORD_DATA_HEADER (3*sizeof(DWORD))
#define SIZEOF_DNS_RPC_SRV_RECORD_DATA_HEADER (3*sizeof(WORD))
#define SIZEOF_DNS_RPC_SIG_RECORD_DATA_HEADER \
(sizeof(WORD)+2*sizeof(BYTE)+3*sizeof(DWORD)+sizeof(WORD)) // then string then blob
#define SIZEOF_DNS_RPC_KEY_RECORD_DATA_HEADER (sizeof(WORD) + sizeof(BYTE) + sizeof(BYTE))
#define SIZEOF_DNS_RPC_NXT_RECORD_DATA_HEADER (sizeof(WORD))
DNS_STATUS CDNSRecord::Update(LPCTSTR lpszServerName, LPCTSTR lpszZoneName, LPCTSTR lpszNodeName,
CDNSRecord* pDNSRecordOld, BOOL bUseDefaultTTL)
{
USES_CONVERSION;
WORD nBytesLen = GetRPCRecordLength();
BYTE* pMem = (BYTE*)malloc(nBytesLen);
if (!pMem)
{
return ERROR_OUTOFMEMORY;
}
memset(pMem, 0x0, nBytesLen);
DNS_STATUS err = 0;
BYTE* pMemOld = 0;
do // false loop
{
DNS_RPC_RECORD* pDnsRpcRecord = NULL;
WriteRPCData(pMem, &pDnsRpcRecord);
ASSERT(pDnsRpcRecord != NULL);
DNS_RPC_RECORD* pDnsRpcRecordOld = NULL;
if (pDNSRecordOld != NULL) // doing an update of existing record
{
WORD nOldBytesLen = pDNSRecordOld->GetRPCRecordLength();
pMemOld = (BYTE*)malloc(nOldBytesLen);
if (!pMemOld)
{
err = ERROR_OUTOFMEMORY;
break;
}
memset(pMemOld, 0x0, nOldBytesLen);
pDNSRecordOld->WriteRPCData(pMemOld, &pDnsRpcRecordOld);
ASSERT(pDnsRpcRecordOld != NULL);
//
// figure out if it is TTL only or full update
//
if (pDnsRpcRecordOld->wDataLength == pDnsRpcRecord->wDataLength)
{
//
// mask the flags
//
DWORD dwFlagSave = pDnsRpcRecord->dwFlags;
pDnsRpcRecord->dwFlags = 0;
//
// mask the TTL
//
DWORD dwTtlSave = pDnsRpcRecord->dwTtlSeconds;
//
// mask the StartRefreshHr
//
DWORD dwStartRefreshHrSave = pDnsRpcRecord->dwTimeStamp;
pDnsRpcRecord->dwTtlSeconds = pDnsRpcRecordOld->dwTtlSeconds;
BOOL bEqual =
memcmp(
pDnsRpcRecord,
pDnsRpcRecordOld,
min(
pDnsRpcRecord->wDataLength + SIZEOF_DNS_RPC_RECORD_HEADER,
pDnsRpcRecordOld->wDataLength + SIZEOF_DNS_RPC_RECORD_HEADER)) == 0;
//
// restore masked fields
//
pDnsRpcRecord->dwTimeStamp = dwStartRefreshHrSave;
pDnsRpcRecord->dwTtlSeconds = dwTtlSave;
pDnsRpcRecord->dwFlags = dwFlagSave;
//
// check if TTL only
//
if (bEqual && (pDnsRpcRecord->dwTtlSeconds != pDnsRpcRecordOld->dwTtlSeconds))
{
pDnsRpcRecord->dwFlags |= DNS_RPC_RECORD_FLAG_TTL_CHANGE;
}
}
}
if (bUseDefaultTTL)
{
pDnsRpcRecord->dwFlags |= DNS_RPC_RECORD_FLAG_DEFAULT_TTL;
}
ASSERT(pDnsRpcRecord->wType != 0);
err =
::DnssrvUpdateRecord(
lpszServerName,
W_TO_UTF8(lpszZoneName),
W_TO_UTF8(lpszNodeName),
pDnsRpcRecord, pDnsRpcRecordOld);
//
// if we get DNS_ERROR_ALREADY_EXISTS and it is an existing record,
// we are actually OK, ignore the error code
//
// NTRAID#Windows Bugs-251410-2001/01/17-jeffjon
// The DNS_ERROR_RECORD_ALREADY_EXISTS was taken out due to bug 251410. I
// am leaving it here in case we run into problems after removing it since
// I don't know why it was here in the first place.
//
/*if ((err == DNS_ERROR_RECORD_ALREADY_EXISTS) && (pDNSRecordOld != NULL))
{
err = 0;
}*/
} while (false);
if (pMem)
{
free(pMem);
pMem = 0;
}
if (pMemOld)
{
free(pMemOld);
pMemOld = 0;
}
return err;
}
DNS_STATUS CDNSRecord::Delete(LPCTSTR lpszServerName,
LPCTSTR lpszZoneName,
LPCTSTR lpszNodeName)
{
USES_CONVERSION;
WORD nBytesLen = GetRPCRecordLength();
BYTE* pMem = (BYTE*)malloc(nBytesLen);
if (!pMem)
{
return ERROR_OUTOFMEMORY;
}
memset(pMem, 0x0, nBytesLen);
DNS_RPC_RECORD* pDnsRpcRecord = NULL;
WriteRPCData(pMem, &pDnsRpcRecord);
ASSERT(pDnsRpcRecord != NULL);
DNS_STATUS err = ::DnssrvUpdateRecord(lpszServerName,
W_TO_UTF8(lpszZoneName),
W_TO_UTF8(lpszNodeName),
NULL, pDnsRpcRecord);
if (pMem)
{
free(pMem);
pMem = 0;
}
return err;
}
// helper function
void CDNSRecord::CopyDNSRecordData(CDNSRecord* pDest, CDNSRecord* pSource)
{
ASSERT(pDest != NULL);
ASSERT(pSource != NULL);
// allocate buffer on the stack
WORD nBytesLen = pSource->GetRPCRecordLength();
BYTE* pMem = (BYTE*)malloc(nBytesLen);
if (!pMem)
{
return;
}
memset(pMem, 0x0, nBytesLen);
DNS_RPC_RECORD* pDnsRPCRecord = NULL;
pSource->WriteRPCData(pMem, &pDnsRPCRecord); // write source to memory
ASSERT(pDnsRPCRecord != NULL);
pDest->ReadRPCData(pDnsRPCRecord); // read destination from memory
// got to test if it is the same
ASSERT(pDest->GetType() == pSource->GetType());
if (pMem)
{
free(pMem);
pMem = 0;
}
}
void CDNSRecord::CloneValue(CDNSRecord* pClone)
{
ASSERT(pClone != NULL);
CopyDNSRecordData(pClone,this);
}
void CDNSRecord::SetValue(CDNSRecord* pRecord)
{
ASSERT(pRecord != NULL);
CopyDNSRecordData(this,pRecord);
}
void CDNSRecord::ReadRPCData(DNS_RPC_RECORD* pDnsRecord)
{
ASSERT(pDnsRecord != NULL);
// base class: just read common attributes
// either we know the type, or we are an unk/null record type
ASSERT(( m_wType == DNS_TYPE_NULL) || (m_wType == pDnsRecord->wType) );
m_wType = pDnsRecord->wType;
m_dwFlags = pDnsRecord->dwFlags;
m_dwTtlSeconds = pDnsRecord->dwTtlSeconds;
m_dwScavengeStart = pDnsRecord->dwTimeStamp;
}
void CDNSRecord::ReadDnsQueryData(DNS_RECORD* pDnsQueryRecord)
{
ASSERT(pDnsQueryRecord != NULL);
// base class: just read common attributes
// either we know the type, or we are an unk/null record type
ASSERT(( m_wType == DNS_TYPE_NULL) || (m_wType == pDnsQueryRecord->wType) );
m_wType = pDnsQueryRecord->wType;
m_dwFlags = 0x0; // pDnsQueryRecord->Flags.W;
m_dwTtlSeconds = pDnsQueryRecord->dwTtl;
}
void CDNSRecord::WriteRPCData(BYTE* pMem, DNS_RPC_RECORD** ppDnsRecord)
{
ASSERT(pMem != NULL);
ASSERT(ppDnsRecord != NULL);
*ppDnsRecord = (DNS_RPC_RECORD*)pMem;
// fill in the common fields
(*ppDnsRecord)->wType = m_wType;
(*ppDnsRecord)->dwFlags = m_dwFlags;
(*ppDnsRecord)->dwTtlSeconds = m_dwTtlSeconds;
(*ppDnsRecord)->dwTimeStamp = m_dwScavengeStart;
// fill in the length info: derived classes will ad to it
(*ppDnsRecord)->wDataLength = 0x0;
}
WORD CDNSRecord::RPCBufferStringLen(LPCWSTR lpsz)
{
// returns the size of a DNS_RPC_STRING written to the buffer
USES_CONVERSION;
LPCSTR lpszAnsi = W_TO_UTF8(lpsz);
// do not count NULL,
// add size of cchNameLength (UCHAR) string length
WORD wLen = 0;
if (lpszAnsi != NULL && lpszAnsi[0] != L'\0')
{
wLen = static_cast<WORD>(UTF8_LEN(lpszAnsi) + sizeof(UCHAR));
}
else
{
wLen = sizeof(UCHAR) + sizeof(CHAR);
}
return wLen;
}
void CDNSRecord::ReadRPCString(CString& sz, DNS_RPC_NAME* pDnsRPCName)
{
// the input string is not NULL terminated
DnsUtf8ToWCStringHelper(sz, pDnsRPCName->achName, pDnsRPCName->cchNameLength);
}
WORD CDNSRecord::WriteString(DNS_RPC_NAME* pDnsRPCName, LPCTSTR lpsz)
{
USES_CONVERSION;
ASSERT(pDnsRPCName != NULL);
LPCSTR lpszAnsi = W_TO_UTF8(lpsz);
if (lpszAnsi != NULL &&
lpszAnsi[0] != '\0')
{
// IMPORTANT: string in the RPC BUFFER are NOT NULL terminated
pDnsRPCName->cchNameLength = (BYTE)UTF8_LEN(lpszAnsi); // don't count NULL
memcpy(pDnsRPCName->achName, lpszAnsi, pDnsRPCName->cchNameLength);
}
else
{
//
// NTRAID#Windows Bugs-305034-2001/02/05-jeffjon :
// According to JWesth a null string should be passed with cchNameLength = 1
// and the string a single NULL UTF8 character
//
pDnsRPCName->cchNameLength = 1;
// We don't want the null terminator here so just copy the one byte.
memcpy(pDnsRPCName->achName, "\0", 1);
}
// return length of the struct
// (add size of cchNameLength (UCHAR) string length)
return static_cast<WORD>(pDnsRPCName->cchNameLength + 1);
}
#ifdef _DEBUG
void CDNSRecord::TestRPCStuff(DNS_RPC_RECORD* pDnsRecord)
{
//
// TEST ONLY!!!!
//
WORD nBytesLen = GetRPCRecordLength();
BYTE* pMem = (BYTE*)malloc(nBytesLen);
if (!pMem)
{
return;
}
memset(pMem, 0x0, nBytesLen);
DNS_RPC_RECORD* pDnsRecordTest = NULL;
WriteRPCData(pMem, &pDnsRecordTest);
ASSERT(pDnsRecordTest != NULL);
//
// got to test if it is the same
//
ASSERT(pDnsRecord->wDataLength == pDnsRecordTest->wDataLength);
ASSERT(memcmp(pDnsRecord, pDnsRecordTest,
SIZEOF_DNS_RPC_RECORD_HEADER + pDnsRecordTest->wDataLength) == 0);
if (pMem)
{
free(pMem);
pMem = 0;
}
}
#endif
////////////////////////////////////////////////////////////////////////////
// CDNSRecordNodeBase
// {720132BB-44B2-11d1-B92F-00A0C9A06D2D}
const GUID CDNSRecordNodeBase::NodeTypeGUID =
{ 0x720132bb, 0x44b2, 0x11d1, { 0xb9, 0x2f, 0x0, 0xa0, 0xc9, 0xa0, 0x6d, 0x2d } };
CDNSRecordNodeBase::~CDNSRecordNodeBase()
{
if (m_pDNSRecord != NULL)
{
delete m_pDNSRecord;
m_pDNSRecord = NULL;
}
}
void CDNSRecordNodeBase::SetViewOptions(DWORD dwRecordViewOptions)
{
// we do not own the upper WORD of the flags
dwRecordViewOptions &= 0x0000ffff; // clear high WORD to be sure
m_dwNodeFlags &= 0xffff0000; // clear all the flags
m_dwNodeFlags |= dwRecordViewOptions;
}
HRESULT CDNSRecordNodeBase::OnSetToolbarVerbState(IToolbar* pToolbar,
CNodeList*)
{
//
// Set the button state for each button on the toolbar
//
VERIFY(SUCCEEDED(pToolbar->SetButtonState(toolbarNewServer, ENABLED, FALSE)));
VERIFY(SUCCEEDED(pToolbar->SetButtonState(toolbarNewZone, ENABLED, FALSE)));
VERIFY(SUCCEEDED(pToolbar->SetButtonState(toolbarNewRecord, ENABLED, FALSE)));
return S_OK;
}
BOOL CDNSRecordNodeBase::OnAddMenuItem(LPCONTEXTMENUITEM2,
long*)
{
ASSERT(FALSE); // never called
return FALSE;
}
BOOL CDNSRecordNodeBase::OnSetDeleteVerbState(DATA_OBJECT_TYPES,
BOOL* pbHide,
CNodeList* pNodeList)
{
if (pNodeList->GetCount() > 1) // multiple selection
{
*pbHide = TRUE;
return FALSE;
}
*pbHide = FALSE;
CDNSZoneNode* pZoneNode = GetDomainNode()->GetZoneNode();
if (pZoneNode->IsAutocreated() ||
(pZoneNode->GetZoneType() == DNS_ZONE_TYPE_SECONDARY) ||
(pZoneNode->GetZoneType() == DNS_ZONE_TYPE_STUB))
{
return FALSE;
}
if (!CanDelete())
{
return FALSE;
}
WORD wType = GetType();
if ((wType == DNS_TYPE_WINS) ||
(wType == DNS_TYPE_NBSTAT) ||
(wType == DNS_TYPE_NS) ||
(wType == DNS_TYPE_SOA))
{
return FALSE;
}
return TRUE;
}
HRESULT CDNSRecordNodeBase::OnCommand(long,
DATA_OBJECT_TYPES,
CComponentDataObject*,
CNodeList*)
{
ASSERT(FALSE); // never called!!!
return E_FAIL;
}
LPCWSTR CDNSRecordNodeBase::GetString(int nCol)
{
switch (nCol)
{
case 0:
return GetDisplayName();
case 1:
{
return CDNSRecordInfo::GetTypeString(m_pDNSRecord->GetType(), CDNSRecordInfo::fullName);
}
case 2:
return (LPCWSTR)m_szDisplayData;
}
return g_lpszNullString;
}
int CDNSRecordNodeBase::GetImageIndex(BOOL)
{
return RECORD_IMAGE_BASE;
}
void CDNSRecordNodeBase::SetRecordName(LPCTSTR lpszName, BOOL bAtTheNode)
{
m_bAtTheNode = bAtTheNode;
m_szDisplayName = m_bAtTheNode ? CDNSRecordInfo::GetAtTheNodeDisplayString() : lpszName;
}
BOOL CDNSRecordNodeBase::ZoneIsCache()
{
CDNSDomainNode* pDomainNode = GetDomainNode();
return (pDomainNode->GetZoneNode()->GetZoneType() == DNS_ZONE_TYPE_CACHE);
}
void CDNSRecordNodeBase::GetFullName(CString& szFullName)
{
CDNSDomainNode* pDomainNode = GetDomainNode();
ASSERT(pDomainNode != NULL);
if (IsAtTheNode())
{
szFullName = pDomainNode->GetFullName();
}
else
{
CString szTrueName = GetTrueRecordName();
ASSERT(szTrueName.GetLength() > 0);
LPCWSTR lpszDomainName = pDomainNode->GetFullName();
if ((lpszDomainName == NULL) || (lpszDomainName[0] == NULL))
{
// domain with no name, use the RR display name as FQDN
// this should be only with a temporary (fake) domain
ASSERT(szTrueName[szTrueName.GetLength()-1] == TEXT('.'));
szFullName = szTrueName;
}
else if ((lpszDomainName[0] == TEXT('.')) && (lpszDomainName[1] == NULL))
{
// the "." domain could be the Root or Root Hints
if ( IS_CLASS(*pDomainNode, CDNSRootHintsNode) &&
(szTrueName[szTrueName.GetLength()-1] == TEXT('.')) )
{
// special case A records in Root Hints, they might
// have "." at the end, e.g. "A.ROOT-SERVERS.NET."
szFullName = szTrueName;
}
else
{
// no need for dot in the format string
// e.g. "myhost" and "." gives "myhost."
szFullName.Format(_T("%s%s"), (LPCWSTR)szTrueName,
lpszDomainName);
}
}
else
{
// standard case, e.g. "myhost" and "banana.com."
// to get "myhost.banana.com."
szFullName.Format(_T("%s.%s"), (LPCWSTR)szTrueName,
lpszDomainName);
}
}
TRACE(_T("\nCDNSRecordNodeBase::GetFullName(%s)\n"), (LPCTSTR)szFullName);
}
void CDNSRecordNodeBase::CreateFromRPCRecord(DNS_RPC_RECORD* pDnsRecord)
{
ASSERT(m_pDNSRecord == NULL);
m_pDNSRecord = CreateRecord();
if (m_pDNSRecord)
{
m_pDNSRecord->ReadRPCData(pDnsRecord);
m_pDNSRecord->UpdateDisplayData(m_szDisplayData);
#ifdef _DEBUG
//
// TEST ONLY!!!!
//
m_pDNSRecord->TestRPCStuff(pDnsRecord);
#endif
}
}
void CDNSRecordNodeBase::CreateFromDnsQueryRecord(DNS_RECORD* pDnsQueryRecord, DWORD dwFlags)
{
ASSERT(m_pDNSRecord == NULL);
m_pDNSRecord = CreateRecord();
if (m_pDNSRecord)
{
m_pDNSRecord->ReadDnsQueryData(pDnsQueryRecord);
m_pDNSRecord->UpdateDisplayData(m_szDisplayData);
m_pDNSRecord->m_dwFlags = dwFlags;
}
}
CDNSRecord* CDNSRecordNodeBase::CreateCloneRecord()
{
ASSERT(m_pDNSRecord != NULL);
CDNSRecord* pClone = CreateRecord();
if (pClone)
{
m_pDNSRecord->CloneValue(pClone);
}
return pClone;
}
BOOL CDNSRecordNodeBase::CanCloseSheets()
{
return (IDCANCEL != DNSMessageBox(IDS_MSG_RECORD_CLOSE_SHEET, MB_OKCANCEL));
}
void CDNSRecordNodeBase::OnDelete(CComponentDataObject* pComponentData,
CNodeList* pNodeList)
{
if (pNodeList->GetCount() > 1) // multiple selection
{
return;
}
UINT nRet = DNSConfirmOperation(IDS_MSG_RECORD_DELETE, this);
if (IDCANCEL == nRet ||
IDNO == nRet)
{
return;
}
if (IsSheetLocked())
{
if (!CanCloseSheets())
return;
pComponentData->GetPropertyPageHolderTable()->DeleteSheetsOfNode(this);
}
ASSERT(!IsSheetLocked());
// try first to delete the record in the server
DNS_STATUS err = DeleteOnServerAndUI(pComponentData);
if (err != 0)
{
DNSErrorDialog(err, IDS_MSG_RECORD_FAIL_DELETE);
return;
}
delete this; // gone
}
DNS_STATUS CDNSRecordNodeBase::DeleteOnServer()
{
ASSERT(m_pDNSRecord != NULL);
CDNSDomainNode* pDomainNode = GetDomainNode();
ASSERT(pDomainNode != NULL);
CDNSServerNode* pServerNode = pDomainNode->GetServerNode();
ASSERT(pServerNode != NULL);
CString szFullName;
GetFullName(szFullName);
LPCTSTR lpszZoneNode = NULL;
CDNSZoneNode* pZoneNode = pDomainNode->GetZoneNode();
if (pZoneNode != NULL)
{
if (pZoneNode->GetZoneType() != DNS_ZONE_TYPE_CACHE)
{
lpszZoneNode = pZoneNode->GetFullName();
if ((lpszZoneNode != NULL) && (lpszZoneNode[0] == NULL))
lpszZoneNode = NULL;
}
}
return m_pDNSRecord->Delete(pServerNode->GetRPCName(), lpszZoneNode, szFullName);
}
DNS_STATUS CDNSRecordNodeBase::DeleteOnServerAndUI(CComponentDataObject* pComponentData)
{
ASSERT(pComponentData != NULL);
DNS_STATUS err = DeleteOnServer();
if (err == 0)
DeleteHelper(pComponentData); // delete in the UI and list of children
return err;
}
BOOL CDNSRecordNodeBase::HasPropertyPages(DATA_OBJECT_TYPES,
BOOL* pbHideVerb,
CNodeList* pNodeList)
{
if (pNodeList->GetCount() > 1) // multiple selection
{
*pbHideVerb = TRUE;
return FALSE;
}
*pbHideVerb = FALSE; // always show the verb
return !GetDomainNode()->GetZoneNode()->IsAutocreated();
}
HRESULT CDNSRecordNodeBase::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider,
LONG_PTR handle,
CNodeList* pNodeList)
{
ASSERT(pNodeList->GetCount() == 1); // multi-select not supported
CComponentDataObject* pComponentDataObject = ((CRootData*)(GetContainer()->GetRootContainer()))->GetComponentDataObject();
ASSERT(pComponentDataObject != NULL);
HRESULT hr = S_OK;
CDNSRecordPropertyPageHolder* pHolder = new CDNSRecordPropertyPageHolder((CDNSDomainNode*)GetContainer(), this, pComponentDataObject);
if (pHolder)
{
if (IsAtTheNode())
{
pHolder->SetSheetTitle(IDS_PROP_SHEET_TITLE_FMT, GetContainer());
}
else
{
pHolder->SetSheetTitle(IDS_PROP_SHEET_TITLE_FMT, this);
}
hr = pHolder->CreateModelessSheet(lpProvider, handle);
}
else
{
hr = E_OUTOFMEMORY;
}
return hr;
}
DNS_STATUS CDNSRecordNodeBase::Update(CDNSRecord* pDNSRecordNew, BOOL bUseDefaultTTL,
BOOL bIgnoreAlreadyExists)
{
// get a new record, write to server, if successful copy it and substitute it in place of the old
// passing pDNSRecordNew == NULL meand we are creating a new record
BOOL bNew = (pDNSRecordNew == NULL);
if (bNew)
{
pDNSRecordNew = m_pDNSRecord;
m_pDNSRecord = NULL;
}
ASSERT(pDNSRecordNew != NULL);
// try to write new record to the server, passing the old as comparison
CDNSDomainNode* pDomainNode = GetDomainNode();
CString szFullName;
LPCTSTR lpszServerName = pDomainNode->GetServerNode()->GetRPCName();
LPCTSTR lpszRecordName;
if (IsAtTheNode())
{
lpszRecordName = pDomainNode->GetFullName(); // e.g. "myzone.com"
}
else
{
GetFullName(szFullName);
lpszRecordName = szFullName; // e.g. "myrec.myzone.com"
}
LPCTSTR lpszZoneNode = NULL;
CDNSZoneNode* pZoneNode = pDomainNode->GetZoneNode();
if (pZoneNode != NULL)
{
if (pZoneNode->GetZoneType() != DNS_ZONE_TYPE_CACHE)
{
lpszZoneNode = pZoneNode->GetFullName();
if ((lpszZoneNode != NULL) && (lpszZoneNode[0] == NULL))
lpszZoneNode = NULL;
}
}
DNS_STATUS err = pDNSRecordNew->Update(lpszServerName, lpszZoneNode, lpszRecordName,
m_pDNSRecord, bUseDefaultTTL);
if (bIgnoreAlreadyExists && (err == DNS_ERROR_RECORD_ALREADY_EXISTS) )
err = 0; // tried to write, but it was already there, so it is fine.
if (err != 0 && err != DNS_WARNING_PTR_CREATE_FAILED)
return err; // failed, no update to the record
if (bNew)
{
// put back the existing DNSRecord, no need to create a new one
ASSERT(pDNSRecordNew != NULL);
m_pDNSRecord = pDNSRecordNew;
}
// update the record with the new one
if (m_pDNSRecord == NULL) // we are creating a new record
{
m_pDNSRecord = CreateRecord();
}
if (m_pDNSRecord)
{
m_pDNSRecord->SetValue(pDNSRecordNew);
//Update the scavenging time on both the temporary and the node's CDNSRecord
SetScavengingTime(m_pDNSRecord);
SetScavengingTime(pDNSRecordNew);
m_pDNSRecord->UpdateDisplayData(m_szDisplayData);
}
else
{
err = ERROR_OUTOFMEMORY;
}
return err;
}
void CDNSRecordNodeBase::SetScavengingTime(CDNSRecord* pRecord)
{
if (pRecord->m_dwFlags & DNS_RPC_RECORD_FLAG_AGING_ON)
{
pRecord->m_dwScavengeStart = CalculateScavengingTime();
}
else
{
pRecord->m_dwScavengeStart = 0;
}
}
DWORD CDNSRecordNodeBase::CalculateScavengingTime()
{
CDNSZoneNode* pZoneNode = GetDomainNode()->GetZoneNode();
ASSERT(pZoneNode != NULL);
if (pZoneNode == NULL)
return 0;
SYSTEMTIME currentSysTime;
::GetSystemTime(&currentSysTime);
LONGLONG llResult = GetSystemTime64(&currentSysTime);
return static_cast<DWORD>(llResult / 3600L);
}
void CDNSRecordNodeBase::CreateDsRecordLdapPath(CString& sz)
{
CDNSDomainNode* pDomainNode = GetDomainNode();
CDNSZoneNode* pZoneNode = pDomainNode->GetZoneNode();
CDNSServerNode* pServerNode = pZoneNode->GetServerNode();
pServerNode->CreateDsZoneName(pZoneNode, sz);
if (sz.IsEmpty())
return; // no LDAP path at all
CString szTmp;
// need to figure out the additional "DC = <>" part
if (pDomainNode->IsZone() && IsAtTheNode())
{
szTmp = L"DC=@,";
}
else
{
CString szRecordFullName;
if (IsAtTheNode())
{
szRecordFullName = GetDomainNode()->GetFullName(); // e.g. "mydom.myzone.com"
}
else
{
GetFullName(szRecordFullName); // e.g. "myrec.mydom.myzone.com"
}
LPCTSTR lpszZoneName = pZoneNode->GetFullName();
// remove zone part (e.g. "myzone.com") from record name,
// to get e.g. "mydom" or "myrec.mydom"
int nZoneLen = static_cast<int>(wcslen(lpszZoneName));
int nRecordLen = szRecordFullName.GetLength();
ASSERT(nRecordLen > nZoneLen);
szTmp.Format(_T("DC=%s,"),(LPCTSTR)szRecordFullName.Left(nRecordLen-nZoneLen-1));
}
szTmp += sz;
pServerNode->CreateLdapPathFromX500Name(szTmp, sz);
}
///////////////////////////////////////////////////////////////////
// CDNS_Null_Record
CDNS_Null_Record::CDNS_Null_Record()
{
m_wType = DNS_TYPE_NULL;
}
WORD CDNS_Null_Record::GetRPCDataLength()
{
return (WORD)m_blob.GetSize();
}
void CDNS_Null_Record::ReadRPCData(DNS_RPC_RECORD* pDnsRecord)
{
CDNSRecord::ReadRPCData(pDnsRecord);
m_blob.Set(pDnsRecord->Data.Null.bData , pDnsRecord->wDataLength);
}
void CDNS_Null_Record::ReadDnsQueryData(DNS_RECORD* pDnsQueryRecord)
{
CDNSRecord::ReadDnsQueryData(pDnsQueryRecord);
ASSERT(FALSE); // TODO
}
void CDNS_Null_Record::WriteRPCData(BYTE* pMem, DNS_RPC_RECORD** ppDnsRecord)
{
CDNSRecord::WriteRPCData(pMem, ppDnsRecord);
UINT nBytes = m_blob.GetSize();
memcpy((*ppDnsRecord)->Data.Null.bData, m_blob.GetData(), sizeof(BYTE)*nBytes);
(*ppDnsRecord)->wDataLength = static_cast<WORD>((((*ppDnsRecord)->wDataLength) + nBytes) & 0xffff);
}
void CDNS_Null_Record::UpdateDisplayData(CString& szDisplayData)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
szDisplayData.LoadString(IDS_RECORD_DATA_UNK);
}
///////////////////////////////////////////////////////////////////
// CDNS_A_Record
CDNS_A_Record::CDNS_A_Record()
{
m_wType = DNS_TYPE_A;
m_ipAddress = 0x0;
}
WORD CDNS_A_Record::GetRPCDataLength()
{
return (WORD)SIZEOF_DNS_RPC_A_RECORD_DATA_HEADER;
}
void CDNS_A_Record::ReadRPCData(DNS_RPC_RECORD* pDnsRecord)
{
CDNSRecord::ReadRPCData(pDnsRecord);
ASSERT(pDnsRecord->wType == DNS_TYPE_A);
ASSERT(pDnsRecord->wDataLength == SIZEOF_DNS_RPC_A_RECORD_DATA_HEADER);
m_ipAddress = pDnsRecord->Data.A.ipAddress;
}
void CDNS_A_Record::ReadDnsQueryData(DNS_RECORD* pDnsQueryRecord)
{
CDNSRecord::ReadDnsQueryData(pDnsQueryRecord);
ASSERT(pDnsQueryRecord->wType == DNS_TYPE_A);
m_ipAddress = pDnsQueryRecord->Data.A.IpAddress;
}
void CDNS_A_Record::WriteRPCData(BYTE* pMem, DNS_RPC_RECORD** ppDnsRecord)
{
CDNSRecord::WriteRPCData(pMem, ppDnsRecord);
(*ppDnsRecord)->Data.A.ipAddress = m_ipAddress;
(*ppDnsRecord)->wDataLength += SIZEOF_DNS_RPC_A_RECORD_DATA_HEADER;
}
void CDNS_A_Record::UpdateDisplayData(CString& szDisplayData)
{
szDisplayData.Format(g_szIpStringFmt, IP_STRING_FMT_ARGS(m_ipAddress));
}
///////////////////////////////////////////////////////////////////
// CDNS_ATMA_Record
void _ATMA_BCD_ToString(CString& s, BYTE* pBuf)
{
const int nHexChars = 2*DNS_ATMA_MAX_ADDR_LENGTH+1;
LPWSTR lpszBuf = s.GetBuffer(nHexChars);
ZeroMemory(lpszBuf, nHexChars*sizeof(WCHAR));
for (int i=0; i<DNS_ATMA_MAX_ADDR_LENGTH; i++)
{
BYTE high = static_cast<BYTE>(*(pBuf+i) >> 4);
BYTE low = static_cast<BYTE>(*(pBuf+i) & 0x0f);
// just offset out of the ASCII table
*(lpszBuf+2*i) = static_cast<WCHAR>((high <= 9) ? (high + TEXT('0')) : ( high - 10 + TEXT('a')));
*(lpszBuf+2*i+1) = static_cast<WCHAR>((low <= 9) ? (low + TEXT('0')) : ( low - 10 + TEXT('a')));
}
s.ReleaseBuffer();
}
BOOL _ATMA_StringTo_BCD(BYTE* pBuf, LPCWSTR lpsz)
{
// verify the string is the right length
size_t nLen = wcslen(lpsz);
if (nLen != 2*DNS_ATMA_MAX_ADDR_LENGTH)
return FALSE;
ZeroMemory(pBuf, DNS_ATMA_MAX_ADDR_LENGTH);
for (int i=0; i<DNS_ATMA_MAX_ADDR_LENGTH; i++)
{
BYTE high = HexCharToByte(lpsz[2*i]);
if (high == 0xFF)
return FALSE;
BYTE low = HexCharToByte(lpsz[2*i+1]);
if (low == 0xFF)
return FALSE;
pBuf[i] = static_cast<BYTE>((high << 4) | (low & 0x0f));
}
return TRUE;
}
CDNS_ATMA_Record::CDNS_ATMA_Record()
{
m_wType = DNS_TYPE_ATMA;
m_chFormat = DNS_ATMA_FORMAT_E164;
}
WORD CDNS_ATMA_Record::GetRPCDataLength()
{
DWORD dwLen = SIZEOF_DNS_RPC_ATMA_RECORD_DATA_HEADER;
ASSERT((m_chFormat == DNS_ATMA_FORMAT_E164) || (m_chFormat == DNS_ATMA_FORMAT_AESA));
if (m_chFormat == DNS_ATMA_FORMAT_E164)
{
USES_CONVERSION;
// it is a null terminated string
dwLen += UTF8_LEN(W_TO_UTF8(m_szAddress)); // do not count NULL at the end
}
else
{
// it is BCD encoding of DNS_ATMA_MAX_ADDR_LENGTH
dwLen += DNS_ATMA_MAX_ADDR_LENGTH;
}
return static_cast<WORD>(dwLen);
}
void CDNS_ATMA_Record::ReadRPCData(DNS_RPC_RECORD* pDnsRecord)
{
CDNSRecord::ReadRPCData(pDnsRecord);
ASSERT(pDnsRecord->wType == DNS_TYPE_ATMA);
m_chFormat = pDnsRecord->Data.ATMA.chFormat;
ASSERT((m_chFormat == DNS_ATMA_FORMAT_E164) || (m_chFormat == DNS_ATMA_FORMAT_AESA));
if (m_chFormat == DNS_ATMA_FORMAT_E164)
{
// non NULL terminated string
int nBytes = pDnsRecord->wDataLength - SIZEOF_DNS_RPC_ATMA_RECORD_DATA_HEADER;
DnsUtf8ToWCStringHelper(m_szAddress, (LPSTR)pDnsRecord->Data.ATMA.bAddress, nBytes);
}
else
{
// it is BCD encoding of DNS_ATMA_MAX_ADDR_LENGTH
ASSERT(pDnsRecord->wDataLength == (SIZEOF_DNS_RPC_ATMA_RECORD_DATA_HEADER+DNS_ATMA_MAX_ADDR_LENGTH));
_ATMA_BCD_ToString(m_szAddress, pDnsRecord->Data.ATMA.bAddress);
}
}
void CDNS_ATMA_Record::ReadDnsQueryData(DNS_RECORD* pDnsQueryRecord)
{
CDNSRecord::ReadDnsQueryData(pDnsQueryRecord);
ASSERT(pDnsQueryRecord->wType == DNS_TYPE_ATMA);
ASSERT(FALSE); // TODO
}
void CDNS_ATMA_Record::WriteRPCData(BYTE* pMem, DNS_RPC_RECORD** ppDnsRecord)
{
CDNSRecord::WriteRPCData(pMem, ppDnsRecord);
(*ppDnsRecord)->Data.ATMA.chFormat = m_chFormat;
(*ppDnsRecord)->wDataLength += SIZEOF_DNS_RPC_ATMA_RECORD_DATA_HEADER;
ASSERT((m_chFormat == DNS_ATMA_FORMAT_E164) || (m_chFormat == DNS_ATMA_FORMAT_AESA));
if (m_chFormat == DNS_ATMA_FORMAT_E164)
{
// it is a non null terminated string
USES_CONVERSION;
LPCSTR lpszAnsi = W_TO_UTF8(m_szAddress);
if (lpszAnsi != NULL)
{
DWORD nAnsiLen = UTF8_LEN(lpszAnsi);
if (nAnsiLen > DNS_ATMA_MAX_ADDR_LENGTH)
nAnsiLen = DNS_ATMA_MAX_ADDR_LENGTH;
UCHAR* pU = ((*ppDnsRecord)->Data.ATMA.bAddress);
memcpy(pU, lpszAnsi, nAnsiLen);
(*ppDnsRecord)->wDataLength = static_cast<WORD>(((*ppDnsRecord)->wDataLength + nAnsiLen) & 0xffff);
}
}
else
{
// it is BCD encoding of DNS_ATMA_MAX_ADDR_LENGTH
VERIFY(_ATMA_StringTo_BCD((*ppDnsRecord)->Data.ATMA.bAddress, m_szAddress));
(*ppDnsRecord)->wDataLength += DNS_ATMA_MAX_ADDR_LENGTH;
}
}
void CDNS_ATMA_Record::UpdateDisplayData(CString& szDisplayData)
{
ASSERT((m_chFormat == DNS_ATMA_FORMAT_E164) || (m_chFormat == DNS_ATMA_FORMAT_AESA));
if (m_chFormat == DNS_ATMA_FORMAT_E164)
{
szDisplayData.Format(L"(E164) %s", (LPCWSTR)m_szAddress);
}
else
{
szDisplayData.Format(L"(NSAP) %s", (LPCWSTR)m_szAddress);
}
}
///////////////////////////////////////////////////////////////////
// CDNS_SOA_Record
CDNS_SOA_Record::CDNS_SOA_Record()
{
m_wType = DNS_TYPE_SOA;
m_dwSerialNo = 0x0;
m_dwRefresh = 0x0;
m_dwRetry = 0x0;
m_dwExpire = 0x0;
m_dwMinimumTtl = 0x0;
}
WORD CDNS_SOA_Record::GetRPCDataLength()
{
return static_cast<WORD>(SIZEOF_DNS_RPC_SOA_RECORD_DATA_HEADER +
RPCBufferStringLen(m_szNamePrimaryServer) +
RPCBufferStringLen(m_szResponsibleParty));
}
void CDNS_SOA_Record::ReadRPCData(DNS_RPC_RECORD* pDnsRecord)
{
CDNSRecord::ReadRPCData(pDnsRecord);
ASSERT(pDnsRecord->wType == DNS_TYPE_SOA);
ASSERT(pDnsRecord->wDataLength >= (SIZEOF_DNS_RPC_SOA_RECORD_DATA_HEADER +4));
// read header data
m_dwSerialNo = pDnsRecord->Data.SOA.dwSerialNo;
m_dwRefresh = pDnsRecord->Data.SOA.dwRefresh;
m_dwRetry = pDnsRecord->Data.SOA.dwRetry;
m_dwExpire = pDnsRecord->Data.SOA.dwExpire;
m_dwMinimumTtl = pDnsRecord->Data.SOA.dwMinimumTtl;
// read primary server name
DNS_RPC_NAME* pRPCName1 = &(pDnsRecord->Data.SOA.namePrimaryServer);
ReadRPCString(m_szNamePrimaryServer, pRPCName1);
// read primary server name
DNS_RPC_NAME* pRPCName2 = DNS_GET_NEXT_NAME(pRPCName1);
ASSERT(DNS_IS_NAME_IN_RECORD(pDnsRecord,pRPCName2));
ReadRPCString(m_szResponsibleParty, pRPCName2);
ASSERT(pDnsRecord->wDataLength == (SIZEOF_DNS_RPC_SOA_RECORD_DATA_HEADER +
pRPCName1->cchNameLength + pRPCName2->cchNameLength + 2) );
}
void CDNS_SOA_Record::ReadDnsQueryData(DNS_RECORD* pDnsQueryRecord)
{
CDNSRecord::ReadDnsQueryData(pDnsQueryRecord);
ASSERT(FALSE); // TODO
}
void CDNS_SOA_Record::WriteRPCData(BYTE* pMem, DNS_RPC_RECORD** ppDnsRecord)
{
CDNSRecord::WriteRPCData(pMem, ppDnsRecord);
// write header data
(*ppDnsRecord)->Data.SOA.dwSerialNo = m_dwSerialNo;
(*ppDnsRecord)->Data.SOA.dwRefresh = m_dwRefresh;
(*ppDnsRecord)->Data.SOA.dwRetry = m_dwRetry;
(*ppDnsRecord)->Data.SOA.dwExpire = m_dwExpire;
(*ppDnsRecord)->Data.SOA.dwMinimumTtl = m_dwMinimumTtl;
(*ppDnsRecord)->wDataLength += SIZEOF_DNS_RPC_SOA_RECORD_DATA_HEADER;
// write primary server name
DNS_RPC_NAME* pRPCName1 = &((*ppDnsRecord)->Data.SOA.namePrimaryServer);
ASSERT(DNS_IS_DWORD_ALIGNED(pRPCName1));
(*ppDnsRecord)->wDataLength = static_cast<WORD>(((*ppDnsRecord)->wDataLength +
WriteString(pRPCName1, m_szNamePrimaryServer)) & 0xffff);
// write the responsible party
DNS_RPC_NAME* pRPCName2 = DNS_GET_NEXT_NAME(pRPCName1);
(*ppDnsRecord)->wDataLength = static_cast<WORD>(((*ppDnsRecord)->wDataLength +
WriteString(pRPCName2, m_szResponsibleParty)) & 0xffff);
ASSERT(DNS_IS_NAME_IN_RECORD((*ppDnsRecord),pRPCName1));
ASSERT(DNS_IS_NAME_IN_RECORD((*ppDnsRecord),pRPCName2));
}
void CDNS_SOA_Record::UpdateDisplayData(CString& szDisplayData)
{
szDisplayData.Format(_T("[%u], %s, %s"), m_dwSerialNo,
(LPCTSTR)m_szNamePrimaryServer,(LPCTSTR)m_szResponsibleParty);
}
///////////////////////////////////////////////////////////////////
// CDNS_PTR_NS_CNAME_MB_MD_MF_MG_MR_Record
CDNS_PTR_NS_CNAME_MB_MD_MF_MG_MR_Record::
CDNS_PTR_NS_CNAME_MB_MD_MF_MG_MR_Record()
{
}
WORD CDNS_PTR_NS_CNAME_MB_MD_MF_MG_MR_Record::GetRPCDataLength()
{
return RPCBufferStringLen(m_szNameNode);
}
void CDNS_PTR_NS_CNAME_MB_MD_MF_MG_MR_Record::
ReadRPCData(DNS_RPC_RECORD* pDnsRecord)
{
CDNSRecord::ReadRPCData(pDnsRecord);
ASSERT( (pDnsRecord->wType == DNS_TYPE_PTR) ||
(pDnsRecord->wType == DNS_TYPE_NS) ||
(pDnsRecord->wType == DNS_TYPE_CNAME) ||
(pDnsRecord->wType == DNS_TYPE_MB) ||
(pDnsRecord->wType == DNS_TYPE_MD) ||
(pDnsRecord->wType == DNS_TYPE_MF) ||
(pDnsRecord->wType == DNS_TYPE_MG) ||
(pDnsRecord->wType == DNS_TYPE_MR) );
DNS_RPC_NAME* pRPCName = &(pDnsRecord->Data.NS.nameNode);
ASSERT(pDnsRecord->wDataLength == pRPCName->cchNameLength +1);
// read name node
ReadRPCString(m_szNameNode, pRPCName);
}
void CDNS_PTR_NS_CNAME_MB_MD_MF_MG_MR_Record::ReadDnsQueryData(DNS_RECORD* pDnsQueryRecord)
{
CDNSRecord::ReadDnsQueryData(pDnsQueryRecord);
ASSERT( (pDnsQueryRecord->wType == DNS_TYPE_PTR) ||
(pDnsQueryRecord->wType == DNS_TYPE_NS) ||
(pDnsQueryRecord->wType == DNS_TYPE_CNAME) ||
(pDnsQueryRecord->wType == DNS_TYPE_MB) ||
(pDnsQueryRecord->wType == DNS_TYPE_MD) ||
(pDnsQueryRecord->wType == DNS_TYPE_MF) ||
(pDnsQueryRecord->wType == DNS_TYPE_MG) ||
(pDnsQueryRecord->wType == DNS_TYPE_MR) );
m_szNameNode = pDnsQueryRecord->Data.NS.pNameHost;
}
void CDNS_PTR_NS_CNAME_MB_MD_MF_MG_MR_Record
::WriteRPCData(BYTE* pMem, DNS_RPC_RECORD** ppDnsRecord)
{
CDNSRecord::WriteRPCData(pMem, ppDnsRecord);
// write name node
DNS_RPC_NAME* pRPCName = &((*ppDnsRecord)->Data.NS.nameNode);
(*ppDnsRecord)->wDataLength = static_cast<WORD>(((*ppDnsRecord)->wDataLength +
WriteString(pRPCName,m_szNameNode)) & 0xffff);
}
void CDNS_PTR_NS_CNAME_MB_MD_MF_MG_MR_Record::UpdateDisplayData(CString& szDisplayData)
{
szDisplayData = m_szNameNode;
}
///////////////////////////////////////////////////////////////////
// CDNS_MINFO_RP_Record
CDNS_MINFO_RP_Record::CDNS_MINFO_RP_Record()
{
}
WORD CDNS_MINFO_RP_Record::GetRPCDataLength()
{
return static_cast<WORD>(RPCBufferStringLen(m_szNameMailBox) +
RPCBufferStringLen(m_szErrorToMailbox));
}
void CDNS_MINFO_RP_Record::ReadRPCData(DNS_RPC_RECORD* pDnsRecord)
{
CDNSRecord::ReadRPCData(pDnsRecord);
ASSERT( (pDnsRecord->wType == DNS_TYPE_MINFO) ||
(pDnsRecord->wType == DNS_TYPE_RP));
// read mailbox name
DNS_RPC_NAME* pRPCName1 = &(pDnsRecord->Data.MINFO.nameMailBox);
ReadRPCString(m_szNameMailBox, pRPCName1);
// read errors to mailbox
DNS_RPC_NAME* pRPCName2 = DNS_GET_NEXT_NAME(pRPCName1);
ASSERT(DNS_IS_NAME_IN_RECORD(pDnsRecord,pRPCName2));
ReadRPCString(m_szErrorToMailbox, pRPCName2);
ASSERT(pDnsRecord->wDataLength ==
(pRPCName1->cchNameLength + pRPCName2->cchNameLength + 2) );
}
void CDNS_MINFO_RP_Record::ReadDnsQueryData(DNS_RECORD* pDnsQueryRecord)
{
CDNSRecord::ReadDnsQueryData(pDnsQueryRecord);
ASSERT(FALSE); // TODO
}
void CDNS_MINFO_RP_Record::
WriteRPCData(BYTE* pMem, DNS_RPC_RECORD** ppDnsRecord)
{
CDNSRecord::WriteRPCData(pMem, ppDnsRecord);
// write mailbox name
DNS_RPC_NAME* pRPCName1 = &((*ppDnsRecord)->Data.MINFO.nameMailBox);
ASSERT(DNS_IS_DWORD_ALIGNED(pRPCName1));
(*ppDnsRecord)->wDataLength = static_cast<WORD>(((*ppDnsRecord)->wDataLength +
WriteString(pRPCName1, m_szNameMailBox)) & 0xffff);
// write errors to mailbox
DNS_RPC_NAME* pRPCName2 = DNS_GET_NEXT_NAME(pRPCName1);
(*ppDnsRecord)->wDataLength = static_cast<WORD>(((*ppDnsRecord)->wDataLength +
WriteString(pRPCName2, m_szErrorToMailbox)) & 0xffff);
ASSERT(DNS_IS_NAME_IN_RECORD((*ppDnsRecord),pRPCName1));
ASSERT(DNS_IS_NAME_IN_RECORD((*ppDnsRecord),pRPCName2));
}
void CDNS_MINFO_RP_Record::UpdateDisplayData(CString& szDisplayData)
{
if ((GetType() == DNS_TYPE_RP) && (m_szErrorToMailbox.IsEmpty()))
{
szDisplayData.Format(_T("%s"),(LPCTSTR)m_szNameMailBox);
}
else
{
szDisplayData.Format(_T("%s, %s"),
(LPCTSTR)m_szNameMailBox,(LPCTSTR)m_szErrorToMailbox);
}
}
///////////////////////////////////////////////////////////////////
// CDNS_MX_AFSDB_RT_Record
CDNS_MX_AFSDB_RT_Record::CDNS_MX_AFSDB_RT_Record()
{
m_wPreference = 0x0;
}
WORD CDNS_MX_AFSDB_RT_Record::GetRPCDataLength()
{
return static_cast<WORD>(SIZEOF_DNS_RPC_MXAFSBD_RT_RECORD_DATA_HEADER +
RPCBufferStringLen(m_szNameExchange));
}
void CDNS_MX_AFSDB_RT_Record::
ReadRPCData(DNS_RPC_RECORD* pDnsRecord)
{
CDNSRecord::ReadRPCData(pDnsRecord);
ASSERT( (pDnsRecord->wType == DNS_TYPE_MX) ||
(pDnsRecord->wType == DNS_TYPE_AFSDB) ||
(pDnsRecord->wType == DNS_TYPE_RT));
// read header data
m_wPreference = pDnsRecord->Data.MX.wPreference;
// read name exchange
DNS_RPC_NAME* pRPCName = &(pDnsRecord->Data.MX.nameExchange);
ASSERT(pDnsRecord->wDataLength ==
SIZEOF_DNS_RPC_MXAFSBD_RT_RECORD_DATA_HEADER + pRPCName->cchNameLength +1);
ReadRPCString(m_szNameExchange, pRPCName);
}
void CDNS_MX_AFSDB_RT_Record::ReadDnsQueryData(DNS_RECORD* pDnsQueryRecord)
{
CDNSRecord::ReadDnsQueryData(pDnsQueryRecord);
ASSERT(FALSE); // TODO
}
void CDNS_MX_AFSDB_RT_Record::
WriteRPCData(BYTE* pMem, DNS_RPC_RECORD** ppDnsRecord)
{
CDNSRecord::WriteRPCData(pMem, ppDnsRecord);
// write header data
(*ppDnsRecord)->Data.MX.wPreference = m_wPreference;
(*ppDnsRecord)->wDataLength = static_cast<WORD>(((*ppDnsRecord)->wDataLength +
SIZEOF_DNS_RPC_MXAFSBD_RT_RECORD_DATA_HEADER) & 0xffff);
// write name exchange
DNS_RPC_NAME* pRPCName = &((*ppDnsRecord)->Data.MX.nameExchange);
(*ppDnsRecord)->wDataLength = static_cast<WORD>(((*ppDnsRecord)->wDataLength +
WriteString(pRPCName,m_szNameExchange)) & 0xffff);
}
void CDNS_MX_AFSDB_RT_Record::UpdateDisplayData(CString& szDisplayData)
{
TCHAR szBuf[32];
szBuf[0] = NULL;
LPCTSTR lpsz;
if ( (m_wType == DNS_TYPE_AFSDB) &&
((m_wPreference == AFSDB_PREF_AFS_CELL_DB_SERV) ||
(m_wPreference == AFSDB_PREF_DCE_AUTH_NAME_SERV)) )
{
if (m_wPreference == AFSDB_PREF_AFS_CELL_DB_SERV)
lpsz = _T("AFS");
else
lpsz = _T("DCE");
}
else
{
wsprintf(szBuf,_T("%d"), m_wPreference);
lpsz = szBuf;
}
szDisplayData.Format(_T("[%s] %s"), lpsz,(LPCTSTR)m_szNameExchange);
}
///////////////////////////////////////////////////////////////////
// CDNS_AAAA_Record
CDNS_AAAA_Record::CDNS_AAAA_Record()
{
m_wType = DNS_TYPE_AAAA;
memset(&m_ipv6Address, 0x0,sizeof(IPV6_ADDRESS));
}
WORD CDNS_AAAA_Record::GetRPCDataLength()
{
return (WORD)SIZEOF_DNS_RPC_AAAA_RECORD_DATA_HEADER;
}
void CDNS_AAAA_Record::ReadRPCData(DNS_RPC_RECORD* pDnsRecord)
{
CDNSRecord::ReadRPCData(pDnsRecord);
ASSERT(pDnsRecord->wType == DNS_TYPE_AAAA);
ASSERT(pDnsRecord->wDataLength == SIZEOF_DNS_RPC_AAAA_RECORD_DATA_HEADER);
memcpy(&m_ipv6Address, (UNALIGNED IPV6_ADDRESS*)(&(pDnsRecord->Data.AAAA.ipv6Address)), sizeof(IPV6_ADDRESS));
}
void CDNS_AAAA_Record::ReadDnsQueryData(DNS_RECORD* pDnsQueryRecord)
{
CDNSRecord::ReadDnsQueryData(pDnsQueryRecord);
ASSERT(FALSE); // TODO
}
void CDNS_AAAA_Record::WriteRPCData(BYTE* pMem, DNS_RPC_RECORD** ppDnsRecord)
{
CDNSRecord::WriteRPCData(pMem, ppDnsRecord);
memcpy(&((*ppDnsRecord)->Data.AAAA.ipv6Address), &m_ipv6Address, sizeof(IPV6_ADDRESS));
(*ppDnsRecord)->wDataLength += SIZEOF_DNS_RPC_AAAA_RECORD_DATA_HEADER;
}
void CDNS_AAAA_Record::UpdateDisplayData(CString& szDisplayData)
{
FormatIPv6Addr(szDisplayData, &m_ipv6Address);
}
///////////////////////////////////////////////////////////////////
// CDNS_HINFO_ISDN_TXT_X25_Record
CDNS_HINFO_ISDN_TXT_X25_Record::
CDNS_HINFO_ISDN_TXT_X25_Record()
{
}
WORD CDNS_HINFO_ISDN_TXT_X25_Record::GetRPCDataLength()
{
ASSERT(FALSE); // intermediate class
return 0;
}
void CDNS_HINFO_ISDN_TXT_X25_Record::
ReadRPCData(DNS_RPC_RECORD* pDnsRecord)
{
CDNSRecord::ReadRPCData(pDnsRecord);
ASSERT( (pDnsRecord->wType == DNS_TYPE_HINFO) ||
(pDnsRecord->wType == DNS_TYPE_ISDN) ||
(pDnsRecord->wType == DNS_TYPE_TEXT) ||
(pDnsRecord->wType == DNS_TYPE_X25) );
// loop to the end of the buffer and copy into array of strings
DNS_RPC_NAME* pRPCName = &(pDnsRecord->Data.HINFO.stringData);
int k = 0;
WORD wDataLength = 0x0;
CString szTemp;
while ((PCHAR)pRPCName < DNS_GET_END_OF_RPC_RECORD_DATA(pDnsRecord))
{
ReadRPCString(szTemp, pRPCName);
OnReadRPCString(szTemp, k++);
wDataLength = wDataLength + static_cast<WORD>(pRPCName->cchNameLength + 1);
pRPCName = DNS_GET_NEXT_NAME(pRPCName);
}
SetStringCount(k);
ASSERT(pDnsRecord->wDataLength == wDataLength);
}
void CDNS_HINFO_ISDN_TXT_X25_Record::ReadDnsQueryData(DNS_RECORD* pDnsQueryRecord)
{
CDNSRecord::ReadDnsQueryData(pDnsQueryRecord);
ASSERT(FALSE); // TODO
}
void CDNS_HINFO_ISDN_TXT_X25_Record::
WriteRPCData(BYTE* pMem, DNS_RPC_RECORD** ppDnsRecord)
{
CDNSRecord::WriteRPCData(pMem, ppDnsRecord);
// loop through the list of strings
DNS_RPC_NAME* pRPCName = &((*ppDnsRecord)->Data.HINFO.stringData);
int nCount = GetStringCount();
for (int j=0; j < nCount; j++)
{
//(*ppDnsRecord)->wDataLength += WriteString(pRPCName,m_stringDataArray[j]);
(*ppDnsRecord)->wDataLength = static_cast<WORD>(((*ppDnsRecord)->wDataLength +
OnWriteString(pRPCName,j)) & 0xffff);
pRPCName = DNS_GET_NEXT_NAME(pRPCName);
}
}
void CDNS_HINFO_ISDN_TXT_X25_Record::UpdateDisplayData(CString& szDisplayData)
{
ASSERT(FALSE);
szDisplayData = _T("ERROR, should never happen");
}
///////////////////////////////////////////////////////////////////
// CDNS_HINFO_Record
WORD CDNS_HINFO_Record::GetRPCDataLength()
{
return static_cast<WORD>(RPCBufferStringLen(m_szCPUType) +
RPCBufferStringLen(m_szOperatingSystem));
}
void CDNS_HINFO_Record::OnReadRPCString(LPCTSTR lpszStr, int k)
{
switch (k)
{
case 0:
m_szCPUType = lpszStr;
break;
case 1:
m_szOperatingSystem = lpszStr;
break;
default:
ASSERT(FALSE);
}
}
WORD CDNS_HINFO_Record::OnWriteString(DNS_RPC_NAME* pDnsRPCName, int k)
{
switch (k)
{
case 0:
return WriteString(pDnsRPCName,m_szCPUType);
case 1:
return WriteString(pDnsRPCName,m_szOperatingSystem);
default:
ASSERT(FALSE);
}
return 0;
}
void CDNS_HINFO_Record::UpdateDisplayData(CString& szDisplayData)
{
szDisplayData.Format(_T("%s, %s"),(LPCTSTR)m_szCPUType, (LPCTSTR)m_szOperatingSystem);
}
///////////////////////////////////////////////////////////////////
// CDNS_ISDN_Record
WORD CDNS_ISDN_Record::GetRPCDataLength()
{
return static_cast<WORD>(RPCBufferStringLen(m_szPhoneNumberAndDDI) +
RPCBufferStringLen(m_szSubAddress));
}
CDNS_ISDN_Record::CDNS_ISDN_Record()
{
m_wType = DNS_TYPE_ISDN;
}
void CDNS_ISDN_Record::OnReadRPCString(LPCTSTR lpszStr, int k)
{
switch (k)
{
case 0:
m_szPhoneNumberAndDDI = lpszStr;
m_szSubAddress.Empty(); // copy from 2 to 1 strings might not execute case 1:
break;
case 1:
m_szSubAddress = lpszStr;
break;
default:
ASSERT(FALSE);
}
}
WORD CDNS_ISDN_Record::OnWriteString(DNS_RPC_NAME* pDnsRPCName, int k)
{
switch (k)
{
case 0:
return WriteString(pDnsRPCName,m_szPhoneNumberAndDDI);
case 1:
{
ASSERT(!m_szSubAddress.IsEmpty());
if (m_szSubAddress.IsEmpty())
return 0;
return WriteString(pDnsRPCName,m_szSubAddress);
}
default:
ASSERT(FALSE);
}
return 0;
}
void CDNS_ISDN_Record::UpdateDisplayData(CString& szDisplayData)
{
if(m_szSubAddress.IsEmpty())
szDisplayData = m_szPhoneNumberAndDDI;
else
szDisplayData.Format(_T("%s, %s"),(LPCTSTR)m_szPhoneNumberAndDDI, (LPCTSTR)m_szSubAddress);
}
///////////////////////////////////////////////////////////////////
// CDNS_TXT_Record
CDNS_TXT_Record::CDNS_TXT_Record()
{
m_wType = DNS_TYPE_TEXT;
m_stringDataArray.SetSize(2,2); // SetSize(size, grow by)
m_nStringDataCount = 0; // empty
}
WORD CDNS_TXT_Record::GetRPCDataLength()
{
WORD wLen = 0;
for (int j=0; j<m_nStringDataCount; j++)
{
wLen = static_cast<WORD>((wLen + (RPCBufferStringLen(m_stringDataArray[j])) & 0xffff));
}
return wLen;
}
void CDNS_TXT_Record::OnReadRPCString(LPCTSTR lpszStr, int k)
{
m_stringDataArray.SetAtGrow(k,lpszStr);
}
WORD CDNS_TXT_Record::OnWriteString(DNS_RPC_NAME* pDnsRPCName, int k)
{
return WriteString(pDnsRPCName,m_stringDataArray[k]);
}
#define MAX_TXT_DISPLAYLEN 80 // arbitrary width
void CDNS_TXT_Record::UpdateDisplayData(CString& szDisplayData)
{
szDisplayData.Empty();
if (m_nStringDataCount == 0)
return;
szDisplayData = m_stringDataArray[0];
if (szDisplayData.GetLength() > MAX_TXT_DISPLAYLEN)
{
szDisplayData.Left(MAX_TXT_DISPLAYLEN);
szDisplayData += _T(" ...");
return;
}
for (int j=1; j<m_nStringDataCount; j++)
{
szDisplayData += _T(", ");
szDisplayData += m_stringDataArray[j];
if (szDisplayData.GetLength() > MAX_TXT_DISPLAYLEN)
{
szDisplayData.Left(MAX_TXT_DISPLAYLEN);
szDisplayData += _T(" ...");
break;
}
}
}
///////////////////////////////////////////////////////////////////
// CDNS_X25_Record
WORD CDNS_X25_Record::GetRPCDataLength()
{
return RPCBufferStringLen(m_szX121PSDNAddress);
}
void CDNS_X25_Record::OnReadRPCString(LPCTSTR lpszStr, int k)
{
ASSERT(k == 0);
m_szX121PSDNAddress = lpszStr;
}
WORD CDNS_X25_Record::OnWriteString(DNS_RPC_NAME* pDnsRPCName, int k)
{
ASSERT(k == 0);
return WriteString(pDnsRPCName,m_szX121PSDNAddress);
}
void CDNS_X25_Record::UpdateDisplayData(CString& szDisplayData)
{
szDisplayData = m_szX121PSDNAddress;
}
///////////////////////////////////////////////////////////////////
// CDNS_WKS_Record
CDNS_WKS_Record::CDNS_WKS_Record()
{
m_wType = DNS_TYPE_WKS;
m_ipAddress = 0x0;
m_chProtocol = DNS_WKS_PROTOCOL_TCP;
//m_bBitMask[0] = 0x0;
}
WORD CDNS_WKS_Record::GetRPCDataLength()
{
return static_cast<WORD>(SIZEOF_DNS_RPC_WKS_RECORD_DATA_HEADER +
RPCBufferStringLen(m_szServiceList));
}
void CDNS_WKS_Record::ReadRPCData(DNS_RPC_RECORD* pDnsRecord)
{
CDNSRecord::ReadRPCData(pDnsRecord);
ASSERT(pDnsRecord->wType == DNS_TYPE_WKS);
m_ipAddress = pDnsRecord->Data.WKS.ipAddress;
m_chProtocol = pDnsRecord->Data.WKS.chProtocol;
DNS_RPC_NAME* pRPCName = (DNS_RPC_NAME*)(pDnsRecord->Data.WKS.bBitMask);
ReadRPCString(m_szServiceList, pRPCName);
//ASSERT(pDnsRecord->wDataLength == SIZEOF_DNS_RPC_WKS_RECORD_DATA_HEADER);
//m_ipAddress = pDnsRecord->Data.WKS.ipAddress;
//m_chProtocol = pDnsRecord->Data.WKS.chProtocol;
//m_bBitMask[0] = pDnsRecord->Data.WKS.bBitMask[0];
}
void CDNS_WKS_Record::ReadDnsQueryData(DNS_RECORD* pDnsQueryRecord)
{
CDNSRecord::ReadDnsQueryData(pDnsQueryRecord);
ASSERT(FALSE); // TODO
}
void CDNS_WKS_Record::WriteRPCData(BYTE* pMem, DNS_RPC_RECORD** ppDnsRecord)
{
CDNSRecord::WriteRPCData(pMem, ppDnsRecord);
(*ppDnsRecord)->Data.WKS.ipAddress = m_ipAddress;
(*ppDnsRecord)->Data.WKS.chProtocol = m_chProtocol;
(*ppDnsRecord)->wDataLength += SIZEOF_DNS_RPC_WKS_RECORD_DATA_HEADER;
DNS_RPC_NAME* pRPCName = (DNS_RPC_NAME*)((*ppDnsRecord)->Data.WKS.bBitMask);
ASSERT(!DNS_IS_DWORD_ALIGNED(pRPCName));
(*ppDnsRecord)->wDataLength = static_cast<WORD>(((*ppDnsRecord)->wDataLength +
WriteString(pRPCName, m_szServiceList)) & 0xffff);
// (*ppDnsRecord)->Data.WKS.ipAddress = m_ipAddress;
// (*ppDnsRecord)->Data.WKS.chProtocol = m_chProtocol;
// (*ppDnsRecord)->Data.WKS.bBitMask[0] = m_bBitMask[0];
}
void CDNS_WKS_Record::UpdateDisplayData(CString& szDisplayData)
{
TCHAR szBuf[32];
szBuf[0] = NULL;
LPCTSTR lpsz;
if (m_chProtocol == DNS_WKS_PROTOCOL_TCP)
lpsz = _T("TCP");
else if (m_chProtocol == DNS_WKS_PROTOCOL_UDP)
lpsz = _T("UDP");
else
{
wsprintf(szBuf,_T("%d"), m_chProtocol);
lpsz = szBuf;
}
szDisplayData.Format(_T("[%s] %s"), lpsz,(LPCTSTR)m_szServiceList);
}
///////////////////////////////////////////////////////////////////
// CDNS_WINS_Record
CDNS_WINS_Record::CDNS_WINS_Record()
{
m_wType = DNS_TYPE_WINS;
m_dwMappingFlag = 0x0;
m_dwLookupTimeout = DNS_RR_WINS_LOOKUP_DEFAULT_TIMEOUT;
m_dwCacheTimeout = DNS_RR_WINS_CACHE_DEFAULT_TIMEOUT;
m_ipWinsServersArray.SetSize(4,4); // SetSize(size, grow by)
m_nWinsServerCount = 0; // empty
}
WORD CDNS_WINS_Record::GetRPCDataLength()
{
return static_cast<WORD>((SIZEOF_DNS_RPC_WINS_RECORD_DATA_HEADER +
m_nWinsServerCount*sizeof(IP_ADDRESS)) & 0xff);
}
void CDNS_WINS_Record::ReadRPCData(DNS_RPC_RECORD* pDnsRecord)
{
CDNSRecord::ReadRPCData(pDnsRecord);
ASSERT(pDnsRecord->wType == DNS_TYPE_WINS);
ASSERT(pDnsRecord->wDataLength == SIZEOF_DNS_RPC_WINS_RECORD_DATA_HEADER +
pDnsRecord->Data.WINS.cWinsServerCount*sizeof(IP_ADDRESS));
m_dwMappingFlag = pDnsRecord->Data.WINS.dwMappingFlag;
m_dwLookupTimeout = pDnsRecord->Data.WINS.dwLookupTimeout;
m_dwCacheTimeout = pDnsRecord->Data.WINS.dwCacheTimeout;
m_nWinsServerCount = pDnsRecord->Data.WINS.cWinsServerCount;
for (DWORD k=0; k<pDnsRecord->Data.WINS.cWinsServerCount; k++)
m_ipWinsServersArray.SetAtGrow(k, pDnsRecord->Data.WINS.aipWinsServers[k]);
}
void CDNS_WINS_Record::ReadDnsQueryData(DNS_RECORD* pDnsQueryRecord)
{
CDNSRecord::ReadDnsQueryData(pDnsQueryRecord);
ASSERT(FALSE); // TODO
}
void CDNS_WINS_Record::WriteRPCData(BYTE* pMem, DNS_RPC_RECORD** ppDnsRecord)
{
CDNSRecord::WriteRPCData(pMem, ppDnsRecord);
(*ppDnsRecord)->Data.WINS.dwMappingFlag = m_dwMappingFlag;
(*ppDnsRecord)->Data.WINS.dwLookupTimeout = m_dwLookupTimeout;
(*ppDnsRecord)->Data.WINS.dwCacheTimeout = m_dwCacheTimeout;
(*ppDnsRecord)->Data.WINS.cWinsServerCount = m_nWinsServerCount;
for (DWORD k=0; k<(*ppDnsRecord)->Data.WINS.cWinsServerCount; k++)
(*ppDnsRecord)->Data.WINS.aipWinsServers[k] = m_ipWinsServersArray[k];
(*ppDnsRecord)->wDataLength = static_cast<WORD>(((*ppDnsRecord)->wDataLength +
SIZEOF_DNS_RPC_WINS_RECORD_DATA_HEADER +
(*ppDnsRecord)->Data.WINS.cWinsServerCount*sizeof(IP_ADDRESS)) &
0xffff);
}
void CDNS_WINS_Record::UpdateDisplayData(CString& szDisplayData)
{
szDisplayData.Empty();
if (m_nWinsServerCount == 0)
return;
// need to chain the IP addresses in a single string
CString szTemp;
szTemp.GetBuffer(20); // length of an IP string
szTemp.ReleaseBuffer();
szDisplayData.GetBuffer(20*m_nWinsServerCount);
szDisplayData.ReleaseBuffer();
for (int k=0; k<m_nWinsServerCount; k++)
{
szDisplayData += _T("[");
FormatIpAddress(szTemp, m_ipWinsServersArray[k]);
szDisplayData += szTemp;
szDisplayData += _T("] ");
}
}
///////////////////////////////////////////////////////////////////
// CDNS_NBSTAT_Record
CDNS_NBSTAT_Record::CDNS_NBSTAT_Record()
{
m_wType = DNS_TYPE_NBSTAT;
m_dwMappingFlag = 0x0;
m_dwLookupTimeout = DNS_RR_WINS_LOOKUP_DEFAULT_TIMEOUT;
m_dwCacheTimeout = DNS_RR_WINS_CACHE_DEFAULT_TIMEOUT;
}
WORD CDNS_NBSTAT_Record::GetRPCDataLength()
{
return static_cast<WORD>(SIZEOF_DNS_RPC_NBSTAT_RECORD_DATA_HEADER +
RPCBufferStringLen(m_szNameResultDomain));
}
void CDNS_NBSTAT_Record::ReadRPCData(DNS_RPC_RECORD* pDnsRecord)
{
CDNSRecord::ReadRPCData(pDnsRecord);
ASSERT(pDnsRecord->wType == DNS_TYPE_NBSTAT);
m_dwMappingFlag = pDnsRecord->Data.NBSTAT.dwMappingFlag;
m_dwLookupTimeout = pDnsRecord->Data.NBSTAT.dwLookupTimeout;
m_dwCacheTimeout = pDnsRecord->Data.NBSTAT.dwCacheTimeout;
DNS_RPC_NAME* pRPCName = &(pDnsRecord->Data.NBSTAT.nameResultDomain);
ASSERT(pDnsRecord->wDataLength ==
SIZEOF_DNS_RPC_NBSTAT_RECORD_DATA_HEADER + pRPCName->cchNameLength +1);
ReadRPCString(m_szNameResultDomain, pRPCName);
}
void CDNS_NBSTAT_Record::ReadDnsQueryData(DNS_RECORD* pDnsQueryRecord)
{
CDNSRecord::ReadDnsQueryData(pDnsQueryRecord);
ASSERT(FALSE); // TODO
}
void CDNS_NBSTAT_Record::WriteRPCData(BYTE* pMem, DNS_RPC_RECORD** ppDnsRecord)
{
CDNSRecord::WriteRPCData(pMem, ppDnsRecord);
(*ppDnsRecord)->Data.NBSTAT.dwMappingFlag = m_dwMappingFlag;
(*ppDnsRecord)->Data.NBSTAT.dwLookupTimeout = m_dwLookupTimeout;
(*ppDnsRecord)->Data.NBSTAT.dwCacheTimeout= m_dwCacheTimeout;
(*ppDnsRecord)->wDataLength += SIZEOF_DNS_RPC_NBSTAT_RECORD_DATA_HEADER;
DNS_RPC_NAME* pRPCName = &((*ppDnsRecord)->Data.NBSTAT.nameResultDomain);
(*ppDnsRecord)->wDataLength = static_cast<WORD>(((*ppDnsRecord)->wDataLength +
WriteString(pRPCName,m_szNameResultDomain)) & 0xffff);
}
void CDNS_NBSTAT_Record::UpdateDisplayData(CString& szDisplayData)
{
szDisplayData = m_szNameResultDomain;
}
///////////////////////////////////////////////////////////////////
// CDNS_SRV_Record
CDNS_SRV_Record::CDNS_SRV_Record()
{
m_wType = DNS_TYPE_SRV;
m_wPriority = 0x0;
m_wWeight = 0x0;
m_wPort = 0x0;
}
WORD CDNS_SRV_Record::GetRPCDataLength()
{
return static_cast<WORD>(SIZEOF_DNS_RPC_SRV_RECORD_DATA_HEADER +
RPCBufferStringLen(m_szNameTarget));
}
void CDNS_SRV_Record::ReadRPCData(DNS_RPC_RECORD* pDnsRecord)
{
CDNSRecord::ReadRPCData(pDnsRecord);
ASSERT(pDnsRecord->wType == DNS_TYPE_SRV);
m_wPriority = pDnsRecord->Data.SRV.wPriority;
m_wWeight = pDnsRecord->Data.SRV.wWeight;
m_wPort= pDnsRecord->Data.SRV.wPort;
DNS_RPC_NAME* pRPCName = &(pDnsRecord->Data.SRV.nameTarget);
ASSERT(pDnsRecord->wDataLength ==
SIZEOF_DNS_RPC_SRV_RECORD_DATA_HEADER + pRPCName->cchNameLength +1);
ReadRPCString(m_szNameTarget, pRPCName);
}
void CDNS_SRV_Record::ReadDnsQueryData(DNS_RECORD* pDnsQueryRecord)
{
CDNSRecord::ReadDnsQueryData(pDnsQueryRecord);
ASSERT(FALSE); // TODO
}
void CDNS_SRV_Record::WriteRPCData(BYTE* pMem, DNS_RPC_RECORD** ppDnsRecord)
{
CDNSRecord::WriteRPCData(pMem, ppDnsRecord);
(*ppDnsRecord)->Data.SRV.wPriority = m_wPriority;
(*ppDnsRecord)->Data.SRV.wWeight = m_wWeight;
(*ppDnsRecord)->Data.SRV.wPort = m_wPort;
(*ppDnsRecord)->wDataLength += SIZEOF_DNS_RPC_SRV_RECORD_DATA_HEADER;
DNS_RPC_NAME* pRPCName = &((*ppDnsRecord)->Data.SRV.nameTarget);
(*ppDnsRecord)->wDataLength = static_cast<WORD>(((*ppDnsRecord)->wDataLength +
WriteString(pRPCName,m_szNameTarget)) & 0xffff);
}
void CDNS_SRV_Record::UpdateDisplayData(CString& szDisplayData)
{
szDisplayData.Format(_T("[%d][%d][%d] %s"),
m_wPriority, m_wWeight, m_wPort, m_szNameTarget);
}
///////////////////////////////////////////////////////////////////
// CDNS_SIG_Record
CDNS_SIG_Record::CDNS_SIG_Record()
{
m_wType = DNS_TYPE_SIG;
m_wTypeCovered = 0;
m_chAlgorithm = 0;
m_chLabels = 0;
m_dwOriginalTtl = 0;
m_dwExpiration = 0;
m_dwTimeSigned = 0;
m_wKeyFootprint = 0;
m_szSignerName = L"";
}
WORD CDNS_SIG_Record::GetRPCDataLength()
{
WORD wSize = static_cast<WORD>(SIZEOF_DNS_RPC_SIG_RECORD_DATA_HEADER);
wSize = static_cast<WORD>(wSize + RPCBufferStringLen(m_szSignerName));
wSize = static_cast<WORD>(wSize + m_Signature.GetSize());
return wSize;
}
void CDNS_SIG_Record::ReadRPCData(DNS_RPC_RECORD* pDnsRecord)
{
CDNSRecord::ReadRPCData(pDnsRecord);
ASSERT(pDnsRecord->wType == DNS_TYPE_SIG);
ASSERT(pDnsRecord->wDataLength >= (SIZEOF_DNS_RPC_SIG_RECORD_DATA_HEADER));
// constant length data
m_wTypeCovered = pDnsRecord->Data.SIG.wTypeCovered;
m_chAlgorithm = pDnsRecord->Data.SIG.chAlgorithm;
m_chLabels = pDnsRecord->Data.SIG.chLabelCount;
m_dwOriginalTtl = pDnsRecord->Data.SIG.dwOriginalTtl;
m_dwExpiration = pDnsRecord->Data.SIG.dwSigExpiration;
m_dwTimeSigned = pDnsRecord->Data.SIG.dwSigInception;
m_wKeyFootprint = pDnsRecord->Data.SIG.wKeyTag;
ReadRPCString(m_szSignerName, &(pDnsRecord->Data.SIG.nameSigner));
BYTE* pBlob = (BYTE*)DNS_GET_NEXT_NAME(&(pDnsRecord->Data.SIG.nameSigner));
UINT blobSize = pDnsRecord->wDataLength -
SIZEOF_DNS_RPC_SIG_RECORD_DATA_HEADER;
// Due to DNS server bug 716362 we must special case the length of the
// nameSigner. The server is returning a cchNameLength of 0 with no achString
// data. We are expecting a cchNameLength of 1 and an achString of '\0' when
// the string is empty. This only seems to happen for SIG records
if (pDnsRecord->Data.SIG.nameSigner.cchNameLength == 0)
{
blobSize -= sizeof(UCHAR);
}
else
{
blobSize -= RPCBufferStringLen(m_szSignerName);
}
m_Signature.Set(pBlob, blobSize);
}
void CDNS_SIG_Record::ReadDnsQueryData(DNS_RECORD* pDnsQueryRecord)
{
CDNSRecord::ReadDnsQueryData(pDnsQueryRecord);
ASSERT(pDnsQueryRecord->wType == DNS_TYPE_SIG);
ASSERT(FALSE); // TODO
}
void CDNS_SIG_Record::WriteRPCData(BYTE* pMem, DNS_RPC_RECORD** ppDnsRecord)
{
CDNSRecord::WriteRPCData(pMem, ppDnsRecord);
// constant length data
(*ppDnsRecord)->Data.SIG.wTypeCovered = m_wTypeCovered;
(*ppDnsRecord)->Data.SIG.chAlgorithm = m_chAlgorithm;
(*ppDnsRecord)->Data.SIG.chLabelCount = m_chLabels;
(*ppDnsRecord)->Data.SIG.dwOriginalTtl = m_dwOriginalTtl;
(*ppDnsRecord)->Data.SIG.dwSigExpiration = m_dwExpiration;
(*ppDnsRecord)->Data.SIG.dwSigInception = m_dwTimeSigned;
(*ppDnsRecord)->Data.SIG.wKeyTag = m_wKeyFootprint;
(*ppDnsRecord)->wDataLength += SIZEOF_DNS_RPC_SIG_RECORD_DATA_HEADER;
DNS_RPC_NAME* pRPCName = &((*ppDnsRecord)->Data.SIG.nameSigner);
(*ppDnsRecord)->wDataLength = static_cast<WORD>(((*ppDnsRecord)->wDataLength +
WriteString(pRPCName, m_szSignerName)) & 0xffff);
BYTE* pSignature = (BYTE*)DNS_GET_NEXT_NAME(&((*ppDnsRecord)->Data.SIG.nameSigner));
memcpy(pSignature, m_Signature.GetData(), m_Signature.GetSize());
(*ppDnsRecord)->wDataLength = static_cast<WORD>((*ppDnsRecord)->wDataLength + m_Signature.GetSize());
}
void CDNS_SIG_Record::UpdateDisplayData(CString& szDisplayData)
{
szDisplayData.Empty();
//
// Load the type covered
//
PCWSTR pszDisplay = NULL;
DNS_RECORD_INFO_ENTRY* pTable = (DNS_RECORD_INFO_ENTRY*)CDNSRecordInfo::GetInfoEntryTable();
while (pTable->nResourceID != DNS_RECORD_INFO_END_OF_TABLE)
{
if (pTable->wType == m_wTypeCovered)
{
pszDisplay = pTable->lpszShortName;
break;
}
pTable++;
}
szDisplayData += L"[";
szDisplayData += pszDisplay;
szDisplayData += L"]";
//
// Show the inception date
//
CString szInceptionTime;
if (::ConvertTTLToLocalTimeString(m_dwTimeSigned, szInceptionTime))
{
szDisplayData += L"[Inception:";
szDisplayData += szInceptionTime;
szDisplayData += L"]";
}
//
// Show the expiration date
//
CString szExpirationTime;
if (::ConvertTTLToLocalTimeString(m_dwExpiration, szExpirationTime))
{
szDisplayData += L"[Expiration:";
szDisplayData += szExpirationTime;
szDisplayData += L"]";
}
//
// Show the signer's name
//
szDisplayData += L"[";
szDisplayData += m_szSignerName;
szDisplayData += L"]";
//
// Show the algorithms
//
PCOMBOBOX_TABLE_ENTRY pTableEntry = g_Algorithms;
while (pTableEntry->nComboStringID != 0)
{
if (static_cast<BYTE>(pTableEntry->dwComboData) == m_chAlgorithm)
{
CString szAlgorithm;
VERIFY(szAlgorithm.LoadString(pTableEntry->nComboStringID));
szDisplayData += L"[";
szDisplayData += szAlgorithm;
szDisplayData += L"]";
break;
}
pTableEntry++;
}
//
// Show the label count
//
szDisplayData.Format(L"%s[%d]", szDisplayData, m_chLabels);
//
// Show the key footprint
//
szDisplayData.Format(L"%s[%d]", szDisplayData, m_wKeyFootprint);
//
// Show the key as base64
//
szDisplayData += L"[";
szDisplayData += Base64BLOBToString(m_Signature);
szDisplayData += L"]";
}
///////////////////////////////////////////////////////////////////
// CDNS_KEY_Record
CDNS_KEY_Record::CDNS_KEY_Record()
{
m_wType = DNS_TYPE_KEY;
m_wFlags = 0;
m_chProtocol = 0;
m_chAlgorithm = 0;
}
WORD CDNS_KEY_Record::GetRPCDataLength()
{
WORD wKeySize = static_cast<WORD>(m_Key.GetSize());
WORD wSize = static_cast<WORD>(SIZEOF_DNS_RPC_KEY_RECORD_DATA_HEADER + wKeySize);
return wSize;
}
void CDNS_KEY_Record::ReadRPCData(DNS_RPC_RECORD* pDnsRecord)
{
CDNSRecord::ReadRPCData(pDnsRecord);
ASSERT(pDnsRecord->wType == DNS_TYPE_KEY);
m_wFlags = pDnsRecord->Data.KEY.wFlags;
m_chProtocol = pDnsRecord->Data.KEY.chProtocol;
m_chAlgorithm = pDnsRecord->Data.KEY.chAlgorithm;
//
// set the blob
//
m_Key.Set(pDnsRecord->Data.KEY.bKey,
pDnsRecord->wDataLength - SIZEOF_DNS_RPC_KEY_RECORD_DATA_HEADER);
}
void CDNS_KEY_Record::ReadDnsQueryData(DNS_RECORD* pDnsQueryRecord)
{
CDNSRecord::ReadDnsQueryData(pDnsQueryRecord);
ASSERT(pDnsQueryRecord->wType == DNS_TYPE_KEY);
ASSERT(FALSE); // TODO
}
void CDNS_KEY_Record::WriteRPCData(BYTE* pMem, DNS_RPC_RECORD** ppDnsRecord)
{
CDNSRecord::WriteRPCData(pMem, ppDnsRecord);
(*ppDnsRecord)->Data.KEY.wFlags = m_wFlags;
(*ppDnsRecord)->Data.KEY.chProtocol = m_chProtocol;
(*ppDnsRecord)->Data.KEY.chAlgorithm = m_chAlgorithm;
(*ppDnsRecord)->wDataLength += SIZEOF_DNS_RPC_KEY_RECORD_DATA_HEADER;
BYTE* pKey = (*ppDnsRecord)->Data.KEY.bKey;
(*ppDnsRecord)->wDataLength = static_cast<WORD>(((*ppDnsRecord)->wDataLength + m_Key.Get(pKey)) & 0xffff);
}
void CDNS_KEY_Record::UpdateDisplayData(CString& szDisplayData)
{
szDisplayData.Empty();
//
// Turn the bitfield into a binary string
//
CString szTempField;
WORD wTemp = m_wFlags;
for (size_t idx = 0; idx < sizeof(WORD) * 8; idx++)
{
if ((wTemp & (0x1 << idx)) == 0)
{
szTempField = L'0' + szTempField;
}
else
{
szTempField = L'1' + szTempField;
}
}
szDisplayData += _T("[") + szTempField + _T("]");
//
// Load the protocols
//
PCOMBOBOX_TABLE_ENTRY pTableEntry = g_Protocols;
while (pTableEntry->nComboStringID != 0)
{
if (static_cast<BYTE>(pTableEntry->dwComboData) == m_chProtocol)
{
CString szProtocol;
VERIFY(szProtocol.LoadString(pTableEntry->nComboStringID));
szDisplayData += L"[";
szDisplayData += szProtocol;
szDisplayData += L"]";
break;
}
pTableEntry++;
}
//
// Load the algorithms
//
pTableEntry = g_Algorithms;
while (pTableEntry->nComboStringID != 0)
{
if (static_cast<BYTE>(pTableEntry->dwComboData) == m_chAlgorithm)
{
CString szAlgorithm;
VERIFY(szAlgorithm.LoadString(pTableEntry->nComboStringID));
szDisplayData += L"[";
szDisplayData += szAlgorithm;
szDisplayData += L"]";
break;
}
pTableEntry++;
}
//
// Show the key as base64
//
szDisplayData += L"[";
szDisplayData += Base64BLOBToString(m_Key);
szDisplayData += L"]";
}
///////////////////////////////////////////////////////////////////
// CDNS_NXT_Record
CDNS_NXT_Record::CDNS_NXT_Record()
{
m_wType = DNS_TYPE_NXT;
m_wNumTypesCovered = 0;
m_pwTypesCovered = NULL;
}
CDNS_NXT_Record::~CDNS_NXT_Record()
{
if (m_pwTypesCovered != NULL)
{
delete[] m_pwTypesCovered;
m_pwTypesCovered = NULL;
}
m_wNumTypesCovered = 0;
}
WORD CDNS_NXT_Record::GetRPCDataLength()
{
WORD wSize = RPCBufferStringLen(m_szNextDomain);
wSize = wSize + static_cast<WORD>(m_wNumTypesCovered * sizeof(WORD));
wSize += static_cast<WORD>(SIZEOF_DNS_RPC_NXT_RECORD_DATA_HEADER);
return wSize;
}
void CDNS_NXT_Record::ReadRPCData(DNS_RPC_RECORD* pDnsRecord)
{
CDNSRecord::ReadRPCData(pDnsRecord);
ASSERT(pDnsRecord->wType == DNS_TYPE_NXT);
m_wNumTypesCovered = pDnsRecord->Data.NXT.wNumTypeWords;
m_pwTypesCovered = new WORD[m_wNumTypesCovered];
if (m_pwTypesCovered != NULL)
{
for (DWORD dwIdx = 0; dwIdx < m_wNumTypesCovered; dwIdx++)
{
m_pwTypesCovered[dwIdx] = pDnsRecord->Data.NXT.wTypeWords[dwIdx];
}
}
ReadRPCString(m_szNextDomain, (DNS_RPC_STRING*)(pDnsRecord->Data.NXT.wTypeWords + m_wNumTypesCovered));
}
void CDNS_NXT_Record::ReadDnsQueryData(DNS_RECORD* pDnsQueryRecord)
{
CDNSRecord::ReadDnsQueryData(pDnsQueryRecord);
ASSERT(pDnsQueryRecord->wType == DNS_TYPE_NXT);
ASSERT(FALSE); // TODO
}
void CDNS_NXT_Record::WriteRPCData(BYTE* pMem, DNS_RPC_RECORD** ppDnsRecord)
{
CDNSRecord::WriteRPCData(pMem, ppDnsRecord);
(*ppDnsRecord)->wDataLength += SIZEOF_DNS_RPC_NXT_RECORD_DATA_HEADER;
(*ppDnsRecord)->Data.NXT.wNumTypeWords = m_wNumTypesCovered;
WORD* pTypesCovered = (*ppDnsRecord)->Data.NXT.wTypeWords;
if (pTypesCovered != NULL)
{
memcpy(pTypesCovered, m_pwTypesCovered, m_wNumTypesCovered * sizeof(WORD));
(*ppDnsRecord)->wDataLength = static_cast<WORD>(((*ppDnsRecord)->wDataLength +
m_wNumTypesCovered * sizeof(WORD)) & 0xffff);
}
DNS_RPC_NAME* pRPCName = (DNS_RPC_NAME*)(pTypesCovered + m_wNumTypesCovered);
(*ppDnsRecord)->wDataLength = static_cast<WORD>(((*ppDnsRecord)->wDataLength +
WriteString(pRPCName,m_szNextDomain)) & 0xffff);
}
void CDNS_NXT_Record::UpdateDisplayData(CString& szDisplayData)
{
szDisplayData = m_szNextDomain;
if (m_wNumTypesCovered > 0)
{
szDisplayData += L"[";
UINT nCount = 0;
for (DWORD dwIdx = 0; dwIdx < m_wNumTypesCovered; dwIdx++)
{
DNS_RECORD_INFO_ENTRY* pTable = (DNS_RECORD_INFO_ENTRY*)CDNSRecordInfo::GetInfoEntryTable();
while (pTable->nResourceID != DNS_RECORD_INFO_END_OF_TABLE)
{
if (pTable->dwFlags & DNS_RECORD_INFO_FLAG_SHOW_NXT)
{
if (pTable->wType == m_pwTypesCovered[dwIdx])
{
if (nCount > 0)
{
szDisplayData += L",";
}
szDisplayData += pTable->lpszShortName;
nCount++;
}
}
pTable++;
}
}
szDisplayData += L"]";
}
}
///////////////////////////////////////////////////////////////////
// CDNS_PTR_RecordNode
LPCWSTR CDNS_PTR_RecordNode::GetTrueRecordName()
{
return m_szLastOctectName;
}
void CDNS_PTR_RecordNode::SetRecordName(LPCTSTR lpszName, BOOL bAtTheNode)
{
// ASSERT(!bAtTheNode); // must have a non null name all the time
m_bAtTheNode = bAtTheNode;
#ifdef _DEBUG
int nDots = 0;
LPWSTR p = (LPWSTR)lpszName;
while (*p)
{
if (*p == TEXT('.'))
nDots++;
p++;
}
ASSERT(nDots == 0);
#endif // _DEBUG
m_szDisplayName = m_bAtTheNode ? CDNSRecordInfo::GetAtTheNodeDisplayString() : lpszName;
// m_szDisplayName = lpszName;
m_szLastOctectName = lpszName;
}
void CDNS_PTR_RecordNode::ChangeDisplayName(CDNSDomainNode* pDomainNode, BOOL bAdvancedView)
{
if (IsAtTheNode())
{
return;
}
if ((!pDomainNode->GetZoneNode()->IsReverse()) || bAdvancedView)
{
// for fwd lookup or advanced view, do not change the name
m_szDisplayName = m_szLastOctectName;
}
else
{
ASSERT(pDomainNode != NULL);
LPCWSTR lpszFullName = pDomainNode->GetFullName(); // e.g. "80.55.157.in-addr.arpa"
m_szDisplayName.Format(_T("%s.%s"), (LPCTSTR)m_szLastOctectName, lpszFullName);
// now got "77.80.55.157.in-addr.arpa"
BOOL bArpa = RemoveInAddrArpaSuffix(m_szDisplayName.GetBuffer(1));
m_szDisplayName.ReleaseBuffer(); // got "77.80.55.157"
if (!bArpa)
{
// failed to detect the arpa suffix, just restore the advanced name
m_szDisplayName = m_szLastOctectName;
}
else
{
ReverseIPString(m_szDisplayName.GetBuffer(1));
m_szDisplayName.ReleaseBuffer(); // finally got "157.55.80.77"
}
}
}
////////////////////////////////////////////////////////////////////////////
// special data structures and definitions to handle NS record editing
////////////////////////////////////////////////////////////////////////////
// CDNSRecordNodeEditInfo
CDNSRecordNodeEditInfo::CDNSRecordNodeEditInfo()
{
m_pRecordNode = NULL;
m_pRecord = NULL;
m_pEditInfoList = new CDNSRecordNodeEditInfoList;
m_bExisting = TRUE;
m_bUpdateUI = TRUE;
m_bOwnMemory = FALSE;
m_bFromDnsQuery = FALSE;
m_action = unchanged;
m_dwErr = 0x0;
}
CDNSRecordNodeEditInfo::~CDNSRecordNodeEditInfo()
{
Cleanup();
delete m_pEditInfoList;
ASSERT(m_pRecordNode == NULL);
ASSERT(m_pRecord == NULL);
}
void CDNSRecordNodeEditInfo::CreateFromExistingRecord(CDNSRecordNodeBase* pNode,
BOOL bOwnMemory,
BOOL bUpdateUI)
{
// copy the pointer to record node, and possibli assume ownership of memory
// but clone the record for editing
ASSERT(pNode != NULL);
m_bExisting = TRUE;
m_bUpdateUI = bUpdateUI;
m_bOwnMemory = bOwnMemory;
m_pRecordNode = pNode;
m_pRecord = pNode->CreateCloneRecord();
m_action = unchanged;
}
void CDNSRecordNodeEditInfo::CreateFromNewRecord(CDNSRecordNodeBase* pNode)
{
// this is a new record, so we own the memory
ASSERT(pNode != NULL);
m_bExisting = FALSE;
m_bOwnMemory = TRUE;
m_pRecordNode = pNode;
m_pRecord = pNode->CreateRecord();
m_action = add;
}
void CDNSRecordNodeEditInfo::Cleanup()
{
if (m_bOwnMemory && (m_pRecordNode != NULL))
delete m_pRecordNode;
m_pRecordNode = NULL;
if (m_pRecord != NULL)
{
delete m_pRecord; // if here, always to be discarded
m_pRecord = NULL;
}
m_pEditInfoList->RemoveAllNodes();
}
DNS_STATUS CDNSRecordNodeEditInfo::Update(CDNSDomainNode* pDomainNode, CComponentDataObject* pComponentData)
{
ASSERT((m_action == add) || (m_action == edit) || (m_action == unchanged));
if (m_action == add)
{
// new record
// hook up container and set name of node (same as the zone)
m_pRecordNode->SetContainer(pDomainNode);
}
else if (m_action == edit)
{
// preexisting, might have touched the TTL
// just in case domain node was not set when reading the RR
m_pRecordNode->SetContainer(pDomainNode);
}
// force a write, ignoring error if the record already exists
BOOL bUseDefaultTTL = (m_pRecord->m_dwTtlSeconds == pDomainNode->GetDefaultTTL());
m_dwErr = m_pRecordNode->Update(m_pRecord, bUseDefaultTTL,
/*bIgnoreAlreadyExists*/ TRUE);
if (m_dwErr == 0 && m_bUpdateUI)
{
// update the UI
if (m_action == add)
{
VERIFY(pDomainNode->AddChildToListAndUI(m_pRecordNode, pComponentData));
pComponentData->SetDescriptionBarText(pDomainNode);
}
else // edit
{
if (pDomainNode->IsVisible())
{
long changeMask = CHANGE_RESULT_ITEM;
VERIFY(SUCCEEDED(pComponentData->ChangeNode(m_pRecordNode, changeMask)));
}
}
}
return m_dwErr;
}
DNS_STATUS CDNSRecordNodeEditInfo::Remove(CDNSDomainNode* pDomainNode,
CComponentDataObject* pComponentData)
{
if (m_bUpdateUI)
{
ASSERT(m_pRecordNode->GetDomainNode() == pDomainNode);
m_dwErr = m_pRecordNode->DeleteOnServerAndUI(pComponentData);
}
else
{
// temporarily attach the provided domain
if (m_pRecordNode->GetContainer() == NULL)
m_pRecordNode->SetContainer(pDomainNode);
m_pRecordNode->DeleteOnServer();
}
if (m_dwErr == 0)
{
// own memory from now on
m_bOwnMemory = TRUE;
}
return m_dwErr;
}
////////////////////////////////////////////////////////////////////////////
// CDNSRecordInfo : table driven info for record types
CDNSRecordNodeBase* CDNSRecordInfo::CreateRecordNodeFromRPCData(LPCTSTR lpszName,
DNS_RPC_RECORD* pDnsRecord,
BOOL bAtTheNode)
{
ASSERT(pDnsRecord != NULL);
//
// construct an object of the right type
//
CDNSRecordNodeBase* pNode = CreateRecordNode(pDnsRecord->wType);
if (pNode == NULL)
{
return NULL;
}
//
// set the object from RPC buffer
//
pNode->SetRecordName(lpszName, bAtTheNode);
pNode->CreateFromRPCRecord(pDnsRecord);
return pNode;
}
#define SWITCH_ENTRY(x) \
case DNS_TYPE_##x : \
pNode = new CDNS_##x_RecordNode; \
break;
CDNSRecordNodeBase* CDNSRecordInfo::CreateRecordNode(WORD wType)
{
CDNSRecordNodeBase* pNode = NULL;
// construct an object of the right type
switch (wType)
{
case DNS_TYPE_A:
pNode = new CDNS_A_RecordNode;
break;
case DNS_TYPE_ATMA:
pNode = new CDNS_ATMA_RecordNode;
break;
case DNS_TYPE_SOA:
{
pNode = new CDNS_SOA_RecordNode;
if (pNode)
{
pNode->SetFlagsDown(TN_FLAG_NO_DELETE, TRUE /*bSet*/);
}
}
break;
case DNS_TYPE_PTR:
pNode = new CDNS_PTR_RecordNode;
break;
case DNS_TYPE_NS:
pNode = new CDNS_NS_RecordNode;
break;
case DNS_TYPE_CNAME:
pNode = new CDNS_CNAME_RecordNode;
break;
case DNS_TYPE_MB:
pNode = new CDNS_MB_RecordNode;
break;
case DNS_TYPE_MD:
pNode = new CDNS_MD_RecordNode;
break;
case DNS_TYPE_MF:
pNode = new CDNS_MF_RecordNode;
break;
case DNS_TYPE_MG:
pNode = new CDNS_MG_RecordNode;
break;
case DNS_TYPE_MR:
pNode = new CDNS_MR_RecordNode;
break;
case DNS_TYPE_MINFO:
pNode = new CDNS_MINFO_RecordNode;
break;
case DNS_TYPE_RP:
pNode = new CDNS_RP_RecordNode;
break;
case DNS_TYPE_MX:
pNode = new CDNS_MX_RecordNode;
break;
case DNS_TYPE_AFSDB:
pNode = new CDNS_AFSDB_RecordNode;
break;
case DNS_TYPE_RT:
pNode = new CDNS_RT_RecordNode;
break;
case DNS_TYPE_AAAA:
pNode = new CDNS_AAAA_RecordNode;
break;
case DNS_TYPE_HINFO:
pNode = new CDNS_HINFO_RecordNode;
break;
case DNS_TYPE_ISDN:
pNode = new CDNS_ISDN_RecordNode;
break;
case DNS_TYPE_TEXT:
pNode = new CDNS_TXT_RecordNode;
break;
case DNS_TYPE_X25:
pNode = new CDNS_X25_RecordNode;
break;
case DNS_TYPE_WKS:
pNode = new CDNS_WKS_RecordNode;
break;
case DNS_TYPE_WINS:
pNode = new CDNS_WINS_RecordNode;
break;
case DNS_TYPE_NBSTAT:
pNode = new CDNS_NBSTAT_RecordNode;
break;
case DNS_TYPE_SRV:
pNode = new CDNS_SRV_RecordNode;
break;
case DNS_TYPE_KEY:
pNode = new CDNS_KEY_RecordNode;
break;
case DNS_TYPE_SIG:
pNode = new CDNS_SIG_RecordNode;
break;
case DNS_TYPE_NXT:
pNode = new CDNS_NXT_RecordNode;
break;
case DNS_TYPE_NULL:
pNode = new CDNS_Null_RecordNode;
break;
default:
{
pNode = new CDNS_Null_RecordNode; // unknown type of record
}
}
ASSERT(pNode != NULL);
return pNode;
}
#define INFO_ENTRY(x) \
{DNS_TYPE_##x , L#x , NULL , NULL , IDS_RECORD_INFO_##x , L"", 0x0},
#define INFO_ENTRY_SHOWNXT(x) \
{DNS_TYPE_##x , L#x , NULL , NULL , IDS_RECORD_INFO_##x , L"", DNS_RECORD_INFO_FLAG_SHOW_NXT},
#define INFO_ENTRY_UI_CREATE(x) \
{DNS_TYPE_##x , L#x , NULL , NULL , IDS_RECORD_INFO_##x , L"", DNS_RECORD_INFO_FLAG_UICREATE | DNS_RECORD_INFO_FLAG_SHOW_NXT},
#define INFO_ENTRY_UI_CREATE_AT_NODE(x) \
{DNS_TYPE_##x , L#x , NULL , NULL , IDS_RECORD_INFO_##x , L"", DNS_RECORD_INFO_FLAG_UICREATE_AT_NODE | DNS_RECORD_INFO_FLAG_SHOW_NXT},
#define INFO_ENTRY_UI_CREATE_WHISTLER_OR_LATER(x) \
{DNS_TYPE_##x , L#x , NULL , NULL , IDS_RECORD_INFO_##x , L"", DNS_RECORD_INFO_FLAG_UICREATE | DNS_RECORD_INFO_FLAG_SHOW_NXT | DNS_RECORD_INFO_FLAG_WHISTLER_OR_LATER},
#define INFO_ENTRY_NAME(x, namestr) \
{DNS_TYPE_##x , namestr , NULL , NULL , IDS_RECORD_INFO_##x , L"", 0x0},
#define INFO_ENTRY_NAME_SHOWNXT(x, namestr) \
{DNS_TYPE_##x , namestr , NULL , NULL , IDS_RECORD_INFO_##x , L"", DNS_RECORD_INFO_FLAG_SHOW_NXT},
#define INFO_ENTRY_NAME_UI_CREATE(x, namestr) \
{DNS_TYPE_##x , namestr , NULL , NULL , IDS_RECORD_INFO_##x , L"", DNS_RECORD_INFO_FLAG_UICREATE | DNS_RECORD_INFO_FLAG_SHOW_NXT},
#define INFO_ENTRY_NAME_UI_CREATE_AT_NODE(x, namestr) \
{DNS_TYPE_##x , namestr , NULL , NULL , IDS_RECORD_INFO_##x , L"", DNS_RECORD_INFO_FLAG_UICREATE_AT_NODE | DNS_RECORD_INFO_FLAG_SHOW_NXT},
#define END_OF_TABLE_INFO_ENTRY { 0 , NULL , NULL , NULL , (UINT)-1 , L"", 0x0}
const DNS_RECORD_INFO_ENTRY* CDNSRecordInfo::GetInfoEntryTable()
{
static DNS_RECORD_INFO_ENTRY info[] =
{
// createble record types (at the node also)
INFO_ENTRY_UI_CREATE_AT_NODE(A)
INFO_ENTRY_UI_CREATE_AT_NODE(ATMA)
INFO_ENTRY_UI_CREATE_AT_NODE(AAAA)
INFO_ENTRY_NAME_UI_CREATE_AT_NODE(TEXT, L"TXT" )
// createble record types (never at the node)
INFO_ENTRY_UI_CREATE(CNAME)
INFO_ENTRY_UI_CREATE(MB)
INFO_ENTRY_UI_CREATE(MG)
INFO_ENTRY_UI_CREATE(MR)
INFO_ENTRY_UI_CREATE(PTR)
INFO_ENTRY_UI_CREATE(WKS)
INFO_ENTRY_UI_CREATE(HINFO)
INFO_ENTRY_UI_CREATE(MINFO)
INFO_ENTRY_UI_CREATE(MX)
INFO_ENTRY_UI_CREATE(RP)
INFO_ENTRY_UI_CREATE(AFSDB)
INFO_ENTRY_UI_CREATE(X25)
INFO_ENTRY_UI_CREATE(ISDN)
INFO_ENTRY_UI_CREATE(RT)
INFO_ENTRY_UI_CREATE(SRV)
INFO_ENTRY_UI_CREATE_WHISTLER_OR_LATER(SIG)
INFO_ENTRY_UI_CREATE_WHISTLER_OR_LATER(KEY)
INFO_ENTRY_UI_CREATE_WHISTLER_OR_LATER(NXT)
// non createble record types
INFO_ENTRY_SHOWNXT(SOA) // cannot create an SOA record!!!
INFO_ENTRY(WINS) // cannot create a WINS record from the Wizard
INFO_ENTRY_NAME(NBSTAT, L"WINS-R" ) //cannot create a NBSTAT(WINS-R) record from the Wizard
INFO_ENTRY(NBSTAT)
INFO_ENTRY_SHOWNXT(NS) // use the Name Servers property page
INFO_ENTRY_SHOWNXT(MD) // obsolete, should use MX
INFO_ENTRY_SHOWNXT(MF) // obsolete, should use MX
INFO_ENTRY_SHOWNXT(NSAP)
INFO_ENTRY_SHOWNXT(NSAPPTR)
INFO_ENTRY_SHOWNXT(PX)
INFO_ENTRY_SHOWNXT(GPOS)
INFO_ENTRY(NULL) // Null/Unk records can only be viewed
INFO_ENTRY(UNK)
END_OF_TABLE_INFO_ENTRY
};
return (const DNS_RECORD_INFO_ENTRY*)&info;
}
const DNS_RECORD_INFO_ENTRY* CDNSRecordInfo::GetEntry(int nIndex)
{
DNS_RECORD_INFO_ENTRY* pTable = (DNS_RECORD_INFO_ENTRY*)GetInfoEntryTable();
int k = 0;
while (pTable->nResourceID != DNS_RECORD_INFO_END_OF_TABLE)
{
if (k == nIndex)
return pTable;
pTable++;
k++;
}
return NULL;
}
const DNS_RECORD_INFO_ENTRY* CDNSRecordInfo::GetEntryFromName(LPCWSTR lpszName)
{
DNS_RECORD_INFO_ENTRY* pTable = (DNS_RECORD_INFO_ENTRY*)GetInfoEntryTable();
while (pTable->nResourceID != DNS_RECORD_INFO_END_OF_TABLE)
{
LPCWSTR lpszTableName = pTable->lpszFullName;
if (_wcsicmp(lpszTableName,lpszName) == 0)
return pTable;
pTable++;
}
return NULL;
}
const DNS_RECORD_INFO_ENTRY* CDNSRecordInfo::GetTypeEntry(WORD wType)
{
DNS_RECORD_INFO_ENTRY* pTable = (DNS_RECORD_INFO_ENTRY*)GetInfoEntryTable();
while (pTable->nResourceID != DNS_RECORD_INFO_END_OF_TABLE)
{
if (pTable->wType == wType)
{
return pTable;
}
pTable++;
}
return NULL;
}
LPCWSTR CDNSRecordInfo::GetTypeString(WORD wType, stringType type)
{
const DNS_RECORD_INFO_ENTRY* pTableEntry = GetTypeEntry(wType);
if (pTableEntry != NULL)
{
switch(type)
{
case shortName:
return pTableEntry->lpszShortName;
case fullName:
return pTableEntry->lpszFullName;
case description:
return pTableEntry->lpszDescription;
}
}
return g_lpszNullString;
}
CString CDNSRecordInfo::m_szAtTheNodeDisplayString;
BOOL CDNSRecordInfo::LoadResources()
{
HINSTANCE hInstance = _Module.GetModuleInstance();
ASSERT(hInstance != NULL);
DNS_RECORD_INFO_ENTRY* pTable = (DNS_RECORD_INFO_ENTRY*)GetInfoEntryTable();
while (pTable->nResourceID != DNS_RECORD_INFO_END_OF_TABLE)
{
if (0 == ::LoadString(hInstance, pTable->nResourceID,
pTable->cStringData, MAX_RECORD_RESOURCE_STRLEN))
return FALSE; // mmissing resource string?
// parse and replace \n with NULL
pTable->lpszFullName = pTable->cStringData;
for (WCHAR* pCh = pTable->cStringData; (*pCh) != NULL; pCh++)
{
if ( (*pCh) == L'\n')
{
pTable->lpszDescription = (pCh+1);
(*pCh) = NULL;
break;
}
}
pTable++;
}
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return m_szAtTheNodeDisplayString.LoadString(IDS_RECORD_AT_THE_NODE);
}