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.

1845 lines
50 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: nspage.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 "nspage.h"
  21. #include "uiutil.h"
  22. #include "ipeditor.h"
  23. #include "browser.h"
  24. ///////////////////////////////////////////////////////////////////////////////
  25. // CDNS_NS_RecordDialog
  26. class CDNS_NS_RecordDialog : public CPropertyPage
  27. {
  28. public:
  29. CDNS_NS_RecordDialog(CDNSNameServersPropertyPage* pNSPage, BOOL bNew);
  30. CDNS_NS_RecordDialog(CDNSNameServersWizardPage* pNSWiz, BOOL bNew);
  31. ~CDNS_NS_RecordDialog();
  32. INT_PTR DoModalSheet(HWND parent = 0);
  33. // data
  34. BOOL m_bDirty;
  35. CDNSRecordNodeEditInfo* m_pNSInfo;
  36. protected:
  37. virtual int OnCreate(LPCREATESTRUCT lpCreateStruct);
  38. virtual BOOL OnInitDialog();
  39. virtual BOOL OnApply();
  40. afx_msg void OnServerNameChange();
  41. afx_msg void OnBrowse();
  42. afx_msg void OnQuery();
  43. BOOL OnHelpInfo(HELPINFO* pHelpInfo);
  44. DECLARE_MESSAGE_MAP()
  45. private:
  46. class CARecordAddressesIPEditor : public CIPEditor
  47. {
  48. public:
  49. CARecordAddressesIPEditor(CDNS_NS_RecordDialog* pNSRecordDialog)
  50. { m_pNSRecordDialog = pNSRecordDialog;}
  51. void SetIpAddresses(CDNSRecordNodeEditInfo* pNSInfo);
  52. BOOL GetIpAddresses(CDNSRecordNodeEditInfo* pNSInfo);
  53. protected:
  54. virtual void OnChangeData();
  55. private:
  56. CDNS_NS_RecordDialog* m_pNSRecordDialog;
  57. };
  58. CARecordAddressesIPEditor m_RecordAddressesEditor;
  59. BOOL m_bNew;
  60. CDNSNameServersPropertyPage* m_pNSPage;
  61. CDNSNameServersWizardPage* m_pNSWiz;
  62. CPropertyPageBase* GetPage()
  63. {
  64. if (m_pNSPage != NULL)
  65. {
  66. return m_pNSPage;
  67. }
  68. return m_pNSWiz;
  69. }
  70. HWND m_hWndOKButton;
  71. HWND m_hWndQueryButton;
  72. CDNSTTLControl* GetTTLCtrl() { return (CDNSTTLControl*)GetDlgItem(IDC_TTLEDIT);}
  73. CEdit* GetServerEdit() { return (CEdit*)GetDlgItem(IDC_SERVER_NAME_EDIT); }
  74. CDNS_NS_Record* GetNSRecord()
  75. {
  76. ASSERT( m_pNSInfo != NULL);
  77. ASSERT( m_pNSInfo->m_pRecord->m_wType == DNS_TYPE_NS);
  78. return (CDNS_NS_Record*)m_pNSInfo->m_pRecord;
  79. }
  80. void GetNSServerName(CString& szNameNode);
  81. void SyncUIButtons();
  82. void EnableTTLCtrl(BOOL bShow);
  83. friend class CARecordAddressesIPEditor;
  84. };
  85. INT_PTR CDNS_NS_RecordDialog::DoModalSheet(HWND parent)
  86. {
  87. /* NOTE : The first call to this may cause a first-chance exception. Excerpt from MSDN January 2000.
  88. Note The first time a property page is created from its corresponding dialog resource,
  89. it may cause a first-chance exception. This is a result of the property page changing
  90. the style of the dialog resource to the required style prior to creating the page. Because
  91. resources are generally read-only, this causes an exception. The exception is handled by
  92. the system, and a copy of the modified resource is made automatically by the system. The
  93. first-chance exception can thus be ignored.
  94. Since this exception must be handled by the operating system, do not wrap calls to
  95. CPropertySheet::DoModal with a C++ try/catch block in which the catch handles all exceptions,
  96. for example, catch (...). This will handle the exception intended for the operating system,
  97. causing unpredictable behavior. Using C++ exception handling with specific exception types
  98. or using structured exception handling where the Access Violation exception is passed through
  99. to the operating system is safe, however.
  100. */
  101. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  102. CThemeContextActivator activator;
  103. CString szTitle;
  104. szTitle.LoadString(m_bNew ? IDS_NEW_RECORD_TITLE : IDS_EDIT_RECORD_TITLE);
  105. CPropertySheet hostSheet;
  106. hostSheet.m_psh.dwFlags |= PSH_NOAPPLYNOW;
  107. hostSheet.m_psh.pszCaption = (LPCTSTR)szTitle;
  108. hostSheet.m_psh.hwndParent = parent;
  109. hostSheet.AddPage(this);
  110. INT_PTR iRes = hostSheet.DoModal();
  111. GetPage()->GetHolder()->PopDialogHWnd();
  112. return iRes;
  113. }
  114. void CDNS_NS_RecordDialog::CARecordAddressesIPEditor::OnChangeData()
  115. {
  116. m_pNSRecordDialog->SyncUIButtons();
  117. }
  118. void CDNS_NS_RecordDialog::CARecordAddressesIPEditor::
  119. SetIpAddresses(CDNSRecordNodeEditInfo* pNSInfo)
  120. {
  121. Clear();
  122. ASSERT(pNSInfo != NULL);
  123. INT_PTR nArraySize = pNSInfo->m_pEditInfoList->GetCount();
  124. if (nArraySize == 0)
  125. return;
  126. DWORD* pArr = (DWORD*)malloc(nArraySize*sizeof(DWORD));
  127. if (!pArr)
  128. {
  129. return;
  130. }
  131. int k=0;
  132. POSITION pos;
  133. for( pos = pNSInfo->m_pEditInfoList->GetHeadPosition(); pos != NULL; )
  134. {
  135. CDNSRecordNodeEditInfo* pARecordInfo = pNSInfo->m_pEditInfoList->GetNext(pos);
  136. ASSERT(pARecordInfo != NULL);
  137. if (pARecordInfo->m_action != CDNSRecordNodeEditInfo::remove)
  138. {
  139. ASSERT(pARecordInfo->m_pRecord != NULL);
  140. ASSERT(pARecordInfo->m_pRecord->m_wType == DNS_TYPE_A);
  141. CDNS_A_Record* pARecord = (CDNS_A_Record*)pARecordInfo->m_pRecord;
  142. pArr[k++] = pARecord->m_ipAddress;
  143. }
  144. }
  145. AddAddresses(pArr, k);
  146. if (pArr)
  147. {
  148. free(pArr);
  149. }
  150. }
  151. BOOL CDNS_NS_RecordDialog::CARecordAddressesIPEditor::
  152. GetIpAddresses(CDNSRecordNodeEditInfo* pNSInfo)
  153. {
  154. BOOL bDirty = FALSE;
  155. int nArraySize = GetCount();
  156. // if the count of IP addresses is zero,
  157. // we mark the NS record as slated for removal
  158. if (nArraySize == 0)
  159. pNSInfo->m_action = CDNSRecordNodeEditInfo::remove;
  160. // read the IP addresses from IP editor, if any
  161. DWORD* pArr = (nArraySize >0) ? (DWORD*)malloc(nArraySize*sizeof(DWORD)) : NULL;
  162. if (!pArr)
  163. {
  164. return FALSE;
  165. }
  166. int nFilled = 0;
  167. if (nArraySize > 0)
  168. GetAddresses(pArr, nArraySize, &nFilled);
  169. ASSERT(nFilled == nArraySize);
  170. ASSERT(pNSInfo->m_pRecord != NULL);
  171. ASSERT(pNSInfo->m_pRecord->GetType() == DNS_TYPE_NS);
  172. CDNS_NS_Record* pNSRecord = (CDNS_NS_Record*)pNSInfo->m_pRecord;
  173. CDNSRecordNodeEditInfoList* pNSInfoList = pNSInfo->m_pEditInfoList;
  174. CDNSRecordNodeEditInfoList NSInfoRemoveList;
  175. POSITION pos;
  176. // walk the list of A records, to mark the ones to be deleted,
  177. // if nArraySize == 0, all of them well be marked for removal
  178. for( pos = pNSInfoList->GetHeadPosition(); pos != NULL; )
  179. {
  180. CDNSRecordNodeEditInfo* pCurrentInfo = pNSInfoList->GetNext(pos);
  181. ASSERT(pCurrentInfo->m_pRecordNode != NULL);
  182. ASSERT(pCurrentInfo->m_pRecord != NULL);
  183. ASSERT(pCurrentInfo->m_pRecord->GetType() == DNS_TYPE_A);
  184. CDNS_A_Record* pARecord = (CDNS_A_Record*)pCurrentInfo->m_pRecord;
  185. BOOL bFound = FALSE;
  186. for (int k=0; k<nArraySize; k++)
  187. {
  188. if (pARecord->m_ipAddress == pArr[k])
  189. {
  190. bFound = TRUE;
  191. break;
  192. }
  193. }
  194. if (!bFound)
  195. {
  196. bDirty = TRUE;
  197. if (pCurrentInfo->m_bExisting)
  198. {
  199. pCurrentInfo->m_action = CDNSRecordNodeEditInfo::remove; // mark as deleted
  200. }
  201. else
  202. {
  203. NSInfoRemoveList.AddTail(pCurrentInfo);
  204. }
  205. }
  206. } // for
  207. // This gives NSInfoRemoveList ownership of all memory management for all nodes
  208. // removed from the pNSInfoList
  209. POSITION listPos = NSInfoRemoveList.GetHeadPosition();
  210. while (listPos != NULL)
  211. {
  212. CDNSRecordNodeEditInfo* pCurrentInfo = NSInfoRemoveList.GetNext(listPos);
  213. ASSERT(pCurrentInfo != NULL);
  214. POSITION removePos = pNSInfoList->Find(pCurrentInfo);
  215. pNSInfoList->RemoveAt(removePos);
  216. }
  217. // Remove and delete all nodes that were removed from the pNSInfoList
  218. NSInfoRemoveList.RemoveAllNodes();
  219. // walk the list of addresses, to look for matching A records to add
  220. // if nArraySize == 0, loop skipped, nothing to add
  221. for (int k=0; k<nArraySize; k++)
  222. {
  223. BOOL bFound = FALSE;
  224. for( pos = pNSInfoList->GetHeadPosition(); pos != NULL; )
  225. {
  226. CDNSRecordNodeEditInfo* pCurrentInfo = pNSInfoList->GetNext(pos);
  227. ASSERT(pCurrentInfo->m_pRecordNode != NULL);
  228. ASSERT(pCurrentInfo->m_pRecord != NULL);
  229. ASSERT(pCurrentInfo->m_pRecord->GetType() == DNS_TYPE_A);
  230. CDNS_A_Record* pARecord = (CDNS_A_Record*)pCurrentInfo->m_pRecord;
  231. if (pARecord->m_ipAddress == pArr[k])
  232. {
  233. bFound = TRUE;
  234. if (pCurrentInfo->m_action == CDNSRecordNodeEditInfo::remove) // we got it already, resuscitate it
  235. {
  236. bDirty = TRUE;
  237. if(pCurrentInfo->m_bExisting)
  238. pCurrentInfo->m_action = CDNSRecordNodeEditInfo::edit;
  239. else
  240. pCurrentInfo->m_action = CDNSRecordNodeEditInfo::add;
  241. }
  242. break;
  243. }
  244. }
  245. if (!bFound)
  246. {
  247. // A record not found, need to create one
  248. CDNSRecordNodeEditInfo* pNewInfo = new CDNSRecordNodeEditInfo;
  249. if (pNewInfo)
  250. {
  251. CDNS_A_RecordNode* pARecordNode = new CDNS_A_RecordNode;
  252. if (pARecordNode)
  253. {
  254. pNewInfo->CreateFromNewRecord(pARecordNode);
  255. CDNS_A_Record* pARecord = (CDNS_A_Record*)pNewInfo->m_pRecord;
  256. pARecord->m_ipAddress = pArr[k];
  257. pNewInfo->m_pRecordNode->m_bAtTheNode = FALSE;
  258. pNewInfo->m_pRecordNode->SetRecordName(pNSRecord->m_szNameNode, FALSE /*bAtTheNode*/);
  259. // inherit the TTL of the NS record
  260. pNewInfo->m_pRecord->m_dwTtlSeconds = pNSInfo->m_pRecord->m_dwTtlSeconds;
  261. pNSInfoList->AddTail(pNewInfo);
  262. bDirty = TRUE;
  263. }
  264. else
  265. {
  266. delete pNewInfo;
  267. }
  268. }
  269. }
  270. } // for
  271. if (pArr)
  272. {
  273. free(pArr);
  274. }
  275. return bDirty;
  276. }
  277. BEGIN_MESSAGE_MAP(CDNS_NS_RecordDialog, CPropertyPage)
  278. ON_WM_CREATE()
  279. ON_EN_CHANGE(IDC_SERVER_NAME_EDIT, OnServerNameChange)
  280. ON_BN_CLICKED(IDC_BROWSE_BUTTON, OnBrowse)
  281. ON_BN_CLICKED(IDC_QUERY_BUTTON, OnQuery)
  282. ON_WM_HELPINFO()
  283. END_MESSAGE_MAP()
  284. CDNS_NS_RecordDialog::CDNS_NS_RecordDialog(CDNSNameServersPropertyPage* pNSPage, BOOL bNew)
  285. : CPropertyPage(IDD_RR_NS_EDIT),
  286. m_RecordAddressesEditor(this)
  287. {
  288. ASSERT(pNSPage != NULL);
  289. m_pNSPage = pNSPage;
  290. m_pNSWiz = NULL;
  291. m_bNew = bNew;
  292. m_bDirty = FALSE;
  293. m_pNSInfo = NULL;
  294. m_hWndOKButton = m_hWndQueryButton = NULL;
  295. }
  296. CDNS_NS_RecordDialog::CDNS_NS_RecordDialog(CDNSNameServersWizardPage* pNSWiz, BOOL bNew)
  297. : CPropertyPage(IDD_RR_NS_EDIT),
  298. m_RecordAddressesEditor(this)
  299. {
  300. ASSERT(pNSWiz != NULL);
  301. m_pNSPage = NULL;
  302. m_pNSWiz = pNSWiz;
  303. m_bNew = bNew;
  304. m_bDirty = FALSE;
  305. m_pNSInfo = NULL;
  306. m_hWndOKButton = m_hWndQueryButton = NULL;
  307. }
  308. CDNS_NS_RecordDialog::~CDNS_NS_RecordDialog()
  309. {
  310. }
  311. int CDNS_NS_RecordDialog::OnCreate(LPCREATESTRUCT lpCreateStruct)
  312. {
  313. int res = CPropertyPage::OnCreate(lpCreateStruct);
  314. DWORD dwStyle = ::GetWindowLong(::GetParent(GetSafeHwnd()), GWL_EXSTYLE);
  315. dwStyle |= WS_EX_CONTEXTHELP; // force the [?] button
  316. ::SetWindowLong(::GetParent(GetSafeHwnd()), GWL_EXSTYLE, dwStyle);
  317. return res;
  318. }
  319. BOOL CDNS_NS_RecordDialog::OnHelpInfo(HELPINFO* pHelpInfo)
  320. {
  321. CComponentDataObject* pComponentData = GetPage()->GetHolder()->GetComponentData();
  322. ASSERT(pComponentData != NULL);
  323. pComponentData->OnDialogContextHelp(m_nIDHelp, pHelpInfo);
  324. return TRUE;
  325. }
  326. void CDNS_NS_RecordDialog::EnableTTLCtrl(BOOL bShow)
  327. {
  328. CDNSTTLControl* pCtrl = GetTTLCtrl();
  329. ASSERT(pCtrl != NULL);
  330. pCtrl->EnableWindow(bShow);
  331. pCtrl->ShowWindow(bShow);
  332. CWnd* pWnd = GetDlgItem(IDC_STATIC_TTL);
  333. ASSERT(pWnd != NULL);
  334. pWnd->EnableWindow(bShow);
  335. pWnd->ShowWindow(bShow);
  336. CWnd* pLabelWnd = GetDlgItem(IDC_TTL_LABEL);
  337. ASSERT(pLabelWnd != NULL);
  338. pLabelWnd->EnableWindow(bShow);
  339. pLabelWnd->ShowWindow(bShow);
  340. }
  341. BOOL CDNS_NS_RecordDialog::OnInitDialog()
  342. {
  343. CPropertyPage::OnInitDialog();
  344. ASSERT(m_pNSInfo != NULL);
  345. ASSERT(m_pNSInfo->m_pRecord != NULL);
  346. ASSERT(m_hWnd != NULL);
  347. ASSERT(::IsWindow(m_hWnd));
  348. HWND hParent = ::GetParent(m_hWnd);
  349. ASSERT(hParent);
  350. GetPage()->GetHolder()->PushDialogHWnd(hParent);
  351. //
  352. // OK button on the sheet
  353. //
  354. m_hWndOKButton = ::GetDlgItem(hParent, IDOK);
  355. ASSERT(::IsWindow(m_hWndOKButton));
  356. //
  357. // query button handle
  358. //
  359. m_hWndQueryButton = :: GetDlgItem(m_hWnd, IDC_QUERY_BUTTON);
  360. ASSERT(::IsWindow(m_hWndQueryButton));
  361. //
  362. // initialize IP editor
  363. //
  364. VERIFY(m_RecordAddressesEditor.Initialize(this,
  365. GetParent(),
  366. IDC_BUTTON_UP,
  367. IDC_BUTTON_DOWN,
  368. IDC_BUTTON_ADD,
  369. IDC_BUTTON_REMOVE,
  370. IDC_IPEDIT,
  371. IDC_LIST));
  372. //
  373. // Load Data in the UI
  374. //
  375. m_RecordAddressesEditor.SetIpAddresses(m_pNSInfo);
  376. GetServerEdit()->LimitText(MAX_DNS_NAME_LEN);
  377. GetServerEdit()->SetWindowText(GetNSRecord()->m_szNameNode);
  378. GetTTLCtrl()->SetTTL(m_pNSInfo->m_pRecord->m_dwTtlSeconds);
  379. // need to decide if we want to show the TTL control
  380. CDNSRootData* pRootData = (CDNSRootData*)GetPage()->GetHolder()->GetComponentData()->GetRootData();
  381. ASSERT(pRootData != NULL);
  382. BOOL bEnableTTLCtrl;
  383. if (m_pNSPage != NULL)
  384. {
  385. bEnableTTLCtrl = m_pNSPage->HasMeaningfulTTL() && pRootData->IsAdvancedView();
  386. }
  387. else
  388. {
  389. bEnableTTLCtrl = m_pNSWiz->HasMeaningfulTTL() && pRootData->IsAdvancedView();
  390. }
  391. EnableTTLCtrl(bEnableTTLCtrl);
  392. return TRUE; // return TRUE unless you set the focus to a control
  393. }
  394. void CDNS_NS_RecordDialog::GetNSServerName(CString& szNameNode)
  395. {
  396. GetServerEdit()->GetWindowText(szNameNode);
  397. szNameNode.TrimLeft();
  398. szNameNode.TrimRight();
  399. if (szNameNode[szNameNode.GetLength()-1] != TEXT('.'))
  400. szNameNode += TEXT('.');
  401. }
  402. void CDNS_NS_RecordDialog::SyncUIButtons()
  403. {
  404. CString szServerName;
  405. GetServerEdit()->GetWindowText(szServerName);
  406. szServerName.TrimLeft();
  407. szServerName.TrimRight();
  408. DWORD dwNameChecking = 0;
  409. if (m_pNSWiz)
  410. {
  411. dwNameChecking = m_pNSWiz->GetDomainNode()->GetServerNode()->GetNameCheckFlag();
  412. }
  413. else if (m_pNSPage)
  414. {
  415. dwNameChecking = m_pNSPage->GetDomainNode()->GetServerNode()->GetNameCheckFlag();
  416. }
  417. //
  418. // Enable OK button if it is a valid name
  419. //
  420. BOOL bIsValidName = (0 == ValidateDnsNameAgainstServerFlags(szServerName,
  421. DnsNameDomain,
  422. dwNameChecking));
  423. ::EnableWindow(m_hWndOKButton, bIsValidName &&
  424. m_RecordAddressesEditor. GetCount() > 0);
  425. ::EnableWindow(m_hWndQueryButton, bIsValidName);
  426. }
  427. BOOL CDNS_NS_RecordDialog::OnApply()
  428. {
  429. ASSERT(m_pNSInfo->m_pRecord != NULL);
  430. CString szNameNode;
  431. GetNSServerName(szNameNode);
  432. // Make sure the new name is an FQDN or else we could have
  433. // a broken delegation
  434. CString szNSName;
  435. GetServerEdit()->GetWindowText(szNSName);
  436. if (szNSName.Find(L".") == -1)
  437. {
  438. DNSMessageBox(IDS_MSG_RECORD_WARNING_NS_NOT_FQDN, MB_OK);
  439. return false;
  440. }
  441. // compare (case insensitive) with old name to see if it changed,
  442. // NOTICE: CDNSDomainNode::UpdateARecordsOfNSInfoHelper() will then
  443. // take care of regenerating the list of A records
  444. m_bDirty = _wcsicmp((LPCWSTR)szNameNode,
  445. (LPCWSTR)GetNSRecord()->m_szNameNode);
  446. if (m_bDirty)
  447. GetNSRecord()->m_szNameNode = szNameNode;
  448. // update list of IP addresses
  449. if (m_bNew)
  450. {
  451. // the dialog is used to create a new entry
  452. ASSERT(!m_pNSInfo->m_bExisting);
  453. m_pNSInfo->m_action = CDNSRecordNodeEditInfo::add;
  454. }
  455. else
  456. {
  457. // the dialog is used to edit
  458. if (m_pNSInfo->m_bExisting)
  459. {
  460. // an existing entry
  461. m_pNSInfo->m_action = CDNSRecordNodeEditInfo::edit;
  462. }
  463. else
  464. {
  465. // a newly created entry, edited before committing
  466. m_pNSInfo->m_action = CDNSRecordNodeEditInfo::add;
  467. }
  468. }
  469. // this call migth mark the info as remove, if no IP addresses are found
  470. if (m_RecordAddressesEditor.GetIpAddresses(m_pNSInfo))
  471. m_bDirty = TRUE;
  472. DWORD dwTTL;
  473. GetTTLCtrl()->GetTTL(&dwTTL);
  474. if (m_pNSInfo->m_pRecord->m_dwTtlSeconds != dwTTL)
  475. {
  476. m_bDirty = TRUE;
  477. m_pNSInfo->m_pRecord->m_dwTtlSeconds = dwTTL;
  478. // Need to change the TTL on all associated A records
  479. CDNSRecordNodeEditInfoList* pNSInfoList = m_pNSInfo->m_pEditInfoList;
  480. for(POSITION pos = pNSInfoList->GetHeadPosition(); pos != NULL; )
  481. {
  482. CDNSRecordNodeEditInfo* pCurrentInfo = pNSInfoList->GetNext(pos);
  483. ASSERT(pCurrentInfo->m_pRecordNode != NULL);
  484. ASSERT(pCurrentInfo->m_pRecord != NULL);
  485. // if slated for removal, don't bother to change
  486. if (pCurrentInfo->m_action != CDNSRecordNodeEditInfo::remove)
  487. {
  488. pCurrentInfo->m_pRecord->m_dwTtlSeconds = m_pNSInfo->m_pRecord->m_dwTtlSeconds;
  489. // if already marked "add" or "edit", leave as is,
  490. // but if unchanged, need to mark as "edit"
  491. if (pCurrentInfo->m_action == CDNSRecordNodeEditInfo::unchanged)
  492. pCurrentInfo->m_action = CDNSRecordNodeEditInfo::edit;
  493. }
  494. }
  495. }
  496. if (m_pNSInfo->m_action == CDNSRecordNodeEditInfo::remove)
  497. {
  498. if (IDNO == DNSMessageBox(IDS_MSG_RECORD_WARNING_NS_NO_IP, MB_YESNO))
  499. return true;
  500. }
  501. return true;
  502. }
  503. void CDNS_NS_RecordDialog::OnServerNameChange()
  504. {
  505. SyncUIButtons();
  506. }
  507. void CDNS_NS_RecordDialog::OnBrowse()
  508. {
  509. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  510. FIX_THREAD_STATE_MFC_BUG();
  511. CThemeContextActivator activator;
  512. CComponentDataObject* pComponentDataObject = GetPage()->GetHolder()->GetComponentData();
  513. CDNSBrowserDlg dlg(pComponentDataObject, GetPage()->GetHolder(), RECORD_A_AND_CNAME);
  514. if (IDOK == dlg.DoModal())
  515. {
  516. GetServerEdit()->SetWindowText(dlg.GetSelectionString());
  517. //
  518. // if it is an A record, add the IP address to the IP editor
  519. //
  520. CDNSRecordNodeBase* pRecordNode = reinterpret_cast<CDNSRecordNodeBase*>(dlg.GetSelection());
  521. if ((pRecordNode != NULL) && (pRecordNode->GetType() == DNS_TYPE_A))
  522. {
  523. DWORD ip = ((CDNS_A_RecordNode*)pRecordNode)->GetIPAddress();
  524. m_RecordAddressesEditor.AddAddresses(&ip,1);
  525. }
  526. }
  527. }
  528. void CDNS_NS_RecordDialog::OnQuery()
  529. {
  530. CWaitCursor cursor;
  531. CDNSRecordNodeEditInfo tempNSInfo; // test
  532. CString szNameNode;
  533. GetNSServerName(szNameNode);
  534. CDNSServerNode* pServerNode;
  535. if (m_pNSPage != NULL)
  536. {
  537. pServerNode = m_pNSPage->GetDomainNode()->GetServerNode();
  538. }
  539. else
  540. {
  541. pServerNode = m_pNSWiz->GetDomainNode()->GetServerNode();
  542. }
  543. LPCWSTR lpszZoneName = NULL;
  544. CDNSZoneNode* pZoneNode = NULL;
  545. if (m_pNSPage != NULL)
  546. {
  547. pZoneNode = m_pNSPage->GetDomainNode()->GetZoneNode();
  548. }
  549. else
  550. {
  551. pZoneNode = m_pNSWiz->GetDomainNode()->GetZoneNode();
  552. }
  553. if (pZoneNode != NULL)
  554. {
  555. lpszZoneName = pZoneNode->GetFullName();
  556. }
  557. ASSERT(pServerNode != NULL);
  558. CComponentDataObject* pComponentDataObject =
  559. GetPage()->GetHolder()->GetComponentData();
  560. CDNSRootData* pRootData = (CDNSRootData*)pComponentDataObject->GetRootData();
  561. ASSERT(pRootData != NULL);
  562. DWORD cAddrCount;
  563. PIP_ADDRESS pipAddrs;
  564. pServerNode->GetListenAddressesInfo(&cAddrCount, &pipAddrs);
  565. if (cAddrCount == 0)
  566. {
  567. // listening on all addresses
  568. pServerNode->GetServerAddressesInfo(&cAddrCount, &pipAddrs);
  569. }
  570. CDNSDomainNode::FindARecordsFromNSInfo(pServerNode->GetRPCName(),
  571. pServerNode->GetVersion(),
  572. cAddrCount, pipAddrs,
  573. lpszZoneName,
  574. szNameNode,
  575. tempNSInfo.m_pEditInfoList,
  576. pRootData->IsAdvancedView());
  577. if (tempNSInfo.m_pEditInfoList->GetCount() > 0)
  578. {
  579. // update the list only if we have valid data
  580. m_RecordAddressesEditor.SetIpAddresses(&tempNSInfo);
  581. }
  582. else
  583. {
  584. DNSMessageBox(IDS_MSG_RECORD_NS_RESOLVE_IP, MB_OK | MB_ICONERROR);
  585. }
  586. }
  587. ///////////////////////////////////////////////////////////////////////////////
  588. // CNSListCtrl
  589. BEGIN_MESSAGE_MAP(CNSListCtrl, CListCtrl)
  590. END_MESSAGE_MAP()
  591. void CNSListCtrl::Initialize()
  592. {
  593. // get size of control to help set the column widths
  594. CRect controlRect;
  595. GetClientRect(controlRect);
  596. // get width of control, width of potential scrollbar, width needed for sub-item
  597. // string
  598. int controlWidth = controlRect.Width();
  599. int scrollThumbWidth = ::GetSystemMetrics(SM_CXHTHUMB);
  600. // clean net width
  601. int nNetControlWidth = controlWidth - scrollThumbWidth - 12 * ::GetSystemMetrics(SM_CXBORDER);
  602. // fields widths
  603. int nWidth1 = 3 * nNetControlWidth / 4;
  604. int nWidth2 = nNetControlWidth - nWidth1;
  605. //
  606. // set up columns
  607. CString szHeaders;
  608. {
  609. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  610. szHeaders.LoadString(IDS_NSPAGE_LISTVIEW_HEADERS);
  611. }
  612. ASSERT(!szHeaders.IsEmpty());
  613. LPWSTR lpszArr[2];
  614. UINT n;
  615. ParseNewLineSeparatedString(szHeaders.GetBuffer(1), lpszArr, &n);
  616. szHeaders.ReleaseBuffer();
  617. ASSERT(n == 2);
  618. InsertColumn(1, lpszArr[0], LVCFMT_LEFT, nWidth1, 1);
  619. InsertColumn(2, lpszArr[1], LVCFMT_LEFT, nWidth2 + 28, 2);
  620. }
  621. int CNSListCtrl::GetSelection()
  622. {
  623. return GetNextItem(-1, LVIS_SELECTED);
  624. }
  625. void CNSListCtrl::SetSelection(int nSel)
  626. {
  627. VERIFY(SetItemState(nSel, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED));
  628. /*
  629. VERIFY(SetItem(nSel, // nItem
  630. 0, // nSubItem
  631. LVIF_STATE, // nMask
  632. NULL, // lpszItem
  633. 0, // nImage
  634. LVIS_SELECTED | LVIS_FOCUSED, // nState
  635. LVIS_SELECTED | LVIS_FOCUSED, // nStateMask
  636. NULL // lParam
  637. ));
  638. */
  639. }
  640. void CNSListCtrl::UpdateNSRecordEntry(int nItemIndex)
  641. {
  642. CDNSRecordNodeEditInfo* pNSInfo = (CDNSRecordNodeEditInfo*)GetItemData(nItemIndex);
  643. VERIFY(SetItem(nItemIndex, // nItem
  644. 0, // nSubItem
  645. LVIF_TEXT, // nMask
  646. ((CDNS_NS_Record*)pNSInfo->m_pRecord)->m_szNameNode, // lpszItem
  647. 0, // nImage
  648. 0, // nState
  649. 0, // nStateMask
  650. NULL // lParam
  651. ));
  652. CString szTemp;
  653. GetIPAddressString(pNSInfo, szTemp);
  654. SetItemText(nItemIndex, 1, szTemp);
  655. }
  656. CDNSRecordNodeEditInfo* CNSListCtrl::GetSelectionEditInfo()
  657. {
  658. int nSel = GetSelection();
  659. if (nSel == -1)
  660. return NULL; // no selection
  661. return (CDNSRecordNodeEditInfo*)GetItemData(nSel);
  662. }
  663. void CNSListCtrl::BuildIPAddrDisplayString(CDNSRecordNodeEditInfo* pNSInfo, CString& szDisplayData)
  664. {
  665. USES_CONVERSION;
  666. // need to chain the IP addresses in a single string
  667. CString szTemp;
  668. szTemp.GetBuffer(20); // length of an IP string
  669. szTemp.ReleaseBuffer();
  670. szDisplayData.GetBuffer(static_cast<int>(20*pNSInfo->m_pEditInfoList->GetCount()));
  671. szDisplayData.ReleaseBuffer();
  672. POSITION pos;
  673. for( pos = pNSInfo->m_pEditInfoList->GetHeadPosition(); pos != NULL; )
  674. {
  675. CDNSRecordNodeEditInfo* pARecordInfo = pNSInfo->m_pEditInfoList->GetNext(pos);
  676. if (pARecordInfo->m_action != CDNSRecordNodeEditInfo::remove)
  677. {
  678. ASSERT(pARecordInfo != NULL);
  679. ASSERT(pARecordInfo->m_pRecord != NULL);
  680. ASSERT(pARecordInfo->m_pRecord->m_wType == DNS_TYPE_A);
  681. CDNS_A_Record* pARecord = (CDNS_A_Record*)pARecordInfo->m_pRecord;
  682. szDisplayData += _T("[");
  683. FormatIpAddress(szTemp, pARecord->m_ipAddress);
  684. szDisplayData += szTemp;
  685. if (pARecordInfo->m_bFromDnsQuery)
  686. {
  687. szDisplayData += _T("*");
  688. }
  689. szDisplayData += _T("] ");
  690. }
  691. }
  692. }
  693. BOOL CNSListCtrl::InsertNSRecordEntry(CDNSRecordNodeEditInfo* pNSInfo, int nItemIndex)
  694. {
  695. ASSERT(pNSInfo != NULL);
  696. ASSERT( (pNSInfo->m_action == CDNSRecordNodeEditInfo::unchanged) ||
  697. (pNSInfo->m_action == CDNSRecordNodeEditInfo::add) );
  698. ASSERT(pNSInfo->m_pRecord != NULL);
  699. ASSERT(pNSInfo->m_pRecordNode != NULL);
  700. ASSERT(pNSInfo->m_pRecordNode->m_bAtTheNode);
  701. BOOL bAlreadyExists = FALSE;
  702. //
  703. // First check to see if its already there
  704. //
  705. for (int idx = 0; idx < GetItemCount(); idx++)
  706. {
  707. CDNSRecordNodeEditInfo* pIdxInfo = reinterpret_cast<CDNSRecordNodeEditInfo*>(GetItemData(idx));
  708. ASSERT(pIdxInfo != NULL);
  709. if (pIdxInfo == NULL)
  710. {
  711. continue;
  712. }
  713. CDNS_NS_Record* pNSRecord = reinterpret_cast<CDNS_NS_Record*>(pIdxInfo->m_pRecord);
  714. ASSERT(pNSRecord != NULL);
  715. if (pNSRecord == NULL)
  716. {
  717. continue;
  718. }
  719. //
  720. // Adding trailing '.' if not already present
  721. //
  722. CString szUINSName = pNSRecord->m_szNameNode;
  723. CString szNewNSName = ((CDNS_NS_Record*)pNSInfo->m_pRecord)->m_szNameNode;
  724. if (szUINSName[szUINSName.GetLength() - 1] != L'.')
  725. {
  726. szUINSName += L".";
  727. }
  728. if (szNewNSName[szNewNSName.GetLength() - 1] != L'.')
  729. {
  730. szNewNSName += L".";
  731. }
  732. //
  733. // if it exists, just update the existing one
  734. //
  735. if (_wcsicmp(szNewNSName, szUINSName) == 0)
  736. {
  737. bAlreadyExists = TRUE;
  738. //
  739. // Merge the A record lists together
  740. //
  741. POSITION newPos = pNSInfo->m_pEditInfoList->GetHeadPosition();
  742. while (newPos != NULL)
  743. {
  744. CDNSRecordNodeEditInfo* pAInfo = pNSInfo->m_pEditInfoList->GetNext(newPos);
  745. CDNS_A_Record* pARecord = reinterpret_cast<CDNS_A_Record*>(pAInfo->m_pRecord);
  746. ASSERT(pARecord != NULL);
  747. if (pARecord == NULL)
  748. {
  749. continue;
  750. }
  751. BOOL bARecordExists = FALSE;
  752. POSITION IdxPos = pIdxInfo->m_pEditInfoList->GetHeadPosition();
  753. while (IdxPos != NULL)
  754. {
  755. CDNSRecordNodeEditInfo* pIdxAInfo = pIdxInfo->m_pEditInfoList->GetNext(IdxPos);
  756. CDNS_A_Record* pIdxARecord = reinterpret_cast<CDNS_A_Record*>(pIdxAInfo->m_pRecord);
  757. ASSERT(pIdxARecord != NULL);
  758. if (pIdxARecord == NULL)
  759. {
  760. continue;
  761. }
  762. if (pIdxARecord->m_ipAddress == pARecord->m_ipAddress)
  763. {
  764. bARecordExists = TRUE;
  765. break;
  766. }
  767. }
  768. if (!bARecordExists)
  769. {
  770. //
  771. // Add the A record since it doesn't already exist in the list
  772. //
  773. pIdxInfo->m_pEditInfoList->AddTail(pAInfo);
  774. pIdxInfo->m_action = CDNSRecordNodeEditInfo::edit;
  775. UpdateNSRecordEntry(idx);
  776. }
  777. }
  778. }
  779. }
  780. if (!bAlreadyExists)
  781. {
  782. CString szTemp;
  783. GetIPAddressString(pNSInfo, szTemp);
  784. InsertItemHelper(nItemIndex, pNSInfo,
  785. ((CDNS_NS_Record*)pNSInfo->m_pRecord)->m_szNameNode,
  786. (LPCTSTR)szTemp);
  787. //
  788. // Added new item so return TRUE;
  789. //
  790. return TRUE;
  791. }
  792. //
  793. // Updated an existing item so return FALSE
  794. //
  795. return FALSE;
  796. }
  797. void CNSListCtrl::InsertItemHelper(int nIndex, CDNSRecordNodeEditInfo* pNSInfo,
  798. LPCTSTR lpszName, LPCTSTR lpszValue)
  799. {
  800. UINT nState = 0;
  801. if (nIndex == 0 )
  802. nState = LVIS_SELECTED | LVIS_FOCUSED; // have at least one item, select it
  803. VERIFY(-1 != InsertItem(LVIF_TEXT | LVIF_PARAM, nIndex,
  804. lpszName, nState, 0, 0, (LPARAM)pNSInfo));
  805. SetItemText(nIndex, 1, lpszValue);
  806. }
  807. void CNSListCtrl::GetIPAddressString(CDNSRecordNodeEditInfo* pNSInfo, CString& sz)
  808. {
  809. if (pNSInfo->m_pEditInfoList->GetCount() > 0)
  810. {
  811. BuildIPAddrDisplayString(pNSInfo, sz);
  812. }
  813. else
  814. sz.LoadString(IDS_UNKNOWN);
  815. }
  816. ///////////////////////////////////////////////////////////////////////////////
  817. // CDNSNameServersPropertyPage
  818. BEGIN_MESSAGE_MAP(CDNSNameServersPropertyPage, CPropertyPageBase)
  819. ON_BN_CLICKED(IDC_ADD_NS_BUTTON, OnAddButton)
  820. ON_BN_CLICKED(IDC_REMOVE_NS_BUTTON, OnRemoveButton)
  821. ON_BN_CLICKED(IDC_EDIT_NS_BUTTON, OnEditButton)
  822. ON_NOTIFY(LVN_ITEMCHANGED, IDC_NS_LIST, OnListItemChanged)
  823. END_MESSAGE_MAP()
  824. CDNSNameServersPropertyPage::CDNSNameServersPropertyPage(UINT nIDTemplate, UINT nIDCaption)
  825. : CPropertyPageBase(nIDTemplate, nIDCaption)
  826. {
  827. m_pDomainNode = NULL;
  828. m_pCloneInfoList = new CDNSRecordNodeEditInfoList;
  829. m_bReadOnly = FALSE;
  830. m_bMeaningfulTTL = TRUE;
  831. }
  832. CDNSNameServersPropertyPage::~CDNSNameServersPropertyPage()
  833. {
  834. delete m_pCloneInfoList;
  835. }
  836. BOOL CDNSNameServersPropertyPage::WriteNSRecordNodesList()
  837. {
  838. ASSERT(!m_bReadOnly);
  839. ASSERT(m_pCloneInfoList != NULL);
  840. CDNSDomainNode* pDomainNode = GetDomainNode();
  841. return pDomainNode->UpdateNSRecordNodesInfo(m_pCloneInfoList, GetHolder()->GetComponentData());
  842. }
  843. BOOL CDNSNameServersPropertyPage::OnWriteNSRecordNodesListError()
  844. {
  845. ASSERT(!m_bReadOnly);
  846. BOOL bSuccess = TRUE;
  847. // loop for each NS record
  848. POSITION pos;
  849. for( pos = m_pCloneInfoList->GetHeadPosition(); pos != NULL; )
  850. {
  851. CDNSRecordNodeEditInfo* pCurrentInfo = m_pCloneInfoList->GetNext(pos);
  852. if (pCurrentInfo->m_dwErr != 0)
  853. {
  854. if (pCurrentInfo->m_dwErr == DNS_ERROR_RECORD_ALREADY_EXISTS)
  855. {
  856. // ignore if the NS record us already there
  857. pCurrentInfo->m_dwErr = 0;
  858. }
  859. else if (pCurrentInfo->m_dwErr == RPC_S_SERVER_UNAVAILABLE)
  860. {
  861. // Couldn't contact the server. Give a single error message
  862. // and then break out.
  863. DNSErrorDialog(pCurrentInfo->m_dwErr, L"");
  864. return FALSE;
  865. }
  866. else
  867. {
  868. bSuccess = FALSE;
  869. ASSERT(pCurrentInfo->m_pRecord->GetType() == DNS_TYPE_NS);
  870. CString szNSMsg;
  871. szNSMsg.Format(_T("Failure to write NS record <%s>"),
  872. (((CDNS_NS_Record*)pCurrentInfo->m_pRecord))->m_szNameNode);
  873. DNSErrorDialog(pCurrentInfo->m_dwErr,szNSMsg);
  874. }
  875. }
  876. // loop for each related A record
  877. CDNSRecordNodeEditInfoList* pARecordInfoList = pCurrentInfo->m_pEditInfoList;
  878. ASSERT(pARecordInfoList != NULL);
  879. POSITION posA;
  880. for( posA = pARecordInfoList->GetHeadPosition(); posA != NULL; )
  881. {
  882. CDNSRecordNodeEditInfo* pARecordCurrentInfo = pARecordInfoList->GetNext(posA);
  883. if (pARecordCurrentInfo->m_dwErr != 0)
  884. {
  885. ASSERT(pARecordCurrentInfo->m_pRecord->GetType() == DNS_TYPE_A);
  886. CString szTemp;
  887. FormatIpAddress(szTemp, (((CDNS_A_Record*)pARecordCurrentInfo->m_pRecord))->m_ipAddress);
  888. CString szAMsg;
  889. szAMsg.Format(_T("Failure to write A record <%s>, IP Address %s"),
  890. (((CDNS_NS_Record*)pARecordCurrentInfo->m_pRecord))->m_szNameNode,
  891. (LPCWSTR)szTemp );
  892. DNSErrorDialog(pCurrentInfo->m_dwErr,szAMsg);
  893. }
  894. }
  895. }
  896. return bSuccess;
  897. }
  898. void CDNSNameServersPropertyPage::OnListItemChanged(NMHDR*, LRESULT*)
  899. {
  900. EnableEditorButtons(m_listCtrl.GetSelection());
  901. }
  902. BOOL CDNSNameServersPropertyPage::OnApply()
  903. {
  904. if (m_bReadOnly)
  905. return TRUE;
  906. if (!IsDirty())
  907. return TRUE;
  908. DNS_STATUS err = GetHolder()->NotifyConsole(this);
  909. if ( (err != 0) && OnWriteNSRecordNodesListError() )
  910. {
  911. err = 0; // error was handled and it was not fatal
  912. }
  913. if (err == 0)
  914. {
  915. // refresh data from the zone/domain
  916. LoadUIData();
  917. SetDirty(FALSE);
  918. }
  919. return (err == 0);
  920. }
  921. BOOL CDNSNameServersPropertyPage::OnPropertyChange(BOOL, long*)
  922. {
  923. if (m_bReadOnly)
  924. {
  925. ASSERT(FALSE); // sould not happen
  926. return FALSE;
  927. }
  928. ASSERT(m_pCloneInfoList != NULL);
  929. if (m_pCloneInfoList == NULL)
  930. return FALSE;
  931. BOOL bRes = WriteNSRecordNodesList();
  932. if (!bRes)
  933. GetHolder()->SetError(static_cast<DWORD>(-1)); // something went wrong, error code will be per item
  934. return bRes; // update flag
  935. }
  936. void CDNSNameServersPropertyPage::OnAddButton()
  937. {
  938. if (m_bReadOnly)
  939. {
  940. ASSERT(FALSE); // sould not happen
  941. return;
  942. }
  943. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  944. FIX_THREAD_STATE_MFC_BUG();
  945. ASSERT(m_pCloneInfoList != NULL);
  946. // provide subdialog to add record, for the time being can have just
  947. // dialog to enter the host name
  948. // create an item in the list of changes
  949. // TODO: first check if we can recycle some old stuff in the list
  950. // create new data
  951. CDNSRecordNodeEditInfo* pNewInfo = new CDNSRecordNodeEditInfo;
  952. if (!pNewInfo)
  953. {
  954. return;
  955. }
  956. pNewInfo->m_action = CDNSRecordNodeEditInfo::add;
  957. CDNS_NS_RecordNode* pNSRecordNode = new CDNS_NS_RecordNode;
  958. if (!pNSRecordNode)
  959. {
  960. delete pNewInfo;
  961. return;
  962. }
  963. pNewInfo->CreateFromNewRecord(pNSRecordNode);
  964. // NS records are ALWAYS at the node
  965. CDNSDomainNode* pDomainNode = GetDomainNode();
  966. CDNSRootData* pRootData = (CDNSRootData*)(GetHolder()->GetComponentData()->GetRootData());
  967. ASSERT(pRootData != NULL);
  968. // set name and type flag
  969. pNewInfo->m_pRecordNode->SetRecordName(pDomainNode->GetDisplayName(), TRUE /*bAtTheNode */);
  970. pNewInfo->m_pRecordNode->SetFlagsDown(TN_FLAG_DNS_RECORD_FULL_NAME, !pRootData->IsAdvancedView());
  971. // set TTL
  972. pNewInfo->m_pRecord->m_dwTtlSeconds = pDomainNode->GetDefaultTTL();
  973. CDNS_NS_RecordDialog dlg(this,TRUE);
  974. dlg.m_pNSInfo = pNewInfo;
  975. if (IDOK == dlg.DoModalSheet(m_hWnd) && pNewInfo->m_action == CDNSRecordNodeEditInfo::add)
  976. {
  977. //
  978. // add to the list view (at the end)
  979. //
  980. int nCount = m_listCtrl.GetItemCount();
  981. if (m_listCtrl.InsertNSRecordEntry(pNewInfo, nCount))
  982. {
  983. //
  984. // create entry into the record info list
  985. //
  986. m_pCloneInfoList->AddTail(pNewInfo);
  987. //
  988. // set selection and button state on the last inserted
  989. //
  990. m_listCtrl.SetSelection(nCount);
  991. EnableEditorButtons(nCount);
  992. //
  993. // notify count change
  994. //
  995. OnCountChange(nCount+1); // added one
  996. }
  997. //
  998. // set dirty flag. It was either a new record or an update of an old one
  999. //
  1000. SetDirty(TRUE);
  1001. }
  1002. else
  1003. {
  1004. delete pNewInfo->m_pRecordNode;
  1005. pNewInfo->m_pRecordNode = NULL;
  1006. delete pNewInfo->m_pRecord;
  1007. pNewInfo->m_pRecord = NULL;
  1008. delete pNewInfo;
  1009. }
  1010. }
  1011. void CDNSNameServersPropertyPage::OnEditButton()
  1012. {
  1013. if (m_bReadOnly)
  1014. {
  1015. ASSERT(FALSE); // sould not happen
  1016. return;
  1017. }
  1018. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1019. FIX_THREAD_STATE_MFC_BUG();
  1020. ASSERT(m_pCloneInfoList != NULL);
  1021. // get the selection and bring up the dialog with the host name for editing
  1022. int nSel = m_listCtrl.GetSelection();
  1023. ASSERT(nSel != -1);
  1024. if (nSel == -1)
  1025. return; // should not happen
  1026. CDNSRecordNodeEditInfo* pNSInfo = (CDNSRecordNodeEditInfo*)m_listCtrl.GetItemData(nSel);
  1027. ASSERT(pNSInfo != NULL);
  1028. CDNS_NS_RecordDialog dlg(this, FALSE);
  1029. ASSERT(pNSInfo->m_pRecord->GetType() == DNS_TYPE_NS);
  1030. dlg.m_pNSInfo = pNSInfo;
  1031. if (IDOK == dlg.DoModalSheet() && dlg.m_bDirty)
  1032. {
  1033. if (pNSInfo->m_action == CDNSRecordNodeEditInfo::add)
  1034. {
  1035. // this was a new entry that was edited after creation
  1036. // but before committing the change
  1037. ASSERT(!pNSInfo->m_bExisting);
  1038. // update the listview
  1039. m_listCtrl.UpdateNSRecordEntry(nSel);
  1040. }
  1041. else if (pNSInfo->m_action == CDNSRecordNodeEditInfo::edit)
  1042. {
  1043. // this was an existing entry that was changed
  1044. ASSERT(pNSInfo->m_bExisting);
  1045. // update the listview
  1046. m_listCtrl.UpdateNSRecordEntry(nSel);
  1047. }
  1048. else
  1049. {
  1050. // there were no IP addresses, so mark the item for removal
  1051. ASSERT(pNSInfo->m_action == CDNSRecordNodeEditInfo::remove);
  1052. OnRemoveButton();
  1053. }
  1054. // set dirty flag
  1055. SetDirty(TRUE);
  1056. }
  1057. }
  1058. void CDNSNameServersPropertyPage::OnRemoveButton()
  1059. {
  1060. if (m_bReadOnly)
  1061. {
  1062. ASSERT(FALSE); // sould not happen
  1063. return;
  1064. }
  1065. int nSel = m_listCtrl.GetSelection();
  1066. if (nSel == -1)
  1067. {
  1068. ASSERT(FALSE);
  1069. return; // should not happen
  1070. }
  1071. //
  1072. // save focus to restore afterwards, if needed
  1073. //
  1074. CWnd* pWndFocusOld = CWnd::GetFocus();
  1075. ASSERT(pWndFocusOld != NULL);
  1076. //
  1077. // got a selection, delete from listview
  1078. //
  1079. CDNSRecordNodeEditInfo* pNSInfo = (CDNSRecordNodeEditInfo*)m_listCtrl.GetItemData(nSel);
  1080. ASSERT(pNSInfo != NULL);
  1081. m_listCtrl.DeleteItem(nSel);
  1082. //
  1083. // we lost the selection, set it again
  1084. //
  1085. int nNewCount = m_listCtrl.GetItemCount();
  1086. if (nNewCount == nSel)
  1087. {
  1088. //
  1089. // last item in the list was deleted, move selection up
  1090. //
  1091. nSel--;
  1092. }
  1093. if (nSel != -1)
  1094. {
  1095. m_listCtrl.SetSelection(nSel);
  1096. ASSERT(m_listCtrl.GetSelection() == nSel);
  1097. }
  1098. //
  1099. // if there are no items left, need to disable the Edit and Remove buttons
  1100. //
  1101. if (nNewCount == 0)
  1102. {
  1103. CButton* pRemoveButton = GetRemoveButton();
  1104. //
  1105. // need to shift focus before disabling buttons
  1106. //
  1107. CButton* pAddButton = GetAddButton();
  1108. pAddButton->SetFocus();
  1109. // avoid to have the OK button on the sheet to become the default button
  1110. pRemoveButton->SendMessage(BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
  1111. pAddButton->SendMessage(BM_SETSTYLE, BS_DEFPUSHBUTTON,
  1112. MAKELPARAM(/*redraw flag*/ TRUE, 0));
  1113. EnableEditorButtons(nSel); // this will disable both Edit and Remove
  1114. }
  1115. ASSERT(CWnd::GetFocus());
  1116. if (pNSInfo->m_action == CDNSRecordNodeEditInfo::add)
  1117. {
  1118. //
  1119. // mark the item action as none since it was just added without being applied
  1120. //
  1121. pNSInfo->m_action = CDNSRecordNodeEditInfo::none;
  1122. }
  1123. else
  1124. {
  1125. // mark the item as deleted in the list of changes
  1126. pNSInfo->m_action = CDNSRecordNodeEditInfo::remove;
  1127. }
  1128. // set dirty flag, removed a record
  1129. SetDirty(TRUE);
  1130. // notify count change
  1131. OnCountChange(nNewCount);
  1132. }
  1133. BOOL CDNSNameServersPropertyPage::OnInitDialog()
  1134. {
  1135. CPropertyPageBase::OnInitDialog();
  1136. // controls initialization
  1137. VERIFY(m_listCtrl.SubclassDlgItem(IDC_NS_LIST, this));
  1138. m_listCtrl.Initialize();
  1139. // load the data
  1140. LoadUIData();
  1141. // set button state
  1142. if (m_bReadOnly)
  1143. {
  1144. EnableButtons(FALSE);
  1145. }
  1146. else
  1147. {
  1148. // set selection to first item in the list, if there
  1149. int nSel = (m_listCtrl.GetItemCount()>0) ? 0 : -1;
  1150. EnableEditorButtons(nSel);
  1151. }
  1152. return TRUE; // return TRUE unless you set the focus to a control
  1153. // EXCEPTION: OCX Property Pages should return FALSE
  1154. }
  1155. void CDNSNameServersPropertyPage::LoadUIData()
  1156. {
  1157. m_pCloneInfoList->RemoveAllNodes();
  1158. ReadRecordNodesList(); // read from source
  1159. FillNsListView();
  1160. }
  1161. void CDNSNameServersPropertyPage::FillNsListView()
  1162. {
  1163. ASSERT(m_pCloneInfoList != NULL);
  1164. m_listCtrl.DeleteAllItems();
  1165. // loop through the list of NS records and insert
  1166. POSITION pos;
  1167. int itemIndex = 0;
  1168. for( pos = m_pCloneInfoList->GetHeadPosition(); pos != NULL; )
  1169. {
  1170. CDNSRecordNodeEditInfo* pCurrentInfo = m_pCloneInfoList->GetNext(pos);
  1171. if (m_listCtrl.InsertNSRecordEntry(pCurrentInfo, itemIndex))
  1172. {
  1173. if (itemIndex == 0)
  1174. m_listCtrl.SetSelection(0);
  1175. itemIndex++;
  1176. }
  1177. }
  1178. }
  1179. void CDNSNameServersPropertyPage::EnableEditorButtons(int nListBoxSel)
  1180. {
  1181. if (m_bReadOnly)
  1182. return;
  1183. // must have item selected to remove or add
  1184. GetRemoveButton()->EnableWindow(nListBoxSel != -1);
  1185. GetEditButton()->EnableWindow(nListBoxSel != -1);
  1186. }
  1187. void CDNSNameServersPropertyPage::EnableButtons(BOOL bEnable)
  1188. {
  1189. GetAddButton()->EnableWindow(bEnable);
  1190. GetRemoveButton()->EnableWindow(bEnable);
  1191. GetEditButton()->EnableWindow(bEnable);
  1192. }
  1193. //////////////////////////////////////////////////////////////////////////////
  1194. ///////////////////////////////////////////////////////////////////////////////
  1195. // CDNSNameServersWizardPage
  1196. BEGIN_MESSAGE_MAP(CDNSNameServersWizardPage, CPropertyPageBase)
  1197. ON_BN_CLICKED(IDC_ADD_NS_BUTTON, OnAddButton)
  1198. ON_BN_CLICKED(IDC_REMOVE_NS_BUTTON, OnRemoveButton)
  1199. ON_BN_CLICKED(IDC_EDIT_NS_BUTTON, OnEditButton)
  1200. ON_NOTIFY(LVN_ITEMCHANGED, IDC_NS_LIST, OnListItemChanged)
  1201. END_MESSAGE_MAP()
  1202. CDNSNameServersWizardPage::CDNSNameServersWizardPage(UINT nIDTemplate)
  1203. : CPropertyPageBase(nIDTemplate)
  1204. {
  1205. InitWiz97(FALSE,IDS_SERVWIZ_ROOTHINTS_TITLE,IDS_SERVWIZ_ROOTHINTS_SUBTITLE);
  1206. m_pDomainNode = NULL;
  1207. m_pCloneInfoList = new CDNSRecordNodeEditInfoList;
  1208. m_bReadOnly = FALSE;
  1209. m_bMeaningfulTTL = TRUE;
  1210. }
  1211. CDNSNameServersWizardPage::~CDNSNameServersWizardPage()
  1212. {
  1213. delete m_pCloneInfoList;
  1214. }
  1215. BOOL CDNSNameServersWizardPage::WriteNSRecordNodesList()
  1216. {
  1217. ASSERT(!m_bReadOnly);
  1218. ASSERT(m_pCloneInfoList != NULL);
  1219. CDNSDomainNode* pDomainNode = GetDomainNode();
  1220. return pDomainNode->UpdateNSRecordNodesInfo(m_pCloneInfoList, GetHolder()->GetComponentData());
  1221. }
  1222. BOOL CDNSNameServersWizardPage::OnWriteNSRecordNodesListError()
  1223. {
  1224. ASSERT(!m_bReadOnly);
  1225. BOOL bSuccess = TRUE;
  1226. // loop for each NS record
  1227. POSITION pos;
  1228. for( pos = m_pCloneInfoList->GetHeadPosition(); pos != NULL; )
  1229. {
  1230. CDNSRecordNodeEditInfo* pCurrentInfo = m_pCloneInfoList->GetNext(pos);
  1231. if (pCurrentInfo->m_dwErr != 0)
  1232. {
  1233. if (pCurrentInfo->m_dwErr == DNS_ERROR_RECORD_ALREADY_EXISTS)
  1234. {
  1235. // ignore if the NS record us already there
  1236. pCurrentInfo->m_dwErr = 0;
  1237. }
  1238. else
  1239. {
  1240. bSuccess = FALSE;
  1241. ASSERT(pCurrentInfo->m_pRecord->GetType() == DNS_TYPE_NS);
  1242. CString szNSMsg;
  1243. szNSMsg.Format(_T("Failure to write NS record <%s>"),
  1244. (((CDNS_NS_Record*)pCurrentInfo->m_pRecord))->m_szNameNode);
  1245. DNSErrorDialog(pCurrentInfo->m_dwErr,szNSMsg);
  1246. }
  1247. }
  1248. // loop for each related A record
  1249. CDNSRecordNodeEditInfoList* pARecordInfoList = pCurrentInfo->m_pEditInfoList;
  1250. ASSERT(pARecordInfoList != NULL);
  1251. POSITION posA;
  1252. for( posA = pARecordInfoList->GetHeadPosition(); posA != NULL; )
  1253. {
  1254. CDNSRecordNodeEditInfo* pARecordCurrentInfo = pARecordInfoList->GetNext(posA);
  1255. if (pARecordCurrentInfo->m_dwErr != 0)
  1256. {
  1257. ASSERT(pARecordCurrentInfo->m_pRecord->GetType() == DNS_TYPE_A);
  1258. CString szTemp;
  1259. FormatIpAddress(szTemp, (((CDNS_A_Record*)pARecordCurrentInfo->m_pRecord))->m_ipAddress);
  1260. CString szAMsg;
  1261. szAMsg.Format(_T("Failure to write A record <%s>, IP Address %s"),
  1262. (((CDNS_NS_Record*)pARecordCurrentInfo->m_pRecord))->m_szNameNode,
  1263. (LPCWSTR)szTemp );
  1264. DNSErrorDialog(pCurrentInfo->m_dwErr,szAMsg);
  1265. }
  1266. }
  1267. }
  1268. return bSuccess;
  1269. }
  1270. BOOL CDNSNameServersWizardPage::OnApply()
  1271. {
  1272. if (m_bReadOnly)
  1273. return TRUE;
  1274. if (!IsDirty())
  1275. return TRUE;
  1276. DNS_STATUS err = GetHolder()->NotifyConsole(this);
  1277. if ( (err != 0) && OnWriteNSRecordNodesListError() )
  1278. {
  1279. err = 0; // error was handled and it was not fatal
  1280. }
  1281. if (err == 0)
  1282. {
  1283. // refresh data from the zone/domain
  1284. LoadUIData();
  1285. SetDirty(FALSE);
  1286. }
  1287. else
  1288. {
  1289. ::SetLastError(err);
  1290. }
  1291. return (err == 0);
  1292. }
  1293. BOOL CDNSNameServersWizardPage::OnPropertyChange(BOOL, long*)
  1294. {
  1295. if (m_bReadOnly)
  1296. {
  1297. ASSERT(FALSE); // sould not happen
  1298. return FALSE;
  1299. }
  1300. ASSERT(m_pCloneInfoList != NULL);
  1301. if (m_pCloneInfoList == NULL)
  1302. return FALSE;
  1303. BOOL bRes = WriteNSRecordNodesList();
  1304. if (!bRes)
  1305. GetHolder()->SetError(static_cast<DWORD>(-1)); // something went wrong, error code will be per item
  1306. return bRes; // update flag
  1307. }
  1308. void CDNSNameServersWizardPage::OnListItemChanged(NMHDR*, LRESULT*)
  1309. {
  1310. EnableEditorButtons(m_listCtrl.GetSelection());
  1311. }
  1312. void CDNSNameServersWizardPage::OnAddButton()
  1313. {
  1314. if (m_bReadOnly)
  1315. {
  1316. ASSERT(FALSE); // sould not happen
  1317. return;
  1318. }
  1319. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1320. FIX_THREAD_STATE_MFC_BUG();
  1321. ASSERT(m_pCloneInfoList != NULL);
  1322. // provide subdialog to add record, for the time being can have just
  1323. // dialog to enter the host name
  1324. // create an item in the list of changes
  1325. // TODO: first check if we can recycle some old stuff in the list
  1326. // create new data
  1327. CDNSRecordNodeEditInfo* pNewInfo = new CDNSRecordNodeEditInfo;
  1328. if (!pNewInfo)
  1329. {
  1330. return;
  1331. }
  1332. pNewInfo->m_action = CDNSRecordNodeEditInfo::add;
  1333. CDNS_NS_RecordNode* pNSRecordNode = new CDNS_NS_RecordNode;
  1334. if (!pNSRecordNode)
  1335. {
  1336. delete pNewInfo;
  1337. return;
  1338. }
  1339. pNewInfo->CreateFromNewRecord(pNSRecordNode);
  1340. // NS records are ALWAYS at the node
  1341. CDNSDomainNode* pDomainNode = GetDomainNode();
  1342. CDNSRootData* pRootData = (CDNSRootData*)(GetHolder()->GetComponentData()->GetRootData());
  1343. ASSERT(pRootData != NULL);
  1344. // set name and type flag
  1345. pNewInfo->m_pRecordNode->SetRecordName(pDomainNode->GetDisplayName(), TRUE /*bAtTheNode */);
  1346. pNewInfo->m_pRecordNode->SetFlagsDown(TN_FLAG_DNS_RECORD_FULL_NAME, !pRootData->IsAdvancedView());
  1347. // set TTL
  1348. pNewInfo->m_pRecord->m_dwTtlSeconds = pDomainNode->GetDefaultTTL();
  1349. CDNS_NS_RecordDialog dlg(this,TRUE);
  1350. dlg.m_pNSInfo = pNewInfo;
  1351. if (IDOK == dlg.DoModalSheet() && pNewInfo->m_action == CDNSRecordNodeEditInfo::add)
  1352. {
  1353. //
  1354. // add to the list view (at the end)
  1355. //
  1356. int nCount = m_listCtrl.GetItemCount();
  1357. if (m_listCtrl.InsertNSRecordEntry(pNewInfo, nCount))
  1358. {
  1359. //
  1360. // create entry into the record info list
  1361. //
  1362. m_pCloneInfoList->AddTail(pNewInfo);
  1363. //
  1364. // set selection and button state on the last inserted
  1365. //
  1366. m_listCtrl.SetSelection(nCount);
  1367. EnableEditorButtons(nCount);
  1368. //
  1369. // notify count change
  1370. //
  1371. OnCountChange(nCount+1); // added one
  1372. }
  1373. //
  1374. // set dirty flag, it is a new record
  1375. //
  1376. SetDirty(TRUE);
  1377. }
  1378. else
  1379. {
  1380. delete pNewInfo->m_pRecordNode;
  1381. pNewInfo->m_pRecordNode = NULL;
  1382. delete pNewInfo->m_pRecord;
  1383. pNewInfo->m_pRecord = NULL;
  1384. delete pNewInfo;
  1385. }
  1386. }
  1387. void CDNSNameServersWizardPage::OnEditButton()
  1388. {
  1389. if (m_bReadOnly)
  1390. {
  1391. ASSERT(FALSE); // sould not happen
  1392. return;
  1393. }
  1394. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1395. FIX_THREAD_STATE_MFC_BUG();
  1396. ASSERT(m_pCloneInfoList != NULL);
  1397. // get the selection and bring up the dialog with the host name for editing
  1398. int nSel = m_listCtrl.GetSelection();
  1399. ASSERT(nSel != -1);
  1400. if (nSel == -1)
  1401. return; // should not happen
  1402. CDNSRecordNodeEditInfo* pNSInfo = (CDNSRecordNodeEditInfo*)m_listCtrl.GetItemData(nSel);
  1403. ASSERT(pNSInfo != NULL);
  1404. CDNS_NS_RecordDialog dlg(this, FALSE);
  1405. ASSERT(pNSInfo->m_pRecord->GetType() == DNS_TYPE_NS);
  1406. dlg.m_pNSInfo = pNSInfo;
  1407. if (IDOK == dlg.DoModalSheet() && dlg.m_bDirty)
  1408. {
  1409. if (pNSInfo->m_action == CDNSRecordNodeEditInfo::add)
  1410. {
  1411. // this was a new entry that was edited after creation
  1412. // but before committing the change
  1413. ASSERT(!pNSInfo->m_bExisting);
  1414. // update the listview
  1415. m_listCtrl.UpdateNSRecordEntry(nSel);
  1416. }
  1417. else if (pNSInfo->m_action == CDNSRecordNodeEditInfo::edit)
  1418. {
  1419. // this was an existing entry that was changed
  1420. ASSERT(pNSInfo->m_bExisting);
  1421. // update the listview
  1422. m_listCtrl.UpdateNSRecordEntry(nSel);
  1423. }
  1424. else
  1425. {
  1426. // there were no IP addresses, so mark the item for removal
  1427. ASSERT(pNSInfo->m_action == CDNSRecordNodeEditInfo::remove);
  1428. OnRemoveButton();
  1429. }
  1430. // set dirty flag
  1431. SetDirty(TRUE);
  1432. }
  1433. }
  1434. void CDNSNameServersWizardPage::OnRemoveButton()
  1435. {
  1436. if (m_bReadOnly)
  1437. {
  1438. ASSERT(FALSE); // sould not happen
  1439. return;
  1440. }
  1441. int nSel = m_listCtrl.GetSelection();
  1442. if (nSel == -1)
  1443. {
  1444. ASSERT(FALSE);
  1445. return; // should not happen
  1446. }
  1447. //
  1448. // save focus to restore afterwards, if needed
  1449. //
  1450. CWnd* pWndFocusOld = CWnd::GetFocus();
  1451. ASSERT(pWndFocusOld != NULL);
  1452. //
  1453. // got a selection, delete from listview
  1454. //
  1455. CDNSRecordNodeEditInfo* pNSInfo = (CDNSRecordNodeEditInfo*)m_listCtrl.GetItemData(nSel);
  1456. ASSERT(pNSInfo != NULL);
  1457. m_listCtrl.DeleteItem(nSel);
  1458. //
  1459. // we lost the selection, set it again
  1460. //
  1461. int nNewCount = m_listCtrl.GetItemCount();
  1462. if (nNewCount == nSel)
  1463. {
  1464. //
  1465. // last item in the list was deleted, move selection up
  1466. //
  1467. nSel--;
  1468. }
  1469. if (nSel != -1)
  1470. {
  1471. m_listCtrl.SetSelection(nSel);
  1472. ASSERT(m_listCtrl.GetSelection() == nSel);
  1473. }
  1474. //
  1475. // if there are no items left, need to disable the Edit and Remove buttons
  1476. //
  1477. if (nNewCount == 0)
  1478. {
  1479. CWnd* pCurrentFocusCtrl = CWnd::GetFocus();
  1480. CButton* pRemoveButton = GetRemoveButton();
  1481. CButton* pEditButton = GetEditButton();
  1482. //
  1483. // need to shift focus before disabling buttons
  1484. //
  1485. if ( (pCurrentFocusCtrl == pRemoveButton) ||
  1486. (pCurrentFocusCtrl == pEditButton) )
  1487. {
  1488. CButton* pAddButton = GetAddButton();
  1489. pAddButton->SetFocus();
  1490. // avoid to have the OK button on the sheet to become the default button
  1491. pAddButton->SendMessage(BM_SETSTYLE, BS_DEFPUSHBUTTON,
  1492. MAKELPARAM(/*redraw flag*/ TRUE, 0));
  1493. }
  1494. EnableEditorButtons(nSel); // this will disable both Edit and Remove
  1495. }
  1496. ASSERT(CWnd::GetFocus());
  1497. if (pNSInfo->m_action == CDNSRecordNodeEditInfo::add)
  1498. {
  1499. //
  1500. // mark the item action as none since the item hasn't been added yet anyways
  1501. //
  1502. pNSInfo->m_action = CDNSRecordNodeEditInfo::none;
  1503. }
  1504. else
  1505. {
  1506. // mark the item as deleted in the list of changes
  1507. pNSInfo->m_action = CDNSRecordNodeEditInfo::remove;
  1508. }
  1509. // set dirty flag, removed a record
  1510. SetDirty(TRUE);
  1511. // notify count change
  1512. OnCountChange(nNewCount);
  1513. }
  1514. BOOL CDNSNameServersWizardPage::OnInitDialog()
  1515. {
  1516. CPropertyPageBase::OnInitDialog();
  1517. // controls initialization
  1518. VERIFY(m_listCtrl.SubclassDlgItem(IDC_NS_LIST, this));
  1519. m_listCtrl.Initialize();
  1520. // load the data
  1521. LoadUIData();
  1522. // set button state
  1523. if (m_bReadOnly)
  1524. {
  1525. EnableButtons(FALSE);
  1526. }
  1527. else
  1528. {
  1529. // set selection to first item in the list, if there
  1530. int nSel = (m_listCtrl.GetItemCount()>0) ? 0 : -1;
  1531. EnableEditorButtons(nSel);
  1532. }
  1533. return TRUE; // return TRUE unless you set the focus to a control
  1534. // EXCEPTION: OCX Property Pages should return FALSE
  1535. }
  1536. void CDNSNameServersWizardPage::LoadUIData()
  1537. {
  1538. m_pCloneInfoList->RemoveAllNodes();
  1539. ReadRecordNodesList(); // read from source
  1540. FillNsListView();
  1541. }
  1542. void CDNSNameServersWizardPage::FillNsListView()
  1543. {
  1544. ASSERT(m_pCloneInfoList != NULL);
  1545. m_listCtrl.DeleteAllItems();
  1546. // loop through the list of NS records and insert
  1547. POSITION pos;
  1548. int itemIndex = 0;
  1549. for( pos = m_pCloneInfoList->GetHeadPosition(); pos != NULL; )
  1550. {
  1551. CDNSRecordNodeEditInfo* pCurrentInfo = m_pCloneInfoList->GetNext(pos);
  1552. if (m_listCtrl.InsertNSRecordEntry(pCurrentInfo, itemIndex))
  1553. {
  1554. if (itemIndex == 0)
  1555. m_listCtrl.SetSelection(0);
  1556. itemIndex++;
  1557. }
  1558. }
  1559. }
  1560. void CDNSNameServersWizardPage::EnableEditorButtons(int nListBoxSel)
  1561. {
  1562. if (m_bReadOnly)
  1563. return;
  1564. // must have item selected to remove or add
  1565. GetRemoveButton()->EnableWindow(nListBoxSel != -1);
  1566. GetEditButton()->EnableWindow(nListBoxSel != -1);
  1567. }
  1568. void CDNSNameServersWizardPage::EnableButtons(BOOL bEnable)
  1569. {
  1570. GetAddButton()->EnableWindow(bEnable);
  1571. GetRemoveButton()->EnableWindow(bEnable);
  1572. GetEditButton()->EnableWindow(bEnable);
  1573. }