//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1998 - 1999 // // File: nspage.cpp // //-------------------------------------------------------------------------- #include "preDNSsn.h" #include #include "resource.h" #include "dnsutil.h" #include "DNSSnap.h" #include "snapdata.h" #include "server.h" #include "domain.h" #include "record.h" #include "zone.h" #include "nspage.h" #include "uiutil.h" #include "ipeditor.h" #include "browser.h" /////////////////////////////////////////////////////////////////////////////// // CDNS_NS_RecordDialog class CDNS_NS_RecordDialog : public CPropertyPage { public: CDNS_NS_RecordDialog(CDNSNameServersPropertyPage* pNSPage, BOOL bNew); CDNS_NS_RecordDialog(CDNSNameServersWizardPage* pNSWiz, BOOL bNew); ~CDNS_NS_RecordDialog(); INT_PTR DoModalSheet(HWND parent = 0); // data BOOL m_bDirty; CDNSRecordNodeEditInfo* m_pNSInfo; protected: virtual int OnCreate(LPCREATESTRUCT lpCreateStruct); virtual BOOL OnInitDialog(); virtual BOOL OnApply(); afx_msg void OnServerNameChange(); afx_msg void OnBrowse(); afx_msg void OnQuery(); BOOL OnHelpInfo(HELPINFO* pHelpInfo); DECLARE_MESSAGE_MAP() private: class CARecordAddressesIPEditor : public CIPEditor { public: CARecordAddressesIPEditor(CDNS_NS_RecordDialog* pNSRecordDialog) { m_pNSRecordDialog = pNSRecordDialog;} void SetIpAddresses(CDNSRecordNodeEditInfo* pNSInfo); BOOL GetIpAddresses(CDNSRecordNodeEditInfo* pNSInfo); protected: virtual void OnChangeData(); private: CDNS_NS_RecordDialog* m_pNSRecordDialog; }; CARecordAddressesIPEditor m_RecordAddressesEditor; BOOL m_bNew; CDNSNameServersPropertyPage* m_pNSPage; CDNSNameServersWizardPage* m_pNSWiz; CPropertyPageBase* GetPage() { if (m_pNSPage != NULL) { return m_pNSPage; } return m_pNSWiz; } HWND m_hWndOKButton; HWND m_hWndQueryButton; CDNSTTLControl* GetTTLCtrl() { return (CDNSTTLControl*)GetDlgItem(IDC_TTLEDIT);} CEdit* GetServerEdit() { return (CEdit*)GetDlgItem(IDC_SERVER_NAME_EDIT); } CDNS_NS_Record* GetNSRecord() { ASSERT( m_pNSInfo != NULL); ASSERT( m_pNSInfo->m_pRecord->m_wType == DNS_TYPE_NS); return (CDNS_NS_Record*)m_pNSInfo->m_pRecord; } void GetNSServerName(CString& szNameNode); void SyncUIButtons(); void EnableTTLCtrl(BOOL bShow); friend class CARecordAddressesIPEditor; }; INT_PTR CDNS_NS_RecordDialog::DoModalSheet(HWND parent) { /* NOTE : The first call to this may cause a first-chance exception. Excerpt from MSDN January 2000. Note The first time a property page is created from its corresponding dialog resource, it may cause a first-chance exception. This is a result of the property page changing the style of the dialog resource to the required style prior to creating the page. Because resources are generally read-only, this causes an exception. The exception is handled by the system, and a copy of the modified resource is made automatically by the system. The first-chance exception can thus be ignored. Since this exception must be handled by the operating system, do not wrap calls to CPropertySheet::DoModal with a C++ try/catch block in which the catch handles all exceptions, for example, catch (...). This will handle the exception intended for the operating system, causing unpredictable behavior. Using C++ exception handling with specific exception types or using structured exception handling where the Access Violation exception is passed through to the operating system is safe, however. */ AFX_MANAGE_STATE(AfxGetStaticModuleState()); CThemeContextActivator activator; CString szTitle; szTitle.LoadString(m_bNew ? IDS_NEW_RECORD_TITLE : IDS_EDIT_RECORD_TITLE); CPropertySheet hostSheet; hostSheet.m_psh.dwFlags |= PSH_NOAPPLYNOW; hostSheet.m_psh.pszCaption = (LPCTSTR)szTitle; hostSheet.m_psh.hwndParent = parent; hostSheet.AddPage(this); INT_PTR iRes = hostSheet.DoModal(); GetPage()->GetHolder()->PopDialogHWnd(); return iRes; } void CDNS_NS_RecordDialog::CARecordAddressesIPEditor::OnChangeData() { m_pNSRecordDialog->SyncUIButtons(); } void CDNS_NS_RecordDialog::CARecordAddressesIPEditor:: SetIpAddresses(CDNSRecordNodeEditInfo* pNSInfo) { Clear(); ASSERT(pNSInfo != NULL); INT_PTR nArraySize = pNSInfo->m_pEditInfoList->GetCount(); if (nArraySize == 0) return; DWORD* pArr = (DWORD*)malloc(nArraySize*sizeof(DWORD)); if (!pArr) { return; } int k=0; POSITION pos; for( pos = pNSInfo->m_pEditInfoList->GetHeadPosition(); pos != NULL; ) { CDNSRecordNodeEditInfo* pARecordInfo = pNSInfo->m_pEditInfoList->GetNext(pos); ASSERT(pARecordInfo != NULL); if (pARecordInfo->m_action != CDNSRecordNodeEditInfo::remove) { ASSERT(pARecordInfo->m_pRecord != NULL); ASSERT(pARecordInfo->m_pRecord->m_wType == DNS_TYPE_A); CDNS_A_Record* pARecord = (CDNS_A_Record*)pARecordInfo->m_pRecord; pArr[k++] = pARecord->m_ipAddress; } } AddAddresses(pArr, k); if (pArr) { free(pArr); } } BOOL CDNS_NS_RecordDialog::CARecordAddressesIPEditor:: GetIpAddresses(CDNSRecordNodeEditInfo* pNSInfo) { BOOL bDirty = FALSE; int nArraySize = GetCount(); // if the count of IP addresses is zero, // we mark the NS record as slated for removal if (nArraySize == 0) pNSInfo->m_action = CDNSRecordNodeEditInfo::remove; // read the IP addresses from IP editor, if any DWORD* pArr = (nArraySize >0) ? (DWORD*)malloc(nArraySize*sizeof(DWORD)) : NULL; if (!pArr) { return FALSE; } int nFilled = 0; if (nArraySize > 0) GetAddresses(pArr, nArraySize, &nFilled); ASSERT(nFilled == nArraySize); ASSERT(pNSInfo->m_pRecord != NULL); ASSERT(pNSInfo->m_pRecord->GetType() == DNS_TYPE_NS); CDNS_NS_Record* pNSRecord = (CDNS_NS_Record*)pNSInfo->m_pRecord; CDNSRecordNodeEditInfoList* pNSInfoList = pNSInfo->m_pEditInfoList; CDNSRecordNodeEditInfoList NSInfoRemoveList; POSITION pos; // walk the list of A records, to mark the ones to be deleted, // if nArraySize == 0, all of them well be marked for removal for( pos = pNSInfoList->GetHeadPosition(); pos != NULL; ) { CDNSRecordNodeEditInfo* pCurrentInfo = pNSInfoList->GetNext(pos); ASSERT(pCurrentInfo->m_pRecordNode != NULL); ASSERT(pCurrentInfo->m_pRecord != NULL); ASSERT(pCurrentInfo->m_pRecord->GetType() == DNS_TYPE_A); CDNS_A_Record* pARecord = (CDNS_A_Record*)pCurrentInfo->m_pRecord; BOOL bFound = FALSE; for (int k=0; km_ipAddress == pArr[k]) { bFound = TRUE; break; } } if (!bFound) { bDirty = TRUE; if (pCurrentInfo->m_bExisting) { pCurrentInfo->m_action = CDNSRecordNodeEditInfo::remove; // mark as deleted } else { NSInfoRemoveList.AddTail(pCurrentInfo); } } } // for // This gives NSInfoRemoveList ownership of all memory management for all nodes // removed from the pNSInfoList POSITION listPos = NSInfoRemoveList.GetHeadPosition(); while (listPos != NULL) { CDNSRecordNodeEditInfo* pCurrentInfo = NSInfoRemoveList.GetNext(listPos); ASSERT(pCurrentInfo != NULL); POSITION removePos = pNSInfoList->Find(pCurrentInfo); pNSInfoList->RemoveAt(removePos); } // Remove and delete all nodes that were removed from the pNSInfoList NSInfoRemoveList.RemoveAllNodes(); // walk the list of addresses, to look for matching A records to add // if nArraySize == 0, loop skipped, nothing to add for (int k=0; kGetHeadPosition(); pos != NULL; ) { CDNSRecordNodeEditInfo* pCurrentInfo = pNSInfoList->GetNext(pos); ASSERT(pCurrentInfo->m_pRecordNode != NULL); ASSERT(pCurrentInfo->m_pRecord != NULL); ASSERT(pCurrentInfo->m_pRecord->GetType() == DNS_TYPE_A); CDNS_A_Record* pARecord = (CDNS_A_Record*)pCurrentInfo->m_pRecord; if (pARecord->m_ipAddress == pArr[k]) { bFound = TRUE; if (pCurrentInfo->m_action == CDNSRecordNodeEditInfo::remove) // we got it already, resuscitate it { bDirty = TRUE; if(pCurrentInfo->m_bExisting) pCurrentInfo->m_action = CDNSRecordNodeEditInfo::edit; else pCurrentInfo->m_action = CDNSRecordNodeEditInfo::add; } break; } } if (!bFound) { // A record not found, need to create one CDNSRecordNodeEditInfo* pNewInfo = new CDNSRecordNodeEditInfo; if (pNewInfo) { CDNS_A_RecordNode* pARecordNode = new CDNS_A_RecordNode; if (pARecordNode) { pNewInfo->CreateFromNewRecord(pARecordNode); CDNS_A_Record* pARecord = (CDNS_A_Record*)pNewInfo->m_pRecord; pARecord->m_ipAddress = pArr[k]; pNewInfo->m_pRecordNode->m_bAtTheNode = FALSE; pNewInfo->m_pRecordNode->SetRecordName(pNSRecord->m_szNameNode, FALSE /*bAtTheNode*/); // inherit the TTL of the NS record pNewInfo->m_pRecord->m_dwTtlSeconds = pNSInfo->m_pRecord->m_dwTtlSeconds; pNSInfoList->AddTail(pNewInfo); bDirty = TRUE; } else { delete pNewInfo; } } } } // for if (pArr) { free(pArr); } return bDirty; } BEGIN_MESSAGE_MAP(CDNS_NS_RecordDialog, CPropertyPage) ON_WM_CREATE() ON_EN_CHANGE(IDC_SERVER_NAME_EDIT, OnServerNameChange) ON_BN_CLICKED(IDC_BROWSE_BUTTON, OnBrowse) ON_BN_CLICKED(IDC_QUERY_BUTTON, OnQuery) ON_WM_HELPINFO() END_MESSAGE_MAP() CDNS_NS_RecordDialog::CDNS_NS_RecordDialog(CDNSNameServersPropertyPage* pNSPage, BOOL bNew) : CPropertyPage(IDD_RR_NS_EDIT), m_RecordAddressesEditor(this) { ASSERT(pNSPage != NULL); m_pNSPage = pNSPage; m_pNSWiz = NULL; m_bNew = bNew; m_bDirty = FALSE; m_pNSInfo = NULL; m_hWndOKButton = m_hWndQueryButton = NULL; } CDNS_NS_RecordDialog::CDNS_NS_RecordDialog(CDNSNameServersWizardPage* pNSWiz, BOOL bNew) : CPropertyPage(IDD_RR_NS_EDIT), m_RecordAddressesEditor(this) { ASSERT(pNSWiz != NULL); m_pNSPage = NULL; m_pNSWiz = pNSWiz; m_bNew = bNew; m_bDirty = FALSE; m_pNSInfo = NULL; m_hWndOKButton = m_hWndQueryButton = NULL; } CDNS_NS_RecordDialog::~CDNS_NS_RecordDialog() { } int CDNS_NS_RecordDialog::OnCreate(LPCREATESTRUCT lpCreateStruct) { int res = CPropertyPage::OnCreate(lpCreateStruct); DWORD dwStyle = ::GetWindowLong(::GetParent(GetSafeHwnd()), GWL_EXSTYLE); dwStyle |= WS_EX_CONTEXTHELP; // force the [?] button ::SetWindowLong(::GetParent(GetSafeHwnd()), GWL_EXSTYLE, dwStyle); return res; } BOOL CDNS_NS_RecordDialog::OnHelpInfo(HELPINFO* pHelpInfo) { CComponentDataObject* pComponentData = GetPage()->GetHolder()->GetComponentData(); ASSERT(pComponentData != NULL); pComponentData->OnDialogContextHelp(m_nIDHelp, pHelpInfo); return TRUE; } void CDNS_NS_RecordDialog::EnableTTLCtrl(BOOL bShow) { CDNSTTLControl* pCtrl = GetTTLCtrl(); ASSERT(pCtrl != NULL); pCtrl->EnableWindow(bShow); pCtrl->ShowWindow(bShow); CWnd* pWnd = GetDlgItem(IDC_STATIC_TTL); ASSERT(pWnd != NULL); pWnd->EnableWindow(bShow); pWnd->ShowWindow(bShow); CWnd* pLabelWnd = GetDlgItem(IDC_TTL_LABEL); ASSERT(pLabelWnd != NULL); pLabelWnd->EnableWindow(bShow); pLabelWnd->ShowWindow(bShow); } BOOL CDNS_NS_RecordDialog::OnInitDialog() { CPropertyPage::OnInitDialog(); ASSERT(m_pNSInfo != NULL); ASSERT(m_pNSInfo->m_pRecord != NULL); ASSERT(m_hWnd != NULL); ASSERT(::IsWindow(m_hWnd)); HWND hParent = ::GetParent(m_hWnd); ASSERT(hParent); GetPage()->GetHolder()->PushDialogHWnd(hParent); // // OK button on the sheet // m_hWndOKButton = ::GetDlgItem(hParent, IDOK); ASSERT(::IsWindow(m_hWndOKButton)); // // query button handle // m_hWndQueryButton = :: GetDlgItem(m_hWnd, IDC_QUERY_BUTTON); ASSERT(::IsWindow(m_hWndQueryButton)); // // initialize IP editor // VERIFY(m_RecordAddressesEditor.Initialize(this, GetParent(), IDC_BUTTON_UP, IDC_BUTTON_DOWN, IDC_BUTTON_ADD, IDC_BUTTON_REMOVE, IDC_IPEDIT, IDC_LIST)); // // Load Data in the UI // m_RecordAddressesEditor.SetIpAddresses(m_pNSInfo); GetServerEdit()->LimitText(MAX_DNS_NAME_LEN); GetServerEdit()->SetWindowText(GetNSRecord()->m_szNameNode); GetTTLCtrl()->SetTTL(m_pNSInfo->m_pRecord->m_dwTtlSeconds); // need to decide if we want to show the TTL control CDNSRootData* pRootData = (CDNSRootData*)GetPage()->GetHolder()->GetComponentData()->GetRootData(); ASSERT(pRootData != NULL); BOOL bEnableTTLCtrl; if (m_pNSPage != NULL) { bEnableTTLCtrl = m_pNSPage->HasMeaningfulTTL() && pRootData->IsAdvancedView(); } else { bEnableTTLCtrl = m_pNSWiz->HasMeaningfulTTL() && pRootData->IsAdvancedView(); } EnableTTLCtrl(bEnableTTLCtrl); return TRUE; // return TRUE unless you set the focus to a control } void CDNS_NS_RecordDialog::GetNSServerName(CString& szNameNode) { GetServerEdit()->GetWindowText(szNameNode); szNameNode.TrimLeft(); szNameNode.TrimRight(); if (szNameNode[szNameNode.GetLength()-1] != TEXT('.')) szNameNode += TEXT('.'); } void CDNS_NS_RecordDialog::SyncUIButtons() { CString szServerName; GetServerEdit()->GetWindowText(szServerName); szServerName.TrimLeft(); szServerName.TrimRight(); DWORD dwNameChecking = 0; if (m_pNSWiz) { dwNameChecking = m_pNSWiz->GetDomainNode()->GetServerNode()->GetNameCheckFlag(); } else if (m_pNSPage) { dwNameChecking = m_pNSPage->GetDomainNode()->GetServerNode()->GetNameCheckFlag(); } // // Enable OK button if it is a valid name // BOOL bIsValidName = (0 == ValidateDnsNameAgainstServerFlags(szServerName, DnsNameDomain, dwNameChecking)); ::EnableWindow(m_hWndOKButton, bIsValidName && m_RecordAddressesEditor. GetCount() > 0); ::EnableWindow(m_hWndQueryButton, bIsValidName); } BOOL CDNS_NS_RecordDialog::OnApply() { ASSERT(m_pNSInfo->m_pRecord != NULL); CString szNameNode; GetNSServerName(szNameNode); // Make sure the new name is an FQDN or else we could have // a broken delegation CString szNSName; GetServerEdit()->GetWindowText(szNSName); if (szNSName.Find(L".") == -1) { DNSMessageBox(IDS_MSG_RECORD_WARNING_NS_NOT_FQDN, MB_OK); return false; } // compare (case insensitive) with old name to see if it changed, // NOTICE: CDNSDomainNode::UpdateARecordsOfNSInfoHelper() will then // take care of regenerating the list of A records m_bDirty = _wcsicmp((LPCWSTR)szNameNode, (LPCWSTR)GetNSRecord()->m_szNameNode); if (m_bDirty) GetNSRecord()->m_szNameNode = szNameNode; // update list of IP addresses if (m_bNew) { // the dialog is used to create a new entry ASSERT(!m_pNSInfo->m_bExisting); m_pNSInfo->m_action = CDNSRecordNodeEditInfo::add; } else { // the dialog is used to edit if (m_pNSInfo->m_bExisting) { // an existing entry m_pNSInfo->m_action = CDNSRecordNodeEditInfo::edit; } else { // a newly created entry, edited before committing m_pNSInfo->m_action = CDNSRecordNodeEditInfo::add; } } // this call migth mark the info as remove, if no IP addresses are found if (m_RecordAddressesEditor.GetIpAddresses(m_pNSInfo)) m_bDirty = TRUE; DWORD dwTTL; GetTTLCtrl()->GetTTL(&dwTTL); if (m_pNSInfo->m_pRecord->m_dwTtlSeconds != dwTTL) { m_bDirty = TRUE; m_pNSInfo->m_pRecord->m_dwTtlSeconds = dwTTL; // Need to change the TTL on all associated A records CDNSRecordNodeEditInfoList* pNSInfoList = m_pNSInfo->m_pEditInfoList; for(POSITION pos = pNSInfoList->GetHeadPosition(); pos != NULL; ) { CDNSRecordNodeEditInfo* pCurrentInfo = pNSInfoList->GetNext(pos); ASSERT(pCurrentInfo->m_pRecordNode != NULL); ASSERT(pCurrentInfo->m_pRecord != NULL); // if slated for removal, don't bother to change if (pCurrentInfo->m_action != CDNSRecordNodeEditInfo::remove) { pCurrentInfo->m_pRecord->m_dwTtlSeconds = m_pNSInfo->m_pRecord->m_dwTtlSeconds; // if already marked "add" or "edit", leave as is, // but if unchanged, need to mark as "edit" if (pCurrentInfo->m_action == CDNSRecordNodeEditInfo::unchanged) pCurrentInfo->m_action = CDNSRecordNodeEditInfo::edit; } } } if (m_pNSInfo->m_action == CDNSRecordNodeEditInfo::remove) { if (IDNO == DNSMessageBox(IDS_MSG_RECORD_WARNING_NS_NO_IP, MB_YESNO)) return true; } return true; } void CDNS_NS_RecordDialog::OnServerNameChange() { SyncUIButtons(); } void CDNS_NS_RecordDialog::OnBrowse() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); FIX_THREAD_STATE_MFC_BUG(); CThemeContextActivator activator; CComponentDataObject* pComponentDataObject = GetPage()->GetHolder()->GetComponentData(); CDNSBrowserDlg dlg(pComponentDataObject, GetPage()->GetHolder(), RECORD_A_AND_CNAME); if (IDOK == dlg.DoModal()) { GetServerEdit()->SetWindowText(dlg.GetSelectionString()); // // if it is an A record, add the IP address to the IP editor // CDNSRecordNodeBase* pRecordNode = reinterpret_cast(dlg.GetSelection()); if ((pRecordNode != NULL) && (pRecordNode->GetType() == DNS_TYPE_A)) { DWORD ip = ((CDNS_A_RecordNode*)pRecordNode)->GetIPAddress(); m_RecordAddressesEditor.AddAddresses(&ip,1); } } } void CDNS_NS_RecordDialog::OnQuery() { CWaitCursor cursor; CDNSRecordNodeEditInfo tempNSInfo; // test CString szNameNode; GetNSServerName(szNameNode); CDNSServerNode* pServerNode; if (m_pNSPage != NULL) { pServerNode = m_pNSPage->GetDomainNode()->GetServerNode(); } else { pServerNode = m_pNSWiz->GetDomainNode()->GetServerNode(); } LPCWSTR lpszZoneName = NULL; CDNSZoneNode* pZoneNode = NULL; if (m_pNSPage != NULL) { pZoneNode = m_pNSPage->GetDomainNode()->GetZoneNode(); } else { pZoneNode = m_pNSWiz->GetDomainNode()->GetZoneNode(); } if (pZoneNode != NULL) { lpszZoneName = pZoneNode->GetFullName(); } ASSERT(pServerNode != NULL); CComponentDataObject* pComponentDataObject = GetPage()->GetHolder()->GetComponentData(); CDNSRootData* pRootData = (CDNSRootData*)pComponentDataObject->GetRootData(); ASSERT(pRootData != NULL); DWORD cAddrCount; PIP_ADDRESS pipAddrs; pServerNode->GetListenAddressesInfo(&cAddrCount, &pipAddrs); if (cAddrCount == 0) { // listening on all addresses pServerNode->GetServerAddressesInfo(&cAddrCount, &pipAddrs); } CDNSDomainNode::FindARecordsFromNSInfo(pServerNode->GetRPCName(), pServerNode->GetVersion(), cAddrCount, pipAddrs, lpszZoneName, szNameNode, tempNSInfo.m_pEditInfoList, pRootData->IsAdvancedView()); if (tempNSInfo.m_pEditInfoList->GetCount() > 0) { // update the list only if we have valid data m_RecordAddressesEditor.SetIpAddresses(&tempNSInfo); } else { DNSMessageBox(IDS_MSG_RECORD_NS_RESOLVE_IP, MB_OK | MB_ICONERROR); } } /////////////////////////////////////////////////////////////////////////////// // CNSListCtrl BEGIN_MESSAGE_MAP(CNSListCtrl, CListCtrl) END_MESSAGE_MAP() void CNSListCtrl::Initialize() { // get size of control to help set the column widths CRect controlRect; GetClientRect(controlRect); // get width of control, width of potential scrollbar, width needed for sub-item // string int controlWidth = controlRect.Width(); int scrollThumbWidth = ::GetSystemMetrics(SM_CXHTHUMB); // clean net width int nNetControlWidth = controlWidth - scrollThumbWidth - 12 * ::GetSystemMetrics(SM_CXBORDER); // fields widths int nWidth1 = 3 * nNetControlWidth / 4; int nWidth2 = nNetControlWidth - nWidth1; // // set up columns CString szHeaders; { AFX_MANAGE_STATE(AfxGetStaticModuleState()); szHeaders.LoadString(IDS_NSPAGE_LISTVIEW_HEADERS); } ASSERT(!szHeaders.IsEmpty()); LPWSTR lpszArr[2]; UINT n; ParseNewLineSeparatedString(szHeaders.GetBuffer(1), lpszArr, &n); szHeaders.ReleaseBuffer(); ASSERT(n == 2); InsertColumn(1, lpszArr[0], LVCFMT_LEFT, nWidth1, 1); InsertColumn(2, lpszArr[1], LVCFMT_LEFT, nWidth2 + 28, 2); } int CNSListCtrl::GetSelection() { return GetNextItem(-1, LVIS_SELECTED); } void CNSListCtrl::SetSelection(int nSel) { VERIFY(SetItemState(nSel, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED)); /* VERIFY(SetItem(nSel, // nItem 0, // nSubItem LVIF_STATE, // nMask NULL, // lpszItem 0, // nImage LVIS_SELECTED | LVIS_FOCUSED, // nState LVIS_SELECTED | LVIS_FOCUSED, // nStateMask NULL // lParam )); */ } void CNSListCtrl::UpdateNSRecordEntry(int nItemIndex) { CDNSRecordNodeEditInfo* pNSInfo = (CDNSRecordNodeEditInfo*)GetItemData(nItemIndex); VERIFY(SetItem(nItemIndex, // nItem 0, // nSubItem LVIF_TEXT, // nMask ((CDNS_NS_Record*)pNSInfo->m_pRecord)->m_szNameNode, // lpszItem 0, // nImage 0, // nState 0, // nStateMask NULL // lParam )); CString szTemp; GetIPAddressString(pNSInfo, szTemp); SetItemText(nItemIndex, 1, szTemp); } CDNSRecordNodeEditInfo* CNSListCtrl::GetSelectionEditInfo() { int nSel = GetSelection(); if (nSel == -1) return NULL; // no selection return (CDNSRecordNodeEditInfo*)GetItemData(nSel); } void CNSListCtrl::BuildIPAddrDisplayString(CDNSRecordNodeEditInfo* pNSInfo, CString& szDisplayData) { USES_CONVERSION; // need to chain the IP addresses in a single string CString szTemp; szTemp.GetBuffer(20); // length of an IP string szTemp.ReleaseBuffer(); szDisplayData.GetBuffer(static_cast(20*pNSInfo->m_pEditInfoList->GetCount())); szDisplayData.ReleaseBuffer(); POSITION pos; for( pos = pNSInfo->m_pEditInfoList->GetHeadPosition(); pos != NULL; ) { CDNSRecordNodeEditInfo* pARecordInfo = pNSInfo->m_pEditInfoList->GetNext(pos); if (pARecordInfo->m_action != CDNSRecordNodeEditInfo::remove) { ASSERT(pARecordInfo != NULL); ASSERT(pARecordInfo->m_pRecord != NULL); ASSERT(pARecordInfo->m_pRecord->m_wType == DNS_TYPE_A); CDNS_A_Record* pARecord = (CDNS_A_Record*)pARecordInfo->m_pRecord; szDisplayData += _T("["); FormatIpAddress(szTemp, pARecord->m_ipAddress); szDisplayData += szTemp; if (pARecordInfo->m_bFromDnsQuery) { szDisplayData += _T("*"); } szDisplayData += _T("] "); } } } BOOL CNSListCtrl::InsertNSRecordEntry(CDNSRecordNodeEditInfo* pNSInfo, int nItemIndex) { ASSERT(pNSInfo != NULL); ASSERT( (pNSInfo->m_action == CDNSRecordNodeEditInfo::unchanged) || (pNSInfo->m_action == CDNSRecordNodeEditInfo::add) ); ASSERT(pNSInfo->m_pRecord != NULL); ASSERT(pNSInfo->m_pRecordNode != NULL); ASSERT(pNSInfo->m_pRecordNode->m_bAtTheNode); BOOL bAlreadyExists = FALSE; // // First check to see if its already there // for (int idx = 0; idx < GetItemCount(); idx++) { CDNSRecordNodeEditInfo* pIdxInfo = reinterpret_cast(GetItemData(idx)); ASSERT(pIdxInfo != NULL); if (pIdxInfo == NULL) { continue; } CDNS_NS_Record* pNSRecord = reinterpret_cast(pIdxInfo->m_pRecord); ASSERT(pNSRecord != NULL); if (pNSRecord == NULL) { continue; } // // Adding trailing '.' if not already present // CString szUINSName = pNSRecord->m_szNameNode; CString szNewNSName = ((CDNS_NS_Record*)pNSInfo->m_pRecord)->m_szNameNode; if (szUINSName[szUINSName.GetLength() - 1] != L'.') { szUINSName += L"."; } if (szNewNSName[szNewNSName.GetLength() - 1] != L'.') { szNewNSName += L"."; } // // if it exists, just update the existing one // if (_wcsicmp(szNewNSName, szUINSName) == 0) { bAlreadyExists = TRUE; // // Merge the A record lists together // POSITION newPos = pNSInfo->m_pEditInfoList->GetHeadPosition(); while (newPos != NULL) { CDNSRecordNodeEditInfo* pAInfo = pNSInfo->m_pEditInfoList->GetNext(newPos); CDNS_A_Record* pARecord = reinterpret_cast(pAInfo->m_pRecord); ASSERT(pARecord != NULL); if (pARecord == NULL) { continue; } BOOL bARecordExists = FALSE; POSITION IdxPos = pIdxInfo->m_pEditInfoList->GetHeadPosition(); while (IdxPos != NULL) { CDNSRecordNodeEditInfo* pIdxAInfo = pIdxInfo->m_pEditInfoList->GetNext(IdxPos); CDNS_A_Record* pIdxARecord = reinterpret_cast(pIdxAInfo->m_pRecord); ASSERT(pIdxARecord != NULL); if (pIdxARecord == NULL) { continue; } if (pIdxARecord->m_ipAddress == pARecord->m_ipAddress) { bARecordExists = TRUE; break; } } if (!bARecordExists) { // // Add the A record since it doesn't already exist in the list // pIdxInfo->m_pEditInfoList->AddTail(pAInfo); pIdxInfo->m_action = CDNSRecordNodeEditInfo::edit; UpdateNSRecordEntry(idx); } } } } if (!bAlreadyExists) { CString szTemp; GetIPAddressString(pNSInfo, szTemp); InsertItemHelper(nItemIndex, pNSInfo, ((CDNS_NS_Record*)pNSInfo->m_pRecord)->m_szNameNode, (LPCTSTR)szTemp); // // Added new item so return TRUE; // return TRUE; } // // Updated an existing item so return FALSE // return FALSE; } void CNSListCtrl::InsertItemHelper(int nIndex, CDNSRecordNodeEditInfo* pNSInfo, LPCTSTR lpszName, LPCTSTR lpszValue) { UINT nState = 0; if (nIndex == 0 ) nState = LVIS_SELECTED | LVIS_FOCUSED; // have at least one item, select it VERIFY(-1 != InsertItem(LVIF_TEXT | LVIF_PARAM, nIndex, lpszName, nState, 0, 0, (LPARAM)pNSInfo)); SetItemText(nIndex, 1, lpszValue); } void CNSListCtrl::GetIPAddressString(CDNSRecordNodeEditInfo* pNSInfo, CString& sz) { if (pNSInfo->m_pEditInfoList->GetCount() > 0) { BuildIPAddrDisplayString(pNSInfo, sz); } else sz.LoadString(IDS_UNKNOWN); } /////////////////////////////////////////////////////////////////////////////// // CDNSNameServersPropertyPage BEGIN_MESSAGE_MAP(CDNSNameServersPropertyPage, CPropertyPageBase) ON_BN_CLICKED(IDC_ADD_NS_BUTTON, OnAddButton) ON_BN_CLICKED(IDC_REMOVE_NS_BUTTON, OnRemoveButton) ON_BN_CLICKED(IDC_EDIT_NS_BUTTON, OnEditButton) ON_NOTIFY(LVN_ITEMCHANGED, IDC_NS_LIST, OnListItemChanged) END_MESSAGE_MAP() CDNSNameServersPropertyPage::CDNSNameServersPropertyPage(UINT nIDTemplate, UINT nIDCaption) : CPropertyPageBase(nIDTemplate, nIDCaption) { m_pDomainNode = NULL; m_pCloneInfoList = new CDNSRecordNodeEditInfoList; m_bReadOnly = FALSE; m_bMeaningfulTTL = TRUE; } CDNSNameServersPropertyPage::~CDNSNameServersPropertyPage() { delete m_pCloneInfoList; } BOOL CDNSNameServersPropertyPage::WriteNSRecordNodesList() { ASSERT(!m_bReadOnly); ASSERT(m_pCloneInfoList != NULL); CDNSDomainNode* pDomainNode = GetDomainNode(); return pDomainNode->UpdateNSRecordNodesInfo(m_pCloneInfoList, GetHolder()->GetComponentData()); } BOOL CDNSNameServersPropertyPage::OnWriteNSRecordNodesListError() { ASSERT(!m_bReadOnly); BOOL bSuccess = TRUE; // loop for each NS record POSITION pos; for( pos = m_pCloneInfoList->GetHeadPosition(); pos != NULL; ) { CDNSRecordNodeEditInfo* pCurrentInfo = m_pCloneInfoList->GetNext(pos); if (pCurrentInfo->m_dwErr != 0) { if (pCurrentInfo->m_dwErr == DNS_ERROR_RECORD_ALREADY_EXISTS) { // ignore if the NS record us already there pCurrentInfo->m_dwErr = 0; } else if (pCurrentInfo->m_dwErr == RPC_S_SERVER_UNAVAILABLE) { // Couldn't contact the server. Give a single error message // and then break out. DNSErrorDialog(pCurrentInfo->m_dwErr, L""); return FALSE; } else { bSuccess = FALSE; ASSERT(pCurrentInfo->m_pRecord->GetType() == DNS_TYPE_NS); CString szNSMsg; szNSMsg.Format(_T("Failure to write NS record <%s>"), (((CDNS_NS_Record*)pCurrentInfo->m_pRecord))->m_szNameNode); DNSErrorDialog(pCurrentInfo->m_dwErr,szNSMsg); } } // loop for each related A record CDNSRecordNodeEditInfoList* pARecordInfoList = pCurrentInfo->m_pEditInfoList; ASSERT(pARecordInfoList != NULL); POSITION posA; for( posA = pARecordInfoList->GetHeadPosition(); posA != NULL; ) { CDNSRecordNodeEditInfo* pARecordCurrentInfo = pARecordInfoList->GetNext(posA); if (pARecordCurrentInfo->m_dwErr != 0) { ASSERT(pARecordCurrentInfo->m_pRecord->GetType() == DNS_TYPE_A); CString szTemp; FormatIpAddress(szTemp, (((CDNS_A_Record*)pARecordCurrentInfo->m_pRecord))->m_ipAddress); CString szAMsg; szAMsg.Format(_T("Failure to write A record <%s>, IP Address %s"), (((CDNS_NS_Record*)pARecordCurrentInfo->m_pRecord))->m_szNameNode, (LPCWSTR)szTemp ); DNSErrorDialog(pCurrentInfo->m_dwErr,szAMsg); } } } return bSuccess; } void CDNSNameServersPropertyPage::OnListItemChanged(NMHDR*, LRESULT*) { EnableEditorButtons(m_listCtrl.GetSelection()); } BOOL CDNSNameServersPropertyPage::OnApply() { if (m_bReadOnly) return TRUE; if (!IsDirty()) return TRUE; DNS_STATUS err = GetHolder()->NotifyConsole(this); if ( (err != 0) && OnWriteNSRecordNodesListError() ) { err = 0; // error was handled and it was not fatal } if (err == 0) { // refresh data from the zone/domain LoadUIData(); SetDirty(FALSE); } return (err == 0); } BOOL CDNSNameServersPropertyPage::OnPropertyChange(BOOL, long*) { if (m_bReadOnly) { ASSERT(FALSE); // sould not happen return FALSE; } ASSERT(m_pCloneInfoList != NULL); if (m_pCloneInfoList == NULL) return FALSE; BOOL bRes = WriteNSRecordNodesList(); if (!bRes) GetHolder()->SetError(static_cast(-1)); // something went wrong, error code will be per item return bRes; // update flag } void CDNSNameServersPropertyPage::OnAddButton() { if (m_bReadOnly) { ASSERT(FALSE); // sould not happen return; } AFX_MANAGE_STATE(AfxGetStaticModuleState()); FIX_THREAD_STATE_MFC_BUG(); ASSERT(m_pCloneInfoList != NULL); // provide subdialog to add record, for the time being can have just // dialog to enter the host name // create an item in the list of changes // TODO: first check if we can recycle some old stuff in the list // create new data CDNSRecordNodeEditInfo* pNewInfo = new CDNSRecordNodeEditInfo; if (!pNewInfo) { return; } pNewInfo->m_action = CDNSRecordNodeEditInfo::add; CDNS_NS_RecordNode* pNSRecordNode = new CDNS_NS_RecordNode; if (!pNSRecordNode) { delete pNewInfo; return; } pNewInfo->CreateFromNewRecord(pNSRecordNode); // NS records are ALWAYS at the node CDNSDomainNode* pDomainNode = GetDomainNode(); CDNSRootData* pRootData = (CDNSRootData*)(GetHolder()->GetComponentData()->GetRootData()); ASSERT(pRootData != NULL); // set name and type flag pNewInfo->m_pRecordNode->SetRecordName(pDomainNode->GetDisplayName(), TRUE /*bAtTheNode */); pNewInfo->m_pRecordNode->SetFlagsDown(TN_FLAG_DNS_RECORD_FULL_NAME, !pRootData->IsAdvancedView()); // set TTL pNewInfo->m_pRecord->m_dwTtlSeconds = pDomainNode->GetDefaultTTL(); CDNS_NS_RecordDialog dlg(this,TRUE); dlg.m_pNSInfo = pNewInfo; if (IDOK == dlg.DoModalSheet(m_hWnd) && pNewInfo->m_action == CDNSRecordNodeEditInfo::add) { // // add to the list view (at the end) // int nCount = m_listCtrl.GetItemCount(); if (m_listCtrl.InsertNSRecordEntry(pNewInfo, nCount)) { // // create entry into the record info list // m_pCloneInfoList->AddTail(pNewInfo); // // set selection and button state on the last inserted // m_listCtrl.SetSelection(nCount); EnableEditorButtons(nCount); // // notify count change // OnCountChange(nCount+1); // added one } // // set dirty flag. It was either a new record or an update of an old one // SetDirty(TRUE); } else { delete pNewInfo->m_pRecordNode; pNewInfo->m_pRecordNode = NULL; delete pNewInfo->m_pRecord; pNewInfo->m_pRecord = NULL; delete pNewInfo; } } void CDNSNameServersPropertyPage::OnEditButton() { if (m_bReadOnly) { ASSERT(FALSE); // sould not happen return; } AFX_MANAGE_STATE(AfxGetStaticModuleState()); FIX_THREAD_STATE_MFC_BUG(); ASSERT(m_pCloneInfoList != NULL); // get the selection and bring up the dialog with the host name for editing int nSel = m_listCtrl.GetSelection(); ASSERT(nSel != -1); if (nSel == -1) return; // should not happen CDNSRecordNodeEditInfo* pNSInfo = (CDNSRecordNodeEditInfo*)m_listCtrl.GetItemData(nSel); ASSERT(pNSInfo != NULL); CDNS_NS_RecordDialog dlg(this, FALSE); ASSERT(pNSInfo->m_pRecord->GetType() == DNS_TYPE_NS); dlg.m_pNSInfo = pNSInfo; if (IDOK == dlg.DoModalSheet() && dlg.m_bDirty) { if (pNSInfo->m_action == CDNSRecordNodeEditInfo::add) { // this was a new entry that was edited after creation // but before committing the change ASSERT(!pNSInfo->m_bExisting); // update the listview m_listCtrl.UpdateNSRecordEntry(nSel); } else if (pNSInfo->m_action == CDNSRecordNodeEditInfo::edit) { // this was an existing entry that was changed ASSERT(pNSInfo->m_bExisting); // update the listview m_listCtrl.UpdateNSRecordEntry(nSel); } else { // there were no IP addresses, so mark the item for removal ASSERT(pNSInfo->m_action == CDNSRecordNodeEditInfo::remove); OnRemoveButton(); } // set dirty flag SetDirty(TRUE); } } void CDNSNameServersPropertyPage::OnRemoveButton() { if (m_bReadOnly) { ASSERT(FALSE); // sould not happen return; } int nSel = m_listCtrl.GetSelection(); if (nSel == -1) { ASSERT(FALSE); return; // should not happen } // // save focus to restore afterwards, if needed // CWnd* pWndFocusOld = CWnd::GetFocus(); ASSERT(pWndFocusOld != NULL); // // got a selection, delete from listview // CDNSRecordNodeEditInfo* pNSInfo = (CDNSRecordNodeEditInfo*)m_listCtrl.GetItemData(nSel); ASSERT(pNSInfo != NULL); m_listCtrl.DeleteItem(nSel); // // we lost the selection, set it again // int nNewCount = m_listCtrl.GetItemCount(); if (nNewCount == nSel) { // // last item in the list was deleted, move selection up // nSel--; } if (nSel != -1) { m_listCtrl.SetSelection(nSel); ASSERT(m_listCtrl.GetSelection() == nSel); } // // if there are no items left, need to disable the Edit and Remove buttons // if (nNewCount == 0) { CButton* pRemoveButton = GetRemoveButton(); // // need to shift focus before disabling buttons // CButton* pAddButton = GetAddButton(); pAddButton->SetFocus(); // avoid to have the OK button on the sheet to become the default button pRemoveButton->SendMessage(BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0)); pAddButton->SendMessage(BM_SETSTYLE, BS_DEFPUSHBUTTON, MAKELPARAM(/*redraw flag*/ TRUE, 0)); EnableEditorButtons(nSel); // this will disable both Edit and Remove } ASSERT(CWnd::GetFocus()); if (pNSInfo->m_action == CDNSRecordNodeEditInfo::add) { // // mark the item action as none since it was just added without being applied // pNSInfo->m_action = CDNSRecordNodeEditInfo::none; } else { // mark the item as deleted in the list of changes pNSInfo->m_action = CDNSRecordNodeEditInfo::remove; } // set dirty flag, removed a record SetDirty(TRUE); // notify count change OnCountChange(nNewCount); } BOOL CDNSNameServersPropertyPage::OnInitDialog() { CPropertyPageBase::OnInitDialog(); // controls initialization VERIFY(m_listCtrl.SubclassDlgItem(IDC_NS_LIST, this)); m_listCtrl.Initialize(); // load the data LoadUIData(); // set button state if (m_bReadOnly) { EnableButtons(FALSE); } else { // set selection to first item in the list, if there int nSel = (m_listCtrl.GetItemCount()>0) ? 0 : -1; EnableEditorButtons(nSel); } return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } void CDNSNameServersPropertyPage::LoadUIData() { m_pCloneInfoList->RemoveAllNodes(); ReadRecordNodesList(); // read from source FillNsListView(); } void CDNSNameServersPropertyPage::FillNsListView() { ASSERT(m_pCloneInfoList != NULL); m_listCtrl.DeleteAllItems(); // loop through the list of NS records and insert POSITION pos; int itemIndex = 0; for( pos = m_pCloneInfoList->GetHeadPosition(); pos != NULL; ) { CDNSRecordNodeEditInfo* pCurrentInfo = m_pCloneInfoList->GetNext(pos); if (m_listCtrl.InsertNSRecordEntry(pCurrentInfo, itemIndex)) { if (itemIndex == 0) m_listCtrl.SetSelection(0); itemIndex++; } } } void CDNSNameServersPropertyPage::EnableEditorButtons(int nListBoxSel) { if (m_bReadOnly) return; // must have item selected to remove or add GetRemoveButton()->EnableWindow(nListBoxSel != -1); GetEditButton()->EnableWindow(nListBoxSel != -1); } void CDNSNameServersPropertyPage::EnableButtons(BOOL bEnable) { GetAddButton()->EnableWindow(bEnable); GetRemoveButton()->EnableWindow(bEnable); GetEditButton()->EnableWindow(bEnable); } ////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // CDNSNameServersWizardPage BEGIN_MESSAGE_MAP(CDNSNameServersWizardPage, CPropertyPageBase) ON_BN_CLICKED(IDC_ADD_NS_BUTTON, OnAddButton) ON_BN_CLICKED(IDC_REMOVE_NS_BUTTON, OnRemoveButton) ON_BN_CLICKED(IDC_EDIT_NS_BUTTON, OnEditButton) ON_NOTIFY(LVN_ITEMCHANGED, IDC_NS_LIST, OnListItemChanged) END_MESSAGE_MAP() CDNSNameServersWizardPage::CDNSNameServersWizardPage(UINT nIDTemplate) : CPropertyPageBase(nIDTemplate) { InitWiz97(FALSE,IDS_SERVWIZ_ROOTHINTS_TITLE,IDS_SERVWIZ_ROOTHINTS_SUBTITLE); m_pDomainNode = NULL; m_pCloneInfoList = new CDNSRecordNodeEditInfoList; m_bReadOnly = FALSE; m_bMeaningfulTTL = TRUE; } CDNSNameServersWizardPage::~CDNSNameServersWizardPage() { delete m_pCloneInfoList; } BOOL CDNSNameServersWizardPage::WriteNSRecordNodesList() { ASSERT(!m_bReadOnly); ASSERT(m_pCloneInfoList != NULL); CDNSDomainNode* pDomainNode = GetDomainNode(); return pDomainNode->UpdateNSRecordNodesInfo(m_pCloneInfoList, GetHolder()->GetComponentData()); } BOOL CDNSNameServersWizardPage::OnWriteNSRecordNodesListError() { ASSERT(!m_bReadOnly); BOOL bSuccess = TRUE; // loop for each NS record POSITION pos; for( pos = m_pCloneInfoList->GetHeadPosition(); pos != NULL; ) { CDNSRecordNodeEditInfo* pCurrentInfo = m_pCloneInfoList->GetNext(pos); if (pCurrentInfo->m_dwErr != 0) { if (pCurrentInfo->m_dwErr == DNS_ERROR_RECORD_ALREADY_EXISTS) { // ignore if the NS record us already there pCurrentInfo->m_dwErr = 0; } else { bSuccess = FALSE; ASSERT(pCurrentInfo->m_pRecord->GetType() == DNS_TYPE_NS); CString szNSMsg; szNSMsg.Format(_T("Failure to write NS record <%s>"), (((CDNS_NS_Record*)pCurrentInfo->m_pRecord))->m_szNameNode); DNSErrorDialog(pCurrentInfo->m_dwErr,szNSMsg); } } // loop for each related A record CDNSRecordNodeEditInfoList* pARecordInfoList = pCurrentInfo->m_pEditInfoList; ASSERT(pARecordInfoList != NULL); POSITION posA; for( posA = pARecordInfoList->GetHeadPosition(); posA != NULL; ) { CDNSRecordNodeEditInfo* pARecordCurrentInfo = pARecordInfoList->GetNext(posA); if (pARecordCurrentInfo->m_dwErr != 0) { ASSERT(pARecordCurrentInfo->m_pRecord->GetType() == DNS_TYPE_A); CString szTemp; FormatIpAddress(szTemp, (((CDNS_A_Record*)pARecordCurrentInfo->m_pRecord))->m_ipAddress); CString szAMsg; szAMsg.Format(_T("Failure to write A record <%s>, IP Address %s"), (((CDNS_NS_Record*)pARecordCurrentInfo->m_pRecord))->m_szNameNode, (LPCWSTR)szTemp ); DNSErrorDialog(pCurrentInfo->m_dwErr,szAMsg); } } } return bSuccess; } BOOL CDNSNameServersWizardPage::OnApply() { if (m_bReadOnly) return TRUE; if (!IsDirty()) return TRUE; DNS_STATUS err = GetHolder()->NotifyConsole(this); if ( (err != 0) && OnWriteNSRecordNodesListError() ) { err = 0; // error was handled and it was not fatal } if (err == 0) { // refresh data from the zone/domain LoadUIData(); SetDirty(FALSE); } else { ::SetLastError(err); } return (err == 0); } BOOL CDNSNameServersWizardPage::OnPropertyChange(BOOL, long*) { if (m_bReadOnly) { ASSERT(FALSE); // sould not happen return FALSE; } ASSERT(m_pCloneInfoList != NULL); if (m_pCloneInfoList == NULL) return FALSE; BOOL bRes = WriteNSRecordNodesList(); if (!bRes) GetHolder()->SetError(static_cast(-1)); // something went wrong, error code will be per item return bRes; // update flag } void CDNSNameServersWizardPage::OnListItemChanged(NMHDR*, LRESULT*) { EnableEditorButtons(m_listCtrl.GetSelection()); } void CDNSNameServersWizardPage::OnAddButton() { if (m_bReadOnly) { ASSERT(FALSE); // sould not happen return; } AFX_MANAGE_STATE(AfxGetStaticModuleState()); FIX_THREAD_STATE_MFC_BUG(); ASSERT(m_pCloneInfoList != NULL); // provide subdialog to add record, for the time being can have just // dialog to enter the host name // create an item in the list of changes // TODO: first check if we can recycle some old stuff in the list // create new data CDNSRecordNodeEditInfo* pNewInfo = new CDNSRecordNodeEditInfo; if (!pNewInfo) { return; } pNewInfo->m_action = CDNSRecordNodeEditInfo::add; CDNS_NS_RecordNode* pNSRecordNode = new CDNS_NS_RecordNode; if (!pNSRecordNode) { delete pNewInfo; return; } pNewInfo->CreateFromNewRecord(pNSRecordNode); // NS records are ALWAYS at the node CDNSDomainNode* pDomainNode = GetDomainNode(); CDNSRootData* pRootData = (CDNSRootData*)(GetHolder()->GetComponentData()->GetRootData()); ASSERT(pRootData != NULL); // set name and type flag pNewInfo->m_pRecordNode->SetRecordName(pDomainNode->GetDisplayName(), TRUE /*bAtTheNode */); pNewInfo->m_pRecordNode->SetFlagsDown(TN_FLAG_DNS_RECORD_FULL_NAME, !pRootData->IsAdvancedView()); // set TTL pNewInfo->m_pRecord->m_dwTtlSeconds = pDomainNode->GetDefaultTTL(); CDNS_NS_RecordDialog dlg(this,TRUE); dlg.m_pNSInfo = pNewInfo; if (IDOK == dlg.DoModalSheet() && pNewInfo->m_action == CDNSRecordNodeEditInfo::add) { // // add to the list view (at the end) // int nCount = m_listCtrl.GetItemCount(); if (m_listCtrl.InsertNSRecordEntry(pNewInfo, nCount)) { // // create entry into the record info list // m_pCloneInfoList->AddTail(pNewInfo); // // set selection and button state on the last inserted // m_listCtrl.SetSelection(nCount); EnableEditorButtons(nCount); // // notify count change // OnCountChange(nCount+1); // added one } // // set dirty flag, it is a new record // SetDirty(TRUE); } else { delete pNewInfo->m_pRecordNode; pNewInfo->m_pRecordNode = NULL; delete pNewInfo->m_pRecord; pNewInfo->m_pRecord = NULL; delete pNewInfo; } } void CDNSNameServersWizardPage::OnEditButton() { if (m_bReadOnly) { ASSERT(FALSE); // sould not happen return; } AFX_MANAGE_STATE(AfxGetStaticModuleState()); FIX_THREAD_STATE_MFC_BUG(); ASSERT(m_pCloneInfoList != NULL); // get the selection and bring up the dialog with the host name for editing int nSel = m_listCtrl.GetSelection(); ASSERT(nSel != -1); if (nSel == -1) return; // should not happen CDNSRecordNodeEditInfo* pNSInfo = (CDNSRecordNodeEditInfo*)m_listCtrl.GetItemData(nSel); ASSERT(pNSInfo != NULL); CDNS_NS_RecordDialog dlg(this, FALSE); ASSERT(pNSInfo->m_pRecord->GetType() == DNS_TYPE_NS); dlg.m_pNSInfo = pNSInfo; if (IDOK == dlg.DoModalSheet() && dlg.m_bDirty) { if (pNSInfo->m_action == CDNSRecordNodeEditInfo::add) { // this was a new entry that was edited after creation // but before committing the change ASSERT(!pNSInfo->m_bExisting); // update the listview m_listCtrl.UpdateNSRecordEntry(nSel); } else if (pNSInfo->m_action == CDNSRecordNodeEditInfo::edit) { // this was an existing entry that was changed ASSERT(pNSInfo->m_bExisting); // update the listview m_listCtrl.UpdateNSRecordEntry(nSel); } else { // there were no IP addresses, so mark the item for removal ASSERT(pNSInfo->m_action == CDNSRecordNodeEditInfo::remove); OnRemoveButton(); } // set dirty flag SetDirty(TRUE); } } void CDNSNameServersWizardPage::OnRemoveButton() { if (m_bReadOnly) { ASSERT(FALSE); // sould not happen return; } int nSel = m_listCtrl.GetSelection(); if (nSel == -1) { ASSERT(FALSE); return; // should not happen } // // save focus to restore afterwards, if needed // CWnd* pWndFocusOld = CWnd::GetFocus(); ASSERT(pWndFocusOld != NULL); // // got a selection, delete from listview // CDNSRecordNodeEditInfo* pNSInfo = (CDNSRecordNodeEditInfo*)m_listCtrl.GetItemData(nSel); ASSERT(pNSInfo != NULL); m_listCtrl.DeleteItem(nSel); // // we lost the selection, set it again // int nNewCount = m_listCtrl.GetItemCount(); if (nNewCount == nSel) { // // last item in the list was deleted, move selection up // nSel--; } if (nSel != -1) { m_listCtrl.SetSelection(nSel); ASSERT(m_listCtrl.GetSelection() == nSel); } // // if there are no items left, need to disable the Edit and Remove buttons // if (nNewCount == 0) { CWnd* pCurrentFocusCtrl = CWnd::GetFocus(); CButton* pRemoveButton = GetRemoveButton(); CButton* pEditButton = GetEditButton(); // // need to shift focus before disabling buttons // if ( (pCurrentFocusCtrl == pRemoveButton) || (pCurrentFocusCtrl == pEditButton) ) { CButton* pAddButton = GetAddButton(); pAddButton->SetFocus(); // avoid to have the OK button on the sheet to become the default button pAddButton->SendMessage(BM_SETSTYLE, BS_DEFPUSHBUTTON, MAKELPARAM(/*redraw flag*/ TRUE, 0)); } EnableEditorButtons(nSel); // this will disable both Edit and Remove } ASSERT(CWnd::GetFocus()); if (pNSInfo->m_action == CDNSRecordNodeEditInfo::add) { // // mark the item action as none since the item hasn't been added yet anyways // pNSInfo->m_action = CDNSRecordNodeEditInfo::none; } else { // mark the item as deleted in the list of changes pNSInfo->m_action = CDNSRecordNodeEditInfo::remove; } // set dirty flag, removed a record SetDirty(TRUE); // notify count change OnCountChange(nNewCount); } BOOL CDNSNameServersWizardPage::OnInitDialog() { CPropertyPageBase::OnInitDialog(); // controls initialization VERIFY(m_listCtrl.SubclassDlgItem(IDC_NS_LIST, this)); m_listCtrl.Initialize(); // load the data LoadUIData(); // set button state if (m_bReadOnly) { EnableButtons(FALSE); } else { // set selection to first item in the list, if there int nSel = (m_listCtrl.GetItemCount()>0) ? 0 : -1; EnableEditorButtons(nSel); } return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } void CDNSNameServersWizardPage::LoadUIData() { m_pCloneInfoList->RemoveAllNodes(); ReadRecordNodesList(); // read from source FillNsListView(); } void CDNSNameServersWizardPage::FillNsListView() { ASSERT(m_pCloneInfoList != NULL); m_listCtrl.DeleteAllItems(); // loop through the list of NS records and insert POSITION pos; int itemIndex = 0; for( pos = m_pCloneInfoList->GetHeadPosition(); pos != NULL; ) { CDNSRecordNodeEditInfo* pCurrentInfo = m_pCloneInfoList->GetNext(pos); if (m_listCtrl.InsertNSRecordEntry(pCurrentInfo, itemIndex)) { if (itemIndex == 0) m_listCtrl.SetSelection(0); itemIndex++; } } } void CDNSNameServersWizardPage::EnableEditorButtons(int nListBoxSel) { if (m_bReadOnly) return; // must have item selected to remove or add GetRemoveButton()->EnableWindow(nListBoxSel != -1); GetEditButton()->EnableWindow(nListBoxSel != -1); } void CDNSNameServersWizardPage::EnableButtons(BOOL bEnable) { GetAddButton()->EnableWindow(bEnable); GetRemoveButton()->EnableWindow(bEnable); GetEditButton()->EnableWindow(bEnable); }