2141 lines
60 KiB
C++
2141 lines
60 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1996-2000 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
// ClusProp.cpp
|
|
//
|
|
// Abstract:
|
|
// Implementation of the cluster property sheet and pages.
|
|
//
|
|
// Author:
|
|
// David Potter (davidp) May 13, 1996
|
|
//
|
|
// Revision History:
|
|
//
|
|
// Notes:
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "ClusProp.h"
|
|
#include "Cluster.h"
|
|
#include "Res.h"
|
|
#include "ClusDoc.h"
|
|
#include "ClusItem.inl"
|
|
//#include "EditAcl.h"
|
|
#include "DDxDDv.h"
|
|
#include "ExcOper.h"
|
|
#include "HelpData.h" // g_rghelpmapClusterGeneral
|
|
#include "WaitDlg.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CClusterPropSheet
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
IMPLEMENT_DYNAMIC(CClusterPropSheet, CBasePropertySheet)
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Message Maps
|
|
|
|
BEGIN_MESSAGE_MAP(CClusterPropSheet, CBasePropertySheet)
|
|
//{{AFX_MSG_MAP(CClusterPropSheet)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterPropSheet::CClusterPropSheet
|
|
//
|
|
// Routine Description:
|
|
// Constructor.
|
|
//
|
|
// Arguments:
|
|
// pci [IN OUT] Cluster item whose properties are to be displayed.
|
|
// pParentWnd [IN OUT] Parent window for this property sheet.
|
|
// iSelectPage [IN] Page to show first.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CClusterPropSheet::CClusterPropSheet(
|
|
IN OUT CWnd * pParentWnd,
|
|
IN UINT iSelectPage
|
|
)
|
|
: CBasePropertySheet(pParentWnd, iSelectPage)
|
|
{
|
|
m_rgpages[0] = &PageGeneral();
|
|
m_rgpages[1] = &PageQuorum();
|
|
m_rgpages[2] = &PageNetPriority();
|
|
|
|
} //*** CClusterPropSheet::CClusterPropSheet()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterPropSheet::BInit
|
|
//
|
|
// Routine Description:
|
|
// Initialize the property sheet.
|
|
//
|
|
// Arguments:
|
|
// pci [IN OUT] Cluster item whose properties are to be displayed.
|
|
// iimgIcon [IN] Index in the large image list for the image to use
|
|
// as the icon on each page.
|
|
//
|
|
// Return Value:
|
|
// TRUE Property sheet initialized successfully.
|
|
// FALSE Error initializing property sheet.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CClusterPropSheet::BInit(
|
|
IN OUT CClusterItem * pci,
|
|
IN IIMG iimgIcon
|
|
)
|
|
{
|
|
// Call the base class method.
|
|
if (!CBasePropertySheet::BInit(pci, iimgIcon))
|
|
return FALSE;
|
|
|
|
// Set the read-only flag if the handles are invalid.
|
|
if ((PciCluster()->Hcluster() == NULL)
|
|
|| (PciCluster()->Hkey() == NULL))
|
|
m_bReadOnly = TRUE;
|
|
|
|
return TRUE;
|
|
|
|
} //*** CClusterPropSheet::BInit()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterPropSheet::Ppages
|
|
//
|
|
// Routine Description:
|
|
// Returns the array of pages to add to the property sheet.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// Page array.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CBasePropertyPage ** CClusterPropSheet::Ppages(void)
|
|
{
|
|
return m_rgpages;
|
|
|
|
} //*** CClusterPropSheet::Ppages()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterPropSheet::Cpages
|
|
//
|
|
// Routine Description:
|
|
// Returns the count of pages in the array.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// Count of pages in the array.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
int CClusterPropSheet::Cpages(void)
|
|
{
|
|
return sizeof(m_rgpages) / sizeof(CBasePropertyPage *);
|
|
|
|
} //*** CClusterPropSheet::Cpages()
|
|
|
|
|
|
//*************************************************************************//
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CClusterGeneralPage property page
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
IMPLEMENT_DYNCREATE(CClusterGeneralPage, CBasePropertyPage)
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Message Maps
|
|
|
|
BEGIN_MESSAGE_MAP(CClusterGeneralPage, CBasePropertyPage)
|
|
//{{AFX_MSG_MAP(CClusterGeneralPage)
|
|
// ON_BN_CLICKED(IDC_PP_CLUS_PERMISSIONS, OnBnClickedPermissions)
|
|
//}}AFX_MSG_MAP
|
|
ON_EN_CHANGE(IDC_PP_CLUS_NAME, CBasePropertyPage::OnChangeCtrl)
|
|
ON_EN_CHANGE(IDC_PP_CLUS_DESC, CBasePropertyPage::OnChangeCtrl)
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterGeneralPage::CClusterGeneralPage
|
|
//
|
|
// Routine Description:
|
|
// Constructor.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CClusterGeneralPage::CClusterGeneralPage(void)
|
|
: CBasePropertyPage(IDD, g_aHelpIDs_IDD_PP_CLUSTER_GENERAL)
|
|
{
|
|
//{{AFX_DATA_INIT(CClusterGeneralPage)
|
|
m_strName = _T("");
|
|
m_strDesc = _T("");
|
|
m_strVendorID = _T("");
|
|
m_strVersion = _T("");
|
|
//}}AFX_DATA_INIT
|
|
|
|
// m_bSecurityChanged = FALSE;
|
|
|
|
} //*** CClusterGeneralPage::CClusterGeneralPage()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterGeneralPage::~CClusterGeneralPage
|
|
//
|
|
// Routine Description:
|
|
// Destructor.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CClusterGeneralPage::~CClusterGeneralPage(void)
|
|
{
|
|
} //*** CClusterGeneralPage::~CClusterGeneralPage()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterGeneralPage::BInit
|
|
//
|
|
// Routine Description:
|
|
// Initialize the page.
|
|
//
|
|
// Arguments:
|
|
// psht [IN OUT] Property sheet to which this page belongs.
|
|
//
|
|
// Return Value:
|
|
// TRUE Page initialized successfully.
|
|
// FALSE Page failed to initialize.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CClusterGeneralPage::BInit(IN OUT CBaseSheet * psht)
|
|
{
|
|
BOOL bSuccess;
|
|
CWaitCursor wc;
|
|
|
|
ASSERT_KINDOF(CClusterPropSheet, psht);
|
|
|
|
bSuccess = CBasePropertyPage::BInit(psht);
|
|
|
|
try
|
|
{
|
|
m_strName = PciCluster()->StrName();
|
|
m_strDesc = PciCluster()->StrDescription();
|
|
m_strVendorID = PciCluster()->Cvi().szVendorId;
|
|
m_strVersion.Format( IDS_OP_VERSION_NUMBER_FORMAT, PciCluster()->Cvi().MajorVersion );
|
|
} // try
|
|
catch (CException * pe)
|
|
{
|
|
pe->ReportError();
|
|
pe->Delete();
|
|
m_bReadOnly = TRUE;
|
|
} // catch: CException
|
|
|
|
return bSuccess;
|
|
|
|
} //*** CClusterGeneralPage::BInit()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterGeneralPage::DoDataExchange
|
|
//
|
|
// Routine Description:
|
|
// Do data exchange between the dialog and the class.
|
|
//
|
|
// Arguments:
|
|
// pDX [IN OUT] Data exchange object
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterGeneralPage::DoDataExchange(CDataExchange * pDX)
|
|
{
|
|
CWaitCursor wc;
|
|
CString strClusName;
|
|
|
|
CBasePropertyPage::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CClusterGeneralPage)
|
|
DDX_Control(pDX, IDC_PP_CLUS_NAME, m_editName);
|
|
DDX_Control(pDX, IDC_PP_CLUS_DESC, m_editDesc);
|
|
DDX_Text(pDX, IDC_PP_CLUS_DESC, m_strDesc);
|
|
DDX_Text(pDX, IDC_PP_CLUS_VENDOR_ID, m_strVendorID);
|
|
DDX_Text(pDX, IDC_PP_CLUS_VERSION, m_strVersion);
|
|
//}}AFX_DATA_MAP
|
|
|
|
if (pDX->m_bSaveAndValidate)
|
|
{
|
|
CLRTL_NAME_STATUS cnStatus;
|
|
|
|
//
|
|
// get the name from the control into a temp variable
|
|
//
|
|
DDX_Text(pDX, IDC_PP_CLUS_NAME, strClusName);
|
|
|
|
if ( (strClusName != m_strName)
|
|
&& !ClRtlIsNetNameValid(strClusName, &cnStatus, FALSE /*CheckIfExists*/))
|
|
{
|
|
CString strMsg;
|
|
UINT idsError;
|
|
|
|
switch (cnStatus)
|
|
{
|
|
case NetNameTooLong:
|
|
idsError = IDS_INVALID_CLUSTER_NAME_TOO_LONG;
|
|
break;
|
|
case NetNameInvalidChars:
|
|
idsError = IDS_INVALID_CLUSTER_NAME_INVALID_CHARS;
|
|
break;
|
|
case NetNameInUse:
|
|
idsError = IDS_INVALID_CLUSTER_NAME_IN_USE;
|
|
break;
|
|
case NetNameDNSNonRFCChars:
|
|
idsError = IDS_INVALID_CLUSTER_NAME_INVALID_DNS_CHARS;
|
|
break;
|
|
case NetNameSystemError:
|
|
{
|
|
DWORD scError = GetLastError();
|
|
CNTException nte(scError, IDS_ERROR_VALIDATING_NETWORK_NAME, (LPCWSTR) strClusName);
|
|
nte.ReportError();
|
|
pDX->Fail();
|
|
}
|
|
default:
|
|
idsError = IDS_INVALID_CLUSTER_NAME;
|
|
break;
|
|
} // switch: cnStatus
|
|
|
|
strMsg.LoadString(idsError);
|
|
|
|
if ( idsError == IDS_INVALID_CLUSTER_NAME_INVALID_DNS_CHARS )
|
|
{
|
|
int id = AfxMessageBox(strMsg, MB_YESNO | MB_DEFBUTTON2 | MB_ICONEXCLAMATION );
|
|
|
|
if ( id == IDNO )
|
|
{
|
|
strMsg.Empty();
|
|
pDX->Fail();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AfxMessageBox(strMsg, MB_ICONEXCLAMATION);
|
|
strMsg.Empty(); // exception prep
|
|
pDX->Fail();
|
|
}
|
|
|
|
m_strName = strClusName;
|
|
} // if: cluster name has changed and an invalid network name was specified
|
|
} // if: getting data from the dialog
|
|
else
|
|
{
|
|
//
|
|
// populate the control with data from the member variable
|
|
//
|
|
DDX_Text(pDX, IDC_PP_CLUS_NAME, m_strName);
|
|
} // else: setting data to the dialog
|
|
|
|
} //*** CClusterGeneralPage::DoDataExchange()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterGeneralPage::OnInitDialog
|
|
//
|
|
// Routine Description:
|
|
// Handler for the WM_INITDIALOG message.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// TRUE Focus not set yet.
|
|
// FALSE Focus already set.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CClusterGeneralPage::OnInitDialog(void)
|
|
{
|
|
// Call the base class method.
|
|
CBasePropertyPage::OnInitDialog();
|
|
|
|
// Set limits on the edit controls.
|
|
m_editName.SetLimitText(MAX_CLUSTERNAME_LENGTH);
|
|
|
|
// If read-only, set all controls to be either disabled or read-only.
|
|
if (BReadOnly())
|
|
{
|
|
m_editName.SetReadOnly(TRUE);
|
|
m_editDesc.SetReadOnly(TRUE);
|
|
} // if: sheet is read-only
|
|
|
|
return FALSE; // return TRUE unless you set the focus to a control
|
|
// EXCEPTION: OCX Property Pages should return FALSE
|
|
|
|
} //*** CClusterGeneralPage::OnInitDialog()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterGeneralPage::OnSetActive
|
|
//
|
|
// Routine Description:
|
|
// Handler for the PSN_SETACTIVE message.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// TRUE Page successfully initialized.
|
|
// FALSE Page not initialized.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CClusterGeneralPage::OnSetActive(void)
|
|
{
|
|
return CBasePropertyPage::OnSetActive();
|
|
|
|
} //*** CClusterGeneralPage::OnSetActive()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterGeneralPage::OnKillActive
|
|
//
|
|
// Routine Description:
|
|
// Handler for the PSN_KILLACTIVE message.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// TRUE Page focus successfully killed.
|
|
// FALSE Error killing page focus.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CClusterGeneralPage::OnKillActive(void)
|
|
{
|
|
return CBasePropertyPage::OnKillActive();
|
|
|
|
} //*** CClusterGeneralPage::OnKillActive()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterGeneralPage::OnApply
|
|
//
|
|
// Routine Description:
|
|
// Handler for the PSN_APPLY message.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// TRUE Page successfully applied.
|
|
// FALSE Error applying page.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CClusterGeneralPage::OnApply(void)
|
|
{
|
|
// Set the data from the page in the cluster item.
|
|
try
|
|
{
|
|
CWaitCursor wc;
|
|
|
|
PciCluster()->SetDescription(m_strDesc);
|
|
PciCluster()->SetName(m_strName);
|
|
} // try
|
|
catch (CException * pe)
|
|
{
|
|
pe->ReportError();
|
|
pe->Delete();
|
|
return FALSE;
|
|
} // catch: CException
|
|
|
|
return CBasePropertyPage::OnApply();
|
|
|
|
} //*** CClusterGeneralPage::OnApply()
|
|
/*
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterGeneralPage::OnBnClickedPermissions
|
|
//
|
|
// Routine Description:
|
|
// Handler for the BN_CLICKED message on the Permissions push button.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterGeneralPage::OnBnClickedPermissions(void)
|
|
{
|
|
LONG lResult;
|
|
BOOL bSecDescModified;
|
|
PSECURITY_DESCRIPTOR psec = NULL;
|
|
CString strServer;
|
|
CResource * pciRes = NULL;
|
|
CWaitCursor wc;
|
|
|
|
// Find the cluster name resource.
|
|
{
|
|
POSITION pos;
|
|
|
|
pos = PciCluster()->Pdoc()->LpciResources().GetHeadPosition();
|
|
while (pos != NULL)
|
|
{
|
|
pciRes = (CResource *) PciCluster()->Pdoc()->LpciResources().GetNext(pos);
|
|
ASSERT_VALID(pciRes);
|
|
|
|
if ( (pciRes->StrRealResourceType().CompareNoCase(CLUS_RESTYPE_NAME_NETNAME))
|
|
&& pciRes->BCore() )
|
|
break;
|
|
pciRes = NULL;
|
|
} // while: more resources in the list
|
|
ASSERT(pciRes != NULL);
|
|
} // Find the cluster name resource
|
|
|
|
strServer.Format(_T("\\\\%s"), PciCluster()->StrName());
|
|
|
|
lResult = EditClusterAcl(
|
|
m_hWnd,
|
|
strServer,
|
|
PciCluster()->StrName(),
|
|
pciRes->StrOwner(),
|
|
m_psec,
|
|
&bSecDescModified,
|
|
&psec
|
|
);
|
|
|
|
if (bSecDescModified)
|
|
{
|
|
delete [] m_psec;
|
|
m_psec = psec;
|
|
m_bSecurityChanged = TRUE;
|
|
SetModified(TRUE);
|
|
} // if: data changed
|
|
|
|
} //*** CClusterGeneralPage::OnBnClickedPermissions()
|
|
*/
|
|
|
|
//*************************************************************************//
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CClusterQuorumPage property page
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
IMPLEMENT_DYNCREATE(CClusterQuorumPage, CBasePropertyPage)
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Message Maps
|
|
|
|
BEGIN_MESSAGE_MAP(CClusterQuorumPage, CBasePropertyPage)
|
|
//{{AFX_MSG_MAP(CClusterQuorumPage)
|
|
ON_CBN_DBLCLK(IDC_PP_CLUS_QUORUM_RESOURCE, OnDblClkQuorumResource)
|
|
ON_CBN_SELCHANGE(IDC_PP_CLUS_QUORUM_RESOURCE, OnChangeQuorumResource)
|
|
ON_WM_DESTROY()
|
|
//}}AFX_MSG_MAP
|
|
ON_CBN_SELCHANGE(IDC_PP_CLUS_QUORUM_PARTITION, CBasePropertyPage::OnChangeCtrl)
|
|
ON_EN_CHANGE(IDC_PP_CLUS_QUORUM_ROOT_PATH, CBasePropertyPage::OnChangeCtrl)
|
|
ON_EN_CHANGE(IDC_PP_CLUS_QUORUM_MAX_LOG_SIZE, CBasePropertyPage::OnChangeCtrl)
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterQuorumPage::CClusterQuorumPage
|
|
//
|
|
// Routine Description:
|
|
// Constructor.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CClusterQuorumPage::CClusterQuorumPage(void)
|
|
: CBasePropertyPage(IDD, g_aHelpIDs_IDD_PP_CLUSTER_QUORUM)
|
|
{
|
|
//{{AFX_DATA_INIT(CClusterQuorumPage)
|
|
m_strQuorumResource = _T("");
|
|
m_strPartition = _T("");
|
|
m_strRootPath = _T("");
|
|
m_nMaxLogSize = 0;
|
|
//}}AFX_DATA_INIT
|
|
|
|
m_pbDiskInfo = NULL;
|
|
m_cbDiskInfo = 0;
|
|
|
|
m_bControlsInitialized = FALSE;
|
|
m_ppid = NULL;
|
|
|
|
} //*** CClusterQuorumPage::CClusterQuorumPage()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterQuorumPage::~CClusterQuorumPage
|
|
//
|
|
// Routine Description:
|
|
// Destructor.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CClusterQuorumPage::~CClusterQuorumPage(void)
|
|
{
|
|
delete [] m_pbDiskInfo;
|
|
|
|
} //*** CClusterQuorumPage::~CClusterQuorumPage()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterQuorumPage::OnDestroy
|
|
//
|
|
// Routine Description:
|
|
// Handler for the WM_DESTROY message.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterQuorumPage::OnDestroy(void)
|
|
{
|
|
// If the controls have been initialized, clear the resource combobox.
|
|
if ( BControlsInitialized() )
|
|
{
|
|
ClearResourceList();
|
|
ClearPartitionList();
|
|
}
|
|
|
|
delete [] m_pbDiskInfo;
|
|
m_pbDiskInfo = NULL;
|
|
m_cbDiskInfo = 0;
|
|
|
|
// Call the base class method.
|
|
CBasePropertyPage::OnDestroy();
|
|
|
|
} //*** CClusterQuorumPage::OnDestroy()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterQuorumPage::BInit
|
|
//
|
|
// Routine Description:
|
|
// Initialize the page.
|
|
//
|
|
// Arguments:
|
|
// psht [IN OUT] Property sheet to which this page belongs.
|
|
//
|
|
// Return Value:
|
|
// TRUE Page initialized successfully.
|
|
// FALSE Page failed to initialize.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CClusterQuorumPage::BInit(IN OUT CBaseSheet * psht)
|
|
{
|
|
BOOL bSuccess;
|
|
CWaitCursor wc;
|
|
|
|
ASSERT_KINDOF(CClusterPropSheet, psht);
|
|
|
|
bSuccess = CBasePropertyPage::BInit(psht);
|
|
|
|
try
|
|
{
|
|
// Get the current quorum resource.
|
|
m_strQuorumResource = PciCluster()->StrQuorumResource();
|
|
|
|
SplitDeviceName(
|
|
PciCluster()->StrQuorumPath(),
|
|
m_strPartition.GetBuffer( _MAX_PATH ),
|
|
m_strRootPath.GetBuffer( _MAX_PATH )
|
|
);
|
|
|
|
m_strPartition.ReleaseBuffer();
|
|
m_strRootPath.ReleaseBuffer();
|
|
|
|
m_nMaxLogSize = (PciCluster()->NMaxQuorumLogSize() + 1023) / 1024;
|
|
|
|
m_strCurrentPartition = m_strPartition;
|
|
m_strCurrentRootPath = m_strRootPath;
|
|
} // try
|
|
catch (CException * pe)
|
|
{
|
|
pe->ReportError();
|
|
pe->Delete();
|
|
m_bReadOnly = TRUE;
|
|
} // catch: CException
|
|
|
|
return bSuccess;
|
|
|
|
} //*** CClusterQuorumPage::BInit()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterQuorumPage::DoDataExchange
|
|
//
|
|
// Routine Description:
|
|
// Do data exchange between the dialog and the class.
|
|
//
|
|
// Arguments:
|
|
// pDX [IN OUT] Data exchange object
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterQuorumPage::DoDataExchange(CDataExchange * pDX)
|
|
{
|
|
CWaitCursor wc;
|
|
|
|
CBasePropertyPage::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CClusterQuorumPage)
|
|
DDX_Control(pDX, IDC_PP_CLUS_QUORUM_MAX_LOG_SIZE, m_editMaxLogSize);
|
|
DDX_Control(pDX, IDC_PP_CLUS_QUORUM_ROOT_PATH, m_editRootPath);
|
|
DDX_Control(pDX, IDC_PP_CLUS_QUORUM_PARTITION, m_cboxPartition);
|
|
DDX_Control(pDX, IDC_PP_CLUS_QUORUM_RESOURCE, m_cboxQuorumResource);
|
|
DDX_CBString(pDX, IDC_PP_CLUS_QUORUM_RESOURCE, m_strQuorumResource);
|
|
DDX_CBString(pDX, IDC_PP_CLUS_QUORUM_PARTITION, m_strPartition);
|
|
DDX_Text(pDX, IDC_PP_CLUS_QUORUM_ROOT_PATH, m_strRootPath);
|
|
DDX_Text(pDX, IDC_PP_CLUS_QUORUM_MAX_LOG_SIZE, m_nMaxLogSize);
|
|
//}}AFX_DATA_MAP
|
|
|
|
if ( ! pDX->m_bSaveAndValidate )
|
|
{
|
|
// Fill the quorum resource combobox with resource names.
|
|
FillResourceList();
|
|
} // if: setting data to the dialog
|
|
|
|
m_bControlsInitialized = TRUE;
|
|
|
|
if (pDX->m_bSaveAndValidate || !BReadOnly())
|
|
DDX_Number(pDX, IDC_PP_CLUS_QUORUM_MAX_LOG_SIZE, m_nMaxLogSize, 1, 0xffffffff / 1024);
|
|
|
|
if (pDX->m_bSaveAndValidate)
|
|
{
|
|
DDV_RequiredText(pDX, IDC_PP_CLUS_QUORUM_RESOURCE, IDC_PP_CLUS_QUORUM_RESOURCE_LABEL, m_strQuorumResource);
|
|
DDV_RequiredText(pDX, IDC_PP_CLUS_QUORUM_PARTITION, IDC_PP_CLUS_QUORUM_PARTITION_LABEL, m_strPartition);
|
|
DDV_RequiredText(pDX, IDC_PP_CLUS_QUORUM_ROOT_PATH, IDC_PP_CLUS_QUORUM_ROOT_PATH_LABEL, m_strRootPath);
|
|
} // if: getting data from the dialog
|
|
|
|
} //*** CClusterQuorumPage::DoDataExchange()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterQuorumPage::OnInitDialog
|
|
//
|
|
// Routine Description:
|
|
// Handler for the WM_INITDIALOG message.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// TRUE Focus not set yet.
|
|
// FALSE Focus already set.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CClusterQuorumPage::OnInitDialog(void)
|
|
{
|
|
// Call the base class method.
|
|
CBasePropertyPage::OnInitDialog();
|
|
|
|
// If read-only, set all controls to be either disabled or read-only.
|
|
if (BReadOnly())
|
|
{
|
|
m_cboxQuorumResource.EnableWindow(FALSE);
|
|
m_cboxPartition.EnableWindow(FALSE);
|
|
m_editRootPath.SetReadOnly();
|
|
m_editMaxLogSize.SetReadOnly();
|
|
} // if: sheet is read-only
|
|
else
|
|
{
|
|
m_editRootPath.SetLimitText(MAX_PATH);
|
|
}
|
|
|
|
return FALSE; // return TRUE unless you set the focus to a control
|
|
// EXCEPTION: OCX Property Pages should return FALSE
|
|
|
|
} //*** CClusterQuorumPage::OnInitDialog()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterQuorumPage::OnApply
|
|
//
|
|
// Routine Description:
|
|
// Handler for the PSN_APPLY message.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// TRUE Page successfully applied.
|
|
// FALSE Error applying page.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CClusterQuorumPage::OnApply(void)
|
|
{
|
|
CWaitCursor wc;
|
|
CString strQuorumPath;
|
|
CString strTemp;
|
|
DWORD nLen;
|
|
CResource * pciRes = NULL;
|
|
int nSelected;
|
|
int nCount;
|
|
CLUSTER_RESOURCE_STATE crs = ClusterResourceStateUnknown;
|
|
|
|
//
|
|
// Get the currently selected resource from the combo box.
|
|
//
|
|
nSelected = m_cboxQuorumResource.GetCurSel();
|
|
nCount = m_cboxQuorumResource.GetCount();
|
|
|
|
if ( CB_ERR != nSelected && 0 < nCount )
|
|
{
|
|
pciRes = (CResource *) m_cboxQuorumResource.GetItemDataPtr(nSelected);
|
|
}
|
|
|
|
//
|
|
// If we successfully retrieved a resource make sure it's online.
|
|
//
|
|
if ( NULL != pciRes )
|
|
{
|
|
crs = pciRes->Crs();
|
|
|
|
if ( ClusterResourceOnline != crs )
|
|
{
|
|
//
|
|
// Prompt the user whether or not they'd like to online the resource.
|
|
//
|
|
strTemp.FormatMessage( IDS_ONLINE_QUORUM_RESOURCE_PROMPT, pciRes->StrName() );
|
|
if ( IDYES == AfxMessageBox( strTemp, MB_YESNO | MB_ICONQUESTION ) )
|
|
{
|
|
CWaitForResourceOnlineDlg dlg( pciRes, AfxGetMainWnd() );
|
|
pciRes->OnCmdBringOnline();
|
|
|
|
dlg.DoModal();
|
|
|
|
crs = pciRes->Crs();
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
} // if: resource !online
|
|
|
|
} // if: pciRes !NULL
|
|
else
|
|
{
|
|
// No resource was selected - this should never happen.
|
|
AfxMessageBox( IDS_SELECT_QUORUM_RESOURCE_ERROR, MB_OK | MB_ICONEXCLAMATION );
|
|
return FALSE;
|
|
}
|
|
|
|
// Set the data from the page in the cluster item.
|
|
if ( ClusterResourceOnline == crs )
|
|
{
|
|
try {
|
|
strTemp = _T("");
|
|
|
|
if( m_ppid != NULL && !m_strRootPath.IsEmpty() )
|
|
{
|
|
nLen = _tcslen( m_ppid->szDeviceName );
|
|
|
|
//
|
|
// Concatenate the strings before calling SetQuorumResource, but make sure that
|
|
// there is only one backslash between them.
|
|
//
|
|
strTemp = m_ppid->szDeviceName;
|
|
|
|
if( ( m_ppid->szDeviceName[nLen-1] != _T('\\') ) && ( m_strRootPath[0] != _T('\\') ) )
|
|
{
|
|
strTemp += _T('\\');
|
|
}
|
|
else if( ( m_ppid->szDeviceName[nLen-1] == _T('\\') ) && ( m_strRootPath[0] == _T('\\') ) )
|
|
{
|
|
strTemp.SetAt( nLen-1, _T('\0') );
|
|
}
|
|
} // if: neither string is empty
|
|
|
|
strQuorumPath.Format( _T("%s%s"), strTemp, m_strRootPath );
|
|
|
|
PciCluster()->SetQuorumResource(
|
|
m_strQuorumResource,
|
|
strQuorumPath,
|
|
(m_nMaxLogSize * 1024)
|
|
);
|
|
|
|
m_strCurrentPartition = m_strPartition;
|
|
m_strCurrentRootPath = m_strRootPath;
|
|
} // try
|
|
catch (CException * pe)
|
|
{
|
|
pe->ReportError();
|
|
pe->Delete();
|
|
strQuorumPath.Empty();
|
|
return FALSE;
|
|
} // catch: CException
|
|
|
|
} // if: the resource is online
|
|
|
|
return CBasePropertyPage::OnApply();
|
|
|
|
} //*** CClusterQuorumPage::OnApply()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterQuorumPage::OnDblClkQuorumResource
|
|
//
|
|
// Routine Description:
|
|
// Handler for the CBN_DBLCLK message on the Quorum Resource combo box.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterQuorumPage::OnDblClkQuorumResource(void)
|
|
{
|
|
int nSelected;
|
|
CResource * pciRes;
|
|
|
|
// Get the selected resource.
|
|
nSelected = m_cboxQuorumResource.GetCurSel();
|
|
ASSERT(nSelected != CB_ERR);
|
|
|
|
// Get the resource object.
|
|
pciRes = (CResource *) m_cboxQuorumResource.GetItemDataPtr(nSelected);
|
|
ASSERT_VALID(pciRes);
|
|
ASSERT_KINDOF(CResource, pciRes);
|
|
|
|
// Display properties for the resource.
|
|
pciRes->OnCmdProperties();
|
|
|
|
} //*** CClusterQuorumPage::OnDblClkQuorumResource()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterQuorumPage::OnChangeQuorumResource
|
|
//
|
|
// Routine Description:
|
|
// Handler for the CBN_SELCHANGE message on the Quorum Resource combobox.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterQuorumPage::OnChangeQuorumResource(void)
|
|
{
|
|
int nSelected;
|
|
CResource * pciRes;
|
|
|
|
OnChangeCtrl();
|
|
|
|
// Get the selected resource.
|
|
nSelected = m_cboxQuorumResource.GetCurSel();
|
|
ASSERT(nSelected != CB_ERR);
|
|
|
|
// Get the resource object.
|
|
pciRes = (CResource *) m_cboxQuorumResource.GetItemDataPtr(nSelected);
|
|
ASSERT_VALID(pciRes);
|
|
ASSERT_KINDOF(CResource, pciRes);
|
|
|
|
// If the resource really did change and is the same as the currently
|
|
// saved resource, set the partition to the currently saved partition.
|
|
// Otherwise, clear the partition setting and use the first one.
|
|
if (pciRes->StrName() != m_strQuorumResource)
|
|
{
|
|
if (pciRes->StrName() == PciCluster()->StrQuorumResource())
|
|
{
|
|
m_strPartition = m_strCurrentPartition;
|
|
m_strRootPath = m_strCurrentRootPath;
|
|
} // if: changed to previously set quorum resource
|
|
else
|
|
{
|
|
m_strPartition = _T("");
|
|
//m_strRootPath = _T("\\") CLUS_NAME_DEFAULT_FILESPATH;
|
|
} // else: changed to new quorum resource
|
|
m_strQuorumResource = pciRes->StrName();
|
|
} // if: resource really did change
|
|
|
|
UpdateData(FALSE /*bSaveAndValidate*/);
|
|
|
|
} //*** CClusterQuorumPage::OnChangeQuorumResource()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterQuorumPage::ClearResourceList
|
|
//
|
|
// Routine Description:
|
|
// Clear the resource list and release references to pointers.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterQuorumPage::ClearResourceList(void)
|
|
{
|
|
int cItems;
|
|
int iItem;
|
|
CResource * pciRes;
|
|
|
|
cItems = m_cboxQuorumResource.GetCount();
|
|
for (iItem = 0 ; iItem < cItems ; iItem++)
|
|
{
|
|
pciRes = (CResource *) m_cboxQuorumResource.GetItemDataPtr(iItem);
|
|
ASSERT_VALID(pciRes);
|
|
ASSERT_KINDOF(CResource, pciRes);
|
|
pciRes->Release();
|
|
} // for: each item in the list
|
|
|
|
m_cboxQuorumResource.ResetContent();
|
|
|
|
} //*** CClusterQuorumPage::ClearResourceList()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterQuorumPage::FillResourceList
|
|
//
|
|
// Routine Description:
|
|
// Fill the quorum resource combobox with all resources and select
|
|
// the quorum resource.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterQuorumPage::FillResourceList(void)
|
|
{
|
|
POSITION pos;
|
|
int nIndex;
|
|
CResource * pciRes;
|
|
CResource * pciSelected = NULL;
|
|
CWaitCursor wc;
|
|
|
|
// Clear the list.
|
|
ClearResourceList();
|
|
|
|
pos = PciCluster()->Pdoc()->LpciResources().GetHeadPosition();
|
|
while (pos != NULL)
|
|
{
|
|
// Get the next resource.
|
|
pciRes = (CResource *) PciCluster()->Pdoc()->LpciResources().GetNext(pos);
|
|
ASSERT_VALID(pciRes);
|
|
ASSERT_KINDOF(CResource, pciRes);
|
|
|
|
// If it is quorum capable, add it to the list.
|
|
try
|
|
{
|
|
if (pciRes->BQuorumCapable())
|
|
{
|
|
nIndex = m_cboxQuorumResource.AddString(pciRes->StrName());
|
|
ASSERT(nIndex != CB_ERR);
|
|
m_cboxQuorumResource.SetItemDataPtr(nIndex, pciRes);
|
|
pciRes->AddRef();
|
|
if (m_strQuorumResource == pciRes->StrName())
|
|
pciSelected = pciRes;
|
|
} // if: resource can be a quorum resource
|
|
} // try
|
|
catch (...)
|
|
{
|
|
// Ignore all errors because there is really nothing we can do.
|
|
// Displaying a message isn't really very useful.
|
|
} // catch: Anything
|
|
} // while: more items in the list
|
|
|
|
// Select the current quorum resource in the list.
|
|
{
|
|
int istr;
|
|
|
|
istr = m_cboxQuorumResource.FindStringExact(-1, m_strQuorumResource);
|
|
ASSERT(istr != CB_ERR);
|
|
VERIFY(m_cboxQuorumResource.SetCurSel(istr) != CB_ERR);
|
|
} // Select the current quorum resource in the list
|
|
|
|
// Check if the current quorum device is in the list of quorum capable resources
|
|
if (pciSelected != NULL)
|
|
{
|
|
// Fill the partition list.
|
|
FillPartitionList(pciSelected);
|
|
}
|
|
else
|
|
{
|
|
// There is nothing we can do in this case. There is something seriously wrong
|
|
// with the cluster.
|
|
CNTException nte(
|
|
ERROR_QUORUM_DISK_NOT_FOUND,
|
|
IDS_GET_QUORUM_DEVICES_ERROR
|
|
);
|
|
nte.ReportError();
|
|
} // else: the current quorum device is not in the list of quorum capable resources
|
|
|
|
} //*** CClusterQuorumPage::FillResourceList()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterQuorumPage::ClearPartitionList
|
|
//
|
|
// Routine Description:
|
|
// Clear the partition list and release references to pointers.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterQuorumPage::ClearPartitionList(void)
|
|
{
|
|
int cItems;
|
|
int iItem;
|
|
SPartitionItemData * ppid = NULL;
|
|
|
|
cItems = m_cboxPartition.GetCount();
|
|
for ( iItem = 0 ; iItem < cItems ; iItem++ )
|
|
{
|
|
ppid = (SPartitionItemData *) m_cboxPartition.GetItemDataPtr( iItem );
|
|
delete ppid;
|
|
} // for: each item in the list
|
|
|
|
m_cboxPartition.ResetContent();
|
|
|
|
} //*** CClusterQuorumPage::ClearPartitionList()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterQuorumPage::FillPartitionList
|
|
//
|
|
// Routine Description:
|
|
// Fill the partition combobox with all partitions available on the
|
|
// currently selected quorum resource.
|
|
//
|
|
// Arguments:
|
|
// pciRes [IN OUT] Currently selected quorum resource.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterQuorumPage::FillPartitionList(IN OUT CResource * pciRes)
|
|
{
|
|
CString strPartitionInfo;
|
|
CLUSPROP_BUFFER_HELPER buf;
|
|
DWORD cbData;
|
|
DWORD cbBuf;
|
|
int nIndex;
|
|
SPartitionItemData * ppid = NULL;
|
|
CWaitCursor wc;
|
|
|
|
ASSERT_VALID(pciRes);
|
|
|
|
// Clear the list.
|
|
ClearPartitionList();
|
|
|
|
// Get disk info for this resource.
|
|
if (BGetDiskInfo(*pciRes))
|
|
{
|
|
buf.pb = m_pbDiskInfo;
|
|
cbBuf = m_cbDiskInfo;
|
|
|
|
while (buf.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK)
|
|
{
|
|
// Calculate the size of the value.
|
|
cbData = sizeof(*buf.pValue) + ALIGN_CLUSPROP(buf.pValue->cbLength);
|
|
ASSERT(cbData <= cbBuf);
|
|
|
|
// Parse the value.
|
|
if (buf.pSyntax->dw == CLUSPROP_SYNTAX_PARTITION_INFO)
|
|
{
|
|
// Add the partition to the combobox if it is a usable partition
|
|
// and it hasn't been added already.
|
|
if ( (buf.pPartitionInfoValue->dwFlags & CLUSPROP_PIFLAG_USABLE)
|
|
&& (m_cboxPartition.FindString(-1, buf.pPartitionInfoValue->szDeviceName) == CB_ERR))
|
|
{
|
|
try
|
|
{
|
|
// Construct the name to display to the user
|
|
// and add the item to the combobox.
|
|
strPartitionInfo.Format(
|
|
( buf.pPartitionInfoValue->szVolumeLabel[ 0 ] ? _T("%ls (%ls) ") : _T("%ls ") ),
|
|
buf.pPartitionInfoValue->szDeviceName,
|
|
buf.pPartitionInfoValue->szVolumeLabel
|
|
);
|
|
nIndex = m_cboxPartition.AddString( strPartitionInfo );
|
|
ASSERT( nIndex != CB_ERR );
|
|
|
|
// Construct a partition item data structure,
|
|
// which consists of the device name, a partition
|
|
// name, and a root path name.
|
|
ppid = new SPartitionItemData;
|
|
if ( ppid == NULL )
|
|
{
|
|
AfxThrowMemoryException();
|
|
}
|
|
ASSERT( ( _tcslen( buf.pPartitionInfoValue->szDeviceName ) + 1 ) * sizeof( TCHAR ) <= sizeof( ppid->szDeviceName ) );
|
|
_tcscpy( ppid->szDeviceName, buf.pPartitionInfoValue->szDeviceName );
|
|
SplitDeviceName(
|
|
buf.pPartitionInfoValue->szDeviceName,
|
|
ppid->szPartitionName,
|
|
ppid->szBaseRootPath
|
|
);
|
|
m_cboxPartition.SetItemDataPtr( nIndex, ppid );
|
|
} // try
|
|
catch (...)
|
|
{
|
|
// Ignore all errors because there is really nothing we can do.
|
|
// Displaying a message isn't really very useful.
|
|
} // catch: Anything
|
|
} // if: partition not added yet
|
|
} // if: partition info
|
|
|
|
// Advance the buffer pointer
|
|
buf.pb += cbData;
|
|
cbBuf -= cbData;
|
|
} // while: more values
|
|
} // if: got disk info successfully
|
|
|
|
// Select the current partition in the list.
|
|
if (m_strPartition.GetLength() > 0)
|
|
{
|
|
nIndex = m_cboxPartition.SelectString( -1, m_strPartition );
|
|
} // if: there is a current partition
|
|
else
|
|
{
|
|
if (m_cboxPartition.GetCount() > 0)
|
|
{
|
|
nIndex = m_cboxPartition.SetCurSel( 0 );
|
|
} // if: combobox has any entries
|
|
else
|
|
{
|
|
nIndex = -1;
|
|
} // else: no entries in the list
|
|
} // else: no current selection
|
|
if ( nIndex != -1 )
|
|
{
|
|
size_t cchBaseRootPath;
|
|
LPTSTR pszRootPath;
|
|
|
|
// Save the item data.
|
|
// If the base root path is contained in the root path,
|
|
// remove the base root path from the root path.
|
|
m_ppid = (SPartitionItemData *) m_cboxPartition.GetItemDataPtr( nIndex );
|
|
if ( m_ppid != NULL )
|
|
{
|
|
m_strPartition = m_ppid->szPartitionName;
|
|
cchBaseRootPath = _tcslen( m_ppid->szBaseRootPath );
|
|
if ( ( cchBaseRootPath > 0 )
|
|
&& ( _tcsncmp( m_strRootPath, m_ppid->szBaseRootPath, cchBaseRootPath ) == 0 ) )
|
|
{
|
|
pszRootPath = m_strRootPath.GetBuffer( 1 );
|
|
_tcscpy( pszRootPath, &pszRootPath[ cchBaseRootPath ] );
|
|
m_strRootPath.ReleaseBuffer();
|
|
} // if: root path contains base root path
|
|
} // if: ppid retrieved successfully
|
|
} // if: an item is selected
|
|
else if ( m_cboxPartition.GetCount() > 0 )
|
|
{
|
|
ASSERT( nIndex != CB_ERR );
|
|
} // else if: combobox is not empty
|
|
|
|
} //*** CClusterQuorumPage::FillPartitionList()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterQuorumPage::SplitDeviceName
|
|
//
|
|
// Routine Description:
|
|
// Split a device name into a partition name and a root path. It is
|
|
// expected that the output buffers are at least of size _MAX_PATH.
|
|
//
|
|
// Arguments:
|
|
// pszDeviceNameIn Device name to split.
|
|
// pszPartitionNameOut Partition name buffer to fill.
|
|
// pszRootPathOut Root path buffer to fill.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
CClusterQuorumPage::SplitDeviceName(
|
|
LPCTSTR pszDeviceNameIn,
|
|
LPTSTR pszPartitionNameOut,
|
|
LPTSTR pszRootPathOut
|
|
)
|
|
{
|
|
//
|
|
// Construct the partition name and base root path from the device name.
|
|
//
|
|
|
|
//
|
|
// If we have a UNC path it will end up looking like \\<X>\<Y>\. If
|
|
// it begins with "\\?\UNC\" we do a special case and pull out "\?\UNC".
|
|
// We then search for the second '\' beyond that to end the partition name,
|
|
// at which point we start grabbing the root path.
|
|
//
|
|
// If we have it pointing to a directory the partition should look like "c:"
|
|
// and the root path should look like "winnt\cluster\MSCS"
|
|
//
|
|
|
|
if ( ( pszDeviceNameIn[ 0 ] == _T('\\') )
|
|
&& ( pszDeviceNameIn[ 1 ] == _T('\\') ) )
|
|
{
|
|
int cSlashes = 0;
|
|
|
|
//
|
|
// pszDeviceNameIn contains a UNC path. Skip over any \\?\UNC\ prefix
|
|
//
|
|
if ( _tcsnicmp( pszDeviceNameIn, _T("\\\\?\\UNC\\"), 8 ) == 0 )
|
|
{
|
|
pszDeviceNameIn += 8;
|
|
}
|
|
else
|
|
{
|
|
pszDeviceNameIn += 2;
|
|
}
|
|
|
|
//
|
|
// Make sure out partition looks like a UNC path on output.
|
|
//
|
|
_sntprintf( pszPartitionNameOut, 2, _T("\\\\") );
|
|
pszPartitionNameOut += 2;
|
|
|
|
// Copy the server and share name to the partition string.
|
|
for ( ; *pszDeviceNameIn != _T('\0') ; pszPartitionNameOut++, pszDeviceNameIn++ )
|
|
{
|
|
if ( *pszDeviceNameIn == _T('\\') )
|
|
{
|
|
cSlashes++;
|
|
if ( cSlashes == 2 )
|
|
{
|
|
break;
|
|
} // if: found the slash after the share name
|
|
} // if: found a slash
|
|
*pszPartitionNameOut = *pszDeviceNameIn;
|
|
} // for: each character in the device name
|
|
|
|
// Copy the rest of the path to the root path string.
|
|
if ( *pszDeviceNameIn == _T('\0') )
|
|
{
|
|
_tcscpy( pszRootPathOut, _T("\\") );
|
|
} // if: no root path
|
|
else
|
|
{
|
|
pszDeviceNameIn++;
|
|
_tcscpy( pszRootPathOut, pszDeviceNameIn );
|
|
} // else: root path specified
|
|
} // if: UNC path
|
|
else
|
|
{
|
|
_tsplitpath( pszDeviceNameIn, pszPartitionNameOut, pszRootPathOut, NULL, NULL );
|
|
} // else: not a UNC path
|
|
|
|
} //*** CClusterQuorumPage::FillPartitionItemData()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterQuorumPage::BGetDiskInfo
|
|
//
|
|
// Routine Description:
|
|
// Get information about the currently selected disk.
|
|
//
|
|
// Arguments:
|
|
// rpciRes [IN OUT] Disk resource to get info about.
|
|
//
|
|
// Return Value:
|
|
// TRUE The operation was successful.
|
|
// FALSE The operation failed.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CClusterQuorumPage::BGetDiskInfo( IN OUT CResource & rpciRes )
|
|
{
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
DWORD cbDiskInfo = sizeof( CLUSPROP_DWORD )
|
|
+ sizeof( CLUSPROP_SCSI_ADDRESS )
|
|
+ sizeof( CLUSPROP_DISK_NUMBER )
|
|
+ sizeof( CLUSPROP_PARTITION_INFO )
|
|
+ sizeof( CLUSPROP_SYNTAX );
|
|
PBYTE pbDiskInfo = NULL;
|
|
|
|
try
|
|
{
|
|
// Get disk info.
|
|
pbDiskInfo = new BYTE[ cbDiskInfo ];
|
|
if ( pbDiskInfo == NULL )
|
|
{
|
|
AfxThrowMemoryException();
|
|
} // if: error allocating memory
|
|
dwStatus = ClusterResourceControl(
|
|
rpciRes.Hresource(),
|
|
NULL,
|
|
CLUSCTL_RESOURCE_STORAGE_GET_DISK_INFO,
|
|
NULL,
|
|
0,
|
|
pbDiskInfo,
|
|
cbDiskInfo,
|
|
&cbDiskInfo
|
|
);
|
|
if ( dwStatus == ERROR_MORE_DATA )
|
|
{
|
|
delete [] pbDiskInfo;
|
|
pbDiskInfo = new BYTE[ cbDiskInfo] ;
|
|
if ( pbDiskInfo == NULL )
|
|
{
|
|
AfxThrowMemoryException();
|
|
} // if: error allocating memory
|
|
dwStatus = ClusterResourceControl(
|
|
rpciRes.Hresource(),
|
|
NULL,
|
|
CLUSCTL_RESOURCE_STORAGE_GET_DISK_INFO,
|
|
NULL,
|
|
0,
|
|
pbDiskInfo,
|
|
cbDiskInfo,
|
|
&cbDiskInfo
|
|
);
|
|
} // if: buffer is too small
|
|
} // try
|
|
catch ( CMemoryException * pme )
|
|
{
|
|
pme->Delete();
|
|
dwStatus = ERROR_NOT_ENOUGH_MEMORY;
|
|
} // catch: CMemoryException
|
|
|
|
if ( dwStatus != ERROR_SUCCESS )
|
|
{
|
|
CNTException nte(
|
|
dwStatus,
|
|
IDS_GET_DISK_INFO_ERROR,
|
|
rpciRes.StrName(),
|
|
NULL,
|
|
FALSE /*bAutoDelete*/
|
|
);
|
|
delete [] pbDiskInfo;
|
|
nte.ReportError();
|
|
nte.Delete();
|
|
return FALSE;
|
|
} // if: error getting disk info
|
|
|
|
delete [] m_pbDiskInfo;
|
|
m_pbDiskInfo = pbDiskInfo;
|
|
m_cbDiskInfo = cbDiskInfo;
|
|
|
|
return TRUE;
|
|
|
|
} //*** CClusterQuorumPage::BGetDiskInfo()
|
|
|
|
|
|
//*************************************************************************//
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CClusterNetPriorityPage property page
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
IMPLEMENT_DYNCREATE(CClusterNetPriorityPage, CBasePropertyPage)
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Message Maps
|
|
|
|
BEGIN_MESSAGE_MAP(CClusterNetPriorityPage, CBasePropertyPage)
|
|
//{{AFX_MSG_MAP(CClusterNetPriorityPage)
|
|
ON_LBN_SELCHANGE(IDC_PP_CLUS_PRIORITY_LIST, OnSelChangeList)
|
|
ON_BN_CLICKED(IDC_PP_CLUS_PRIORITY_UP, OnUp)
|
|
ON_BN_CLICKED(IDC_PP_CLUS_PRIORITY_DOWN, OnDown)
|
|
ON_BN_CLICKED(IDC_PP_CLUS_PRIORITY_PROPERTIES, OnProperties)
|
|
ON_WM_DESTROY()
|
|
ON_WM_CONTEXTMENU()
|
|
ON_LBN_DBLCLK(IDC_PP_CLUS_PRIORITY_LIST, OnDblClkList)
|
|
//}}AFX_MSG_MAP
|
|
ON_COMMAND(ID_FILE_PROPERTIES, OnProperties)
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterNetPriorityPage::CClusterNetPriorityPage
|
|
//
|
|
// Routine Description:
|
|
// Constructor.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CClusterNetPriorityPage::CClusterNetPriorityPage(void)
|
|
: CBasePropertyPage(IDD, g_aHelpIDs_IDD_PP_CLUSTER_NET_PRIORITY)
|
|
{
|
|
//{{AFX_DATA_INIT(CClusterNetPriorityPage)
|
|
//}}AFX_DATA_INIT
|
|
|
|
m_bControlsInitialized = FALSE;
|
|
|
|
} //*** CClusterNetPriorityPage::CClusterNetPriorityPage()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterNetPriorityPage::OnDestroy
|
|
//
|
|
// Routine Description:
|
|
// Handler for the WM_DESTROY message.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterNetPriorityPage::OnDestroy(void)
|
|
{
|
|
// If the controls have been initialized, clear the list box.
|
|
if (BControlsInitialized())
|
|
ClearNetworkList();
|
|
|
|
// Call the base class method.
|
|
CBasePropertyPage::OnDestroy();
|
|
|
|
} //*** CClusterNetPriorityPage::OnDestroy()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterNetPriorityPage::DoDataExchange
|
|
//
|
|
// Routine Description:
|
|
// Do data exchange between the dialog and the class.
|
|
//
|
|
// Arguments:
|
|
// pDX [IN OUT] Data exchange object
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterNetPriorityPage::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CBasePropertyPage::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CClusterNetPriorityPage)
|
|
DDX_Control(pDX, IDC_PP_CLUS_PRIORITY_PROPERTIES, m_pbProperties);
|
|
DDX_Control(pDX, IDC_PP_CLUS_PRIORITY_DOWN, m_pbDown);
|
|
DDX_Control(pDX, IDC_PP_CLUS_PRIORITY_UP, m_pbUp);
|
|
DDX_Control(pDX, IDC_PP_CLUS_PRIORITY_LIST, m_lbList);
|
|
//}}AFX_DATA_MAP
|
|
|
|
m_bControlsInitialized = TRUE;
|
|
|
|
if (pDX->m_bSaveAndValidate)
|
|
{
|
|
int nIndex;
|
|
int cItems;
|
|
CNetwork * pciNet;
|
|
|
|
ASSERT(!BReadOnly());
|
|
|
|
// Save the list.
|
|
LpciNetworkPriority().RemoveAll();
|
|
|
|
cItems = m_lbList.GetCount();
|
|
for (nIndex = 0 ; nIndex < cItems ; nIndex++)
|
|
{
|
|
pciNet = (CNetwork *) m_lbList.GetItemDataPtr(nIndex);
|
|
ASSERT_VALID(pciNet);
|
|
LpciNetworkPriority().AddTail(pciNet);
|
|
} // for: each item in the list box
|
|
} // if: saving data from the dialog
|
|
|
|
} //*** CClusterNetPriorityPage::DoDataExchange()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterNetPriorityPage::OnInitDialog
|
|
//
|
|
// Routine Description:
|
|
// Handler for the WM_INITDIALOG message.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// TRUE Focus not set yet.
|
|
// FALSE Focus already set.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CClusterNetPriorityPage::OnInitDialog(void)
|
|
{
|
|
CBasePropertyPage::OnInitDialog();
|
|
|
|
if (BReadOnly())
|
|
{
|
|
m_lbList.EnableWindow(FALSE);
|
|
m_pbUp.EnableWindow(FALSE);
|
|
m_pbDown.EnableWindow(FALSE);
|
|
} // if: object is read only
|
|
|
|
try
|
|
{
|
|
// Duplicate the network priority list.
|
|
{
|
|
POSITION pos;
|
|
CNetwork * pciNet;
|
|
|
|
pos = PciCluster()->LpciNetworkPriority().GetHeadPosition();
|
|
while (pos != NULL)
|
|
{
|
|
pciNet = (CNetwork *) PciCluster()->LpciNetworkPriority().GetNext(pos);
|
|
ASSERT_VALID(pciNet);
|
|
m_lpciNetworkPriority.AddTail(pciNet);
|
|
} // while: more networks in the list
|
|
} // Duplicate the network priority list
|
|
} // try
|
|
catch (CException * pe)
|
|
{
|
|
pe->ReportError();
|
|
pe->Delete();
|
|
} // catch: CException
|
|
|
|
// Fill the list.
|
|
FillList();
|
|
|
|
// Set button states.
|
|
OnSelChangeList();
|
|
|
|
return TRUE; // return TRUE unless you set the focus to a control
|
|
// EXCEPTION: OCX Property Pages should return FALSE
|
|
|
|
} //*** CClusterNetPriorityPage::OnInitDialog()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterNetPriorityPage::OnApply
|
|
//
|
|
// Routine Description:
|
|
// Handler for the PSN_APPLY message.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// TRUE Page successfully applied.
|
|
// FALSE Error applying page.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CClusterNetPriorityPage::OnApply(void)
|
|
{
|
|
ASSERT(!BReadOnly());
|
|
|
|
try
|
|
{
|
|
PciCluster()->SetNetworkPriority(LpciNetworkPriority());
|
|
} // try
|
|
catch (CException * pe)
|
|
{
|
|
pe->ReportError();
|
|
pe->Delete();
|
|
return FALSE;
|
|
} // catch: CException
|
|
|
|
return CPropertyPage::OnApply();
|
|
|
|
} //*** CClusterNetPriorityPage::OnApply()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterNetPriorityPage::OnSelChangeList
|
|
//
|
|
// Routine Description:
|
|
// Handler for the LBN_SELCHANGE message on the list box.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterNetPriorityPage::OnSelChangeList(void)
|
|
{
|
|
BOOL bEnableUp;
|
|
BOOL bEnableDown;
|
|
BOOL bEnableProperties;
|
|
int isel;
|
|
int cItems;
|
|
|
|
isel = m_lbList.GetCurSel();
|
|
cItems = m_lbList.GetCount();
|
|
|
|
// Enable buttons only if there is a selection and there
|
|
// is more than one item in the list.
|
|
if (BReadOnly() || (isel == LB_ERR) || (cItems <= 1))
|
|
{
|
|
bEnableUp = FALSE;
|
|
bEnableDown = FALSE;
|
|
} // if: no selection or only 0 or 1 items in the list
|
|
else
|
|
{
|
|
bEnableUp = (isel > 0);
|
|
bEnableDown = (isel < cItems - 1);
|
|
} // else: buttons allowed to be enabled
|
|
|
|
bEnableProperties = (isel != LB_ERR);
|
|
|
|
m_pbUp.EnableWindow(bEnableUp);
|
|
m_pbDown.EnableWindow(bEnableDown);
|
|
m_pbProperties.EnableWindow(bEnableProperties);
|
|
|
|
} //*** CClusterNetPriorityPage::OnSelChangeList()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterNetPriorityPage::OnUp
|
|
//
|
|
// Routine Description:
|
|
// Handler for the BN_CLICKED message on the Up push button.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterNetPriorityPage::OnUp(void)
|
|
{
|
|
int isel;
|
|
CNetwork * pciNet;
|
|
|
|
isel = m_lbList.GetCurSel();
|
|
ASSERT(isel != LB_ERR);
|
|
|
|
pciNet = (CNetwork *) m_lbList.GetItemDataPtr(isel);
|
|
ASSERT_VALID(pciNet);
|
|
|
|
VERIFY(m_lbList.DeleteString(isel) != LB_ERR);
|
|
isel = m_lbList.InsertString(isel - 1, pciNet->StrName());
|
|
ASSERT(isel != LB_ERR);
|
|
VERIFY(m_lbList.SetItemDataPtr(isel, pciNet) != LB_ERR);
|
|
VERIFY(m_lbList.SetCurSel(isel) != LB_ERR);
|
|
|
|
OnSelChangeList();
|
|
m_lbList.SetFocus();
|
|
|
|
SetModified(TRUE);
|
|
|
|
} //*** CClusterNetPriorityPage::OnUp()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterNetPriorityPage::OnDown
|
|
//
|
|
// Routine Description:
|
|
// Handler for the BN_CLICKED message on the Down push button.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterNetPriorityPage::OnDown(void)
|
|
{
|
|
int isel;
|
|
CNetwork * pciNet;
|
|
|
|
isel = m_lbList.GetCurSel();
|
|
ASSERT(isel != LB_ERR);
|
|
|
|
pciNet = (CNetwork *) m_lbList.GetItemDataPtr(isel);
|
|
ASSERT_VALID(pciNet);
|
|
|
|
VERIFY(m_lbList.DeleteString(isel) != LB_ERR);
|
|
isel = m_lbList.InsertString(isel + 1, pciNet->StrName());
|
|
ASSERT(isel != LB_ERR);
|
|
VERIFY(m_lbList.SetItemDataPtr(isel, pciNet) != LB_ERR);
|
|
VERIFY(m_lbList.SetCurSel(isel) != LB_ERR);
|
|
|
|
OnSelChangeList();
|
|
m_lbList.SetFocus();
|
|
|
|
SetModified(TRUE);
|
|
|
|
} //*** CClusterNetPriorityPage::OnDown()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterNetPriorityPage::OnProperties
|
|
//
|
|
// Routine Description:
|
|
// Handler for the BN_CLICKED message on the Properties push button.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterNetPriorityPage::OnProperties(void)
|
|
{
|
|
DisplayProperties();
|
|
|
|
} //*** CClusterNetPriorityPage::OnProperties()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterNetPriorityPage::FillList
|
|
//
|
|
// Routine Description:
|
|
// Fill the network list.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterNetPriorityPage::FillList(void)
|
|
{
|
|
int nIndex;
|
|
POSITION pos;
|
|
CNetwork * pciNet;
|
|
CWaitCursor wc;
|
|
|
|
ClearNetworkList();
|
|
PciCluster()->CollectNetworkPriority(NULL);
|
|
|
|
pos = LpciNetworkPriority().GetHeadPosition();
|
|
while (pos != NULL)
|
|
{
|
|
pciNet = (CNetwork *) LpciNetworkPriority().GetNext(pos);
|
|
ASSERT_VALID(pciNet);
|
|
|
|
try
|
|
{
|
|
nIndex = m_lbList.AddString(pciNet->StrName());
|
|
ASSERT(nIndex != LB_ERR);
|
|
m_lbList.SetItemDataPtr(nIndex, pciNet);
|
|
pciNet->AddRef();
|
|
} // try
|
|
catch (...)
|
|
{
|
|
// Ignore all errors because there is really nothing we can do.
|
|
// Displaying a message isn't really very useful.
|
|
} // catch: Anything
|
|
} // while: more items in the list
|
|
|
|
} // CClusterNetPriorityPage::FillList
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterNetPriorityPage::ClearNetworkList
|
|
//
|
|
// Routine Description:
|
|
// Clear the network list and release references to pointers.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterNetPriorityPage::ClearNetworkList(void)
|
|
{
|
|
int cItems;
|
|
int iItem;
|
|
CNetwork * pciNet;
|
|
|
|
cItems = m_lbList.GetCount();
|
|
for (iItem = 0 ; iItem < cItems ; iItem++)
|
|
{
|
|
pciNet = (CNetwork *) m_lbList.GetItemDataPtr(iItem);
|
|
ASSERT_VALID(pciNet);
|
|
ASSERT_KINDOF(CNetwork, pciNet);
|
|
pciNet->Release();
|
|
} // for: each item in the list
|
|
|
|
m_lbList.ResetContent();
|
|
|
|
} //*** CClusterNetPriorityPage::ClearNetworkList()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CResourceDependsPage::DisplayProperties
|
|
//
|
|
// Routine Description:
|
|
// Display properties of the item with the focus.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterNetPriorityPage::DisplayProperties()
|
|
{
|
|
int isel;
|
|
CNetwork * pciNet;
|
|
|
|
isel = m_lbList.GetCurSel();
|
|
ASSERT(isel != LB_ERR);
|
|
|
|
if (isel != LB_ERR)
|
|
{
|
|
// Get the network pointer.
|
|
pciNet = (CNetwork *) m_lbList.GetItemDataPtr(isel);
|
|
ASSERT_VALID(pciNet);
|
|
|
|
// Set properties of that item.
|
|
if (pciNet->BDisplayProperties())
|
|
{
|
|
// Remove the item. If it is still used for internal cluster
|
|
// communications, add it back in.
|
|
VERIFY(m_lbList.DeleteString(isel) != LB_ERR);
|
|
if (pciNet->Cnr() & ClusterNetworkRoleInternalUse)
|
|
{
|
|
isel = m_lbList.InsertString(isel, pciNet->StrName());
|
|
ASSERT(isel != LB_ERR);
|
|
VERIFY(m_lbList.SetItemDataPtr(isel, pciNet) != LB_ERR);
|
|
VERIFY(m_lbList.SetCurSel(isel) != LB_ERR);
|
|
} // if: still used for internal cluster communications
|
|
else
|
|
pciNet->Release();
|
|
|
|
// Make sure only appropriate buttons are enabled.
|
|
OnSelChangeList();
|
|
} // if: properties changed
|
|
m_lbList.SetFocus();
|
|
} // if: found an item with focus
|
|
|
|
} //*** CClusterNetPriorityPage::DisplayProperties()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterNetPriorityPage::OnContextMenu
|
|
//
|
|
// Routine Description:
|
|
// Handler for the WM_CONTEXTMENU method.
|
|
//
|
|
// Arguments:
|
|
// pWnd Window in which the user right clicked the mouse.
|
|
// point Position of the cursor, in screen coordinates.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterNetPriorityPage::OnContextMenu( CWnd * pWnd, CPoint point )
|
|
{
|
|
BOOL bHandled = FALSE;
|
|
CMenu * pmenu = NULL;
|
|
CListBox * pListBox = (CListBox *) pWnd;
|
|
CString strMenuName;
|
|
CWaitCursor wc;
|
|
|
|
// If focus is not in the list box, don't handle the message.
|
|
if ( pWnd == &m_lbList )
|
|
{
|
|
// Create the menu to display.
|
|
try
|
|
{
|
|
pmenu = new CMenu;
|
|
if ( pmenu == NULL )
|
|
{
|
|
AfxThrowMemoryException();
|
|
} // if: error allocating memory
|
|
if ( pmenu->CreatePopupMenu() )
|
|
{
|
|
UINT nFlags = MF_STRING;
|
|
|
|
// If there are no items in the list, disable the menu item.
|
|
if ( pListBox->GetCount() == 0 )
|
|
{
|
|
nFlags |= MF_GRAYED;
|
|
} // if: no items in the list
|
|
|
|
// Add the Properties item to the menu.
|
|
strMenuName.LoadString( IDS_MENU_PROPERTIES );
|
|
if ( pmenu->AppendMenu( nFlags, ID_FILE_PROPERTIES, strMenuName ) )
|
|
{
|
|
bHandled = TRUE;
|
|
} // if: successfully added menu item
|
|
} // if: menu created successfully
|
|
} // try
|
|
catch ( CException * pe )
|
|
{
|
|
pe->ReportError();
|
|
pe->Delete();
|
|
} // catch: CException
|
|
} // if: focus is on the list control
|
|
|
|
if ( bHandled )
|
|
{
|
|
// Display the menu.
|
|
if ( ! pmenu->TrackPopupMenu(
|
|
TPM_LEFTALIGN | TPM_RIGHTBUTTON,
|
|
point.x,
|
|
point.y,
|
|
this
|
|
) )
|
|
{
|
|
} // if: unsuccessfully displayed the menu
|
|
} // if: there is a menu to display
|
|
else
|
|
{
|
|
CBasePropertyPage::OnContextMenu( pWnd, point );
|
|
} // else: no menu to display
|
|
|
|
delete pmenu;
|
|
|
|
} //*** CClusterNetPriorityPage::OnContextMenu()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CClusterNetPriorityPage::OnDblClkList
|
|
//
|
|
// Routine Description:
|
|
// Handler method for the NM_DBLCLK message.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CClusterNetPriorityPage::OnDblClkList()
|
|
{
|
|
DisplayProperties();
|
|
|
|
} //*** CClusterNetPriorityPage::OnDblClkList()
|