Source code of Windows XP (NT5)
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.

2810 lines
78 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: domain.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "preDNSsn.h"
  11. #include <SnapBase.h>
  12. #include "resource.h"
  13. #include "dnsutil.h"
  14. #include "DNSSnap.h"
  15. #include "snapdata.h"
  16. #include "server.h"
  17. #include "domain.h"
  18. #include "record.h"
  19. #include "zone.h"
  20. #include "delegwiz.h"
  21. #ifdef DEBUG_ALLOCATOR
  22. #ifdef _DEBUG
  23. #define new DEBUG_NEW
  24. #undef THIS_FILE
  25. static char THIS_FILE[] = __FILE__;
  26. #endif
  27. #endif
  28. BOOL _match(LPCWSTR lpszNSName,
  29. CDNS_A_RecordNode* pARecordNode)
  30. {
  31. TRACE(_T("NS %s A %s\n"), lpszNSName, pARecordNode->GetString(0));
  32. return DnsNameCompare_W((LPWSTR)lpszNSName, (LPWSTR)pARecordNode->GetString(0));
  33. }
  34. /////////////////////////////////////////////////////////////////////////
  35. // CNewDomainDialog
  36. class CNewDomainDialog : public CHelpDialog
  37. {
  38. // Construction
  39. public:
  40. CNewDomainDialog(CDNSDomainNode* pParentDomainNode,
  41. CComponentDataObject* pComponentData);
  42. enum { IDD = IDD_DOMAIN_ADDNEWDOMAIN };
  43. // Implementation
  44. protected:
  45. virtual BOOL OnInitDialog();
  46. virtual void OnOK();
  47. afx_msg void OnEditChange();
  48. afx_msg void OnIPv4CtrlChange();
  49. afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo);
  50. DECLARE_MESSAGE_MAP()
  51. private:
  52. CDNSDomainNode* m_pParentDomainNode;
  53. CComponentDataObject* m_pComponentData;
  54. CEdit* GetDomainEdit() { return (CEdit*)GetDlgItem(IDC_EDIT_DOMAIN_NAME);}
  55. CDNSIPv4Control* GetDomainIPv4Ctrl()
  56. { return (CDNSIPv4Control*)GetDlgItem(IDC_IPEDIT_DOMAIN_NAME);}
  57. CString m_szDomainName;
  58. BOOL m_bAdvancedView;
  59. int m_nOctects;
  60. int m_nUTF8ParentLen;
  61. };
  62. BEGIN_MESSAGE_MAP(CNewDomainDialog, CHelpDialog)
  63. ON_EN_CHANGE(IDC_EDIT_DOMAIN_NAME,OnEditChange)
  64. ON_EN_CHANGE(IDC_IPEDIT_DOMAIN_NAME, OnIPv4CtrlChange)
  65. END_MESSAGE_MAP()
  66. CNewDomainDialog::CNewDomainDialog(CDNSDomainNode* pParentDomainNode,
  67. CComponentDataObject* pComponentData)
  68. : CHelpDialog(CNewDomainDialog::IDD, pComponentData)
  69. {
  70. ASSERT(pParentDomainNode != NULL);
  71. ASSERT(pComponentData != NULL);
  72. m_pParentDomainNode = pParentDomainNode;
  73. m_pComponentData = pComponentData;
  74. m_bAdvancedView = TRUE;
  75. m_nOctects = -1; // invalid if advanced view
  76. m_nUTF8ParentLen = UTF8StringLen(pParentDomainNode->GetFullName());
  77. }
  78. BOOL CNewDomainDialog::OnInitDialog()
  79. {
  80. CHelpDialog::OnInitDialog();
  81. // move the edit box in place of the IP control
  82. CDNSIPv4Control* pNameIPCtrl = GetDomainIPv4Ctrl();
  83. CEdit* pNameEdit = GetDomainEdit();
  84. pNameEdit->SetLimitText(MAX_DNS_NAME_LEN - m_nUTF8ParentLen - 1);
  85. CRect editRect;
  86. pNameEdit->GetWindowRect(editRect);
  87. ScreenToClient(editRect);
  88. CRect ipRect;
  89. pNameIPCtrl->GetWindowRect(ipRect);
  90. ScreenToClient(ipRect);
  91. ipRect.bottom = editRect.top + ipRect.Height();
  92. ipRect.right = editRect.left + ipRect.Width();
  93. ipRect.top = editRect.top;
  94. ipRect.left = editRect.left;
  95. pNameIPCtrl->MoveWindow(ipRect,TRUE);
  96. // determine if we need/can have advanced view
  97. CDNSRootData* pRootData = (CDNSRootData*)m_pComponentData->GetRootData();
  98. ASSERT(pRootData != NULL);
  99. m_bAdvancedView = pRootData->IsAdvancedView();
  100. // force advanced view if we are in a forward lookup zone
  101. if (!(m_pParentDomainNode->GetZoneNode()->IsReverse()))
  102. m_bAdvancedView = TRUE;
  103. // determine if we can have a normal view representation
  104. CString szDomainName = m_pParentDomainNode->GetFullName();
  105. if (!m_bAdvancedView)
  106. {
  107. // to have normal view we have to have a valid arpa suffix
  108. BOOL bArpa = RemoveInAddrArpaSuffix(szDomainName.GetBuffer(1));
  109. szDomainName.ReleaseBuffer(); // got "77.80.55.157"
  110. if (!bArpa)
  111. {
  112. m_bAdvancedView = TRUE; // no need to toggle
  113. }
  114. else
  115. {
  116. m_nOctects = ReverseIPString(szDomainName.GetBuffer(1));
  117. szDomainName.ReleaseBuffer(); // finally got "157.55.80.77"
  118. // to have a normal view representation we cannot
  119. // have more than 2 octects
  120. if (m_nOctects > 2)
  121. {
  122. m_bAdvancedView = TRUE; // force advanced for classless
  123. }
  124. else
  125. {
  126. ASSERT(m_nOctects > 0);
  127. switch(m_nOctects)
  128. {
  129. case 1: // e.g. "157", now "157._"
  130. szDomainName += _T(".0.0"); // got "157._.0.0"
  131. break;
  132. case 2: // e.g. "157.55"
  133. szDomainName += _T(".0"); // got "157.55._.0"
  134. break;
  135. };
  136. // set the IP control with IP mask value
  137. IP_ADDRESS ipAddr = IPStringToAddr(szDomainName);
  138. ASSERT(ipAddr != INADDR_NONE);
  139. pNameIPCtrl->SetIPv4Val(ipAddr);
  140. for (int k=0; k<4; k++)
  141. pNameIPCtrl->EnableField(k, k == m_nOctects);
  142. }
  143. }
  144. } // if (!m_bAdvancedView)
  145. // toggle text in static control
  146. CDNSToggleTextControlHelper staticTextToggle;
  147. UINT pnButtonStringIDs[2] = { IDS_NEW_DOMAIN_INST1, IDS_NEW_DOMAIN_INST2 };
  148. VERIFY(staticTextToggle.Init(this, IDC_STATIC_TEXT, pnButtonStringIDs));
  149. staticTextToggle.SetToggleState(m_bAdvancedView);
  150. //
  151. // enable/hide appropriate controls
  152. //
  153. if (m_bAdvancedView)
  154. {
  155. pNameIPCtrl->EnableWindow(FALSE);
  156. pNameIPCtrl->ShowWindow(FALSE);
  157. }
  158. else
  159. {
  160. pNameEdit->EnableWindow(FALSE);
  161. pNameEdit->ShowWindow(FALSE);
  162. }
  163. GetDlgItem(IDOK)->EnableWindow(!m_bAdvancedView);
  164. return TRUE; // return TRUE unless you set the focus to a control
  165. }
  166. void CNewDomainDialog::OnEditChange()
  167. {
  168. ASSERT(m_bAdvancedView);
  169. //
  170. // Get new name from control
  171. //
  172. GetDomainEdit()->GetWindowText(m_szDomainName);
  173. //
  174. // Trim white space
  175. //
  176. m_szDomainName.TrimLeft();
  177. m_szDomainName.TrimRight();
  178. //
  179. // Enable OK button if its a valid name
  180. //
  181. CString szFullDomainName;
  182. if (_wcsicmp(m_pParentDomainNode->GetFullName(), L".") == 0)
  183. {
  184. //
  185. // If the parent domain is the root zone just check the name followed by a '.'
  186. //
  187. szFullDomainName.Format(L"%s.", m_szDomainName);
  188. }
  189. else
  190. {
  191. //
  192. // Else append the parent domain name to the new name
  193. //
  194. szFullDomainName.Format(L"%s.%s", m_szDomainName, m_pParentDomainNode->GetFullName());
  195. }
  196. //
  197. // Get server flags
  198. //
  199. DWORD dwNameChecking = m_pParentDomainNode->GetServerNode()->GetNameCheckFlag();
  200. //
  201. // Is valid?
  202. //
  203. BOOL bIsValidName = (0 == ValidateDnsNameAgainstServerFlags(szFullDomainName,
  204. DnsNameDomain,
  205. dwNameChecking));
  206. GetDlgItem(IDOK)->EnableWindow(bIsValidName);
  207. }
  208. void CNewDomainDialog::OnIPv4CtrlChange()
  209. {
  210. ASSERT(!m_bAdvancedView);
  211. CDNSIPv4Control* pNameIPCtrl = GetDomainIPv4Ctrl();
  212. DWORD dwArr[4];
  213. pNameIPCtrl->GetArray(dwArr, 4);
  214. BOOL bEmpty = (dwArr[m_nOctects] == FIELD_EMPTY);
  215. if (!bEmpty)
  216. {
  217. ASSERT(dwArr[m_nOctects] <= 255);
  218. m_szDomainName.Format(_T("%d"), dwArr[m_nOctects]);
  219. }
  220. GetDlgItem(IDOK)->EnableWindow(!bEmpty);
  221. }
  222. void CNewDomainDialog::OnOK()
  223. {
  224. RECORD_SEARCH recordSearch = RECORD_NOT_FOUND;
  225. CDNSDomainNode* pNewParentDomain = NULL;
  226. CString szFullRecordName = m_szDomainName + L"." + m_pParentDomainNode->GetFullName();
  227. CString szNonExistentDomain;
  228. recordSearch = m_pParentDomainNode->GetZoneNode()->DoesContain(szFullRecordName,
  229. m_pComponentData,
  230. &pNewParentDomain,
  231. szNonExistentDomain,
  232. TRUE);
  233. if (recordSearch == RECORD_NOT_FOUND &&
  234. pNewParentDomain != NULL)
  235. {
  236. DNS_STATUS err = pNewParentDomain->CreateSubdomain(m_szDomainName,m_pComponentData);
  237. if (err != 0)
  238. {
  239. // creation error, warn the user and prompt again
  240. DNSErrorDialog(err, IDS_MSG_DOMAIN_FAIL_CREATE);
  241. CEdit* pDomainNameEdit = GetDomainEdit();
  242. pDomainNameEdit->SetSel(0,-1);
  243. pDomainNameEdit->SetFocus();
  244. return;
  245. }
  246. }
  247. else if (recordSearch == NON_EXISTENT_SUBDOMAIN && pNewParentDomain != NULL)
  248. {
  249. CDNSRootData* pRootData = (CDNSRootData*)m_pComponentData->GetRootData();
  250. //
  251. // Create the node on the server
  252. //
  253. CDNSDomainNode* pNewDomainNode = pNewParentDomain->CreateSubdomainNode();
  254. if (pNewDomainNode == NULL)
  255. {
  256. ASSERT(pNewDomainNode != NULL);
  257. return;
  258. }
  259. pNewParentDomain->SetSubdomainName(pNewDomainNode, m_szDomainName, pRootData->IsAdvancedView());
  260. //
  261. // tell the newly created object to write to the server
  262. //
  263. DNS_STATUS err = pNewDomainNode->Create();
  264. if (err != 0)
  265. {
  266. DNSErrorDialog(err, IDS_MSG_DOMAIN_FAIL_CREATE);
  267. return;
  268. }
  269. if (!szNonExistentDomain.IsEmpty())
  270. {
  271. //
  272. // Create the first subdomain because the current domain is already enumerated
  273. // so we have to start the remaining enumeration at the new subdomain that is needed
  274. //
  275. CDNSDomainNode* pSubdomainNode = pNewParentDomain->CreateSubdomainNode();
  276. ASSERT(pSubdomainNode != NULL);
  277. pNewParentDomain->SetSubdomainName(pSubdomainNode, szNonExistentDomain, pRootData->IsAdvancedView());
  278. VERIFY(pNewParentDomain->AddChildToListAndUISorted(pSubdomainNode, m_pComponentData));
  279. m_pComponentData->SetDescriptionBarText(pNewParentDomain);
  280. //
  281. // I don't care what the results of this are, I am just using it
  282. // to do the expansion to the new record
  283. //
  284. recordSearch = pSubdomainNode->GetZoneNode()->DoesContain(szFullRecordName,
  285. m_pComponentData,
  286. &pNewParentDomain,
  287. szNonExistentDomain,
  288. TRUE);
  289. }
  290. }
  291. else if (recordSearch == RECORD_NOT_FOUND_AT_THE_NODE)
  292. {
  293. //
  294. // Do nothing since this is a domain and it already exists
  295. //
  296. }
  297. else
  298. {
  299. DNS_STATUS err = m_pParentDomainNode->CreateSubdomain(m_szDomainName,m_pComponentData);
  300. if (err != 0)
  301. {
  302. // creation error, warn the user and prompt again
  303. DNSErrorDialog(err, IDS_MSG_DOMAIN_FAIL_CREATE);
  304. CEdit* pDomainNameEdit = GetDomainEdit();
  305. pDomainNameEdit->SetSel(0,-1);
  306. pDomainNameEdit->SetFocus();
  307. return;
  308. }
  309. }
  310. CHelpDialog::OnOK();
  311. }
  312. /////////////////////////////////////////////////////////////////////////
  313. // CDNSDomainQueryObj
  314. class CDNSDomainMsg : public CObjBase
  315. {
  316. };
  317. BOOL CDNSDomainQueryObj::Enumerate()
  318. {
  319. USES_CONVERSION;
  320. TRACE(_T("CDNSDomainQueryObj::Enumerate(): Server <%s> Zone/Domain %s Enumerating\n"), (LPCTSTR)m_szServerName, (LPCTSTR)m_szNodeName);
  321. DNS_STATUS err = 0;
  322. // if needed, get the zone info
  323. if (m_bIsZone && !m_bCache)
  324. {
  325. CDNSZoneInfoEx* pZoneInfo = new CDNSZoneInfoEx;
  326. err = pZoneInfo->Query(m_szServerName, m_szFullNodeName, m_dwServerVersion);
  327. if (err != 0)
  328. {
  329. delete pZoneInfo;
  330. pZoneInfo = NULL;
  331. OnError(err);
  332. return FALSE; // no need to enumerate if we have no zone info
  333. }
  334. else
  335. {
  336. VERIFY(AddQueryResult(pZoneInfo));
  337. }
  338. }
  339. // if executing a query for a specific RR type, just do it right away
  340. if (m_wRecordType != DNS_TYPE_ALL)
  341. {
  342. // we assume that a type specific query does not have filtering enabled
  343. ASSERT(m_bGetAll);
  344. ASSERT(m_nFilterOption == DNS_QUERY_FILTER_DISABLED);
  345. err = EnumerateFiltered(m_wRecordType);
  346. if (err != 0)
  347. OnError(err);
  348. return FALSE; // we are done
  349. }
  350. // DO A MULTI PASS QUERY
  351. m_bFirstPass = TRUE;
  352. // there are items that cannot be filtered out for consistency
  353. // (zone info, SOA, Ns, etc.), so we disable any filtering while
  354. // getting them
  355. BOOL bGetAllOld = m_bGetAll;
  356. BOOL nFilterOptionOld = m_nFilterOption;
  357. m_bGetAll = TRUE;
  358. m_nFilterOption = DNS_QUERY_FILTER_DISABLED;
  359. // only zones or the cache have SOA RR's
  360. if (m_bIsZone || m_bCache)
  361. {
  362. err = EnumerateFiltered(DNS_TYPE_SOA);
  363. if (err != 0)
  364. {
  365. OnError(err);
  366. return FALSE;
  367. }
  368. }
  369. // only zones have WINS and NBSTAT RR's
  370. if (m_bIsZone)
  371. {
  372. if (m_bReverse)
  373. err = EnumerateFiltered(DNS_TYPE_NBSTAT);
  374. else
  375. err = EnumerateFiltered(DNS_TYPE_WINS);
  376. if (err != 0)
  377. {
  378. OnError(err);
  379. return FALSE;
  380. }
  381. }
  382. // need also to check for NS (zone or delegation)
  383. err = EnumerateFiltered(DNS_TYPE_NS);
  384. if (err != 0)
  385. {
  386. OnError(err);
  387. return FALSE;
  388. }
  389. // add a message in the queue to signal we are done with
  390. // the first phase
  391. AddQueryResult(new CDNSDomainMsg);
  392. // now query again, for all RR's, but need to filter the
  393. // known types out
  394. m_bFirstPass = FALSE;
  395. // restore the filtering parameters we had before
  396. m_bGetAll = bGetAllOld;
  397. m_nFilterOption = nFilterOptionOld;
  398. err = EnumerateFiltered(DNS_TYPE_ALL);
  399. if (err != 0)
  400. OnError(err);
  401. return FALSE;
  402. }
  403. DNS_STATUS CDNSDomainQueryObj::EnumerateFiltered(WORD wRecordType)
  404. {
  405. DWORD dwSelectFlags = m_dwSelectFlags;
  406. // for single type queries, we do not want subfolders
  407. if (wRecordType != DNS_TYPE_ALL)
  408. dwSelectFlags |= DNS_RPC_VIEW_NO_CHILDREN;
  409. return CDNSDomainNode::EnumerateNodes(m_szServerName,
  410. m_szZoneName.IsEmpty() ? NULL : (LPCWSTR)m_szZoneName,
  411. m_szNodeName,
  412. m_szFullNodeName,
  413. wRecordType,
  414. dwSelectFlags,
  415. m_bIsZone,
  416. m_bReverse,
  417. m_bAdvancedView,
  418. this);
  419. }
  420. BOOL CDNSDomainQueryObj::CanAddRecord(WORD wRecordType, LPCWSTR lpszRecordName)
  421. {
  422. if (m_nFilterOption == DNS_QUERY_FILTER_DISABLED)
  423. return TRUE; // we have no filtering at all
  424. // determine if this is a special record type for filtered queries
  425. BOOL bSpecialType = (wRecordType == DNS_TYPE_SOA) || (wRecordType == DNS_TYPE_NS) ||
  426. (wRecordType == DNS_TYPE_WINS) || (wRecordType == DNS_TYPE_NBSTAT);
  427. // in the first pass only special types allowed
  428. if (m_bFirstPass)
  429. return bSpecialType;
  430. // in the second pass do not allow special types
  431. if (!m_bFirstPass && bSpecialType)
  432. return FALSE;
  433. // we are left with normal types, apply the filtering, if required
  434. if (m_nFilterOption == DNS_QUERY_FILTER_NONE)
  435. return TRUE; // allow all
  436. // need to match the record name
  437. return MatchName(lpszRecordName);
  438. }
  439. /////////////////////////////////////////////////////////////////////////
  440. // CDNSDomainNode
  441. BEGIN_TOOLBAR_MAP(CDNSDomainNode)
  442. TOOLBAR_EVENT(toolbarNewRecord, OnNewRecord)
  443. END_TOOLBAR_MAP()
  444. // {720132BA-44B2-11d1-B92F-00A0C9A06D2D}
  445. const GUID CDNSDomainNode::NodeTypeGUID =
  446. { 0x720132ba, 0x44b2, 0x11d1, { 0xb9, 0x2f, 0x0, 0xa0, 0xc9, 0xa0, 0x6d, 0x2d } };
  447. CDNSDomainNode::CDNSDomainNode(BOOL bDelegation)
  448. {
  449. m_bDelegation = bDelegation;
  450. m_pZoneNode = NULL;
  451. m_pNSRecordNodeList = new CDNS_NS_RecordNodeList;
  452. ASSERT(m_pNSRecordNodeList != NULL);
  453. m_bHasDataForPropPages = FALSE;
  454. }
  455. CDNSDomainNode::~CDNSDomainNode()
  456. {
  457. TRACE(_T("~CDNSDomainNode(), name <%s>\n"),GetDisplayName());
  458. ASSERT(m_pNSRecordNodeList != NULL);
  459. delete m_pNSRecordNodeList;
  460. m_pNSRecordNodeList = NULL;
  461. }
  462. DWORD CDNSDomainNode::GetDefaultTTL()
  463. {
  464. if ( (m_pZoneNode != NULL) && (m_pZoneNode->GetZoneType() != DNS_ZONE_TYPE_CACHE) )
  465. return m_pZoneNode->GetSOARecordMinTTL();
  466. else
  467. return (DWORD)0; // no info available from SOA RR
  468. }
  469. void CDNSDomainNode::SetFullDNSName(BOOL bIsZone,
  470. BOOL,
  471. LPCTSTR lpszNodeName,
  472. LPCTSTR lpszParentFullName)
  473. {
  474. ASSERT(lpszNodeName != NULL);
  475. ASSERT(lpszParentFullName != NULL);
  476. if (bIsZone)
  477. {
  478. //
  479. // the two names have to be the same, zone parent of itself
  480. //
  481. ASSERT(_wcsicmp(lpszParentFullName, lpszNodeName) == 0);
  482. m_szFullName = lpszParentFullName;
  483. }
  484. else // it is a domain
  485. {
  486. ASSERT(_wcsicmp(lpszParentFullName, lpszNodeName) != 0);
  487. //
  488. // chain the node name to the parent full name to get the node's full name
  489. //
  490. if (lpszParentFullName[0] == L'.' )
  491. {
  492. //
  493. // if parent is "." and name is "bar", get "bar.": this is the case for the root
  494. // if parent is ".com" and name is "bar", get "bar.com":
  495. //
  496. m_szFullName.Format(_T("%s%s"), lpszNodeName,lpszParentFullName);
  497. }
  498. else
  499. {
  500. //
  501. // if parent is "foo.com" and name is "bar", get "bar.foo.com"
  502. //
  503. m_szFullName.Format(_T("%s.%s"), lpszNodeName,lpszParentFullName);
  504. }
  505. }
  506. TRACE(_T("CDNSDomainNode::SetFullDNSName() fullName = <%s>\n"), (LPCTSTR)m_szFullName);
  507. }
  508. void CDNSDomainNode::SetDisplayDNSName(BOOL bIsZone,
  509. BOOL bReverse,
  510. BOOL bAdvancedView,
  511. LPCTSTR lpszNodeName,
  512. LPCTSTR lpszParentFullName)
  513. {
  514. ASSERT(lpszNodeName != NULL);
  515. ASSERT(lpszParentFullName != NULL);
  516. if (_wcsicmp(lpszNodeName, L".") == 0)
  517. {
  518. CString szRootString;
  519. VERIFY(szRootString.LoadString(IDS_ROOT_ZONE_LABEL));
  520. m_szDisplayName = L"." + szRootString;
  521. }
  522. else
  523. {
  524. m_szDisplayName = lpszNodeName;
  525. }
  526. if (bIsZone && bReverse && !bAdvancedView)
  527. {
  528. CDNSZoneNode::SetZoneNormalViewHelper(m_szDisplayName);
  529. }
  530. }
  531. void CDNSDomainNode::SetNames(BOOL bIsZone, BOOL bReverse, BOOL bAdvancedView,
  532. LPCTSTR lpszNodeName, LPCTSTR lpszParentFullName)
  533. {
  534. ASSERT(lpszNodeName != NULL);
  535. ASSERT(lpszParentFullName != NULL);
  536. TRACE(_T("CDNSDomainNode::SetNames(bIsZone=%d, bReverse=%d, bAdvancedView=%d, lpszNodeName=<%s>, lpszParentFullName=<%s>)\n"),
  537. bIsZone, bReverse, bAdvancedView, lpszNodeName,lpszParentFullName);
  538. SetFullDNSName(bIsZone, bReverse, lpszNodeName, lpszParentFullName);
  539. SetDisplayDNSName(bIsZone, bReverse, bAdvancedView, lpszNodeName, lpszParentFullName);
  540. }
  541. void CDNSDomainNode::ChangePTRRecordsViewOption(BOOL bAdvanced,
  542. CComponentDataObject* pComponentDataObject)
  543. {
  544. POSITION pos;
  545. for( pos = m_containerChildList.GetHeadPosition(); pos != NULL; )
  546. {
  547. CTreeNode* pCurrentChild = m_containerChildList.GetNext(pos);
  548. // recurse down the tree
  549. CDNSDomainNode* pDomainNode = dynamic_cast<CDNSDomainNode*>(pCurrentChild);
  550. ASSERT(pDomainNode != NULL);
  551. pDomainNode->ChangePTRRecordsViewOption(bAdvanced, pComponentDataObject);
  552. }
  553. POSITION leafPos;
  554. for ( leafPos = m_leafChildList.GetHeadPosition(); leafPos != NULL; )
  555. {
  556. CTreeNode* pCurrentLeafNode = m_leafChildList.GetNext(leafPos);
  557. CDNSRecordNodeBase* pRecordNode = dynamic_cast<CDNSRecordNodeBase*>(pCurrentLeafNode);
  558. ASSERT(pRecordNode != NULL);
  559. if (DNS_TYPE_PTR == pRecordNode->GetType())
  560. {
  561. CDNS_PTR_RecordNode* pPTRRecordNode = (CDNS_PTR_RecordNode*)pRecordNode;
  562. pPTRRecordNode->ChangeDisplayName(this, bAdvanced);
  563. }
  564. }
  565. }
  566. CQueryObj* CDNSDomainNode::OnCreateQuery()
  567. {
  568. // generic default setting
  569. WORD wRecordType = DNS_TYPE_ALL;
  570. DWORD dwSelectFlags = (m_pZoneNode->GetZoneType() == DNS_ZONE_TYPE_CACHE) ?
  571. DNS_RPC_VIEW_CACHE_DATA : DNS_RPC_VIEW_AUTHORITY_DATA;
  572. if (IsDelegation())
  573. {
  574. // special case the delegation: show only NS records and
  575. // will have no children shown (delegation cut)
  576. wRecordType = DNS_TYPE_NS;
  577. dwSelectFlags = DNS_RPC_VIEW_GLUE_DATA | DNS_RPC_VIEW_NO_CHILDREN;
  578. //dwSelectFlags = DNS_RPC_VIEW_GLUE_DATA |
  579. // DNS_RPC_VIEW_NO_CHILDREN | DNS_RPC_VIEW_ADDITIONAL_DATA;
  580. }
  581. BOOL bCache = GetZoneNode()->GetZoneType() == DNS_ZONE_TYPE_CACHE;
  582. LPCWSTR lpszZoneName = bCache ? NULL : m_pZoneNode->GetFullName();
  583. CDNSRootData* pRootData = (CDNSRootData*)GetRootContainer();
  584. ASSERT(pRootData != NULL);
  585. CDNSDomainQueryObj* pQuery = new
  586. CDNSDomainQueryObj(GetServerNode()->GetRPCName(),
  587. lpszZoneName,
  588. GetServerNode()->GetVersion(),
  589. GetDisplayName(),
  590. m_szFullName,
  591. wRecordType,
  592. dwSelectFlags,
  593. IsZone(),
  594. GetZoneNode()->IsReverse(),
  595. bCache,
  596. pRootData->IsAdvancedView());
  597. // delegations will not have any filtering option (data consistency)
  598. if (!IsDelegation())
  599. {
  600. pQuery->SetFilterOptions(pRootData->GetFilter());
  601. }
  602. return pQuery;
  603. }
  604. BOOL CDNSDomainNode::OnRefresh(CComponentDataObject* pComponentData,
  605. CNodeList* pNodeList)
  606. {
  607. if (pNodeList->GetCount() > 1) // multiple selection
  608. {
  609. BOOL bRet = TRUE;
  610. POSITION pos = pNodeList->GetHeadPosition();
  611. while (pos != NULL)
  612. {
  613. CTreeNode* pNode = pNodeList->GetNext(pos);
  614. ASSERT(pNode != NULL);
  615. CNodeList nodeList;
  616. nodeList.AddTail(pNode);
  617. if (!pNode->OnRefresh(pComponentData, &nodeList))
  618. {
  619. bRet = FALSE;
  620. }
  621. }
  622. return bRet;
  623. }
  624. //
  625. // single selection
  626. //
  627. if (CMTContainerNode::OnRefresh(pComponentData, pNodeList))
  628. {
  629. GetNSRecordNodeList()->RemoveAll();
  630. m_bHasDataForPropPages = FALSE;
  631. return TRUE;
  632. }
  633. return FALSE;
  634. }
  635. void CDNSDomainNode::OnThreadExitingNotification(CComponentDataObject* pComponentDataObject)
  636. {
  637. if (!m_bHasDataForPropPages)
  638. {
  639. // never got a CDNSDomainMsg notification object
  640. // but we are done anyway, so change it back
  641. m_bHasDataForPropPages = TRUE;
  642. }
  643. // call now the base class
  644. CDNSMTContainerNode::OnThreadExitingNotification(pComponentDataObject);
  645. }
  646. void CDNSDomainNode::OnHaveData(CObjBase* pObj, CComponentDataObject* pComponentDataObject)
  647. {
  648. if (IS_CLASS(*pObj, CDNSDomainMsg))
  649. {
  650. // special case for a "message" object sent through to update verbs
  651. TRACE(_T("Got CDNSDomainMsg\n"));
  652. delete pObj;
  653. ASSERT(!m_bHasDataForPropPages); // should get only once
  654. m_bHasDataForPropPages = TRUE;
  655. VERIFY(SUCCEEDED(pComponentDataObject->UpdateVerbState(this)));
  656. return;
  657. }
  658. if (IS_CLASS(*pObj, CDNSDomainNode))
  659. {
  660. // assume all the child containers are derived from this class
  661. CDNSDomainNode* pDomainNode = dynamic_cast<CDNSDomainNode*>(pObj);
  662. pDomainNode->SetServerNode(GetServerNode());
  663. pDomainNode->SetZone(m_pZoneNode);
  664. }
  665. else
  666. {
  667. OnHaveRecord(dynamic_cast<CDNSRecordNodeBase*>(pObj), pComponentDataObject);
  668. }
  669. AddChildToListAndUI(dynamic_cast<CTreeNode*>(pObj), pComponentDataObject);
  670. pComponentDataObject->SetDescriptionBarText(this);
  671. }
  672. void CDNSDomainNode::OnHaveRecord(CDNSRecordNodeBase* pRecordNode,
  673. CComponentDataObject* pComponentDataObject)
  674. {
  675. WORD wType = pRecordNode->GetType();
  676. if (wType == DNS_TYPE_PTR)
  677. {
  678. ASSERT(pComponentDataObject != NULL); // assume this for PTR
  679. CDNSRootData* pRootData = (CDNSRootData*)pComponentDataObject->GetRootData();
  680. ASSERT(pRootData != NULL);
  681. // if we are in normal view, have to change the
  682. // default advanced representation
  683. BOOL bAdvancedView = pRootData->IsAdvancedView();
  684. if (!bAdvancedView)
  685. ((CDNS_PTR_RecordNode*)pRecordNode)->ChangeDisplayName(this, bAdvancedView);
  686. }
  687. else if (wType == DNS_TYPE_NS)
  688. {
  689. ASSERT(pRecordNode->IsAtTheNode());
  690. GetNSRecordNodeList()->AddTail((CDNS_NS_RecordNode*)pRecordNode);
  691. }
  692. }
  693. BOOL CDNSDomainNode::OnAddMenuItem(LPCONTEXTMENUITEM2 pContextMenuItem2,
  694. long*)
  695. {
  696. if (pContextMenuItem2->lCommandID == IDM_SNAPIN_ADVANCED_VIEW)
  697. {
  698. pContextMenuItem2->fFlags = ((CDNSRootData*)GetRootContainer())->IsAdvancedView() ? MF_CHECKED : 0;
  699. return TRUE;
  700. }
  701. if (pContextMenuItem2->lCommandID == IDM_SNAPIN_FILTERING)
  702. {
  703. if (((CDNSRootData*)GetRootContainer())->IsFilteringEnabled())
  704. {
  705. pContextMenuItem2->fFlags = MF_CHECKED;
  706. }
  707. return TRUE;
  708. }
  709. DWORD dwType = m_pZoneNode->GetZoneType();
  710. BOOL bIsAutocreated = m_pZoneNode->IsAutocreated();
  711. BOOL bIsSecondaryOrCache = (dwType == DNS_ZONE_TYPE_SECONDARY) ||
  712. (dwType == DNS_ZONE_TYPE_CACHE) ||
  713. (dwType == DNS_ZONE_TYPE_STUB);
  714. BOOL bIsDelegatedDomain = !IsZone() && IsDelegation();
  715. if (bIsSecondaryOrCache || bIsAutocreated || bIsDelegatedDomain)
  716. {
  717. return FALSE;
  718. }
  719. // different add operations depending on the FWD/REV type
  720. if (!GetZoneNode()->IsReverse() &&
  721. (pContextMenuItem2->lCommandID == IDM_DOMAIN_NEW_PTR))
  722. {
  723. // do not add a PTR to a FWD lookup zone
  724. return FALSE;
  725. }
  726. if (GetZoneNode()->IsReverse() &&
  727. ((pContextMenuItem2->lCommandID == IDM_DOMAIN_NEW_HOST) ||
  728. (pContextMenuItem2->lCommandID == IDM_DOMAIN_NEW_MX)))
  729. {
  730. // do not add a HOST, MX, ALIAS to a REV lookup zone
  731. return FALSE;
  732. }
  733. // have the menu item added. but it might be grayed out...
  734. if (m_nState != loaded)
  735. {
  736. pContextMenuItem2->fFlags |= MF_GRAYED;
  737. }
  738. return TRUE;
  739. }
  740. HRESULT CDNSDomainNode::OnSetToolbarVerbState(IToolbar* pToolbar,
  741. CNodeList* pNodeList)
  742. {
  743. HRESULT hr = S_OK;
  744. //
  745. // Set the button state for each button on the toolbar
  746. //
  747. hr = pToolbar->SetButtonState(toolbarNewServer, ENABLED, FALSE);
  748. ASSERT(SUCCEEDED(hr));
  749. hr = pToolbar->SetButtonState(toolbarNewZone, ENABLED, FALSE);
  750. ASSERT(SUCCEEDED(hr));
  751. if (pNodeList->GetCount() > 1) // multiple selection
  752. {
  753. hr = pToolbar->SetButtonState(toolbarNewRecord, ENABLED, FALSE);
  754. }
  755. else if (pNodeList->GetCount() == 1) // single selection
  756. {
  757. DWORD dwType = m_pZoneNode->GetZoneType();
  758. BOOL bIsAutocreated = m_pZoneNode->IsAutocreated();
  759. BOOL bIsSecondaryOrCache = (dwType == DNS_ZONE_TYPE_SECONDARY) ||
  760. (dwType == DNS_ZONE_TYPE_CACHE) ||
  761. (dwType == DNS_ZONE_TYPE_STUB);
  762. BOOL bIsDelegatedDomain = !IsZone() && IsDelegation();
  763. BOOL bEnable = TRUE;
  764. if (bIsSecondaryOrCache || bIsAutocreated || bIsDelegatedDomain)
  765. {
  766. bEnable = FALSE;
  767. }
  768. hr = pToolbar->SetButtonState(toolbarNewRecord, ENABLED, bEnable);
  769. }
  770. return hr;
  771. }
  772. BOOL CDNSDomainNode::OnSetDeleteVerbState(DATA_OBJECT_TYPES type,
  773. BOOL* pbHide,
  774. CNodeList* pNodeList)
  775. {
  776. if (pNodeList->GetCount() > 1) // multiple selection
  777. {
  778. BOOL bRet = TRUE;
  779. BOOL bRetHide = FALSE;
  780. *pbHide = FALSE;
  781. POSITION pos = pNodeList->GetHeadPosition();
  782. while (pos != NULL)
  783. {
  784. CTreeNode* pNode = pNodeList->GetNext(pos);
  785. ASSERT(pNode != NULL);
  786. CNodeList nodeList;
  787. nodeList.AddTail(pNode);
  788. if (!pNode->OnSetDeleteVerbState(type, &bRetHide, &nodeList))
  789. {
  790. bRet = FALSE;
  791. break;
  792. }
  793. if (bRetHide)
  794. {
  795. *pbHide = TRUE;
  796. }
  797. }
  798. return bRet;
  799. }
  800. *pbHide = FALSE;
  801. DWORD dwType = m_pZoneNode->GetZoneType();
  802. BOOL bIsAutocreated = m_pZoneNode->IsAutocreated();
  803. if (IsThreadLocked())
  804. {
  805. return FALSE;
  806. }
  807. //
  808. // cannot delete from an autocreate zone/domain
  809. //
  810. if (bIsAutocreated)
  811. {
  812. return FALSE;
  813. }
  814. //
  815. // cannot delete from a secondary or stub zone, but can delete the zone itself
  816. // cannot delete the cache
  817. //
  818. if (
  819. (
  820. ( ((dwType == DNS_ZONE_TYPE_SECONDARY) || (dwType == DNS_ZONE_TYPE_STUB)) && !IsZone() ) || // subdomain of secondary
  821. ( (dwType == DNS_ZONE_TYPE_CACHE) && IsZone() ) // cache zone itself
  822. )
  823. )
  824. {
  825. return FALSE;
  826. }
  827. return TRUE;
  828. }
  829. BOOL CDNSDomainNode::OnSetRefreshVerbState(DATA_OBJECT_TYPES,
  830. BOOL* pbHide,
  831. CNodeList*)
  832. {
  833. *pbHide = FALSE;
  834. return !IsThreadLocked();
  835. }
  836. HRESULT CDNSDomainNode::OnCommand(long nCommandID,
  837. DATA_OBJECT_TYPES,
  838. CComponentDataObject* pComponentData,
  839. CNodeList* pNodeList)
  840. {
  841. if (pNodeList->GetCount() > 1) // multiple selection
  842. {
  843. return E_FAIL;
  844. }
  845. switch (nCommandID)
  846. {
  847. case IDM_DOMAIN_NEW_DOMAIN:
  848. OnNewDomain(pComponentData);
  849. break;
  850. case IDM_DOMAIN_NEW_DELEGATION:
  851. OnNewDelegation(pComponentData);
  852. break;
  853. case IDM_DOMAIN_NEW_RECORD:
  854. OnNewRecord(pComponentData, pNodeList);
  855. break;
  856. case IDM_DOMAIN_NEW_HOST:
  857. OnNewHost(pComponentData);
  858. break;
  859. case IDM_DOMAIN_NEW_ALIAS:
  860. OnNewAlias(pComponentData);
  861. break;
  862. case IDM_DOMAIN_NEW_MX:
  863. OnNewMailExchanger(pComponentData);
  864. break;
  865. case IDM_DOMAIN_NEW_PTR:
  866. OnNewPointer(pComponentData);
  867. break;
  868. case IDM_SNAPIN_ADVANCED_VIEW:
  869. ((CDNSRootData*)pComponentData->GetRootData())->OnViewOptions(pComponentData);
  870. break;
  871. case IDM_SNAPIN_FILTERING:
  872. {
  873. if(((CDNSRootData*)pComponentData->GetRootData())->OnFilteringOptions(pComponentData))
  874. {
  875. pComponentData->SetDescriptionBarText(this);
  876. }
  877. }
  878. break;
  879. default:
  880. ASSERT(FALSE); // Unknown command!
  881. return E_FAIL;
  882. }
  883. return S_OK;
  884. }
  885. LPWSTR CDNSDomainNode::GetDescriptionBarText()
  886. {
  887. static CString szFilterEnabled;
  888. static CString szRecordsFormat;
  889. INT_PTR nContainerCount = GetContainerChildList()->GetCount();
  890. INT_PTR nLeafCount = GetLeafChildList()->GetCount();
  891. //
  892. // If not already loaded, then load the format string L"%d record(s)"
  893. //
  894. if (szRecordsFormat.IsEmpty())
  895. {
  896. szRecordsFormat.LoadString(IDS_FORMAT_RECORDS);
  897. }
  898. //
  899. // Format the child count into the description bar text
  900. //
  901. m_szDescriptionBar.Format(szRecordsFormat, nContainerCount + nLeafCount);
  902. //
  903. // Add L"[Filter Activated]" if the filter is on
  904. //
  905. if(((CDNSRootData*)GetRootContainer())->IsFilteringEnabled())
  906. {
  907. //
  908. // If not already loaded, then load the L"[Filter Activated]" string
  909. //
  910. if (szFilterEnabled.IsEmpty())
  911. {
  912. szFilterEnabled.LoadString(IDS_FILTER_ENABLED);
  913. }
  914. m_szDescriptionBar += szFilterEnabled;
  915. }
  916. return (LPWSTR)(LPCWSTR)m_szDescriptionBar;
  917. }
  918. int CDNSDomainNode::GetImageIndex(BOOL)
  919. {
  920. int nIndex = 0;
  921. BOOL bDelegation = IsDelegation();
  922. switch (m_nState)
  923. {
  924. case notLoaded:
  925. nIndex = bDelegation ? DELEGATED_DOMAIN_IMAGE_NOT_LOADED : DOMAIN_IMAGE_NOT_LOADED;
  926. break;
  927. case loading:
  928. nIndex = bDelegation ? DELEGATED_DOMAIN_IMAGE_LOADING : DOMAIN_IMAGE_LOADING;
  929. break;
  930. case loaded:
  931. nIndex = bDelegation ? DELEGATED_DOMAIN_IMAGE_LOADED : DOMAIN_IMAGE_LOADED;
  932. break;
  933. case unableToLoad:
  934. nIndex = bDelegation ? DELEGATED_DOMAIN_IMAGE_UNABLE_TO_LOAD : DOMAIN_IMAGE_UNABLE_TO_LOAD;
  935. break;
  936. case accessDenied:
  937. nIndex = bDelegation ? DELEGATED_DOMAIN_IMAGE_ACCESS_DENIED : DOMAIN_IMAGE_ACCESS_DENIED;
  938. break;
  939. default:
  940. ASSERT(FALSE);
  941. }
  942. return nIndex;
  943. }
  944. void CDNSDomainNode::OnDelete(CComponentDataObject* pComponentData,
  945. CNodeList* pNodeList)
  946. {
  947. if (pNodeList->GetCount() > 1) // multiple selection
  948. {
  949. OnMultiselectDelete(pComponentData, pNodeList);
  950. return;
  951. }
  952. UINT nRet = DNSConfirmOperation(IDS_MSG_DOMAIN_DELETE, this);
  953. if (IDNO == nRet ||
  954. IDCANCEL == nRet)
  955. {
  956. return;
  957. }
  958. if (IsSheetLocked())
  959. {
  960. if (!CanCloseSheets())
  961. return;
  962. pComponentData->GetPropertyPageHolderTable()->DeleteSheetsOfNode(this);
  963. }
  964. ASSERT(!IsSheetLocked());
  965. DNS_STATUS err = Delete();
  966. if (err != 0)
  967. {
  968. DNSErrorDialog(err, IDS_MSG_DOMAIN_FAIL_DELETE);
  969. return;
  970. }
  971. // now remove from the UI and from the cache
  972. DeleteHelper(pComponentData);
  973. delete this; // gone
  974. }
  975. void CDNSDomainNode::OnMultiselectDelete(CComponentDataObject* pComponentData,
  976. CNodeList* pNodeList)
  977. {
  978. UINT nRet = DNSConfirmOperation(IDS_MSG_DOMAIN_MULTI_DELETE, this);
  979. if (IDCANCEL == nRet ||
  980. IDNO == nRet)
  981. {
  982. return;
  983. }
  984. DNS_STATUS* errArray = new DNS_STATUS[pNodeList->GetCount()];
  985. if (errArray == NULL)
  986. {
  987. DNSErrorDialog(E_OUTOFMEMORY, IDS_MSG_DOMAIN_FAIL_DELETE);
  988. return;
  989. }
  990. memset(errArray, 0, sizeof(DNS_STATUS) * pNodeList->GetCount());
  991. BOOL bErrorOccurred = FALSE;
  992. UINT idx = 0;
  993. POSITION pos = pNodeList->GetHeadPosition();
  994. while (pos != NULL)
  995. {
  996. CTreeNode* pTreeNode = pNodeList->GetNext(pos);
  997. if (pTreeNode != NULL)
  998. {
  999. if (pTreeNode->IsSheetLocked())
  1000. {
  1001. if (!pTreeNode->CanCloseSheets())
  1002. {
  1003. idx++;
  1004. continue;
  1005. }
  1006. pComponentData->GetPropertyPageHolderTable()->DeleteSheetsOfNode(pTreeNode);
  1007. }
  1008. ASSERT(!pTreeNode->IsSheetLocked());
  1009. CDNSDomainNode* pDomainNode = dynamic_cast<CDNSDomainNode*>(pTreeNode);
  1010. if (pDomainNode != NULL)
  1011. {
  1012. errArray[idx] = pDomainNode->Delete();
  1013. if (errArray[idx] != 0)
  1014. {
  1015. bErrorOccurred = TRUE;
  1016. idx++;
  1017. continue;
  1018. }
  1019. //
  1020. // now remove from the UI and from the cache
  1021. //
  1022. pDomainNode->DeleteHelper(pComponentData);
  1023. delete pDomainNode; // gone
  1024. }
  1025. else
  1026. {
  1027. //
  1028. // If its not a domain node then it must be a record node
  1029. //
  1030. CDNSRecordNodeBase* pRecordNode = dynamic_cast<CDNSRecordNodeBase*>(pTreeNode);
  1031. if (pRecordNode != NULL)
  1032. {
  1033. errArray[idx] = pRecordNode->DeleteOnServerAndUI(pComponentData);
  1034. if (errArray[idx] != 0)
  1035. {
  1036. bErrorOccurred = TRUE;
  1037. idx++;
  1038. continue;
  1039. }
  1040. delete pRecordNode; // gone
  1041. }
  1042. else
  1043. {
  1044. //
  1045. // What type of node is this???
  1046. //
  1047. ASSERT(FALSE);
  1048. }
  1049. }
  1050. }
  1051. idx++;
  1052. }
  1053. //
  1054. // Now display the errors in some meaningful manner
  1055. //
  1056. if (bErrorOccurred)
  1057. {
  1058. CMultiselectErrorDialog dlg;
  1059. CString szTitle;
  1060. CString szCaption;
  1061. CString szColumnHeader;
  1062. VERIFY(szTitle.LoadString(IDS_MULTISELECT_ERROR_DIALOG_TITLE));
  1063. VERIFY(szCaption.LoadString(IDS_MULTISELECT_ERROR_DIALOG_CAPTION));
  1064. VERIFY(szColumnHeader.LoadString(IDS_MULTISELECT_ERROR_DIALOG_COLUMN_HEADER));
  1065. HRESULT hr = dlg.Initialize(pNodeList,
  1066. errArray,
  1067. static_cast<UINT>(pNodeList->GetCount()),
  1068. szTitle,
  1069. szCaption,
  1070. szColumnHeader);
  1071. if (SUCCEEDED(hr))
  1072. {
  1073. dlg.DoModal();
  1074. }
  1075. }
  1076. }
  1077. void CDNSDomainNode::OnNewDomain(CComponentDataObject* pComponentData)
  1078. {
  1079. CNewDomainDialog dlg(this, pComponentData);
  1080. // the dialog will do the creation
  1081. dlg.DoModal();
  1082. }
  1083. void CDNSDomainNode::OnNewDelegation(CComponentDataObject* pComponentData)
  1084. {
  1085. ASSERT(pComponentData != NULL);
  1086. CDNSMTContainerNode* pContainerNode = (CDNSMTContainerNode*)GetContainer();
  1087. ASSERT(pContainerNode != NULL);
  1088. CDNSDelegationWizardHolder* pHolder =
  1089. new CDNSDelegationWizardHolder(pContainerNode, this, pComponentData);
  1090. ASSERT(pHolder != NULL);
  1091. pHolder->DoModalWizard();
  1092. }
  1093. RECORD_SEARCH CDNSDomainNode::DoesContain(PCWSTR pszRecName,
  1094. CComponentDataObject* pComponentData,
  1095. CDNSDomainNode** ppDomainNode,
  1096. CString& szNonExistentDomain,
  1097. BOOL bExpandNodes)
  1098. {
  1099. #if TRUE
  1100. CDNSNameTokenizer recordTokenizer(pszRecName);
  1101. CDNSNameTokenizer domainTokenizer((IsZone()) ? GetFullName() : GetDisplayName());
  1102. if (!recordTokenizer.Tokenize(L".") || !domainTokenizer.Tokenize(L"."))
  1103. {
  1104. *ppDomainNode = NULL;
  1105. return RECORD_NOT_FOUND;
  1106. }
  1107. recordTokenizer.RemoveMatchingFromTail(domainTokenizer);
  1108. if (recordTokenizer.GetCount() == 0 && domainTokenizer.GetCount() == 0)
  1109. {
  1110. //
  1111. // Record is "At the node"
  1112. //
  1113. *ppDomainNode = this;
  1114. return RECORD_NOT_FOUND_AT_THE_NODE;
  1115. }
  1116. else if ((recordTokenizer.GetCount() == 0 && domainTokenizer.GetCount() != 0) ||
  1117. (recordTokenizer.GetCount() != 0 && domainTokenizer.GetCount() != 0))
  1118. {
  1119. //
  1120. // I don't understand how we got in this situation. It means we are searching in
  1121. // the wrong domain.
  1122. //
  1123. ASSERT(FALSE);
  1124. *ppDomainNode = NULL;
  1125. return RECORD_NOT_FOUND;
  1126. }
  1127. else // recordTokenizer.GetCount() != 0 && domainTokenizer.GetCount() == 0
  1128. {
  1129. //
  1130. // Need to search the children lists
  1131. //
  1132. //
  1133. // If the node hasn't been enumerated, do that now
  1134. //
  1135. if (!IsEnumerated())
  1136. {
  1137. if (!bExpandNodes)
  1138. {
  1139. *ppDomainNode = this;
  1140. return DOMAIN_NOT_ENUMERATED;
  1141. }
  1142. else
  1143. {
  1144. //
  1145. // Expand the node
  1146. //
  1147. HWND hWnd = NULL;
  1148. HRESULT hr = pComponentData->GetConsole()->GetMainWindow(&hWnd);
  1149. ASSERT(SUCCEEDED(hr));
  1150. CWnd* pParentWnd = CWnd::FromHandle(hWnd);
  1151. CLongOperationDialog dlg(
  1152. new CNodeEnumerationThread(pComponentData, this),
  1153. pParentWnd,
  1154. IDR_SEARCH_AVI);
  1155. dlg.DoModal();
  1156. }
  1157. }
  1158. CString szRemaining;
  1159. recordTokenizer.GetRemaining(szRemaining, L".");
  1160. //
  1161. // Search for domains that match the last token remaining in the record name
  1162. //
  1163. POSITION pos = m_containerChildList.GetHeadPosition();
  1164. while (pos != NULL)
  1165. {
  1166. CTreeNode* pCurrentChild = m_containerChildList.GetNext(pos);
  1167. CDNSDomainNode* pDomainNode = dynamic_cast<CDNSDomainNode*>(pCurrentChild);
  1168. if (pDomainNode == NULL)
  1169. {
  1170. ASSERT(FALSE);
  1171. continue;
  1172. }
  1173. if (_wcsicmp(pDomainNode->GetDisplayName(), recordTokenizer.GetTail()) == 0)
  1174. {
  1175. //
  1176. // Found a sub-domain in the path that we have in the UI
  1177. // recurse to see if it or any of its child match pszFullName
  1178. //
  1179. return pDomainNode->DoesContain(szRemaining, pComponentData, ppDomainNode, szNonExistentDomain, bExpandNodes);
  1180. }
  1181. }
  1182. //
  1183. // If the remaining name doesn't match a domain and there
  1184. // is still a '.' in it then there is a non-existent domain
  1185. //
  1186. if (szRemaining.Find(L'.') != -1)
  1187. {
  1188. szNonExistentDomain = recordTokenizer.GetTail();
  1189. *ppDomainNode = this;
  1190. return NON_EXISTENT_SUBDOMAIN;
  1191. }
  1192. //
  1193. // Since no domains match, lets check the records
  1194. //
  1195. pos = m_leafChildList.GetHeadPosition();
  1196. while (pos != NULL)
  1197. {
  1198. CTreeNode* pCurrentChild = m_leafChildList.GetNext(pos);
  1199. if (pCurrentChild == NULL)
  1200. {
  1201. ASSERT(FALSE);
  1202. continue;
  1203. }
  1204. if (_wcsicmp(pCurrentChild->GetDisplayName(), szRemaining) == 0)
  1205. {
  1206. //
  1207. // We found the record and its in this domain
  1208. //
  1209. *ppDomainNode = this;
  1210. return RECORD_FOUND;
  1211. }
  1212. }
  1213. }
  1214. *ppDomainNode = this;
  1215. return RECORD_NOT_FOUND;
  1216. #else
  1217. //
  1218. // The fast way that doesn't quite work
  1219. //
  1220. CString szDomainFullName = GetFullName();
  1221. CString szFullName = pszFullName;
  1222. //
  1223. // Check to see if the end of the names are equal
  1224. //
  1225. int iFindResult = szFullName.Find(szDomainFullName);
  1226. if (iFindResult == -1)
  1227. {
  1228. //
  1229. // If they are not we are never going to find them
  1230. //
  1231. *ppDomainNode = NULL;
  1232. return RECORD_NOT_FOUND;
  1233. }
  1234. if (iFindResult == 0)
  1235. {
  1236. //
  1237. // We found it
  1238. //
  1239. *ppDomainNode = this;
  1240. return RECORD_FOUND;
  1241. }
  1242. //
  1243. // Remove the matching parts plus the trailing dot
  1244. // This should leave us with something like foo.bar or just foo
  1245. //
  1246. CString szRelativeName = szFullName.Left(iFindResult - 1);
  1247. ASSERT(!szRelativeName.IsEmpty());
  1248. CString szChild;
  1249. CString szRemaining;
  1250. //
  1251. // Now search for a dot starting on the right
  1252. //
  1253. iFindResult = szRelativeName.ReverseFind(L'.');
  1254. if (iFindResult == -1)
  1255. {
  1256. //
  1257. // The relative name doesn't contain a dot so it is the child
  1258. // we are looking for
  1259. //
  1260. szChild = szRelativeName;
  1261. }
  1262. else
  1263. {
  1264. szChild = szRelativeName.Right(szRelativeName.GetLength() - iFindResult - 1);
  1265. szRemaining = szRelativeName;
  1266. }
  1267. //
  1268. // If the node hasn't been enumerated, do that now
  1269. //
  1270. if (!IsEnumerated())
  1271. {
  1272. if (!bExpandNodes)
  1273. {
  1274. *ppDomainNode = this;
  1275. return DOMAIN_NOT_ENUMERATED;
  1276. }
  1277. else
  1278. {
  1279. //
  1280. // Expand the node
  1281. //
  1282. HWND hWnd = NULL;
  1283. HRESULT hr = pComponentData->GetConsole()->GetMainWindow(&hWnd);
  1284. ASSERT(SUCCEEDED(hr));
  1285. CWnd* pParentWnd = CWnd::FromHandle(hWnd);
  1286. CLongOperationDialog dlg(
  1287. new CNodeEnumerationThread(pComponentData, this),
  1288. pParentWnd,
  1289. IDR_SEARCH_AVI);
  1290. dlg.DoModal();
  1291. }
  1292. }
  1293. //
  1294. // Search for domains that match this name
  1295. //
  1296. POSITION pos = m_containerChildList.GetHeadPosition();
  1297. while (pos != NULL)
  1298. {
  1299. CTreeNode* pCurrentChild = m_containerChildList.GetNext(pos);
  1300. CDNSDomainNode* pDomainNode = dynamic_cast<CDNSDomainNode*>(pCurrentChild);
  1301. if (pDomainNode == NULL)
  1302. {
  1303. ASSERT(FALSE);
  1304. continue;
  1305. }
  1306. if (_wcsicmp(pDomainNode->GetDisplayName(), szChild) == 0)
  1307. {
  1308. //
  1309. // Found a sub-domain in the path that we have in the UI
  1310. // recurse to see if it or any of its child match pszFullName
  1311. //
  1312. return pDomainNode->DoesContain(pszFullName, pComponentData, ppDomainNode, szNonExistentDomain, bExpandNodes);
  1313. }
  1314. }
  1315. //
  1316. // Since no domains match, lets check the records
  1317. //
  1318. pos = m_leafChildList.GetHeadPosition();
  1319. while (pos != NULL)
  1320. {
  1321. CTreeNode* pCurrentChild = m_leafChildList.GetNext(pos);
  1322. if (pCurrentChild == NULL)
  1323. {
  1324. ASSERT(FALSE);
  1325. continue;
  1326. }
  1327. if (_wcsicmp(pCurrentChild->GetDisplayName(), szChild) == 0)
  1328. {
  1329. //
  1330. // We found the record and its in this domain
  1331. //
  1332. *ppDomainNode = this;
  1333. return RECORD_FOUND;
  1334. }
  1335. }
  1336. //
  1337. // Well, we didn't find the record, If the remaining part of the name
  1338. // still contains a '.' then we know the domain the that contains the
  1339. // record is not in the UI so return NULL. If there isn't a '.' then
  1340. // we are at the correct level but just couldn't find the record. Return
  1341. // this domain.
  1342. //
  1343. if (szRemaining.Find(L'.') == -1)
  1344. {
  1345. *ppDomainNode = this;
  1346. return RECORD_NOT_FOUND;
  1347. }
  1348. else
  1349. {
  1350. //
  1351. // We were not able to find a subdomain that the record should be in
  1352. //
  1353. *ppDomainNode = this;
  1354. return NON_EXISTENT_SUBDOMAIN;
  1355. }
  1356. return RECORD_NOT_FOUND;
  1357. #endif
  1358. }
  1359. CDNSDomainNode* CDNSDomainNode::FindSubdomainNode(LPCTSTR lpszSubdomainNode)
  1360. {
  1361. //
  1362. // assume the string is the name of the subnode as FQDN
  1363. //
  1364. //
  1365. // Check the current node first since it could be zone that is a delegation of
  1366. // one of the protocol domains
  1367. //
  1368. if (_wcsicmp(GetFullName(), lpszSubdomainNode) == 0)
  1369. {
  1370. return this;
  1371. }
  1372. POSITION pos;
  1373. for( pos = m_containerChildList.GetHeadPosition(); pos != NULL; )
  1374. {
  1375. CTreeNode* pCurrentChild = m_containerChildList.GetNext(pos);
  1376. CDNSDomainNode* pSubDomainNode = dynamic_cast<CDNSDomainNode*>(pCurrentChild);
  1377. ASSERT(pSubDomainNode != NULL);
  1378. if (_wcsicmp(pSubDomainNode->GetFullName(), lpszSubdomainNode) == 0)
  1379. {
  1380. return pSubDomainNode;
  1381. }
  1382. }
  1383. return NULL; // not found
  1384. }
  1385. CDNSDomainNode* CDNSDomainNode::CreateSubdomainNode(BOOL bDelegation)
  1386. {
  1387. CDNSDomainNode* pNode = new CDNSDomainNode(bDelegation);
  1388. pNode->SetServerNode(GetServerNode());
  1389. ASSERT(m_pZoneNode != NULL);
  1390. pNode->SetZone(m_pZoneNode);
  1391. return pNode;
  1392. }
  1393. void CDNSDomainNode::SetSubdomainName(CDNSDomainNode* pSubdomainNode,
  1394. LPCTSTR lpszSubdomainName, BOOL bAdvancedView)
  1395. {
  1396. ASSERT(m_pZoneNode != NULL);
  1397. ASSERT(pSubdomainNode != NULL);
  1398. BOOL bReverse = GetZoneNode()->IsReverse();
  1399. pSubdomainNode->SetNames(FALSE, bReverse, bAdvancedView, lpszSubdomainName, GetFullName());
  1400. }
  1401. DNS_STATUS CDNSDomainNode::CreateSubdomain(CDNSDomainNode* pSubdomainNode,
  1402. CComponentDataObject* pComponentData)
  1403. {
  1404. // tell the newly created object to write to the server
  1405. DNS_STATUS err = pSubdomainNode->Create();
  1406. if (err == 0)
  1407. {
  1408. // success, add to the UI
  1409. VERIFY(AddChildToListAndUI(pSubdomainNode, pComponentData));
  1410. pComponentData->SetDescriptionBarText(this);
  1411. }
  1412. return err;
  1413. }
  1414. DNS_STATUS CDNSDomainNode::CreateSubdomain(LPCTSTR lpszDomainName,
  1415. CComponentDataObject* pComponentData)
  1416. {
  1417. CDNSDomainNode* pSubdomainNode = CreateSubdomainNode();
  1418. ASSERT(pSubdomainNode != NULL);
  1419. CDNSRootData* pRootData = (CDNSRootData*)pComponentData->GetRootData();
  1420. SetSubdomainName(pSubdomainNode, lpszDomainName, pRootData->IsAdvancedView());
  1421. // tell the newly created object to write to the server
  1422. DNS_STATUS err = CreateSubdomain(pSubdomainNode, pComponentData);
  1423. if (err != 0)
  1424. {
  1425. // something went wrong, bail out
  1426. delete pSubdomainNode;
  1427. }
  1428. return err;
  1429. }
  1430. void CDNSDomainNode::OnNewRecordHelper(CComponentDataObject* pComponentData, WORD wType)
  1431. {
  1432. ASSERT(pComponentData != NULL);
  1433. if (wType == 0)
  1434. {
  1435. CSelectDNSRecordTypeDialog dlg(this, pComponentData);
  1436. dlg.DoModal();
  1437. }
  1438. else
  1439. {
  1440. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1441. CString szTitle;
  1442. szTitle.LoadString(IDS_NEW_RECORD_TITLE);
  1443. CDNSRecordPropertyPageHolder recordHolder(this, NULL, pComponentData, wType);
  1444. recordHolder.DoModalDialog(szTitle);
  1445. }
  1446. }
  1447. HRESULT CDNSDomainNode::OnNewRecord(CComponentDataObject* pComponentData,
  1448. CNodeList* pNodeList)
  1449. {
  1450. ASSERT(pNodeList->GetCount() == 1);
  1451. OnNewRecordHelper(pComponentData, 0);
  1452. return S_OK;
  1453. }
  1454. void CDNSDomainNode::OnNewHost(CComponentDataObject* pComponentData)
  1455. {
  1456. //AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1457. //OnNewRecordHelper(pComponentData, DNS_TYPE_A);
  1458. CNewHostDialog dlg(this, pComponentData);
  1459. dlg.DoModal();
  1460. }
  1461. void CDNSDomainNode::OnNewAlias(CComponentDataObject* pComponentData)
  1462. {
  1463. OnNewRecordHelper(pComponentData, DNS_TYPE_CNAME);
  1464. }
  1465. void CDNSDomainNode::OnNewMailExchanger(CComponentDataObject* pComponentData)
  1466. {
  1467. OnNewRecordHelper(pComponentData, DNS_TYPE_MX);
  1468. }
  1469. void CDNSDomainNode::OnNewPointer(CComponentDataObject* pComponentData)
  1470. {
  1471. OnNewRecordHelper(pComponentData, DNS_TYPE_PTR);
  1472. }
  1473. //////////////////////////////////////////////////////////////////////////////////
  1474. // display of property pages
  1475. BOOL CDNSDomainNode::HasPropertyPages(DATA_OBJECT_TYPES,
  1476. BOOL* pbHideVerb,
  1477. CNodeList* pNodeList)
  1478. {
  1479. if (pNodeList->GetCount() > 1) // multiple selection
  1480. {
  1481. *pbHideVerb = TRUE;
  1482. return FALSE;
  1483. }
  1484. *pbHideVerb = FALSE; // always show the verb
  1485. if (!m_bHasDataForPropPages)
  1486. return FALSE;
  1487. // cannot have property pages only in loaded state
  1488. //if (m_nState != loaded)
  1489. // return FALSE;
  1490. // have pages if it is a delegation
  1491. return IsDelegation();
  1492. }
  1493. HRESULT CDNSDomainNode::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider,
  1494. LONG_PTR handle,
  1495. CNodeList* pNodeList)
  1496. {
  1497. ASSERT(pNodeList->GetCount() == 1); // multi-select not supported
  1498. ASSERT(m_bHasDataForPropPages);
  1499. ASSERT(IsDelegation() || GetZoneNode()->IsDSIntegrated());
  1500. if (GetSheetCount() > 0)
  1501. {
  1502. CComponentDataObject* pComponentDataObject =
  1503. ((CRootData*)(GetContainer()->GetRootContainer()))->GetComponentDataObject();
  1504. ASSERT(pComponentDataObject != NULL);
  1505. pComponentDataObject->GetPropertyPageHolderTable()->BroadcastSelectPage(this, DOMAIN_HOLDER_NS);
  1506. return S_OK;
  1507. }
  1508. return CreatePropertyPagesHelper(lpProvider, handle, DOMAIN_HOLDER_NS);
  1509. }
  1510. void CDNSDomainNode::Show(BOOL bShow, CComponentDataObject* pComponentData)
  1511. {
  1512. CDNSMTContainerNode::Show(bShow, pComponentData);
  1513. if (!bShow)
  1514. GetNSRecordNodeList()->RemoveAll();
  1515. }
  1516. HRESULT CDNSDomainNode::CreatePropertyPagesHelper(LPPROPERTYSHEETCALLBACK lpProvider,
  1517. LONG_PTR handle, long)
  1518. {
  1519. CComponentDataObject* pComponentDataObject =
  1520. ((CRootData*)(GetContainer()->GetRootContainer()))->GetComponentDataObject();
  1521. ASSERT(pComponentDataObject != NULL);
  1522. CDNSDomainPropertyPageHolder* pHolder =
  1523. new CDNSDomainPropertyPageHolder((CDNSDomainNode*)GetContainer(), this, pComponentDataObject);
  1524. ASSERT(pHolder != NULL);
  1525. pHolder->SetSheetTitle(IDS_PROP_SHEET_TITLE_FMT, this);
  1526. return pHolder->CreateModelessSheet(lpProvider, handle);
  1527. }
  1528. //////////////////////////////////////////////////////////////////////////////////
  1529. // Record Sorting in result pane
  1530. int FieldCompareHelper(CTreeNode* pNodeA, CTreeNode* pNodeB, int nCol)
  1531. {
  1532. int iRet = 0;
  1533. if (nCol == N_HEADER_NAME)
  1534. {
  1535. //
  1536. // If the name column is selected we have to sort PTR records by their
  1537. // address
  1538. //
  1539. CDNS_PTR_RecordNode* pRecNodeA = dynamic_cast<CDNS_PTR_RecordNode*>(pNodeA);
  1540. CDNS_PTR_RecordNode* pRecNodeB = dynamic_cast<CDNS_PTR_RecordNode*>(pNodeB);
  1541. if (pRecNodeA == NULL && pRecNodeB == NULL)
  1542. {
  1543. //
  1544. // Neither node is a PTR record, process normally
  1545. //
  1546. LPCTSTR lpszA = pNodeA->GetString(nCol);
  1547. LPCTSTR lpszB = pNodeB->GetString(nCol);
  1548. //
  1549. // cannot process NULL strings, have to use ""
  1550. //
  1551. if (lpszA == NULL || lpszB == NULL)
  1552. {
  1553. ASSERT(FALSE);
  1554. return -1;
  1555. }
  1556. iRet = _wcsicmp(lpszA, lpszB);
  1557. }
  1558. else if (pRecNodeA == NULL)
  1559. {
  1560. //
  1561. // Push non PTR records down in the list
  1562. //
  1563. iRet = 1;
  1564. }
  1565. else if (pRecNodeB == NULL)
  1566. {
  1567. //
  1568. // Push non PTR records down in the list
  1569. //
  1570. iRet = -1;
  1571. }
  1572. else
  1573. {
  1574. //
  1575. // Both nodes are PTR records, compare their Addresses
  1576. // Subtract one from the other
  1577. // This will result in < 0 returned if the first one is less than the second
  1578. // 0 if they are equal, and > 0 if the first is greater than the second
  1579. //
  1580. LPCWSTR lpszNameA, lpszNameB;
  1581. lpszNameA = pRecNodeA->GetTrueRecordName();
  1582. lpszNameB = pRecNodeB->GetTrueRecordName();
  1583. if (lpszNameA == NULL)
  1584. {
  1585. return -1;
  1586. }
  1587. if (lpszNameB == NULL)
  1588. {
  1589. return 1;
  1590. }
  1591. DWORD dwAddrA, dwAddrB;
  1592. int iConverts = swscanf(lpszNameA, L"%d", &dwAddrA);
  1593. if (iConverts != 1)
  1594. {
  1595. return -1;
  1596. }
  1597. iConverts = swscanf(lpszNameB, L"%d", &dwAddrB);
  1598. if (iConverts != 1)
  1599. {
  1600. return 1;
  1601. }
  1602. iRet = dwAddrA - dwAddrB;
  1603. }
  1604. }
  1605. else if (nCol == N_HEADER_DATA)
  1606. {
  1607. //
  1608. // If the data column is selected we have to check the record type so
  1609. // that we can sort by IP address
  1610. //
  1611. CDNS_A_RecordNode* pRecNodeA = dynamic_cast<CDNS_A_RecordNode*>(pNodeA);
  1612. CDNS_A_RecordNode* pRecNodeB = dynamic_cast<CDNS_A_RecordNode*>(pNodeB);
  1613. if (pRecNodeA == NULL && pRecNodeB == NULL)
  1614. {
  1615. //
  1616. // Neither node is an A record, process normally
  1617. //
  1618. LPCTSTR lpszA = pNodeA->GetString(nCol);
  1619. LPCTSTR lpszB = pNodeB->GetString(nCol);
  1620. //
  1621. // cannot process NULL strings, have to use ""
  1622. //
  1623. if (lpszA == NULL || lpszB == NULL)
  1624. {
  1625. ASSERT(FALSE);
  1626. return -1;
  1627. }
  1628. iRet = _wcsicmp(lpszA, lpszB);
  1629. }
  1630. else if (pRecNodeA == NULL)
  1631. {
  1632. //
  1633. // Push non A records down in the list
  1634. //
  1635. iRet = 1;
  1636. }
  1637. else if (pRecNodeB == NULL)
  1638. {
  1639. //
  1640. // Push non A records down in the list
  1641. //
  1642. iRet = -1;
  1643. }
  1644. else
  1645. {
  1646. //
  1647. // Both nodes are A records, compare their IP Addresses
  1648. // Subtract one from the other
  1649. // This will result in < 0 returned if the first one is less than the second
  1650. // 0 if they are equal, and > 0 if the first is greater than the second
  1651. //
  1652. DWORD dwIPA, dwIPB;
  1653. dwIPA = pRecNodeA->GetIPAddress();
  1654. dwIPB = pRecNodeB->GetIPAddress();
  1655. UINT nOctetCount = 0;
  1656. iRet = 0;
  1657. while (iRet == 0 && nOctetCount < 4)
  1658. {
  1659. iRet = (dwIPA & 0xff) - (dwIPB & 0xff);
  1660. dwIPA = dwIPA >> 8;
  1661. dwIPB = dwIPB >> 8;
  1662. ++nOctetCount;
  1663. }
  1664. }
  1665. }
  1666. else
  1667. {
  1668. LPCTSTR lpszA = pNodeA->GetString(nCol);
  1669. LPCTSTR lpszB = pNodeB->GetString(nCol);
  1670. //
  1671. // cannot process NULL strings, have to use ""
  1672. //
  1673. if (lpszA == NULL || lpszB == NULL)
  1674. {
  1675. ASSERT(FALSE);
  1676. return -1;
  1677. }
  1678. iRet = _wcsicmp(lpszA, lpszB);
  1679. }
  1680. return iRet;
  1681. }
  1682. int CDNSDomainNode::Compare(CTreeNode* pNodeA, CTreeNode* pNodeB, int nCol, long)
  1683. {
  1684. // sorting rules for secondary fields
  1685. int nColSec = N_HEADER_TYPE;
  1686. int nColThird = N_HEADER_DATA;
  1687. switch (nCol)
  1688. {
  1689. case N_HEADER_NAME:
  1690. nColSec = N_HEADER_TYPE;
  1691. nColThird = N_HEADER_DATA;
  1692. break;
  1693. case N_HEADER_TYPE:
  1694. nColSec = N_HEADER_NAME;
  1695. nColThird = N_HEADER_DATA;
  1696. break;
  1697. case N_HEADER_DATA:
  1698. nColSec = N_HEADER_NAME;
  1699. nColThird = N_HEADER_TYPE;
  1700. break;
  1701. default:
  1702. ASSERT(FALSE);
  1703. }
  1704. int nResult = FieldCompareHelper(pNodeA, pNodeB, nCol);
  1705. if (nResult != 0)
  1706. return nResult;
  1707. nResult = FieldCompareHelper(pNodeA, pNodeB, nColSec);
  1708. if (nResult != 0)
  1709. return nResult;
  1710. return FieldCompareHelper(pNodeA, pNodeB, nColThird);
  1711. }
  1712. //////////////////////////////////////////////////////////////////////////////////
  1713. // NS record bulk manipulation
  1714. // function to the user for confirmation on editing of A records
  1715. // associated with an NS record
  1716. BOOL _ConfirmEditAction(CDNSRecordNodeEditInfo* pInfo, BOOL bAsk)
  1717. {
  1718. if (!bAsk)
  1719. return TRUE; // silently do it
  1720. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1721. ASSERT(pInfo->m_pRecord->GetType() == DNS_TYPE_A);
  1722. ASSERT(pInfo->m_pRecord != NULL);
  1723. CDNS_A_RecordNode* pARecordNode = (CDNS_A_RecordNode*)pInfo->m_pRecordNode;
  1724. // load format message
  1725. CString szFmt;
  1726. szFmt.LoadString(IDS_MSG_RECORD_DEL_A_FROM_NS);
  1727. // compose message
  1728. CString szMsg;
  1729. szMsg.Format((LPCWSTR)szFmt, pARecordNode->GetString(0), pARecordNode->GetString(2));
  1730. return (IDYES == DNSMessageBox(szMsg, MB_YESNO | MB_ICONWARNING ) );
  1731. }
  1732. void CDNSDomainNode::GetNSRecordNodesInfo(CDNSRecordNodeEditInfoList* pNSInfoList)
  1733. {
  1734. ASSERT(pNSInfoList != NULL);
  1735. if (!pNSInfoList->IsEmpty())
  1736. {
  1737. ASSERT(FALSE); // should never happen
  1738. pNSInfoList->RemoveAllNodes();
  1739. }
  1740. CDNS_NS_RecordNodeList* pNodeList = GetNSRecordNodeList();
  1741. // for each NS record in the list, create an entry in the info list
  1742. POSITION pos;
  1743. for( pos = pNodeList->GetHeadPosition(); pos != NULL; )
  1744. {
  1745. CDNS_NS_RecordNode* pCurrNode = pNodeList->GetNext(pos);
  1746. ASSERT(pCurrNode != NULL);
  1747. CDNSRecordNodeEditInfo* pNSNodeInfo = new CDNSRecordNodeEditInfo();
  1748. if (pNSNodeInfo)
  1749. {
  1750. // set the data for the NS record, already in the list, so we do now own the memory
  1751. pNSNodeInfo->CreateFromExistingRecord(pCurrNode, FALSE /*bOwnMemory*/, TRUE /*bUpdateUI*/);
  1752. // for the current NS record, find the associated A records
  1753. FindARecordsFromNSInfo(pCurrNode->GetString(2),pNSNodeInfo->m_pEditInfoList);
  1754. pNSInfoList->AddTail(pNSNodeInfo);
  1755. }
  1756. }
  1757. }
  1758. BOOL CDNSDomainNode::HasNSRecords()
  1759. {
  1760. return GetNSRecordNodeList()->GetCount() > 0;
  1761. }
  1762. BOOL CDNSDomainNode::UpdateNSRecordNodesInfo(CDNSRecordNodeEditInfoList* pNewInfoList,
  1763. CComponentDataObject* pComponentData)
  1764. {
  1765. ASSERT(pNewInfoList != NULL);
  1766. // return false if at least one operation failed
  1767. BOOL bRes = TRUE;
  1768. CDNS_NS_RecordNodeList* pNSRecordNodeList = GetNSRecordNodeList();
  1769. // clear the current state in this domain object
  1770. pNSRecordNodeList->RemoveAll();
  1771. // rebuild the current list from the new one, while applying the changes
  1772. POSITION pos;
  1773. for ( pos = pNewInfoList->GetHeadPosition(); pos != NULL; )
  1774. {
  1775. CDNSRecordNodeEditInfo* pCurrentInfo = pNewInfoList->GetNext(pos);
  1776. ASSERT(pCurrentInfo->m_pRecordNode != NULL);
  1777. ASSERT(pCurrentInfo->m_pRecord != NULL);
  1778. switch (pCurrentInfo->m_action)
  1779. {
  1780. case CDNSRecordNodeEditInfo::add:
  1781. case CDNSRecordNodeEditInfo::edit:
  1782. {
  1783. if (pCurrentInfo->Update(this, pComponentData) == 0)
  1784. {
  1785. ASSERT(pCurrentInfo->m_pRecordNode->GetType() == DNS_TYPE_NS);
  1786. pNSRecordNodeList->AddTail((CDNS_NS_RecordNode*)pCurrentInfo->m_pRecordNode);
  1787. pCurrentInfo->m_bOwnMemory = FALSE; // relinquish ownership
  1788. }
  1789. else
  1790. {
  1791. bRes = FALSE;
  1792. }
  1793. }
  1794. break;
  1795. case CDNSRecordNodeEditInfo::remove:
  1796. {
  1797. if (pCurrentInfo->m_bExisting)
  1798. {
  1799. if (pCurrentInfo->Remove(this, pComponentData) != 0)
  1800. bRes = FALSE;
  1801. }
  1802. }
  1803. break;
  1804. case CDNSRecordNodeEditInfo::none:
  1805. //
  1806. // Do nothing if the the node has been added and then removed without having been applied
  1807. //
  1808. break;
  1809. default:
  1810. {
  1811. ASSERT(pCurrentInfo->m_bOwnMemory == FALSE);
  1812. ASSERT(pCurrentInfo->m_action == CDNSRecordNodeEditInfo::unchanged);
  1813. //
  1814. // We still have to update the NS record because the server needs to
  1815. // update the record in memory (bug 23905)
  1816. //
  1817. if (pCurrentInfo->Update(this, pComponentData) == 0)
  1818. {
  1819. pNSRecordNodeList->AddTail((CDNS_NS_RecordNode*)pCurrentInfo->m_pRecordNode);
  1820. }
  1821. }
  1822. }; // switch
  1823. // now we have to apply the changes in the list of A records
  1824. if (pCurrentInfo->m_dwErr == 0 && pCurrentInfo->m_action != CDNSRecordNodeEditInfo::none)
  1825. UpdateARecordsOfNSInfo(pCurrentInfo, pComponentData);
  1826. } // for
  1827. return bRes;
  1828. }
  1829. // static function
  1830. void CDNSDomainNode::UpdateARecordsOfNSInfoHelper(CDNSDomainNode* pDomainNode,
  1831. CDNSRecordNodeEditInfo* pNSInfo,
  1832. CComponentDataObject* pComponentData,
  1833. BOOL bAskConfirmation)
  1834. {
  1835. ASSERT(pNSInfo->m_dwErr == 0);
  1836. ASSERT(pNSInfo->m_pRecordNode != NULL);
  1837. ASSERT(pNSInfo->m_pRecordNode->GetType() == DNS_TYPE_NS);
  1838. POSITION pos;
  1839. // get the list of related A records
  1840. CDNSRecordNodeEditInfoList* pNSInfoList = pNSInfo->m_pEditInfoList;
  1841. for( pos = pNSInfoList->GetHeadPosition(); pos != NULL; )
  1842. {
  1843. CDNSRecordNodeEditInfo* pCurrentInfo = pNSInfoList->GetNext(pos);
  1844. ASSERT(pCurrentInfo->m_pRecordNode != NULL);
  1845. ASSERT(pCurrentInfo->m_pRecord != NULL);
  1846. CDNS_A_RecordNode* pARecordNode = (CDNS_A_RecordNode*)pCurrentInfo->m_pRecordNode;
  1847. ASSERT(pNSInfo->m_pRecord != NULL);
  1848. CDNS_NS_Record* pNSRecord = (CDNS_NS_Record*)pNSInfo->m_pRecord;
  1849. BOOL bHostNameChanged = !_match(pNSRecord->m_szNameNode, pARecordNode);
  1850. if (bHostNameChanged)
  1851. {
  1852. // the NS record points to a different host, so need
  1853. // to delete the old A RR and create a new one
  1854. BOOL bRemoveOld = _ConfirmEditAction(pCurrentInfo, bAskConfirmation);
  1855. CDNSRecordNodeEditInfo::actionType oldAction = pCurrentInfo->m_action;
  1856. if (pCurrentInfo->m_bExisting && bRemoveOld)
  1857. {
  1858. // if the A record was an existing one, need to remove first
  1859. pCurrentInfo->m_action = CDNSRecordNodeEditInfo::remove;
  1860. pCurrentInfo->Remove(pDomainNode, pComponentData);
  1861. }
  1862. // now decide if have to add
  1863. if (oldAction == CDNSRecordNodeEditInfo::remove && bRemoveOld)
  1864. {
  1865. // it was meant to be removed anyway
  1866. pCurrentInfo->m_bOwnMemory = TRUE; // edit info will clean up memory
  1867. }
  1868. else
  1869. {
  1870. // it was meant to be edited or added, restore old action code
  1871. pCurrentInfo->m_action = oldAction;
  1872. // change the name of the record
  1873. pCurrentInfo->m_pRecordNode->SetRecordName(pNSRecord->m_szNameNode, FALSE /*bAtTheNode*/);
  1874. // add new A record with different FQDN
  1875. pCurrentInfo->m_action = CDNSRecordNodeEditInfo::add;
  1876. pCurrentInfo->Update(pDomainNode, pComponentData);
  1877. pCurrentInfo->m_bOwnMemory = FALSE; // written im master structures
  1878. }
  1879. }
  1880. else // the name is still the same
  1881. {
  1882. switch(pNSInfo->m_action)
  1883. {
  1884. case CDNSRecordNodeEditInfo::remove:
  1885. {
  1886. // NS record marked for deletion means removing the associated A records
  1887. if (pCurrentInfo->m_bExisting && _ConfirmEditAction(pCurrentInfo, bAskConfirmation))
  1888. {
  1889. pCurrentInfo->Remove(pDomainNode, pComponentData);
  1890. pCurrentInfo->m_bOwnMemory = TRUE; // it will cleanup itself
  1891. }
  1892. }
  1893. break;
  1894. case CDNSRecordNodeEditInfo::add:
  1895. {
  1896. if (!pCurrentInfo->m_bExisting)
  1897. {
  1898. pCurrentInfo->Update(pDomainNode, pComponentData);
  1899. pCurrentInfo->m_bOwnMemory = FALSE; // written im master structures
  1900. }
  1901. }
  1902. break;
  1903. case CDNSRecordNodeEditInfo::edit:
  1904. {
  1905. // NS host name not changed, just update list of A records
  1906. switch(pCurrentInfo->m_action)
  1907. {
  1908. case CDNSRecordNodeEditInfo::remove:
  1909. {
  1910. if (pCurrentInfo->m_bExisting && _ConfirmEditAction(pCurrentInfo, bAskConfirmation))
  1911. {
  1912. pCurrentInfo->Remove(pDomainNode, pComponentData);
  1913. pCurrentInfo->m_bOwnMemory = TRUE; // it will cleanup itself
  1914. }
  1915. }
  1916. break;
  1917. case CDNSRecordNodeEditInfo::edit:
  1918. {
  1919. // we just changed the TTL
  1920. ASSERT(pCurrentInfo->m_bExisting);
  1921. pCurrentInfo->Update(pDomainNode, pComponentData);
  1922. pCurrentInfo->m_bOwnMemory = FALSE; // written im master structures
  1923. }
  1924. break;
  1925. case CDNSRecordNodeEditInfo::add:
  1926. {
  1927. if (!pCurrentInfo->m_bExisting)
  1928. {
  1929. pCurrentInfo->Update(pDomainNode, pComponentData);
  1930. pCurrentInfo->m_bOwnMemory = FALSE; // written im master structures
  1931. }
  1932. }
  1933. break;
  1934. }; // switch
  1935. }
  1936. break;
  1937. }; // switch
  1938. } // if,else
  1939. } // for
  1940. }
  1941. void CDNSDomainNode::UpdateARecordsOfNSInfo(CDNSRecordNodeEditInfo* pNSInfo,
  1942. CComponentDataObject* pComponentData)
  1943. {
  1944. // create a fake domain object to run a query looking for
  1945. // A records that match the given list of NS records
  1946. CDNSDummyDomainNode fakeDomain;
  1947. fakeDomain.SetServerNode(GetServerNode());
  1948. fakeDomain.SetZone(GetZoneNode());
  1949. BOOL bAskConfirmation = TRUE; // we migth delete A RR's that we need
  1950. UpdateARecordsOfNSInfoHelper(&fakeDomain, pNSInfo, pComponentData, bAskConfirmation);
  1951. }
  1952. void CDNSDomainNode::FindARecordsFromNSInfo(LPCTSTR lpszNSName,
  1953. CDNSRecordNodeEditInfoList* pNSInfoList)
  1954. {
  1955. // just call the static version
  1956. CDNSRootData* pRootData = (CDNSRootData*)GetRootContainer();
  1957. ASSERT(pRootData != NULL);
  1958. DWORD cAddrCount;
  1959. PIP_ADDRESS pipAddrs;
  1960. GetServerNode()->GetListenAddressesInfo(&cAddrCount, &pipAddrs);
  1961. if (cAddrCount == 0)
  1962. {
  1963. // listening on all addresses
  1964. GetServerNode()->GetServerAddressesInfo(&cAddrCount, &pipAddrs);
  1965. }
  1966. FindARecordsFromNSInfo(GetServerNode()->GetRPCName(),
  1967. GetServerNode()->GetVersion(),
  1968. cAddrCount, pipAddrs,
  1969. GetZoneNode()->GetFullName(),
  1970. lpszNSName,
  1971. pNSInfoList,
  1972. pRootData->IsAdvancedView());
  1973. }
  1974. void CDNSDomainNode::FindARecordsFromNSInfo(LPCWSTR lpszServerName, DWORD dwServerVersion,
  1975. DWORD cServerAddrCount, PIP_ADDRESS pipServerAddrs,
  1976. LPCWSTR lpszZoneName,
  1977. LPCWSTR lpszNSName,
  1978. CDNSRecordNodeEditInfoList* pNSInfoList,
  1979. BOOL bAdvancedView)
  1980. {
  1981. ASSERT(pNSInfoList != NULL);
  1982. ASSERT(pNSInfoList->IsEmpty());
  1983. // specifically look for A records matching a given NS name
  1984. // set query flags to get all the possible data
  1985. DWORD dwSelectFlags = DNS_RPC_VIEW_AUTHORITY_DATA | DNS_RPC_VIEW_GLUE_DATA |
  1986. DNS_RPC_VIEW_ADDITIONAL_DATA;
  1987. CDNSDomainQueryObj query(lpszServerName,
  1988. lpszZoneName,
  1989. dwServerVersion,
  1990. NULL, // lpszNodeName, no need here
  1991. lpszNSName,
  1992. DNS_TYPE_A,
  1993. dwSelectFlags,
  1994. FALSE, // zone
  1995. FALSE, // reverse
  1996. FALSE, // cache
  1997. bAdvancedView);
  1998. query.Enumerate();
  1999. // get record from the queue into the info
  2000. CObjBaseList* pChildList = query.GetQueue();
  2001. //int n = pChildList->GetCount();
  2002. while (!pChildList->IsEmpty())
  2003. {
  2004. CTreeNode* pNode = dynamic_cast<CTreeNode*>(pChildList->RemoveHead());
  2005. ASSERT(pNode != NULL);
  2006. if (!pNode->IsContainer())
  2007. {
  2008. CDNSRecordNodeBase* pRec = (CDNSRecordNodeBase*)pNode;
  2009. if (pRec->GetType() == DNS_TYPE_A)
  2010. {
  2011. TRACE(_T("Record <%s>\n"), pRec->GetString(2));
  2012. pRec->SetRecordName(lpszNSName, FALSE /*bAtTheNode*/);
  2013. CDNSRecordNodeEditInfo* pANodeInfo = new CDNSRecordNodeEditInfo;
  2014. if (pANodeInfo)
  2015. {
  2016. // NOTICE: we assume that all the nodes are glue, so we own the memory
  2017. pANodeInfo->CreateFromExistingRecord(pRec, TRUE /*bOwnMemory*/, FALSE /*bUpdateUI*/);
  2018. pNSInfoList->AddTail(pANodeInfo);
  2019. }
  2020. }
  2021. }
  2022. else
  2023. delete pNode; // discard
  2024. }
  2025. if (pNSInfoList->GetCount() > 0)
  2026. return; // got the info we needed just using RPC
  2027. // Could not find the A records, we need to try DnsQuery to get info outside the server
  2028. // search using DnsQuery and convert
  2029. PDNS_RECORD pDnsQueryARecordList = NULL;
  2030. // if available, use the provided addresses to do a DnsQuery()
  2031. PIP_ARRAY pipArr = NULL;
  2032. if ( (cServerAddrCount > 0) && (pipServerAddrs != NULL) )
  2033. {
  2034. pipArr = (PIP_ARRAY)malloc(sizeof(DWORD)+sizeof(IP_ADDRESS)*cServerAddrCount);
  2035. if (!pipArr)
  2036. {
  2037. return;
  2038. }
  2039. pipArr->AddrCount = cServerAddrCount;
  2040. memcpy(pipArr->AddrArray, pipServerAddrs, sizeof(IP_ADDRESS)*cServerAddrCount);
  2041. }
  2042. DWORD dwErr = ::DnsQuery((LPWSTR)lpszNSName, DNS_TYPE_A,
  2043. DNS_QUERY_NO_RECURSION, pipArr, &pDnsQueryARecordList, NULL);
  2044. if (pipArr)
  2045. {
  2046. free(pipArr);
  2047. pipArr = 0;
  2048. }
  2049. // no luck, try a simple query, with no IP addresses specified
  2050. if (pDnsQueryARecordList == NULL)
  2051. {
  2052. dwErr = ::DnsQuery((LPWSTR)lpszNSName, DNS_TYPE_A,
  2053. DNS_QUERY_NO_RECURSION, NULL, &pDnsQueryARecordList, NULL);
  2054. }
  2055. if (pDnsQueryARecordList == NULL)
  2056. return; // failed, no way to resolve IP address
  2057. PDNS_RECORD pCurrDnsQueryRecord = pDnsQueryARecordList;
  2058. while (pCurrDnsQueryRecord)
  2059. {
  2060. if (pCurrDnsQueryRecord->Flags.S.Section == DNSREC_ANSWER)
  2061. {
  2062. if (pCurrDnsQueryRecord->wType == DNS_TYPE_A)
  2063. {
  2064. // create a record node
  2065. CDNSRecordNodeBase* pRecordNode =
  2066. CDNSRecordInfo::CreateRecordNode(pCurrDnsQueryRecord->wType);
  2067. pRecordNode->CreateFromDnsQueryRecord(pCurrDnsQueryRecord, 0x0);
  2068. pRecordNode->SetRecordName(lpszNSName, FALSE /*bAtTheNode*/);
  2069. CDNSRecordNodeEditInfo* pANodeInfo = new CDNSRecordNodeEditInfo;
  2070. if (pANodeInfo)
  2071. {
  2072. pANodeInfo->m_bFromDnsQuery = TRUE;
  2073. //
  2074. // NOTICE: we assume that all the nodes are glue, so we own the memory
  2075. //
  2076. pANodeInfo->CreateFromExistingRecord(pRecordNode, TRUE /*bOwnMemory*/, FALSE /*bUpdateUI*/);
  2077. pNSInfoList->AddTail(pANodeInfo);
  2078. }
  2079. }
  2080. }
  2081. // goto next record
  2082. pCurrDnsQueryRecord = pCurrDnsQueryRecord->pNext;
  2083. }
  2084. DnsRecordListFree(pDnsQueryARecordList, DnsFreeRecordListDeep);
  2085. }
  2086. //////////////////////////////////////////////////////////////////////////////////
  2087. DNS_STATUS CDNSDomainNode::EnumerateNodes(LPCTSTR lpszServerName,
  2088. LPCTSTR lpszZoneName,
  2089. LPCTSTR lpszNodeName,
  2090. LPCTSTR lpszFullNodeName,
  2091. WORD wRecordType,
  2092. DWORD dwSelectFlag,
  2093. BOOL, BOOL bReverse, BOOL bAdvancedView,
  2094. CDNSDomainQueryObj* pQuery)
  2095. {
  2096. ASSERT(pQuery != NULL);
  2097. USES_CONVERSION;
  2098. DNS_STATUS err = 0;
  2099. CHAR szStartChildAnsi[3*MAX_DNS_NAME_LEN + 1]; // can have multibyte chars, count NULL
  2100. szStartChildAnsi[0] = NULL;
  2101. WCHAR szStartChild[MAX_DNS_NAME_LEN + 1]; // count NULL
  2102. szStartChild[0] = NULL;
  2103. CTreeNode* pNodeToInsert = NULL; // delayed insert
  2104. CDNSRecordNodeBase* pMoreDataNode = NULL;
  2105. // convert to UTF8 names
  2106. LPCSTR lpszFullNodeNameAnsi = W_TO_UTF8(lpszFullNodeName);
  2107. LPCSTR lpszZoneNameAnsi = W_TO_UTF8(lpszZoneName);
  2108. BOOL bTooMuchData = FALSE;
  2109. do // while more data
  2110. {
  2111. // get a chunk of data from RPC call
  2112. BYTE* pbRpcBuffer = NULL;
  2113. DWORD cbRpcBufferUsed = 0;
  2114. err = ::DnssrvEnumRecords(lpszServerName,
  2115. lpszZoneNameAnsi,
  2116. lpszFullNodeNameAnsi, // e.g. "foo.bar.com."
  2117. szStartChildAnsi, // Start Child
  2118. wRecordType,
  2119. dwSelectFlag,
  2120. NULL, // pszFilterStart
  2121. NULL, // pszFilterStop
  2122. &cbRpcBufferUsed,
  2123. &pbRpcBuffer);
  2124. if ((err != ERROR_MORE_DATA) && (err != 0))
  2125. return err; // bail out if there is an error
  2126. // walk the memory and build objects
  2127. DNS_RPC_NODE * pDnsNode = (DNS_RPC_NODE *)pbRpcBuffer;
  2128. DNS_RPC_RECORD * pDnsRecord;
  2129. void* pvEndOfRpcBuffer = pbRpcBuffer + cbRpcBufferUsed;
  2130. while ( (!bTooMuchData) && (pDnsNode < pvEndOfRpcBuffer) )
  2131. {
  2132. // get an ANSI null terminated copy
  2133. memcpy(szStartChildAnsi, pDnsNode->dnsNodeName.achName, pDnsNode->dnsNodeName.cchNameLength);
  2134. szStartChildAnsi[pDnsNode->dnsNodeName.cchNameLength] = NULL;
  2135. //
  2136. // get a UNICODE null terminated copy
  2137. //
  2138. if (szStartChildAnsi[0] == NULL)
  2139. {
  2140. szStartChild[0] = NULL;
  2141. }
  2142. else
  2143. {
  2144. DnsUtf8ToWHelper(szStartChild, szStartChildAnsi, pDnsNode->dnsNodeName.cchNameLength+1);
  2145. }
  2146. if (pDnsNode->dwChildCount || (pDnsNode->dwFlags & DNS_RPC_NODE_FLAG_STICKY))
  2147. {
  2148. BOOL bDelegation = ( ((dwSelectFlag & DNS_RPC_VIEW_CACHE_DATA) == 0) &&
  2149. ((pDnsNode->dwFlags & DNS_RPC_FLAG_ZONE_ROOT) != 0) );
  2150. CDNSDomainNode* p = NULL;
  2151. if (pQuery->CanAddDomain(szStartChild))
  2152. {
  2153. bTooMuchData = pQuery->TooMuchData();
  2154. if (!bTooMuchData)
  2155. {
  2156. p = new CDNSDomainNode(bDelegation);
  2157. p->SetNames(FALSE, bReverse, bAdvancedView, szStartChild, lpszFullNodeName);
  2158. }
  2159. }
  2160. if (pNodeToInsert != NULL)
  2161. {
  2162. VERIFY(pQuery->AddQueryResult(pNodeToInsert));
  2163. }
  2164. pNodeToInsert = p;
  2165. }
  2166. pDnsRecord = (DNS_RPC_RECORD *)((BYTE *)pDnsNode + NEXT_DWORD(pDnsNode->wLength));
  2167. ASSERT(IS_DWORD_ALIGNED(pDnsRecord));
  2168. //
  2169. // Add the records under that node
  2170. //
  2171. UINT cRecordCount = pDnsNode->wRecordCount;
  2172. while ( (!bTooMuchData) && (cRecordCount--) )
  2173. {
  2174. CDNSRecordNodeBase* p = NULL;
  2175. BOOL bAtTheNode = szStartChild[0] == NULL;
  2176. LPCWSTR lpszRecordName = (bAtTheNode) ? lpszNodeName : szStartChild;
  2177. if (pQuery->CanAddRecord(pDnsRecord->wType, lpszRecordName))
  2178. {
  2179. TRACE(_T("\tCan add record %ws\n"), lpszRecordName);
  2180. bTooMuchData = pQuery->TooMuchData();
  2181. if (!bTooMuchData)
  2182. {
  2183. if (bAtTheNode)
  2184. {
  2185. p = CDNSRecordInfo::CreateRecordNodeFromRPCData(
  2186. lpszRecordName, pDnsRecord,bAtTheNode);
  2187. }
  2188. else
  2189. {
  2190. // filter out the NS records that are not at the node
  2191. if (pDnsRecord->wType != DNS_TYPE_NS)
  2192. {
  2193. p = CDNSRecordInfo::CreateRecordNodeFromRPCData(
  2194. lpszRecordName, pDnsRecord,bAtTheNode);
  2195. }
  2196. }
  2197. } // if not too much data
  2198. } // if can add
  2199. if (p != NULL)
  2200. {
  2201. p->SetFlagsDown(TN_FLAG_DNS_RECORD_FULL_NAME, !bAdvancedView);
  2202. if (pNodeToInsert != NULL)
  2203. {
  2204. VERIFY(pQuery->AddQueryResult(pNodeToInsert));
  2205. }
  2206. if (pMoreDataNode != NULL)
  2207. {
  2208. //
  2209. // If there was more data check to see if the new node is the same as the
  2210. // last node from the previous batch. Insert it if they are different, delete
  2211. // it if they are not
  2212. //
  2213. CString szMoreDataName = pMoreDataNode->GetDisplayName();
  2214. CString szPName = p->GetDisplayName();
  2215. if (szMoreDataName == szPName &&
  2216. pMoreDataNode->GetType() == p->GetType() &&
  2217. _wcsicmp(pMoreDataNode->GetString(3), p->GetString(3)) == 0)
  2218. {
  2219. delete pMoreDataNode;
  2220. }
  2221. else
  2222. {
  2223. VERIFY(pQuery->AddQueryResult(pMoreDataNode));
  2224. }
  2225. pMoreDataNode = NULL;
  2226. }
  2227. pNodeToInsert = p;
  2228. }
  2229. pDnsRecord = DNS_NEXT_RECORD(pDnsRecord);
  2230. } // while cRecordCount
  2231. // The new node is found at the end of the last record
  2232. pDnsNode = (DNS_RPC_NODE *)pDnsRecord;
  2233. } // while end of buffer
  2234. // we still have a node to insert, but we discard it if there is more data
  2235. // because we are going to get it again and we want to avoid duplication
  2236. if (pNodeToInsert != NULL)
  2237. {
  2238. if (bTooMuchData)
  2239. {
  2240. delete pNodeToInsert;
  2241. }
  2242. else if (err == ERROR_MORE_DATA)
  2243. {
  2244. //
  2245. // Doesn't matter if this turns out NULL because we only want
  2246. // pMoreDataNode to be a record node. If its a domain node we
  2247. // can just ignore it
  2248. //
  2249. pMoreDataNode = dynamic_cast<CDNSRecordNodeBase*>(pNodeToInsert);
  2250. }
  2251. else
  2252. {
  2253. VERIFY(pQuery->AddQueryResult(pNodeToInsert));
  2254. }
  2255. pNodeToInsert = NULL;
  2256. }
  2257. ::DnssrvFreeRecordsBuffer(pbRpcBuffer);
  2258. } while ( !bTooMuchData && (err == ERROR_MORE_DATA) ) ;
  2259. // we are bailing out because of too much data,
  2260. // need to let the main tread know
  2261. if (bTooMuchData && (err != ERROR_MORE_DATA))
  2262. {
  2263. err = ERROR_MORE_DATA;
  2264. }
  2265. return err;
  2266. }
  2267. DNS_STATUS CDNSDomainNode::Create()
  2268. {
  2269. USES_CONVERSION;
  2270. LPCWSTR lpszFullZoneName = NULL;
  2271. CDNSZoneNode* pZoneNode = GetZoneNode();
  2272. if (pZoneNode != NULL)
  2273. lpszFullZoneName = pZoneNode->GetFullName();
  2274. DNS_STATUS err = ::DnssrvUpdateRecord(GetServerNode()->GetRPCName(),
  2275. W_TO_UTF8(lpszFullZoneName),
  2276. W_TO_UTF8(GetFullName()),
  2277. NULL, NULL);
  2278. return err;
  2279. }
  2280. DNS_STATUS CDNSDomainNode::Delete()
  2281. {
  2282. USES_CONVERSION;
  2283. LPCWSTR lpszFullZoneName = NULL;
  2284. CDNSZoneNode* pZoneNode = GetZoneNode();
  2285. if (pZoneNode != NULL)
  2286. lpszFullZoneName = pZoneNode->GetFullName();
  2287. return ::DnssrvDeleteNode(GetServerNode()->GetRPCName(),
  2288. W_TO_UTF8(lpszFullZoneName),
  2289. W_TO_UTF8(GetFullName()),
  2290. TRUE // fDeleteSubtree
  2291. );
  2292. }
  2293. /////////////////////////////////////////////////////////////////////////
  2294. // CDNSRootHintsNode
  2295. DNS_STATUS CDNSRootHintsNode::QueryForRootHints(LPCTSTR lpszServerName, DWORD dwServerVersion)
  2296. {
  2297. USES_CONVERSION;
  2298. DWORD dwSelectFlags = DNS_RPC_VIEW_ROOT_HINT_DATA | DNS_RPC_VIEW_ADDITIONAL_DATA | DNS_RPC_VIEW_NO_CHILDREN;
  2299. CDNSDomainQueryObj query(lpszServerName,
  2300. UTF8_TO_W(DNS_ZONE_ROOT_HINTS), //lpszZoneName, needs to be "..RootHints" as defined in dnsrpc.h
  2301. dwServerVersion,
  2302. GetDisplayName(),
  2303. m_szFullName,
  2304. DNS_TYPE_NS,
  2305. dwSelectFlags,
  2306. FALSE, // zone
  2307. FALSE, // reverse
  2308. FALSE, // cache
  2309. FALSE);
  2310. query.Enumerate();
  2311. DWORD dwErr = query.GetError();
  2312. if (dwErr != 0)
  2313. return dwErr;
  2314. // get record from the queue into the folder
  2315. CObjBaseList* pChildList = query.GetQueue();
  2316. //int n = pChildList->GetCount();
  2317. while (!pChildList->IsEmpty())
  2318. {
  2319. CTreeNode* pNode = dynamic_cast<CTreeNode*>(pChildList->RemoveHead());
  2320. // NOTICE: for NT 4.0 servers, we get bogus container nodes
  2321. // that we have to suppress
  2322. if(pNode->IsContainer())
  2323. {
  2324. delete pNode;
  2325. }
  2326. else
  2327. {
  2328. OnHaveRecord((CDNSRecordNodeBase*)pNode, NULL); // add to the list of NS records
  2329. AddChildToList(pNode);
  2330. }
  2331. }
  2332. return (DNS_STATUS)dwErr;
  2333. }
  2334. void CDNSRootHintsNode::FindARecordsFromNSInfo(LPCTSTR lpszNSName,
  2335. CDNSRecordNodeEditInfoList* pNSInfoList)
  2336. {
  2337. ASSERT(pNSInfoList != NULL);
  2338. //
  2339. // for root hints, we have all the records in this folder and we
  2340. // can edit them
  2341. //
  2342. POSITION pos;
  2343. for( pos = m_leafChildList.GetHeadPosition(); pos != NULL; )
  2344. {
  2345. CTreeNode* pCurrentChild = m_leafChildList.GetNext(pos);
  2346. ASSERT(!pCurrentChild->IsContainer());
  2347. CDNSRecordNodeBase* pRecordNode = (CDNSRecordNodeBase*)pCurrentChild;
  2348. if (DNS_TYPE_A == pRecordNode->GetType())
  2349. {
  2350. CDNS_A_RecordNode* pARecordNode = (CDNS_A_RecordNode*)pRecordNode;
  2351. if (_match(lpszNSName, pARecordNode))
  2352. {
  2353. CDNSRecordNodeEditInfo* pANodeInfo = new CDNSRecordNodeEditInfo;
  2354. //
  2355. // NOTICE: the root hints folder owns the memory
  2356. //
  2357. if (pANodeInfo != NULL)
  2358. {
  2359. pANodeInfo->CreateFromExistingRecord(pARecordNode, FALSE /*bOwnMemory*/, TRUE /*bUpdateUI*/);
  2360. pNSInfoList->AddTail(pANodeInfo);
  2361. }
  2362. else
  2363. {
  2364. TRACE(_T("Failed to allocate memory in CDNSRootHintsNode::FindARecordsFromNSInfo"));
  2365. ASSERT(FALSE);
  2366. }
  2367. }
  2368. }
  2369. }
  2370. }
  2371. void CDNSRootHintsNode::UpdateARecordsOfNSInfo(CDNSRecordNodeEditInfo* pNSInfo,
  2372. CComponentDataObject* pComponentData)
  2373. {
  2374. BOOL bAskConfirmation = FALSE; // need to edit ALL A records
  2375. UpdateARecordsOfNSInfoHelper(this, pNSInfo, pComponentData, bAskConfirmation);
  2376. }
  2377. DNS_STATUS CDNSRootHintsNode::Clear()
  2378. {
  2379. //
  2380. // clear the list of cached NS record pointers
  2381. //
  2382. GetNSRecordNodeList()->RemoveAll();
  2383. //
  2384. // remove all the records from the server
  2385. //
  2386. DNS_STATUS err = 0;
  2387. POSITION pos;
  2388. for( pos = m_leafChildList.GetHeadPosition(); pos != NULL; )
  2389. {
  2390. CTreeNode* pCurrentChild = m_leafChildList.GetNext(pos);
  2391. ASSERT(!pCurrentChild->IsContainer());
  2392. CDNSRecordNodeBase* pRecordNode = (CDNSRecordNodeBase*)pCurrentChild;
  2393. DNS_STATUS currErr = pRecordNode->DeleteOnServer();
  2394. if (currErr != 0)
  2395. {
  2396. //
  2397. // just ge the last error, if any
  2398. //
  2399. err = currErr;
  2400. }
  2401. }
  2402. //
  2403. // clear the list of children in the folder (we are hidden, so no UI deletions)
  2404. //
  2405. RemoveAllChildrenFromList();
  2406. return err;
  2407. }
  2408. DNS_STATUS CDNSRootHintsNode::InitializeFromDnsQueryData(PDNS_RECORD pRootHintsRecordList)
  2409. {
  2410. // need to remove all the previous root hints from the server
  2411. // let's be sure we get recent data
  2412. // clear the list of children in the folder (we are hidden, so no UI deletions)
  2413. RemoveAllChildrenFromList();
  2414. // acqure the list of current root hints
  2415. CDNSServerNode* pServerNode = GetServerNode();
  2416. DNS_STATUS dwErr = QueryForRootHints(pServerNode->GetRPCName(), pServerNode->GetVersion());
  2417. if (dwErr != 0)
  2418. {
  2419. TRACE(_T("Failed to remove old Root Hints, dwErr = %x hex\n"), dwErr);
  2420. return dwErr;
  2421. }
  2422. // remove all the old root hints from server and client side
  2423. dwErr = Clear();
  2424. if (dwErr != 0)
  2425. {
  2426. TRACE(_T("Failed to clear Root Hints, dwErr = %x hex\n"), dwErr);
  2427. return dwErr;
  2428. }
  2429. // walk through the list of root hints,
  2430. // convert to C++ format,
  2431. // write to server and add to the folder list (no UI, folder hidden)
  2432. PDNS_RECORD pCurrDnsQueryRecord = pRootHintsRecordList;
  2433. while (pCurrDnsQueryRecord != NULL)
  2434. {
  2435. ASSERT( (pCurrDnsQueryRecord->wType == DNS_TYPE_A) ||
  2436. (pCurrDnsQueryRecord->wType == DNS_TYPE_NS) );
  2437. // create a record node and read data from DnsQuery format
  2438. CDNSRecordNodeBase* pRecordNode =
  2439. CDNSRecordInfo::CreateRecordNode(pCurrDnsQueryRecord->wType);
  2440. pRecordNode->CreateFromDnsQueryRecord(pCurrDnsQueryRecord, DNS_RPC_RECORD_FLAG_ZONE_ROOT);
  2441. // set the record node container
  2442. pRecordNode->SetContainer(this);
  2443. // set the record node name
  2444. BOOL bAtTheNode = (pCurrDnsQueryRecord->wType == DNS_TYPE_NS);
  2445. pRecordNode->SetRecordName(pCurrDnsQueryRecord->pName, bAtTheNode);
  2446. // write on server
  2447. // the default TTL does not apply here
  2448. DNS_STATUS err = pRecordNode->Update(NULL, FALSE); // NULL = create new, FALSE = use def TTL
  2449. if (err == 0)
  2450. VERIFY(AddChildToList(pRecordNode));
  2451. else
  2452. {
  2453. dwErr = err; // mark las error
  2454. delete pRecordNode; // something went wrong
  2455. }
  2456. pCurrDnsQueryRecord = pCurrDnsQueryRecord->pNext;
  2457. }
  2458. // force a write on the server, to make sure the cache file is written right away
  2459. return CDNSZoneNode::WriteToDatabase(pServerNode->GetRPCName(), DNS_ZONE_ROOT_HINTS);
  2460. }