windows-nt/Source/XPSP1/NT/base/cluster/admin/cluadmex/netname.cpp

741 lines
24 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/////////////////////////////////////////////////////////////////////////////
//
// 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()