///////////////////////////////////////////////////////////////////////////// // // Copyright (c) 1996-1999 Microsoft Corporation // // Module Name: // NetName.cpp // // Abstract: // Implementation of the CNetworkNameParamsPage class. // // Author: // David Potter (davidp) June 28, 1996 // // Revision History: // // Notes: // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "CluAdmX.h" #include "ExtObj.h" #include "NetName.h" #include "DDxDDv.h" #include "ExcOper.h" #include "ClusName.h" #include "HelpData.h" // for g_rghelpmap* #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CNetworkNameParamsPage property page ///////////////////////////////////////////////////////////////////////////// IMPLEMENT_DYNCREATE(CNetworkNameParamsPage, CBasePropertyPage) ///////////////////////////////////////////////////////////////////////////// // Message Maps BEGIN_MESSAGE_MAP(CNetworkNameParamsPage, CBasePropertyPage) //{{AFX_MSG_MAP(CNetworkNameParamsPage) ON_EN_CHANGE(IDC_PP_NETNAME_PARAMS_NAME, OnChangeName) ON_BN_CLICKED(IDC_PP_NETNAME_PARAMS_RENAME, OnRename) ON_BN_CLICKED(IDC_PP_NETNAME_PARAMS_CHECKBOX_DNS, OnRequireDNS) ON_BN_CLICKED(IDC_PP_NETNAME_PARAMS_CHECKBOX_KERBEROS, CBasePropertyPage::OnChangeCtrl) //}}AFX_MSG_MAP // TODO: Modify the following lines to represent the data displayed on this page. END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// //++ // // CNetworkNameParamsPage::CNetworkNameParamsPage // // Routine Description: // Default constructor. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// CNetworkNameParamsPage::CNetworkNameParamsPage(void) : CBasePropertyPage(g_aHelpIDs_IDD_PP_NETNAME_PARAMETERS, g_aHelpIDs_IDD_WIZ_NETNAME_PARAMETERS) { // TODO: Modify the following lines to represent the data displayed on this page. //{{AFX_DATA_INIT(CNetworkNameParamsPage) m_strName = _T(""); m_strPrevName = _T(""); m_nRequireDNS = BST_UNCHECKED; m_nRequireKerberos = BST_UNCHECKED; m_dwNetBIOSStatus = 0; m_dwDNSStatus = 0; m_dwKerberosStatus = 0; //}}AFX_DATA_INIT // Setup the property array. { m_rgProps[epropName].Set(REGPARAM_NETNAME_NAME, m_strName, m_strPrevName); m_rgProps[epropRequireDNS].Set(REGPARAM_NETNAME_REQUIRE_DNS, m_nRequireDNS, m_nPrevRequireDNS); m_rgProps[epropRequireKerberos].Set(REGPARAM_NETNAME_REQUIRE_KERBEROS, m_nRequireKerberos, m_nPrevRequireKerberos); m_rgProps[epropStatusNetBIOS].Set(REGPARAM_NETNAME_STATUS_NETBIOS, m_dwNetBIOSStatus, m_dwPrevNetBIOSStatus); m_rgProps[epropStatusDNS].Set(REGPARAM_NETNAME_STATUS_DNS, m_dwDNSStatus, m_dwPrevDNSStatus); m_rgProps[epropStatusKerberos].Set(REGPARAM_NETNAME_STATUS_KERBEROS, m_dwKerberosStatus, m_dwPrevKerberosStatus); } // Setup the property array m_dwFlags = 0; m_iddPropertyPage = IDD_PP_NETNAME_PARAMETERS; m_iddWizardPage = IDD_WIZ_NETNAME_PARAMETERS; } //*** CNetworkNameParamsPage::CNetworkNameParamsPage() ///////////////////////////////////////////////////////////////////////////// //++ // // CNetworkNameParamsPage::HrInit // // Routine Description: // Initialize the page. // // Arguments: // peo [IN OUT] Pointer to the extension object. // // Return Value: // S_OK Page initialized successfully. // hr Page failed to initialize. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CNetworkNameParamsPage::HrInit(IN OUT CExtObject * peo) { HRESULT hr; CWaitCursor wc; DWORD sc; DWORD cbReturned; // Call the base class method. // This populates the m_rgProps struct. hr = CBasePropertyPage::HrInit(peo); if (!FAILED(hr)) { m_strPrevName = m_strName; // Read the flags for this resource. sc = ClusterResourceControl( Peo()->PrdResData()->m_hresource, NULL, CLUSCTL_RESOURCE_GET_FLAGS, NULL, NULL, &m_dwFlags, sizeof(m_dwFlags), &cbReturned ); if (sc != ERROR_SUCCESS) { CNTException nte(sc, NULL, NULL, FALSE /*bAutoDelete*/); nte.ReportError(); nte.Delete(); } // if: error retrieving data else { ASSERT(cbReturned == sizeof(m_dwFlags)); } // else: data retrieved successfully } // if: base class init was successful return hr; } //*** CNetworkNameParamsPage::HrInit() ///////////////////////////////////////////////////////////////////////////// //++ // // CNetworkNameParamsPage::DoDataExchange // // Routine Description: // Do data exchange between the dialog and the class. // // Arguments: // pDX [IN OUT] Data exchange object // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CNetworkNameParamsPage::DoDataExchange(CDataExchange * pDX) { DWORD scError; BOOL bError; if (!pDX->m_bSaveAndValidate || !BSaved()) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CWaitCursor wc; CString strNetName; // TODO: Modify the following lines to represent the data displayed on this page. //{{AFX_DATA_MAP(CNetworkNameParamsPage) DDX_Control(pDX, IDC_PP_NETNAME_PARAMS_NAME_LABEL, m_staticName); DDX_Control(pDX, IDC_PP_NETNAME_PARAMS_RENAME, m_pbRename); DDX_Control(pDX, IDC_PP_NETNAME_PARAMS_CORE_TEXT, m_staticCore); DDX_Control(pDX, IDC_PP_NETNAME_PARAMS_NAME, m_editName); DDX_Control(pDX, IDC_PP_NETNAME_PARAMS_CHECKBOX_DNS, m_cbRequireDNS); DDX_Control(pDX, IDC_PP_NETNAME_PARAMS_CHECKBOX_KERBEROS, m_cbRequireKerberos); DDX_Control(pDX, IDC_PP_NETNAME_PARAMS_STATUS_NETBIOS, m_editNetBIOSStatus); DDX_Control(pDX, IDC_PP_NETNAME_PARAMS_STATUS_DNS, m_editDNSStatus); DDX_Control(pDX, IDC_PP_NETNAME_PARAMS_STATUS_KERBEROS, m_editKerberosStatus); // // Get the status of the checkboxes. // DDX_Check(pDX, IDC_PP_NETNAME_PARAMS_CHECKBOX_DNS, m_nRequireDNS); DDX_Check(pDX, IDC_PP_NETNAME_PARAMS_CHECKBOX_KERBEROS, m_nRequireKerberos); //}}AFX_DATA_MAP bError = FALSE; if (pDX->m_bSaveAndValidate && !BBackPressed()) { CLRTL_NAME_STATUS cnStatus; CString strMsg; UINT idsError; // // Get the name from the control into a temp variable // DDX_Text(pDX, IDC_PP_NETNAME_PARAMS_NAME, strNetName); DDV_RequiredText(pDX, IDC_PP_NETNAME_PARAMS_NAME, IDC_PP_NETNAME_PARAMS_NAME_LABEL, strNetName); DDV_MaxChars(pDX, strNetName, MAX_CLUSTERNAME_LENGTH); if( m_nRequireDNS == BST_UNCHECKED ) { m_nRequireKerberos = BST_UNCHECKED; } if ( (m_strName != strNetName ) && (! ClRtlIsNetNameValid(strNetName, &cnStatus, FALSE /*CheckIfExists*/)) ) { switch (cnStatus) { case NetNameTooLong: idsError = IDS_INVALID_NETWORK_NAME_TOO_LONG; break; case NetNameInvalidChars: idsError = IDS_INVALID_NETWORK_NAME_INVALID_CHARS; break; case NetNameInUse: idsError = IDS_INVALID_NETWORK_NAME_IN_USE; break; case NetNameDNSNonRFCChars: idsError = IDS_INVALID_NETWORK_NAME_INVALID_DNS_CHARS; break; case NetNameSystemError: { scError = GetLastError(); CNTException nte(scError, IDS_ERROR_VALIDATING_NETWORK_NAME, (LPCWSTR) strNetName); nte.ReportError(); pDX->Fail(); } default: idsError = IDS_INVALID_NETWORK_NAME; break; } // switch: cnStatus strMsg.LoadString(idsError); if ( idsError == IDS_INVALID_NETWORK_NAME_INVALID_DNS_CHARS ) { int id = AfxMessageBox(strMsg, MB_YESNO | MB_DEFBUTTON2 | MB_ICONEXCLAMATION ); if ( id == IDNO ) { strMsg.Empty(); pDX->Fail(); bError = TRUE; } } else { AfxMessageBox(strMsg, MB_ICONEXCLAMATION); strMsg.Empty(); // exception prep pDX->Fail(); bError = TRUE; } } // if: ((m_strName != strNetName) && (! ClRtlIsNetNameValid(strNetName, &cnStatus, FALSE)) ) // // Everything was validated - apply all of the changes. // if( FALSE == bError ) { m_strName = strNetName; } }// if: (pDX->m_bSaveAndValidate && !BBackPressed()) else // if: populating controls { CString m_strStatus; // // Populate the controls with data from the member variables. // DDX_Text(pDX, IDC_PP_NETNAME_PARAMS_NAME, m_strName); m_strStatus.Format( _T("%d (0x%08x)"), m_dwNetBIOSStatus, m_dwNetBIOSStatus ); DDX_Text( pDX, IDC_PP_NETNAME_PARAMS_STATUS_NETBIOS, m_strStatus ); m_strStatus.Format( _T("%d (0x%08x)"), m_dwDNSStatus, m_dwDNSStatus ); DDX_Text( pDX, IDC_PP_NETNAME_PARAMS_STATUS_DNS, m_strStatus ); m_strStatus.Format( _T("%d (0x%08x)"), m_dwKerberosStatus, m_dwKerberosStatus ); DDX_Text( pDX, IDC_PP_NETNAME_PARAMS_STATUS_KERBEROS, m_strStatus ); } } // if: not saving or haven't saved yet CBasePropertyPage::DoDataExchange(pDX); } //*** CNetworkNameParamsPage::DoDataExchange() ///////////////////////////////////////////////////////////////////////////// //++ // // CNetworkNameParamsPage::OnInitDialog // // Routine Description: // Handler for the WM_INITDIALOG message. // // Arguments: // None. // // Return Value: // TRUE We need the focus to be set for us. // FALSE We already set the focus to the proper control. // //-- ///////////////////////////////////////////////////////////////////////////// BOOL CNetworkNameParamsPage::OnInitDialog(void) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CBasePropertyPage::OnInitDialog(); // Set limits on the edit controls. m_editName.SetLimitText(MAX_CLUSTERNAME_LENGTH); // Set up the checkboxes. m_cbRequireDNS.EnableWindow( TRUE ); m_cbRequireKerberos.EnableWindow( m_nRequireDNS != 0 ); // // Make sure we're not dealing with a non-Whistler Cluster. If we are then // disable both checkboxes (the props didn't exist back then - don't set them). // CheckForDownlevelCluster(); // If this is a core resource, set the name control to be read-only // and enable the Core Resource static control. if (BCore()) { WINDOWPLACEMENT wpLabel; WINDOWPLACEMENT wpName; WINDOWPLACEMENT wpButton; WINDOWPLACEMENT wpText; WINDOWPLACEMENT wpCheckDNS; WINDOWPLACEMENT wpCheckKerberos; CRect rectName; CRect rectText; RECT * prect; LONG nHeight; // Get the placement of the controls. m_editName.GetWindowPlacement(&wpName); m_staticCore.GetWindowPlacement(&wpText); m_staticName.GetWindowPlacement(&wpLabel); m_pbRename.GetWindowPlacement(&wpButton); m_cbRequireDNS.GetWindowPlacement(&wpCheckDNS); m_cbRequireKerberos.GetWindowPlacement(&wpCheckKerberos); // Get the positions of the edit control and text control. rectName = wpName.rcNormalPosition; rectText = wpText.rcNormalPosition; // Move the name control to where the text control is. prect = &wpName.rcNormalPosition; *prect = rectText; nHeight = rectName.bottom - rectName.top; prect->left = rectName.left; prect->right = rectName.right; prect->bottom = prect->top + nHeight; m_editName.SetWindowPlacement(&wpName); // Move the text control to where the name control was. prect = &wpText.rcNormalPosition; *prect = rectName; nHeight = rectText.bottom - rectText.top; prect->left = rectText.left; prect->right = rectText.right; prect->bottom = prect->top + nHeight; m_staticCore.SetWindowPlacement(&wpText); // Move the name label control to be next to the name edit control. prect = &wpLabel.rcNormalPosition; nHeight = prect->bottom - prect->top; prect->top = wpName.rcNormalPosition.top + 2; prect->bottom = prect->top + nHeight; m_staticName.SetWindowPlacement(&wpLabel); // Move the button control to be next to the name edit control. prect = &wpButton.rcNormalPosition; nHeight = prect->bottom - prect->top; prect->top = wpName.rcNormalPosition.top; prect->bottom = prect->top + nHeight; m_pbRename.SetWindowPlacement(&wpButton); // Move the Require DNS checkbox down. prect = &wpCheckDNS.rcNormalPosition; nHeight = prect->bottom - prect->top; // Move us down by the height of the now displayed static text. prect->top = prect->top + (wpText.rcNormalPosition.bottom - wpText.rcNormalPosition.top); prect->top = prect->top + rectText.top - rectName.bottom; prect->bottom = prect->top + nHeight; m_cbRequireDNS.SetWindowPlacement(&wpCheckDNS); // Move the Require Kerberos checkbox down. prect = &wpCheckKerberos.rcNormalPosition; nHeight = prect->bottom - prect->top; // Move us down by the height of the now displayed static text. prect->top = prect->top + (wpText.rcNormalPosition.bottom - wpText.rcNormalPosition.top); prect->top = prect->top + rectText.top - rectName.bottom; prect->bottom = prect->top + nHeight; m_cbRequireKerberos.SetWindowPlacement(&wpCheckKerberos); // Prevent the name edit control from being editable and // Show the text and the button. m_editName.SetReadOnly(TRUE); m_staticCore.ShowWindow(SW_SHOW); m_pbRename.ShowWindow(SW_SHOW); m_pbRename.EnableWindow( TRUE ); } else // if: core resource (show static text & move other controls down) { m_editName.SetReadOnly(FALSE); m_staticCore.ShowWindow(SW_HIDE); m_pbRename.ShowWindow(SW_HIDE); m_pbRename.EnableWindow( FALSE ); } // else: not core resource return TRUE; // return TRUE unless you set the focus to a control // EXCEPTION: OCX Property Pages should return FALSE } //*** CNetworkNameParamsPage::OnInitDialog() ///////////////////////////////////////////////////////////////////////////// //++ // // CNetworkNameParamsPage::OnSetActive // // Routine Description: // Handler for the PSN_SETACTIVE message. // // Arguments: // None. // // Return Value: // TRUE Page successfully initialized. // FALSE Page not initialized. // //-- ///////////////////////////////////////////////////////////////////////////// BOOL CNetworkNameParamsPage::OnSetActive(void) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); // Enable/disable the Next/Finish button. if (BWizard()) { if (m_strName.GetLength() == 0) EnableNext(FALSE); else EnableNext(TRUE); } // if: enable/disable the Next button return CBasePropertyPage::OnSetActive(); } //*** CNetworkNameParamsPage::OnSetActive() ///////////////////////////////////////////////////////////////////////////// //++ // // CNetworkNameParamsPage::BApplyChanges // // Routine Description: // Apply changes made on the page. // // Arguments: // None. // // Return Value: // TRUE Page successfully applied. // FALSE Error applying page. // //-- ///////////////////////////////////////////////////////////////////////////// BOOL CNetworkNameParamsPage::BApplyChanges(void) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CWaitCursor wc; BOOL bSuccess = TRUE; // Save data. if (BCore()) { DWORD scStatus; // // If this is the core Network Name (Cluster Name) we should set the name via // the SetClusterName API. If that succeeds then we'll set the other properties. // if ( m_strName != m_strPrevName ) { scStatus = SetClusterName(Hcluster(), m_strName); if (scStatus != ERROR_SUCCESS) { if (scStatus == ERROR_RESOURCE_PROPERTIES_STORED) { TCHAR szError[1024]; CNTException nte(scStatus, NULL, m_strName, NULL, FALSE /*bAutoDelete*/); nte.FormatErrorMessage(szError, sizeof(szError) / sizeof(TCHAR), NULL, FALSE /*bIncludeID*/); nte.Delete(); AfxMessageBox(szError); } // if: properties stored else { CNTException nte(scStatus, IDS_ERROR_SETTING_CLUSTER_NAME, m_strName, NULL, FALSE /*bAutoDelete*/); nte.ReportError(); nte.Delete(); bSuccess = FALSE; } // else: other error occurred } // if: error setting the cluster name else { // // By setting the prev value equal to the current value the BSetPrivateProps // function will skip this prop when constructing it's list of props to set. // m_strPrevName = m_strName; } } // if: name has changed // // Now set the other private properties. // if ( bSuccess == TRUE ) { bSuccess = BSetPrivateProps(); } } // if: core resource else { bSuccess = BSetPrivateProps(); } // // If we applied the changes then clear the require kerberos check if // the checkbox was disabled. Don't make this dependent upon the require // DNS checkbox state as the dependency may change in the future. // if( ( bSuccess == TRUE ) && ( m_cbRequireKerberos.IsWindowEnabled() == FALSE ) ) { m_cbRequireKerberos.SetCheck( BST_UNCHECKED ); } return bSuccess; } //*** CNetworkNameParamsPage::BApplyChanges() ///////////////////////////////////////////////////////////////////////////// //++ // // CNetworkNameParamsPage::OnChangeName // // Routine Description: // Handler for the EN_CHANGE message on the Name edit control. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CNetworkNameParamsPage::OnChangeName(void) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); OnChangeCtrl(); if (BWizard()) { if (m_editName.GetWindowTextLength() == 0) { EnableNext(FALSE); } else { EnableNext(TRUE); } } // if: in a wizard } //*** CNetworkNameParamsPage::OnChangeName() ///////////////////////////////////////////////////////////////////////////// //++ // // CNetworkNameParamsPage::OnRename // // Routine Description: // Handler for the BN_CLICKED message on the Rename push button. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CNetworkNameParamsPage::OnRename(void) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); CChangeClusterNameDlg dlg(this); ASSERT(BCore()); dlg.m_strClusName = m_strName; if (dlg.DoModal() == IDOK) { if (m_strName != dlg.m_strClusName) { OnChangeCtrl(); m_strName = dlg.m_strClusName; UpdateData(FALSE /*bSaveAndValidate*/); } // if: the name changed } // if: user accepted change } //*** CNetworkNameParamsPage::OnRename() ///////////////////////////////////////////////////////////////////////////// //++ // // CNetworkNameParamsPage::OnRequireDNS // // Routine Description: // Handler for the BN_CLICKED message on the RequireDNS checkbox. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CNetworkNameParamsPage::OnRequireDNS(void) { int nChecked; nChecked = m_cbRequireDNS.GetCheck(); m_cbRequireKerberos.EnableWindow( nChecked == BST_CHECKED ); SetModified( TRUE ); } //*** CNetworkNameParamsPage::OnRequireDNS() ///////////////////////////////////////////////////////////////////////////// //++ // // CNetworkNameParamsPage::CheckForDownlevelCluster // // Routine Description: // If determine whether the cluster we're connected to is pre-Whistler. // If it is then disable the buttons. If an error occurs display a // message box. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CNetworkNameParamsPage::CheckForDownlevelCluster(void) { CLUSTERVERSIONINFO cvi; DWORD sc; DWORD scErr; DWORD cchName; // // Determine whether we're talking to a pre-Whistler cluster. // If so, disable the Require DNS & Kerberos checkboxes. // memset( &cvi, 0, sizeof( cvi ) ); cvi.dwVersionInfoSize = sizeof( cvi ); cchName = 0; sc = GetClusterInformation( Hcluster(), NULL, &cchName, &cvi ); scErr = GetLastError(); if( ERROR_SUCCESS != sc ) { // // API failed. Pop up a message box. // TCHAR szError[1024]; CNTException nte(scErr, IDS_ERROR_GETTING_CLUSTER_INFORMATION, m_strName, NULL, FALSE /*bAutoDelete*/); nte.FormatErrorMessage(szError, sizeof(szError) / sizeof(TCHAR), NULL, FALSE /*bIncludeID*/); nte.ReportError(); nte.Delete(); // // We can't be sure that we're on a down-level cluster (chances are that we're not), // so leave the checkboxes enabled - the worst that will happen is that some extra props // will be added that are ignored by the resource. // } else { if( CLUSTER_GET_MAJOR_VERSION( cvi.dwClusterHighestVersion ) < NT51_MAJOR_VERSION ) { // // We're on a pre-Whistler Cluster where the DNS & Kerberos setting make no // sense. So, disable the checkboxes to indicate that the settings // are unavailable. // m_cbRequireKerberos.EnableWindow( FALSE ); m_cbRequireDNS.EnableWindow( FALSE ); } } } //*** CNetworkNameParamsPage::CheckForDownlevelCluster()