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.

1271 lines
34 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: recordui.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. #ifdef DEBUG_ALLOCATOR
  21. #ifdef _DEBUG
  22. #define new DEBUG_NEW
  23. #undef THIS_FILE
  24. static char THIS_FILE[] = __FILE__;
  25. #endif
  26. #endif
  27. /*
  28. void TestDefButton(HWND hWnd)
  29. {
  30. HWND hParent = ::GetParent(hWnd);
  31. LRESULT lres = ::SendMessage(hParent, DM_GETDEFID, 0,0);
  32. WORD hi = HIWORD(lres);
  33. ASSERT( DC_HASDEFID == hi);
  34. UINT nCtrlID = LOWORD(lres);
  35. if (nCtrlID == IDCANCEL)
  36. {
  37. TRACE(_T("Got changed to cancel, reset to OK\n"));
  38. ::SendMessage(hParent, DM_SETDEFID, (WPARAM)IDOK, 0);
  39. }
  40. }
  41. */
  42. ////////////////////////////////////////////////////////////////////////
  43. // CDNSRecordPropertyPageHolder
  44. CDNSRecordPropertyPageHolder::CDNSRecordPropertyPageHolder(CDNSDomainNode* pDNSDomainNode,
  45. CDNSRecordNodeBase* pRecordNode,
  46. CComponentDataObject* pComponentData,
  47. WORD wPredefinedRecordType)
  48. : CPropertyPageHolderBase(pDNSDomainNode, pRecordNode, pComponentData)
  49. {
  50. m_nRecordPages = 0;
  51. m_pTempDNSRecord = NULL;
  52. m_wPredefinedRecordType = wPredefinedRecordType;
  53. m_pAclEditorPage = NULL;
  54. m_forceContextHelpButton = forceOn;
  55. ASSERT(pRecordNode == GetRecordNode());
  56. if (pRecordNode != NULL)
  57. {
  58. ASSERT(m_wPredefinedRecordType == 0); // we do not use it
  59. // have record node selected, we are putting up modeless property sheet
  60. m_pTempDNSRecord = pRecordNode->CreateCloneRecord(); // temporary copy to work on
  61. ASSERT(m_pTempDNSRecord != NULL);
  62. AddPagesFromCurrentRecordNode(FALSE); // do not add to sheet, will add later
  63. // security page added only if needed
  64. ASSERT(!IsWizardMode());
  65. CDNSZoneNode* pZoneNode = pDNSDomainNode->GetZoneNode();
  66. if (pZoneNode->IsDSIntegrated())
  67. {
  68. CString szPath;
  69. pRecordNode->CreateDsRecordLdapPath(szPath);
  70. if (!szPath.IsEmpty())
  71. m_pAclEditorPage = CAclEditorPage::CreateInstance(szPath, this);
  72. }
  73. }
  74. else
  75. {
  76. // we do not have a record node selected, we are creating a new one
  77. ASSERT(m_wPredefinedRecordType != 0);
  78. // know the record type
  79. SetRecordSelection(m_wPredefinedRecordType, FALSE); // do not add Page to Sheet
  80. }
  81. }
  82. CDNSRecordPropertyPageHolder::~CDNSRecordPropertyPageHolder()
  83. {
  84. if (m_pTempDNSRecord != NULL)
  85. {
  86. delete m_pTempDNSRecord;
  87. m_pTempDNSRecord = NULL;
  88. }
  89. if (IsWizardMode())
  90. {
  91. CDNSRecordNodeBase* pRecordNode = GetRecordNode();
  92. if (pRecordNode != NULL)
  93. {
  94. // a node was created, but never written to the server
  95. SetRecordNode(NULL);
  96. delete pRecordNode;
  97. }
  98. }
  99. if (m_pAclEditorPage != NULL)
  100. delete m_pAclEditorPage;
  101. }
  102. HRESULT CDNSRecordPropertyPageHolder::OnAddPage(int nPage, CPropertyPageBase*)
  103. {
  104. // add the ACL editor page after the last, if present
  105. if ( (nPage != -1) || (m_pAclEditorPage == NULL) )
  106. return S_OK;
  107. // add the ACL page
  108. HPROPSHEETPAGE hPage = m_pAclEditorPage->CreatePage();
  109. if (hPage == NULL)
  110. return E_FAIL;
  111. // add the raw HPROPSHEETPAGE to sheet, not in the list
  112. return AddPageToSheetRaw(hPage);
  113. }
  114. void CDNSRecordPropertyPageHolder::AddPagesFromCurrentRecordNode(BOOL bAddToSheet)
  115. {
  116. CDNSRecordNodeBase* pRecordNode = GetRecordNode();
  117. ASSERT(pRecordNode != NULL);
  118. // ask the record to get all the property pages
  119. ASSERT(m_nRecordPages == 0);
  120. pRecordNode->CreatePropertyPages(m_pRecordPropPagesArr,&m_nRecordPages);
  121. ASSERT( (m_nRecordPages >= 0 ) && (m_nRecordPages <= DNS_RECORD_MAX_PROPRETY_PAGES) );
  122. // add them to the list of pages
  123. for (int k=0; k < m_nRecordPages; k++)
  124. {
  125. AddPageToList((CPropertyPageBase*)m_pRecordPropPagesArr[k]);
  126. if (bAddToSheet)
  127. VERIFY(SUCCEEDED(AddPageToSheet((CPropertyPageBase*)m_pRecordPropPagesArr[k])));
  128. }
  129. }
  130. void CDNSRecordPropertyPageHolder::RemovePagesFromCurrentRecordNode(BOOL bRemoveFromSheet)
  131. {
  132. CDNSRecordNodeBase* pRecordNode = GetRecordNode();
  133. ASSERT(pRecordNode != NULL);
  134. ASSERT( (m_nRecordPages >= 0 ) && (m_nRecordPages <= DNS_RECORD_MAX_PROPRETY_PAGES) );
  135. // add them to the list of pages
  136. for (int k=0; k < m_nRecordPages; k++)
  137. {
  138. if (bRemoveFromSheet)
  139. VERIFY(SUCCEEDED(RemovePageFromSheet((CPropertyPageBase*)m_pRecordPropPagesArr[k])));
  140. RemovePageFromList((CPropertyPageBase*)m_pRecordPropPagesArr[k], TRUE); // delete C++ object
  141. }
  142. m_nRecordPages = 0; // cleared
  143. }
  144. DNS_STATUS CDNSRecordPropertyPageHolder::CreateNewRecord(BOOL bAllowDuplicates)
  145. {
  146. ASSERT(IsWizardMode());
  147. CDNSRecordNodeBase* pRecordNode = GetRecordNode();
  148. ASSERT(pRecordNode != NULL);
  149. CDNSDomainNode* pDomainNode = GetDomainNode();
  150. ASSERT(pDomainNode != NULL);
  151. RECORD_SEARCH recordSearch = RECORD_NOT_FOUND;
  152. CDNSDomainNode* pNewParentDomain = NULL;
  153. CString szFullRecordName;
  154. pRecordNode->GetFullName(szFullRecordName);
  155. CString szNonExistentDomain;
  156. CDNSRecordNodeBase* pExistingRecordNode = 0;
  157. recordSearch = pDomainNode->GetZoneNode()->DoesContain(szFullRecordName,
  158. GetComponentData(),
  159. &pNewParentDomain,
  160. &pExistingRecordNode,
  161. szNonExistentDomain,
  162. TRUE);
  163. DNS_STATUS err = 0;
  164. //
  165. // add the node to the UI if domain doesn't already exist
  166. //
  167. if ((recordSearch == RECORD_NOT_FOUND || pRecordNode->IsAtTheNode() || recordSearch == RECORD_NOT_FOUND_AT_THE_NODE) &&
  168. pNewParentDomain != NULL)
  169. {
  170. //
  171. // Set the container to the found domain and alter the record name to reflect this
  172. //
  173. CDNSDomainNode* pOldParent = pRecordNode->GetDomainNode();
  174. pRecordNode->SetContainer(pNewParentDomain);
  175. CString szSingleLabel;
  176. int iFindResult = szFullRecordName.Find(L'.');
  177. if (iFindResult != -1)
  178. {
  179. szSingleLabel = szFullRecordName.Left(iFindResult);
  180. }
  181. BOOL isAtTheNode = TRUE;
  182. if (recordSearch == RECORD_NOT_FOUND)
  183. {
  184. isAtTheNode = pRecordNode->IsAtTheNode();
  185. }
  186. pRecordNode->SetRecordName(szSingleLabel, isAtTheNode);
  187. if (IS_CLASS(*pRecordNode, CDNS_PTR_RecordNode))
  188. {
  189. CDNSRootData* pRootData = (CDNSRootData*)GetComponentData()->GetRootData();
  190. BOOL advancedView = pRootData->IsAdvancedView();
  191. // If the record is a PTR then we have to call ChangeDisplayName
  192. // so that the display name will properly reflect the Advanced View
  193. // flag
  194. ((CDNS_PTR_RecordNode*)pRecordNode)->ChangeDisplayName(pNewParentDomain, advancedView);
  195. }
  196. err = WriteCurrentRecordToServer();
  197. if (err == DNS_WARNING_PTR_CREATE_FAILED)
  198. {
  199. DNSMessageBox(IDS_MSG_RECORD_WARNING_CREATE_PTR);
  200. err = 0; // this was just a warning
  201. }
  202. if (err != 0)
  203. {
  204. // NTRAID#NTBUG9-487817-2001/10/31-JeffJon
  205. // reset the parent to the original so that if the name is changed we
  206. // don't try to create the record in the subdomain
  207. pRecordNode->SetContainer(pOldParent);
  208. return err; // failed the write
  209. }
  210. VERIFY(pNewParentDomain->AddChildToListAndUI(pRecordNode, GetComponentData()));
  211. GetComponentData()->SetDescriptionBarText(pNewParentDomain);
  212. }
  213. else if (recordSearch == DOMAIN_NOT_ENUMERATED && pNewParentDomain != NULL)
  214. {
  215. //
  216. // this shouldn't happen unless we pass FALSE to DoesContain()
  217. //
  218. err = WriteCurrentRecordToServer();
  219. if (err == DNS_WARNING_PTR_CREATE_FAILED)
  220. {
  221. DNSMessageBox(IDS_MSG_RECORD_WARNING_CREATE_PTR);
  222. err = 0;
  223. }
  224. if (err != 0)
  225. {
  226. return err;
  227. }
  228. }
  229. else if (recordSearch == NON_EXISTENT_SUBDOMAIN && pNewParentDomain != NULL)
  230. {
  231. //
  232. // Create the record and then search for it so that we expand the newly
  233. // created domains on the way down
  234. //
  235. err = WriteCurrentRecordToServer();
  236. if (err == DNS_WARNING_PTR_CREATE_FAILED)
  237. {
  238. DNSMessageBox(IDS_MSG_RECORD_WARNING_CREATE_PTR);
  239. err = 0;
  240. }
  241. if (err != 0)
  242. {
  243. return err;
  244. }
  245. ASSERT(!szNonExistentDomain.IsEmpty());
  246. if (!szNonExistentDomain.IsEmpty())
  247. {
  248. CString szSingleLabelDomain;
  249. int iFindResult = szNonExistentDomain.ReverseFind(L'.');
  250. if (iFindResult == -1)
  251. {
  252. szSingleLabelDomain = szNonExistentDomain;
  253. }
  254. else
  255. {
  256. int iDomainLength = szNonExistentDomain.GetLength();
  257. szSingleLabelDomain = szNonExistentDomain.Right(iDomainLength - iFindResult - 1);
  258. }
  259. //
  260. // Create the first subdomain because the current domain is already enumerated
  261. // so we have to start the remaining enumeration at the new subdomain that is needed
  262. //
  263. CDNSDomainNode* pSubdomainNode = pNewParentDomain->CreateSubdomainNode();
  264. ASSERT(pSubdomainNode != NULL);
  265. CDNSRootData* pRootData = (CDNSRootData*)GetComponentData()->GetRootData();
  266. pNewParentDomain->SetSubdomainName(pSubdomainNode, szSingleLabelDomain, pRootData->IsAdvancedView());
  267. VERIFY(pNewParentDomain->AddChildToListAndUISorted(pSubdomainNode, GetComponentData()));
  268. GetComponentData()->SetDescriptionBarText(pNewParentDomain);
  269. //
  270. // I don't care what the results of this are, I am just using it
  271. // to do the expansion to the new record
  272. //
  273. recordSearch = pSubdomainNode->GetZoneNode()->DoesContain(szFullRecordName,
  274. GetComponentData(),
  275. &pNewParentDomain,
  276. &pExistingRecordNode,
  277. szNonExistentDomain,
  278. TRUE);
  279. }
  280. }
  281. else
  282. {
  283. //
  284. // Record with name exists
  285. //
  286. BOOL bContinueCreate = bAllowDuplicates;
  287. if (!bAllowDuplicates)
  288. {
  289. if (pExistingRecordNode &&
  290. pExistingRecordNode->GetType() != DNS_TYPE_CNAME)
  291. {
  292. // let the creation continue so that the user gets an error message
  293. bContinueCreate = TRUE;
  294. }
  295. else
  296. {
  297. // Ask the user if they want to replace the existing CNAME record
  298. if (DNSMessageBox(IDS_MSG_RECORD_WARNING_DUPLICATE_RECORD, MB_YESNO) == IDYES)
  299. {
  300. bContinueCreate = TRUE;
  301. }
  302. else
  303. {
  304. if (pRecordNode != NULL)
  305. {
  306. delete pRecordNode;
  307. }
  308. }
  309. }
  310. }
  311. if (bContinueCreate)
  312. {
  313. if (pNewParentDomain != NULL)
  314. {
  315. //
  316. // Set the container to the found domain and alter the record name to reflect this
  317. //
  318. CDNSDomainNode* pOldParent = pRecordNode->GetDomainNode();
  319. pRecordNode->SetContainer(pNewParentDomain);
  320. CString szSingleLabel;
  321. int iFindResult = szFullRecordName.Find(L'.');
  322. if (iFindResult != -1)
  323. {
  324. szSingleLabel = szFullRecordName.Left(iFindResult);
  325. pRecordNode->SetRecordName(szSingleLabel, pRecordNode->IsAtTheNode());
  326. }
  327. err = WriteCurrentRecordToServer();
  328. if (err == DNS_WARNING_PTR_CREATE_FAILED)
  329. {
  330. DNSMessageBox(IDS_MSG_RECORD_WARNING_CREATE_PTR);
  331. err = 0; // this was just a warning
  332. }
  333. if (err != 0)
  334. {
  335. // NTRAID#NTBUG9-487817-2001/10/31-JeffJon
  336. // reset the parent to the original so that if the name is changed we
  337. // don't try to create the record in the subdomain
  338. pRecordNode->SetContainer(pOldParent);
  339. return err; // failed the write
  340. }
  341. VERIFY(pNewParentDomain->AddChildToListAndUI(pRecordNode, GetComponentData()));
  342. GetComponentData()->SetDescriptionBarText(pNewParentDomain);
  343. if (!bAllowDuplicates)
  344. {
  345. CNodeList myList;
  346. myList.AddTail(pNewParentDomain);
  347. pNewParentDomain->OnRefresh(GetComponentData(), &myList);
  348. }
  349. }
  350. else
  351. {
  352. //
  353. // Error message: Cannot create record in a delegation
  354. //
  355. DNSMessageBox(IDS_MSG_DOMAIN_EXISTS);
  356. if (pRecordNode != NULL)
  357. {
  358. delete pRecordNode;
  359. }
  360. }
  361. }
  362. }
  363. //
  364. // the holder does not own the record node anymore
  365. //
  366. SetRecordNode(NULL);
  367. return err;
  368. }
  369. DNS_STATUS CDNSRecordPropertyPageHolder::CreateNonExistentParentDomains(CDNSRecordNodeBase* pRecordNode,
  370. /*IN/OUT*/CDNSDomainNode** ppNewParentDomain)
  371. {
  372. DNS_STATUS err = 0;
  373. CString szFullRecordName;
  374. pRecordNode->GetFullName(szFullRecordName);
  375. CString szParentFullName = (*ppNewParentDomain)->GetFullName();
  376. CString szRemaining = szFullRecordName;
  377. //
  378. // Determine which domains need to be created
  379. //
  380. int iMatching = szFullRecordName.Find(szParentFullName);
  381. if (iMatching != -1)
  382. {
  383. szRemaining = szFullRecordName.Right(szFullRecordName.GetLength() - iMatching);
  384. }
  385. return err;
  386. }
  387. BOOL CDNSRecordPropertyPageHolder::OnPropertyChange(BOOL, long*)
  388. {
  389. TRACE(_T("CDNSRecordPropertyPageHolder::OnPropertyChange()\n"));
  390. //
  391. // WARNING!!! this call cannot be made from the secondary thread the sheet runs from
  392. // the framework calls it from IComponentData::OnPropertyChange()
  393. //
  394. ASSERT(!IsWizardMode()); // it is an existing record!!!
  395. DNS_STATUS err = WriteCurrentRecordToServer();
  396. SetError(err);
  397. TRACE(_T("DNSError = %x\n"), err);
  398. if (err != 0)
  399. {
  400. TRACE(_T("// failed, do not update the UI\n"));
  401. return FALSE; // failed the write, do not update the UI
  402. }
  403. TRACE(_T("// now have to update the UI\n"));
  404. return TRUE; // make the changes to the UI
  405. }
  406. DNS_STATUS CDNSRecordPropertyPageHolder::WriteCurrentRecordToServer()
  407. {
  408. CDNSRecordNodeBase* pRecordNode = GetRecordNode();
  409. ASSERT(pRecordNode != NULL);
  410. CDNSRecord* pRecord = GetTempDNSRecord();
  411. ASSERT(pRecord != NULL);
  412. BOOL bUseDefaultTTL = (pRecord->m_dwTtlSeconds ==
  413. GetDomainNode()->GetDefaultTTL());
  414. return pRecordNode->Update(pRecord, bUseDefaultTTL);
  415. }
  416. void CDNSRecordPropertyPageHolder::SetRecordSelection(WORD wRecordType, BOOL bAddToSheet)
  417. {
  418. ASSERT(GetRecordNode() == NULL);
  419. //
  420. // do not have record node created yet, create one
  421. //
  422. CDNSRecordNodeBase* pRecordNode = CDNSRecordInfo::CreateRecordNode(wRecordType);
  423. ASSERT(pRecordNode != NULL);
  424. //
  425. // set the normal/advanced view option
  426. //
  427. CDNSRootData* pRootData = (CDNSRootData*)GetComponentData()->GetRootData();
  428. ASSERT(pRootData != NULL);
  429. pRecordNode->SetFlagsDown(TN_FLAG_DNS_RECORD_FULL_NAME, !pRootData->IsAdvancedView());
  430. //
  431. // create the temporary record
  432. //
  433. ASSERT(GetTempDNSRecord() == NULL);
  434. CDNSRecord* pTempDNSRecord = pRecordNode->CreateRecord();
  435. if (!pTempDNSRecord)
  436. {
  437. delete pRecordNode;
  438. return;
  439. }
  440. SetTempDNSRecord(pTempDNSRecord);
  441. //
  442. // assign the min TTL from the zone
  443. //
  444. pTempDNSRecord->m_dwTtlSeconds = GetDomainNode()->GetDefaultTTL();
  445. //
  446. // hookup into the holder
  447. //
  448. pRecordNode->SetContainer(GetContainerNode());
  449. SetRecordNode(pRecordNode);
  450. //
  451. // add the pages for the specific record
  452. //
  453. AddPagesFromCurrentRecordNode(bAddToSheet); // add to sheet
  454. }
  455. //////////////////////////////////////////////////////////////////////////
  456. // CSelectDNSRecordTypeDialog
  457. BEGIN_MESSAGE_MAP(CSelectDNSRecordTypeDialog, CHelpDialog)
  458. ON_BN_CLICKED(IDC_CREATE_RECORD_BUTTON, OnCreateRecord)
  459. ON_LBN_DBLCLK(IDC_RECORD_TYPE_LIST, OnDoubleClickSelTypeList)
  460. ON_LBN_SELCHANGE(IDC_RECORD_TYPE_LIST, OnSelchangeTypeList)
  461. END_MESSAGE_MAP()
  462. CSelectDNSRecordTypeDialog::CSelectDNSRecordTypeDialog(CDNSDomainNode* pDNSDomainNode,
  463. CComponentDataObject* pComponentData)
  464. : CHelpDialog(IDD_SELECT_RECORD_TYPE_DIALOG, pComponentData)
  465. {
  466. m_pDNSDomainNode = pDNSDomainNode;
  467. m_pComponentData = pComponentData;
  468. m_bFirstCreation = TRUE;
  469. }
  470. void CSelectDNSRecordTypeDialog::SyncDescriptionText()
  471. {
  472. const DNS_RECORD_INFO_ENTRY* pEntry = GetSelectedEntry();
  473. ASSERT(pEntry != NULL);
  474. if (pEntry != NULL)
  475. {
  476. GetDlgItem(IDC_RECORD_TYPE_DESCR)->SetWindowText(pEntry->lpszDescription);
  477. }
  478. }
  479. const DNS_RECORD_INFO_ENTRY* CSelectDNSRecordTypeDialog::GetSelectedEntry()
  480. {
  481. CListBox* pListBox = GetRecordTypeListBox();
  482. int nSel = pListBox->GetCurSel();
  483. ASSERT(nSel != -1);
  484. CString s;
  485. pListBox->GetText(nSel, s);
  486. const DNS_RECORD_INFO_ENTRY* pEntry = CDNSRecordInfo::GetEntryFromName(s);
  487. ASSERT(pEntry != NULL);
  488. return pEntry;
  489. }
  490. BOOL CSelectDNSRecordTypeDialog::OnInitDialog()
  491. {
  492. CHelpDialog::OnInitDialog();
  493. UINT nButtonIDs[2] = { IDS_BUTTON_TEXT_CANCEL, IDS_BUTTON_TEXT_DONE };
  494. VERIFY(m_cancelDoneTextHelper.Init(this, IDCANCEL, nButtonIDs));
  495. m_cancelDoneTextHelper.SetToggleState(m_bFirstCreation);
  496. //
  497. // Get the server version because we can only add certain records if we are
  498. // administering a certain version of the server
  499. //
  500. CDNSServerNode* pServerNode = m_pDNSDomainNode->GetServerNode();
  501. ASSERT(pServerNode);
  502. CListBox* pListBox = GetRecordTypeListBox();
  503. DNS_RECORD_INFO_ENTRY* pTable = (DNS_RECORD_INFO_ENTRY*)CDNSRecordInfo::GetInfoEntryTable();
  504. while (pTable->nResourceID != DNS_RECORD_INFO_END_OF_TABLE)
  505. {
  506. // some record types cannot be created with this wizard
  507. if (pTable->dwFlags & DNS_RECORD_INFO_FLAG_UICREATE)
  508. {
  509. if (pTable->dwFlags & DNS_RECORD_INFO_FLAG_WHISTLER_OR_LATER)
  510. {
  511. if (pServerNode->GetBuildNumber() >= DNS_SRV_BUILD_NUMBER_WHISTLER &&
  512. (pServerNode->GetMajorVersion() >= DNS_SRV_MAJOR_VERSION_NT_5 &&
  513. pServerNode->GetMinorVersion() >= DNS_SRV_MINOR_VERSION_WHISTLER))
  514. {
  515. pListBox->AddString(pTable->lpszFullName);
  516. }
  517. }
  518. else
  519. {
  520. pListBox->AddString(pTable->lpszFullName);
  521. }
  522. }
  523. pTable++;
  524. }
  525. pListBox->SetCurSel(0);
  526. SyncDescriptionText();
  527. return TRUE; // return TRUE unless you set the focus to a control
  528. // EXCEPTION: OCX Property Pages should return FALSE
  529. }
  530. void CSelectDNSRecordTypeDialog::OnSelchangeTypeList()
  531. {
  532. SyncDescriptionText();
  533. }
  534. void CSelectDNSRecordTypeDialog::OnDoubleClickSelTypeList()
  535. {
  536. OnCreateRecord();
  537. }
  538. void CSelectDNSRecordTypeDialog::OnCreateRecord()
  539. {
  540. const DNS_RECORD_INFO_ENTRY* pEntry = GetSelectedEntry();
  541. ASSERT(pEntry != NULL);
  542. if (pEntry == NULL)
  543. return; // should never happen!!!
  544. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  545. CThemeContextActivator activator;
  546. CString szTitle;
  547. szTitle.LoadString(IDS_NEW_RECORD_TITLE);
  548. CDNSRecordPropertyPageHolder recordHolder(m_pDNSDomainNode, NULL, m_pComponentData, pEntry->wType);
  549. if (IDOK == recordHolder.DoModalDialog(szTitle))
  550. {
  551. // toggle the Cancel/Done button label
  552. if (m_bFirstCreation)
  553. {
  554. m_bFirstCreation = FALSE;
  555. m_cancelDoneTextHelper.SetToggleState(m_bFirstCreation);
  556. }
  557. }
  558. }
  559. //////////////////////////////////////////////////////////////////////
  560. // CDNSRecordPropertyPage
  561. BEGIN_MESSAGE_MAP(CDNSRecordPropertyPage, CPropertyPageBase)
  562. ON_EN_CHANGE(IDC_TTLEDIT, OnTTLChange)
  563. ON_BN_CLICKED(IDC_DEFAULT_DELETE_STALE_RECORD, OnDeleteStaleRecord)
  564. END_MESSAGE_MAP()
  565. CDNSRecordPropertyPage::CDNSRecordPropertyPage(UINT nIDTemplate, UINT nIDCaption)
  566. : CPropertyPageBase(nIDTemplate, nIDCaption)
  567. {
  568. }
  569. CDNSRecordPropertyPage::~CDNSRecordPropertyPage()
  570. {
  571. }
  572. BOOL CDNSRecordPropertyPage::OnInitDialog()
  573. {
  574. CPropertyPageBase::OnInitDialog();
  575. CDNSRootData* pRootData = (CDNSRootData*)GetHolder()->GetComponentData()->GetRootData();
  576. ASSERT(pRootData != NULL);
  577. EnableTTLCtrl(pRootData->IsAdvancedView());
  578. EnableAgingCtrl(pRootData->IsAdvancedView());
  579. return TRUE;
  580. }
  581. CDNSTTLControl* CDNSRecordPropertyPage::GetTTLCtrl()
  582. {
  583. CDNSTTLControl* pTTLCtrl = (CDNSTTLControl*)GetDlgItem(IDC_TTLEDIT);
  584. ASSERT(pTTLCtrl != NULL);
  585. return pTTLCtrl;
  586. }
  587. void CDNSRecordPropertyPage::EnableAgingCtrl(BOOL bShow)
  588. {
  589. GetDeleteStale()->EnableWindow(bShow);
  590. GetDeleteStale()->ShowWindow(bShow);
  591. GetTimeStampEdit()->EnableWindow(bShow);
  592. GetTimeStampEdit()->ShowWindow(bShow);
  593. GetTimeStampStatic()->EnableWindow(bShow);
  594. GetTimeStampStatic()->ShowWindow(bShow);
  595. }
  596. void CDNSRecordPropertyPage::EnableTTLCtrl(BOOL bShow)
  597. {
  598. CDNSTTLControl* pCtrl = GetTTLCtrl();
  599. ASSERT(pCtrl != NULL);
  600. pCtrl->EnableWindow(bShow);
  601. pCtrl->ShowWindow(bShow);
  602. CWnd* pWnd = GetDlgItem(IDC_STATIC_TTL);
  603. ASSERT(pWnd != NULL);
  604. pWnd->EnableWindow(bShow);
  605. pWnd->ShowWindow(bShow);
  606. CWnd* pLabelWnd = GetDlgItem(IDC_TTL_LABEL);
  607. ASSERT(pLabelWnd != NULL);
  608. pLabelWnd->EnableWindow(bShow);
  609. pLabelWnd->ShowWindow(bShow);
  610. }
  611. void CDNSRecordPropertyPage::SetValidState(BOOL bValid)
  612. {
  613. if (GetHolder()->IsWizardMode())
  614. GetHolder()->EnableSheetControl(IDOK, bValid);
  615. else
  616. SetDirty(bValid);
  617. }
  618. void CDNSRecordPropertyPage::OnDeleteStaleRecord()
  619. {
  620. SetDirty(TRUE);
  621. }
  622. void CDNSRecordPropertyPage::OnTTLChange()
  623. {
  624. /*
  625. DWORD dwTTL;
  626. CDNSRecordPropertyPageHolder* pHolder = (CDNSRecordPropertyPageHolder*)GetHolder();
  627. CDNSRecord* pRecord = pHolder->GetTempDNSRecord();
  628. GetTTLCtrl()->GetTTL(&dwTTL);
  629. if (pRecord->m_dwTtlSeconds != dwTTL)
  630. */
  631. SetDirty(TRUE);
  632. }
  633. BOOL CDNSRecordPropertyPage::OnPropertyChange(BOOL, long*)
  634. {
  635. ASSERT(FALSE);
  636. return FALSE;
  637. }
  638. //////////////////////////////////////////////////////////////////////
  639. // CDNSRecordStandardPropertyPage
  640. BEGIN_MESSAGE_MAP(CDNSRecordStandardPropertyPage, CDNSRecordPropertyPage)
  641. ON_EN_CHANGE(IDC_RR_NAME_EDIT, OnEditChange)
  642. END_MESSAGE_MAP()
  643. CDNSRecordStandardPropertyPage::CDNSRecordStandardPropertyPage(UINT nIDTemplate, UINT nIDCaption)
  644. : CDNSRecordPropertyPage(nIDTemplate, nIDCaption)
  645. {
  646. m_bAllowAtTheNode = TRUE;
  647. m_nUTF8ParentLen = 0;
  648. }
  649. BOOL CDNSRecordStandardPropertyPage::CreateRecord()
  650. {
  651. CDNSRecordPropertyPageHolder* pHolder = (CDNSRecordPropertyPageHolder*)GetHolder();
  652. ASSERT(pHolder->IsWizardMode());
  653. //
  654. // Get the data from the UI
  655. //
  656. DNS_STATUS err = GetUIDataEx(FALSE);
  657. if (err != 0)
  658. {
  659. DNSErrorDialog(err,IDS_MSG_RECORD_CREATE_FAILED);
  660. return FALSE;
  661. }
  662. //
  663. // Create the new record
  664. //
  665. err = pHolder->CreateNewRecord(CanCreateDuplicateRecords());
  666. if (err != 0)
  667. {
  668. DNSErrorDialog(err,IDS_MSG_RECORD_CREATE_FAILED);
  669. return FALSE;
  670. }
  671. return TRUE;
  672. }
  673. BOOL CDNSRecordStandardPropertyPage::OnSetActive()
  674. {
  675. CDNSRecordPropertyPageHolder* pHolder = (CDNSRecordPropertyPageHolder*)GetHolder();
  676. ASSERT(pHolder->GetTempDNSRecord() != NULL);
  677. //
  678. // load the data from the record to the UI
  679. //
  680. SetUIData();
  681. //
  682. //loading triggered change notifications on controls,
  683. // so reset the dirty flag
  684. //
  685. SetDirty(FALSE);
  686. CDNSRecordNodeBase* pRecordNode = pHolder->GetRecordNode();
  687. ASSERT(pRecordNode != NULL);
  688. DWORD dwZoneType = pRecordNode->GetDomainNode()->GetZoneNode()->GetZoneType();
  689. if ((dwZoneType == DNS_ZONE_TYPE_SECONDARY) ||
  690. (dwZoneType == DNS_ZONE_TYPE_STUB) ||
  691. (dwZoneType == DNS_ZONE_TYPE_CACHE))
  692. {
  693. EnableDialogControls(m_hWnd, FALSE);
  694. }
  695. return CDNSRecordPropertyPage::OnSetActive();
  696. }
  697. BOOL CDNSRecordStandardPropertyPage::OnKillActive()
  698. {
  699. GetUIDataEx(TRUE);
  700. return CDNSRecordPropertyPage::OnKillActive();
  701. }
  702. BOOL CDNSRecordStandardPropertyPage::OnApply()
  703. {
  704. CDNSRecordPropertyPageHolder* pHolder = (CDNSRecordPropertyPageHolder*)GetHolder();
  705. if(pHolder->IsWizardMode())
  706. {
  707. //
  708. // this is the case of record creation,
  709. // the user hit OK and we want to create the record
  710. //
  711. return CreateRecord();
  712. }
  713. //
  714. // we are in the case of modeless sheet on existing record
  715. //
  716. CDNSRecordNodeBase* pRecordNode = pHolder->GetRecordNode();
  717. ASSERT(pRecordNode != NULL);
  718. DWORD dwZoneType = pRecordNode->GetDomainNode()->GetZoneNode()->GetZoneType();
  719. if ((dwZoneType == DNS_ZONE_TYPE_SECONDARY) ||
  720. (dwZoneType == DNS_ZONE_TYPE_STUB) ||
  721. (dwZoneType == DNS_ZONE_TYPE_CACHE))
  722. {
  723. // read only case
  724. return TRUE;
  725. }
  726. DNS_STATUS err = GetUIDataEx(FALSE);
  727. if (err != 0)
  728. {
  729. DNSErrorDialog(err,IDS_MSG_RECORD_UPDATE_FAILED);
  730. return FALSE;
  731. }
  732. if (!IsDirty())
  733. {
  734. return TRUE;
  735. }
  736. err = pHolder->NotifyConsole(this);
  737. if (err == DNS_WARNING_PTR_CREATE_FAILED)
  738. {
  739. DNSMessageBox(IDS_MSG_RECORD_WARNING_CREATE_PTR);
  740. err = 0; // was just a warning
  741. }
  742. if (err != 0)
  743. {
  744. DNSErrorDialog(err,IDS_MSG_RECORD_UPDATE_FAILED);
  745. return FALSE;
  746. }
  747. else
  748. {
  749. SetDirty(FALSE);
  750. }
  751. return TRUE; // all is cool
  752. }
  753. void CDNSRecordStandardPropertyPage::OnInitName()
  754. {
  755. CDNSRecordPropertyPageHolder* pHolder = (CDNSRecordPropertyPageHolder*)GetHolder();
  756. // limit the text length the user can type
  757. m_nUTF8ParentLen = UTF8StringLen(pHolder->GetDomainNode()->GetFullName());
  758. int nUTF8Len = MAX_DNS_NAME_LEN - m_nUTF8ParentLen - 3; // count dot when chaining
  759. //
  760. // hook up name edit control
  761. //
  762. GetRRNameEdit()->SetLimitText(nUTF8Len);
  763. GetRRNameEdit()->SetReadOnly(!GetHolder()->IsWizardMode());
  764. // set the FQDN for the domain the record is in
  765. if (GetHolder()->IsWizardMode())
  766. {
  767. GetDomainEditBox()->SetWindowText(pHolder->GetDomainNode()->GetFullName());
  768. }
  769. else
  770. {
  771. CString szName;
  772. pHolder->GetRecordNode()->GetFullName(szName);
  773. GetDomainEditBox()->SetWindowText(szName);
  774. }
  775. }
  776. void CDNSRecordStandardPropertyPage::OnSetName(CDNSRecordNodeBase* pRecordNode)
  777. {
  778. if (pRecordNode != NULL)
  779. {
  780. GetRRNameEdit()->SetWindowText(pRecordNode->GetDisplayName());
  781. }
  782. }
  783. void CDNSRecordStandardPropertyPage::OnGetName(CString& s)
  784. {
  785. GetEditBoxText(s);
  786. }
  787. void CDNSRecordStandardPropertyPage::GetEditBoxText(CString& s)
  788. {
  789. GetRRNameEdit()->GetWindowText(s);
  790. }
  791. BOOL CDNSRecordStandardPropertyPage::OnInitDialog()
  792. {
  793. // call base class to enable/disable TTL control
  794. CDNSRecordPropertyPage::OnInitDialog();
  795. #if (FALSE)
  796. //REVIEW_MARCOC: still to debate if we need this altogether
  797. // determine if the RR can be created at the node
  798. CDNSRecordPropertyPageHolder* pHolder = (CDNSRecordPropertyPageHolder*)GetHolder();
  799. CDNSRecord* pRecord = pHolder->GetTempDNSRecord();
  800. ASSERT(pRecord != NULL);
  801. const DNS_RECORD_INFO_ENTRY* pTableEntry = CDNSRecordInfo::GetTypeEntry(pRecord->GetType());
  802. if (pTableEntry != NULL)
  803. {
  804. ASSERT(pTableEntry->dwFlags & DNS_RECORD_INFO_FLAG_UICREATE);
  805. m_bAllowAtTheNode = (pTableEntry->dwFlags & DNS_RECORD_INFO_FLAG_CREATE_AT_NODE) > 0;
  806. }
  807. #endif
  808. // initialize the control(s) to display the RR node name
  809. OnInitName();
  810. return TRUE;
  811. }
  812. #ifdef _USE_BLANK
  813. void CDNSRecordStandardPropertyPage::OnEditChange()
  814. {
  815. CDNSRecordPropertyPageHolder* pHolder = GetDNSRecordHolder();
  816. if (!pHolder->IsWizardMode())
  817. {
  818. //
  819. // Property Pages do not need this
  820. //
  821. return;
  822. }
  823. //
  824. // Get the new name from the control
  825. //
  826. CString s;
  827. GetEditBoxText(s);
  828. CString szFullName;
  829. CString szDisplayName;
  830. CString szTempName = pHolder->GetDomainNode()->GetFullName();
  831. ASSERT(szTempName.GetLength() > 0);
  832. if (szTempName.GetAt(szTempName.GetLength() - 1) != L'.')
  833. {
  834. szTempName += L".";
  835. }
  836. if (s.IsEmpty())
  837. {
  838. szFullName = szTempName;
  839. }
  840. else
  841. {
  842. szFullName.Format(L"%s.%s", s, szTempName);
  843. }
  844. //
  845. // Get server flags
  846. //
  847. DWORD dwNameChecking = pHolder->GetDomainNode()->GetServerNode()->GetNameCheckFlag();
  848. //
  849. // Is valid?
  850. //
  851. BOOL bIsValidName = (0 == ValidateRecordName(szFullName, dwNameChecking));
  852. if (m_bAllowAtTheNode)
  853. {
  854. //
  855. // must be a valid name or empty
  856. //
  857. bIsValidName = bIsValidName || s.IsEmpty();
  858. }
  859. SetDirty(bIsValidName);
  860. //
  861. // We only have one page up for record creation
  862. // so we show only the OK button and no apply button
  863. // therefore we have to enable the OK button because
  864. // SetDirty doesn't do that for us
  865. //
  866. pHolder->EnableSheetControl(IDOK, bIsValidName);
  867. GetDomainEditBox()->SetWindowText(szFullName);
  868. }
  869. #else
  870. void CDNSRecordStandardPropertyPage::OnEditChange()
  871. {
  872. CDNSRecordPropertyPageHolder* pHolder = GetDNSRecordHolder();
  873. //
  874. // Get the new name from the control
  875. //
  876. CString s;
  877. GetEditBoxText(s);
  878. CString szFullName;
  879. CString szDisplayName;
  880. CString szTempName = pHolder->GetDomainNode()->GetFullName();
  881. if (szTempName.GetAt(szTempName.GetLength() - 1) != L'.')
  882. {
  883. szTempName += L".";
  884. }
  885. if (s.IsEmpty())
  886. {
  887. szFullName = szTempName;
  888. }
  889. else
  890. {
  891. szFullName.Format(L"%s.%s", s, szTempName);
  892. }
  893. //
  894. // Get server flags
  895. //
  896. DWORD dwNameChecking = pHolder->GetDomainNode()->GetServerNode()->GetNameCheckFlag();
  897. //
  898. // Is valid?
  899. //
  900. BOOL bIsValidName = (0 == ValidateRecordName(szFullName, dwNameChecking));
  901. pHolder->EnableSheetControl(IDOK, bIsValidName);
  902. GetDomainEditBox()->SetWindowText(szFullName);
  903. }
  904. #endif
  905. DNS_STATUS CDNSRecordStandardPropertyPage::ValidateRecordName(PCWSTR pszName, DWORD dwNameChecking)
  906. {
  907. CDNSRecordPropertyPageHolder* pHolder = GetDNSRecordHolder();
  908. CDNSRootData* pRootData = (CDNSRootData*)pHolder->GetComponentData()->GetRootData();
  909. ASSERT(pRootData != NULL);
  910. if (pRootData->IsAdvancedView())
  911. {
  912. //
  913. // Don't validate the name in advanced view
  914. //
  915. return 0;
  916. }
  917. return ::ValidateDnsNameAgainstServerFlags(pszName, DnsNameDomain, dwNameChecking);
  918. }
  919. void CDNSRecordStandardPropertyPage::SetUIData()
  920. {
  921. TRACE(_T("CDNSRecordStandardPropertyPage::SetUIData()\n"));
  922. CDNSRecordPropertyPageHolder* pHolder = GetDNSRecordHolder();
  923. CDNSRecord* pRecord = pHolder->GetTempDNSRecord();
  924. OnSetName(pHolder->GetRecordNode()); // overridable
  925. GetTTLCtrl()->SetTTL(pRecord->m_dwTtlSeconds);
  926. GetDeleteStale()->SetCheck(pRecord->m_dwScavengeStart != 0);
  927. SetTimeStampEdit(pRecord->m_dwScavengeStart);
  928. }
  929. void CDNSRecordStandardPropertyPage::SetTimeStampEdit(DWORD dwScavengeStart)
  930. {
  931. if (dwScavengeStart == 0)
  932. {
  933. GetTimeStampEdit()->SetWindowText(_T(""));
  934. return;
  935. }
  936. SYSTEMTIME sysUTimeStamp, sysLTimeStamp;
  937. VERIFY(SUCCEEDED(Dns_SystemHrToSystemTime(dwScavengeStart, &sysUTimeStamp)));
  938. if (!::SystemTimeToTzSpecificLocalTime(NULL, &sysUTimeStamp, &sysLTimeStamp))
  939. {
  940. GetTimeStampEdit()->SetWindowText(_T(""));
  941. return;
  942. }
  943. // Format the string with respect to locale
  944. CString strref;
  945. PTSTR ptszDate = NULL;
  946. int cchDate = 0;
  947. cchDate = GetDateFormat(LOCALE_USER_DEFAULT, 0 ,
  948. &sysLTimeStamp, NULL,
  949. ptszDate, 0);
  950. ptszDate = (PTSTR)malloc(sizeof(TCHAR) * cchDate);
  951. if (ptszDate)
  952. {
  953. if (GetDateFormat(LOCALE_USER_DEFAULT, 0,
  954. &sysLTimeStamp, NULL,
  955. ptszDate, cchDate))
  956. {
  957. strref = ptszDate;
  958. }
  959. else
  960. {
  961. strref = L"";
  962. }
  963. free(ptszDate);
  964. }
  965. else
  966. {
  967. strref = L"";
  968. }
  969. PTSTR ptszTime = NULL;
  970. cchDate = GetTimeFormat(LOCALE_USER_DEFAULT, 0 ,
  971. &sysLTimeStamp, NULL,
  972. ptszTime, 0);
  973. ptszTime = (PTSTR)malloc(sizeof(TCHAR) * cchDate);
  974. if (ptszTime)
  975. {
  976. if (GetTimeFormat(LOCALE_USER_DEFAULT, 0,
  977. &sysLTimeStamp, NULL,
  978. ptszTime, cchDate))
  979. {
  980. strref += _T(" ") + CString(ptszTime);
  981. }
  982. else
  983. {
  984. strref += _T("");
  985. }
  986. free(ptszTime);
  987. }
  988. else
  989. {
  990. strref += _T("");
  991. }
  992. GetTimeStampEdit()->SetWindowText(strref);
  993. }
  994. DNS_STATUS CDNSRecordStandardPropertyPage::GetUIDataEx(BOOL)
  995. {
  996. DNS_STATUS dwErr = 0;
  997. CDNSRecordPropertyPageHolder* pHolder = GetDNSRecordHolder();
  998. CDNSRecord* pRecord = pHolder->GetTempDNSRecord();
  999. //
  1000. // only in wizard mode we can change the edit box content
  1001. //
  1002. if(pHolder->IsWizardMode())
  1003. {
  1004. CString s;
  1005. OnGetName(s);
  1006. CDNSZoneNode* pZone = pHolder->GetDomainNode()->GetZoneNode();
  1007. ASSERT(pZone != NULL);
  1008. if (!s.IsEmpty())
  1009. {
  1010. //
  1011. // Validate the record name using the server flags as a guideline
  1012. //
  1013. CString szFullName;
  1014. szFullName.Format(L"%s.%s", s, pHolder->GetDomainNode()->GetFullName());
  1015. DWORD dwNameChecking = pZone->GetServerNode()->GetNameCheckFlag();
  1016. dwErr = ValidateRecordName(szFullName, dwNameChecking);
  1017. }
  1018. #ifdef _USE_BLANK
  1019. BOOL bAtTheNode = s.IsEmpty();
  1020. #else
  1021. BOOL bAtTheNode = (s == g_szAtTheNodeInput);
  1022. #endif
  1023. CDNSRecordNodeBase* pRecordNode = pHolder->GetRecordNode();
  1024. if (bAtTheNode)
  1025. {
  1026. //name null, node is at the node level, use name of parent
  1027. pRecordNode->SetRecordName(pRecordNode->GetDomainNode()->GetDisplayName(),bAtTheNode);
  1028. }
  1029. else
  1030. {
  1031. // non null name, node is a child
  1032. pRecordNode->SetRecordName(s,bAtTheNode);
  1033. }
  1034. }
  1035. GetTTLCtrl()->GetTTL(&(pRecord->m_dwTtlSeconds));
  1036. if (GetDeleteStale()->GetCheck())
  1037. {
  1038. pRecord->m_dwFlags |= DNS_RPC_RECORD_FLAG_AGING_ON;
  1039. }
  1040. else
  1041. {
  1042. pRecord->m_dwFlags &= ~DNS_RPC_RECORD_FLAG_AGING_ON;
  1043. }
  1044. return dwErr;
  1045. }
  1046. //
  1047. // This is a place holder for new pages
  1048. //
  1049. #if (FALSE)
  1050. ///////////////////////////////////////////////////////////////////////
  1051. // CDNSRecordDummyPropertyPage
  1052. CDNSDummyRecordPropertyPageHolder::CDNSDummyRecordPropertyPageHolder(CDNSDomainNode* pDNSDomainNode,
  1053. CDNSRecordNodeBase* pRecordNode,
  1054. CComponentDataObject* pComponentData,
  1055. WORD wPredefinedRecordType)
  1056. : CPropertyPageHolderBase(pDNSDomainNode, pRecordNode, pComponentData)
  1057. {
  1058. m_bAutoDeletePages = FALSE; // we have the pages as embedded members
  1059. // add pages
  1060. AddPageToList((CPropertyPageBase*)&m_dummyPage);
  1061. }
  1062. CDNSDummyRecordPropertyPageHolder::~CDNSDummyRecordPropertyPageHolder()
  1063. {
  1064. }
  1065. CDNSRecordDummyPropertyPage::CDNSRecordDummyPropertyPage()
  1066. : CPropertyPageBase(IID_DUMMY_REC_PPAGE)
  1067. {
  1068. }
  1069. BOOL CDNSRecordDummyPropertyPage::OnApply()
  1070. {
  1071. return TRUE;
  1072. }
  1073. void CDNSRecordDummyPropertyPage::OnOK()
  1074. {
  1075. }
  1076. #endif