1527 lines
45 KiB
C++
1527 lines
45 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1996-2000 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
// Cluster.cpp
|
|
//
|
|
// Abstract:
|
|
// Implementation of the CCluster class.
|
|
//
|
|
// Author:
|
|
// David Potter (davidp) May 13, 1996
|
|
//
|
|
// Revision History:
|
|
//
|
|
// Notes:
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "CluAdmin.h"
|
|
#include "ConstDef.h"
|
|
#include "Cluster.h"
|
|
#include "CASvc.h"
|
|
#include "ClusDoc.h"
|
|
#include "ClusProp.h"
|
|
#include "ExcOper.h"
|
|
#include "ClusItem.inl"
|
|
|
|
#include "resource.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Global Variables
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef _DEBUG
|
|
CTraceTag g_tagCluster( _T("Document"), _T("CLUSTER"), 0 );
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CCluster
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
IMPLEMENT_DYNCREATE( CCluster, CClusterItem )
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Message Maps
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
BEGIN_MESSAGE_MAP( CCluster, CClusterItem )
|
|
//{{AFX_MSG_MAP(CCluster)
|
|
ON_UPDATE_COMMAND_UI(ID_FILE_PROPERTIES, OnUpdateProperties)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::CCluster
|
|
//
|
|
// Routine Description:
|
|
// Default construtor.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CCluster::CCluster( void ) : CClusterItem( NULL, IDS_ITEMTYPE_CLUSTER )
|
|
{
|
|
m_idmPopupMenu = IDM_CLUSTER_POPUP;
|
|
|
|
ZeroMemory( &m_cvi, sizeof( m_cvi ) );
|
|
m_nMaxQuorumLogSize = 0;
|
|
|
|
m_plpciNetworkPriority = NULL;
|
|
|
|
// Set the object type and state images.
|
|
m_iimgObjectType = GetClusterAdminApp()->Iimg( IMGLI_CLUSTER );
|
|
m_iimgState = m_iimgObjectType;
|
|
|
|
// Setup the property array.
|
|
{
|
|
m_rgProps[epropDefaultNetworkRole].Set(CLUSREG_NAME_CLUS_DEFAULT_NETWORK_ROLE, m_nDefaultNetworkRole, m_nDefaultNetworkRole);
|
|
m_rgProps[epropDescription].Set(CLUSREG_NAME_CLUS_DESC, m_strDescription, m_strDescription);
|
|
m_rgProps[epropEnableEventLogReplication].Set(CLUSREG_NAME_CLUS_EVTLOG_PROPAGATION, m_bEnableEventLogReplication, m_bEnableEventLogReplication);
|
|
m_rgProps[epropQuorumArbitrationTimeMax].Set(CLUSREG_NAME_QUORUM_ARBITRATION_TIMEOUT, m_nQuorumArbitrationTimeMax, m_nQuorumArbitrationTimeMax);
|
|
m_rgProps[epropQuorumArbitrationTimeMin].Set(CLUSREG_NAME_QUORUM_ARBITRATION_EQUALIZER, m_nQuorumArbitrationTimeMin, m_nQuorumArbitrationTimeMin);
|
|
} // Setup the property array
|
|
|
|
} //*** CCluster::CCluster()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::~CCluster
|
|
//
|
|
// Routine Description:
|
|
// Destructor.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CCluster::~CCluster( void )
|
|
{
|
|
Cleanup();
|
|
|
|
} //*** CCluster::~CCluster()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::Cleanup
|
|
//
|
|
// Routine Description:
|
|
// Cleanup the item.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CCluster::Cleanup( void )
|
|
{
|
|
// Delete the NetworkPriority list.
|
|
if ( m_plpciNetworkPriority != NULL )
|
|
{
|
|
m_plpciNetworkPriority->RemoveAll();
|
|
delete m_plpciNetworkPriority;
|
|
m_plpciNetworkPriority = NULL;
|
|
} // if: NetworkPriority list exists
|
|
|
|
m_hkey = NULL;
|
|
|
|
} //*** CCluster::Cleanup()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::Init
|
|
//
|
|
// Routine Description:
|
|
// Initialize the item.
|
|
//
|
|
// Arguments:
|
|
// pdoc [IN OUT] Document to which this item belongs.
|
|
// lpszName [IN] Name of the item.
|
|
// hOpenedCluster [IN] Handle to cluster to use that is already open.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CNTException Errors from OpenCluster(), GetClusterKey(), or
|
|
// CreateClusterNotifyPort().
|
|
// Any exceptions thrown by CCluster::ReadClusterInfo().
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CCluster::Init(
|
|
IN OUT CClusterDoc * pdoc,
|
|
IN LPCTSTR lpszName,
|
|
IN HCLUSTER hOpenedCluster // = NULL
|
|
)
|
|
{
|
|
CWaitCursor wc;
|
|
TCHAR szClusterName[ MAX_PATH ];
|
|
|
|
ASSERT( Hkey() == NULL );
|
|
ASSERT( lstrlen( lpszName ) < sizeof( szClusterName ) / sizeof( TCHAR ) );
|
|
|
|
try
|
|
{
|
|
// If connecting the local machine, get its name.
|
|
if ( lstrcmp( lpszName, _T(".") ) == 0 )
|
|
{
|
|
DWORD nSize = sizeof( szClusterName ) / sizeof( TCHAR );
|
|
GetComputerName( szClusterName, &nSize );
|
|
} // if: connecting to the local machine
|
|
else
|
|
{
|
|
lstrcpy( szClusterName, lpszName );
|
|
} // else: not connecting to the local machine
|
|
|
|
// Open the cluster.
|
|
if ( hOpenedCluster == NULL )
|
|
{
|
|
pdoc->m_hcluster = HOpenCluster( lpszName );
|
|
if ( pdoc->m_hcluster == NULL )
|
|
{
|
|
ThrowStaticException( GetLastError(), IDS_OPEN_CLUSTER_ERROR, szClusterName );
|
|
} // if: error opening the cluster
|
|
} // if: no opened cluster passed in
|
|
else
|
|
{
|
|
pdoc->m_hcluster = hOpenedCluster;
|
|
} // if: cluster already opened
|
|
|
|
// Get the cluster registry key.
|
|
pdoc->m_hkeyCluster = GetClusterKey( pdoc->m_hcluster, MAXIMUM_ALLOWED );
|
|
if ( pdoc->m_hkeyCluster == NULL )
|
|
{
|
|
ThrowStaticException( GetLastError(), IDS_GET_CLUSTER_KEY_ERROR, szClusterName );
|
|
} // if: error opening the cluster key
|
|
|
|
// Call the base class method. We can use Hcluster() after calling this.
|
|
CClusterItem::Init( pdoc, szClusterName );
|
|
|
|
// Get the cluster registry key.
|
|
m_hkey = pdoc->m_hkeyCluster;
|
|
|
|
// Register this cluster with the notification port.
|
|
{
|
|
HCHANGE hchange;
|
|
|
|
// We want these notifications to go to the document, not us.
|
|
ASSERT( Pcnk() != NULL );
|
|
m_pcnk->m_cnkt = cnktDoc;
|
|
m_pcnk->m_pdoc = pdoc;
|
|
Trace( g_tagClusItemNotify, _T("CCluster::Init() - Registering for cluster notifications (%08.8x)"), Pcnk() );
|
|
|
|
// Create the notification port.
|
|
hchange = CreateClusterNotifyPort(
|
|
GetClusterAdminApp()->HchangeNotifyPort(),
|
|
Hcluster(),
|
|
(CLUSTER_CHANGE_NODE_ADDED
|
|
| CLUSTER_CHANGE_GROUP_ADDED
|
|
| CLUSTER_CHANGE_RESOURCE_ADDED
|
|
| CLUSTER_CHANGE_RESOURCE_TYPE_ADDED
|
|
| CLUSTER_CHANGE_RESOURCE_TYPE_DELETED
|
|
| CLUSTER_CHANGE_RESOURCE_TYPE_PROPERTY
|
|
| CLUSTER_CHANGE_NETWORK_ADDED
|
|
| CLUSTER_CHANGE_NETINTERFACE_ADDED
|
|
| CLUSTER_CHANGE_QUORUM_STATE
|
|
| CLUSTER_CHANGE_CLUSTER_STATE
|
|
| CLUSTER_CHANGE_CLUSTER_PROPERTY
|
|
| CLUSTER_CHANGE_REGISTRY_NAME
|
|
| CLUSTER_CHANGE_REGISTRY_ATTRIBUTES
|
|
| CLUSTER_CHANGE_REGISTRY_VALUE
|
|
| CLUSTER_CHANGE_REGISTRY_SUBTREE),
|
|
(DWORD_PTR) Pcnk()
|
|
);
|
|
if ( hchange == NULL )
|
|
{
|
|
ThrowStaticException( GetLastError(), IDS_CLUSTER_NOTIF_REG_ERROR, szClusterName );
|
|
} // if: error creating the notify port
|
|
ASSERT( hchange == GetClusterAdminApp()->HchangeNotifyPort() );
|
|
} // Register this cluster with the notification port
|
|
|
|
// Get the name of the cluster as recorded by the cluster.
|
|
ReadClusterInfo();
|
|
|
|
// Allocate lists.
|
|
m_plpciNetworkPriority = new CNetworkList;
|
|
if ( m_plpciNetworkPriority == NULL )
|
|
{
|
|
AfxThrowMemoryException();
|
|
} // if: error allocating the network list
|
|
|
|
// Read the initial state.
|
|
UpdateState();
|
|
} // try
|
|
catch ( CException * )
|
|
{
|
|
if ( pdoc->m_hkeyCluster != NULL )
|
|
{
|
|
ClusterRegCloseKey( pdoc->m_hkeyCluster );
|
|
pdoc->m_hkeyCluster = NULL;
|
|
m_hkey = NULL;
|
|
} // if: registry key opened
|
|
if ( ( pdoc->m_hcluster != NULL ) && ( pdoc->m_hcluster != hOpenedCluster ) )
|
|
{
|
|
CloseCluster( Hcluster() );
|
|
pdoc->m_hcluster = NULL;
|
|
} // if: group opened
|
|
m_bReadOnly = TRUE;
|
|
throw;
|
|
} // catch: CException
|
|
|
|
} //*** CCluster::Init()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::ReadItem
|
|
//
|
|
// Routine Description:
|
|
// Read the item parameters from the cluster database.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CNTException Errors from CClusterItem::DwReadValue() or
|
|
// CClusterItem::ReadItem().
|
|
// Any exceptions thrown by CCluster::ReadExtensions().
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CCluster::ReadItem( void )
|
|
{
|
|
DWORD dwStatus;
|
|
DWORD dwRetStatus = ERROR_SUCCESS;
|
|
CWaitCursor wc;
|
|
|
|
ASSERT( Hcluster() != NULL );
|
|
ASSERT( Hkey() != NULL );
|
|
|
|
if ( Hcluster() != NULL )
|
|
{
|
|
m_rgProps[epropDefaultNetworkRole].m_value.pdw = &m_nDefaultNetworkRole;
|
|
m_rgProps[epropDescription].m_value.pstr = &m_strDescription;
|
|
m_rgProps[epropEnableEventLogReplication].m_value.pb = &m_bEnableEventLogReplication;
|
|
m_rgProps[epropQuorumArbitrationTimeMax].m_value.pdw = &m_nQuorumArbitrationTimeMax;
|
|
m_rgProps[epropQuorumArbitrationTimeMin].m_value.pdw = &m_nQuorumArbitrationTimeMin;
|
|
|
|
// Call the base class method.
|
|
try
|
|
{
|
|
CClusterItem::ReadItem();
|
|
} // try
|
|
catch ( CNTException * pnte )
|
|
{
|
|
dwRetStatus = pnte->Sc();
|
|
pnte->Delete();
|
|
} // catch: CNTException
|
|
|
|
// Get the name of the cluster as recorded by the cluster.
|
|
ReadClusterInfo();
|
|
|
|
// Read and parse the common properties.
|
|
{
|
|
CClusPropList cpl;
|
|
|
|
Trace( g_tagCluster, _T("(%x) - CCluster::ReadItem() - Getting common properties"), this );
|
|
dwStatus = cpl.ScGetClusterProperties(
|
|
Hcluster(),
|
|
CLUSCTL_CLUSTER_GET_COMMON_PROPERTIES
|
|
);
|
|
if (dwStatus == ERROR_SUCCESS)
|
|
{
|
|
Trace( g_tagCluster, _T("(%x) - CCluster::ReadItem() - Parsing common properties"), this );
|
|
dwStatus = DwParseProperties(cpl);
|
|
} // if: properties read successfully
|
|
if (dwStatus != ERROR_SUCCESS)
|
|
{
|
|
Trace( g_tagError, _T("(%x) - CCluster::ReadItem() - Error 0x%08.8x getting or parsing common properties"), this, dwStatus );
|
|
|
|
// PROCNUM_OUT_OF_RANGE occurs when the server side
|
|
// (clussvc.exe) doesn't support the ClusterControl( )
|
|
// API. In this case, read the data using the cluster
|
|
// registry APIs.
|
|
if ( dwStatus == RPC_S_PROCNUM_OUT_OF_RANGE )
|
|
{
|
|
if ( Hkey() != NULL )
|
|
{
|
|
// Read the Description
|
|
dwStatus = DwReadValue( CLUSREG_NAME_CLUS_DESC, m_strDescription );
|
|
if ( ( dwStatus != ERROR_SUCCESS )
|
|
&& ( dwStatus != ERROR_FILE_NOT_FOUND ) )
|
|
{
|
|
dwRetStatus = dwStatus;
|
|
} // if: error reading the value
|
|
} // if: key is available
|
|
} // if: must be talking to an NT4 node
|
|
else
|
|
{
|
|
dwRetStatus = dwStatus;
|
|
} // else: not talking to an NT4 node
|
|
} // if: error reading or parsing properties
|
|
} // Read and parse the common properties
|
|
|
|
// Get quorum resource information.
|
|
{
|
|
LPWSTR pwszQResName = NULL;
|
|
LPWSTR pwszQuorumPath = NULL;
|
|
DWORD cchQResName;
|
|
DWORD cchQuorumPath;
|
|
|
|
// Get the size of the resource name.
|
|
cchQResName = 0;
|
|
cchQuorumPath = 0;
|
|
dwStatus = GetClusterQuorumResource(
|
|
Hcluster(),
|
|
NULL,
|
|
&cchQResName,
|
|
NULL,
|
|
&cchQuorumPath,
|
|
&m_nMaxQuorumLogSize
|
|
);
|
|
if ( ( dwStatus == ERROR_SUCCESS ) || ( dwStatus == ERROR_MORE_DATA ) )
|
|
{
|
|
// Allocate enough space for the data.
|
|
cchQResName++; // Don't forget the final null-terminator.
|
|
pwszQResName = new WCHAR[ cchQResName ];
|
|
cchQuorumPath++;
|
|
pwszQuorumPath = new WCHAR[ cchQuorumPath ];
|
|
ASSERT( pwszQResName != NULL && pwszQuorumPath != NULL );
|
|
|
|
|
|
// Read the resource name.
|
|
dwStatus = GetClusterQuorumResource(
|
|
Hcluster(),
|
|
pwszQResName,
|
|
&cchQResName,
|
|
pwszQuorumPath,
|
|
&cchQuorumPath,
|
|
&m_nMaxQuorumLogSize
|
|
);
|
|
} // if: got the size successfully
|
|
if ( dwStatus != ERROR_SUCCESS )
|
|
{
|
|
dwRetStatus = dwStatus;
|
|
} // if: error occurred
|
|
else
|
|
{
|
|
m_strQuorumResource = pwszQResName;
|
|
m_strQuorumPath = pwszQuorumPath;
|
|
ASSERT( m_strQuorumPath[ m_strQuorumPath.GetLength() - 1 ] == _T('\\') );
|
|
} // else: quorum resource info retrieved successfully
|
|
|
|
delete [] pwszQResName;
|
|
delete [] pwszQuorumPath;
|
|
} // Get the quorum resource name
|
|
|
|
// Read the FQDN for the cluster.
|
|
{
|
|
DWORD cbReturned;
|
|
DWORD cbFQDN;
|
|
LPWSTR pszFQDN = NULL;
|
|
|
|
pszFQDN = m_strFQDN.GetBuffer( 256 );
|
|
cbFQDN = 256 * sizeof( WCHAR );
|
|
dwStatus = ClusterControl(
|
|
Hcluster(),
|
|
NULL,
|
|
CLUSCTL_CLUSTER_GET_FQDN,
|
|
NULL,
|
|
NULL,
|
|
pszFQDN,
|
|
cbFQDN,
|
|
&cbReturned
|
|
);
|
|
if ( dwStatus == ERROR_MORE_DATA )
|
|
{
|
|
cbFQDN = cbReturned + sizeof( WCHAR );
|
|
pszFQDN = m_strFQDN.GetBuffer( ( cbReturned / sizeof( WCHAR ) ) + 1 );
|
|
dwStatus = ClusterControl(
|
|
Hcluster(),
|
|
NULL,
|
|
CLUSCTL_CLUSTER_GET_FQDN,
|
|
NULL,
|
|
NULL,
|
|
pszFQDN,
|
|
cbFQDN,
|
|
&cbReturned
|
|
);
|
|
} // if: buffer not large enough
|
|
if ( dwStatus != ERROR_SUCCESS )
|
|
{
|
|
// Handle the case where the API doesn't exist (e.g. NT4).
|
|
// also
|
|
// Handle the case where the control code is not known (e.g. Win2K)
|
|
if ( ( dwStatus == RPC_S_PROCNUM_OUT_OF_RANGE )
|
|
|| ( dwStatus == ERROR_INVALID_FUNCTION ) )
|
|
{
|
|
lstrcpy( pszFQDN, StrName() );
|
|
m_strFQDN.ReleaseBuffer();
|
|
}
|
|
else
|
|
{
|
|
dwRetStatus = dwStatus;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_strFQDN.ReleaseBuffer();
|
|
} // else: data retrieved successfully
|
|
} // if: no error yet
|
|
|
|
} // if: cluster is available
|
|
|
|
// If any errors occurred, throw an exception.
|
|
if ( dwRetStatus != ERROR_SUCCESS )
|
|
{
|
|
ThrowStaticException( dwRetStatus, IDS_READ_CLUSTER_PROPS_ERROR, StrName() );
|
|
} // if: error occurred
|
|
|
|
// Read extension lists.
|
|
ReadClusterExtensions();
|
|
ReadNodeExtensions();
|
|
ReadGroupExtensions();
|
|
ReadResourceExtensions();
|
|
ReadResTypeExtensions();
|
|
ReadNetworkExtensions();
|
|
ReadNetInterfaceExtensions();
|
|
|
|
// Read the initial state.
|
|
UpdateState();
|
|
|
|
MarkAsChanged( FALSE );
|
|
|
|
} //*** CCluster::ReadItem()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::PlstrExtensions
|
|
//
|
|
// Routine Description:
|
|
// Return the list of admin extensions.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// plstr List of extensions.
|
|
// NULL No extension associated with this object.
|
|
//
|
|
// Exceptions Thrown:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
const CStringList * CCluster::PlstrExtensions( void ) const
|
|
{
|
|
return &LstrClusterExtensions();
|
|
|
|
} //*** CCluster::PlstrExtensions()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::ReadClusterInfo
|
|
//
|
|
// Routine Description:
|
|
// Get the name of the cluster as recorded by the cluster and the
|
|
// version of the cluster software.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// Any exceptions thrown by new.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CCluster::ReadClusterInfo( void )
|
|
{
|
|
DWORD dwStatus;
|
|
LPWSTR pwszName = NULL;
|
|
DWORD cchName = 128;
|
|
CWaitCursor wc;
|
|
|
|
try
|
|
{
|
|
pwszName = new WCHAR[ cchName ];
|
|
if ( pwszName == NULL )
|
|
{
|
|
AfxThrowMemoryException();
|
|
} // if: error allocating the name buffer
|
|
m_cvi.dwVersionInfoSize = sizeof( m_cvi );
|
|
dwStatus = GetClusterInformation( Hcluster(), pwszName, &cchName, &m_cvi );
|
|
if ( dwStatus == ERROR_MORE_DATA )
|
|
{
|
|
delete [] pwszName;
|
|
cchName++;
|
|
pwszName = new WCHAR[ cchName ];
|
|
if ( pwszName == NULL )
|
|
{
|
|
AfxThrowMemoryException();
|
|
} // if: error allocating the name buffer
|
|
dwStatus = GetClusterInformation( Hcluster(), pwszName, &cchName, &m_cvi );
|
|
} // if: buffer is too small
|
|
if ( dwStatus == ERROR_SUCCESS )
|
|
{
|
|
Pdoc()->m_strName = pwszName;
|
|
} // if: error occurred
|
|
else
|
|
{
|
|
TraceError( _T("CCluster::Init() calling GetClusterInformation"), dwStatus );
|
|
} // else: no error occurred
|
|
m_strName = pwszName;
|
|
delete [] pwszName;
|
|
} // try
|
|
catch (CException *)
|
|
{
|
|
delete [] pwszName;
|
|
throw;
|
|
} // catch: CException
|
|
|
|
} //*** CCluster::ReadClusterInfo()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::ReadClusterExtensions
|
|
//
|
|
// Routine Description:
|
|
// Read the extension list for the cluster object.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CNTException Errors from CClusterItem::DwReadValue().
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CCluster::ReadClusterExtensions( void )
|
|
{
|
|
DWORD dwStatus;
|
|
CWaitCursor wc;
|
|
|
|
ASSERT( Hkey() != NULL );
|
|
|
|
if ( Hkey() != NULL )
|
|
{
|
|
// Read the Cluster extension string.
|
|
dwStatus = DwReadValue( CLUSREG_NAME_ADMIN_EXT, m_lstrClusterExtensions );
|
|
if ( ( dwStatus != ERROR_SUCCESS )
|
|
&& ( dwStatus != ERROR_FILE_NOT_FOUND ) )
|
|
{
|
|
ThrowStaticException( dwStatus );
|
|
} // if: error reading the value
|
|
} // if: key is available
|
|
else
|
|
{
|
|
m_lstrClusterExtensions.RemoveAll();
|
|
} // else: key is not available
|
|
|
|
} //*** CCluster::ReadClusterExtensions()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::ReadNodeExtensions
|
|
//
|
|
// Routine Description:
|
|
// Read the extension list for all nodes.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CNTException Errors from CClusterItem::DwReadValue().
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CCluster::ReadNodeExtensions( void )
|
|
{
|
|
DWORD dwStatus;
|
|
CWaitCursor wc;
|
|
|
|
ASSERT( Hkey() != NULL );
|
|
|
|
if ( Hkey() != NULL )
|
|
{
|
|
// Read the Nodes extension string.
|
|
dwStatus = DwReadValue( CLUSREG_NAME_ADMIN_EXT, CLUSREG_KEYNAME_NODES, m_lstrNodeExtensions );
|
|
if ( ( dwStatus != ERROR_SUCCESS )
|
|
&& ( dwStatus != ERROR_FILE_NOT_FOUND ) )
|
|
{
|
|
ThrowStaticException( dwStatus );
|
|
} // if: error reading the value
|
|
} // if: key is available
|
|
else
|
|
{
|
|
m_lstrNodeExtensions.RemoveAll();
|
|
} // else: key is not available
|
|
|
|
} //*** CCluster::ReadNodeExtensions()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::ReadGroupExtensions
|
|
//
|
|
// Routine Description:
|
|
// Read the extension list for all groups.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CNTException Errors from CClusterItem::DwReadValue().
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CCluster::ReadGroupExtensions( void )
|
|
{
|
|
DWORD dwStatus;
|
|
CWaitCursor wc;
|
|
|
|
ASSERT( Hkey() != NULL );
|
|
|
|
if ( Hkey() != NULL )
|
|
{
|
|
// Read the Groups extension string.
|
|
dwStatus = DwReadValue( CLUSREG_NAME_ADMIN_EXT, CLUSREG_KEYNAME_GROUPS, m_lstrGroupExtensions );
|
|
if ( ( dwStatus != ERROR_SUCCESS )
|
|
&& ( dwStatus != ERROR_FILE_NOT_FOUND ) )
|
|
{
|
|
ThrowStaticException( dwStatus );
|
|
} // if: error reading the value
|
|
} // if: key is available
|
|
else
|
|
{
|
|
m_lstrGroupExtensions.RemoveAll();
|
|
} // else: key is not available
|
|
|
|
} //*** CCluster::ReadGroupExtensions()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::ReadResourceExtensions
|
|
//
|
|
// Routine Description:
|
|
// Read the extension list for all resources.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CNTException Errors from CClusterItem::DwReadValue().
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CCluster::ReadResourceExtensions( void )
|
|
{
|
|
DWORD dwStatus;
|
|
CWaitCursor wc;
|
|
|
|
ASSERT( Hkey() != NULL );
|
|
|
|
if ( Hkey() != NULL )
|
|
{
|
|
// Read the Resources extension string.
|
|
dwStatus = DwReadValue( CLUSREG_NAME_ADMIN_EXT, CLUSREG_KEYNAME_RESOURCES, m_lstrResourceExtensions );
|
|
if ( ( dwStatus != ERROR_SUCCESS )
|
|
&& ( dwStatus != ERROR_FILE_NOT_FOUND ) )
|
|
{
|
|
ThrowStaticException( dwStatus );
|
|
} // if: error reading the value
|
|
} // if: key is available
|
|
else
|
|
{
|
|
m_lstrResourceExtensions.RemoveAll();
|
|
} // else: key is not available
|
|
|
|
} //*** CCluster::ReadResourceExtensions()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::ReadResTypeExtensions
|
|
//
|
|
// Routine Description:
|
|
// Read the extension list for all resouce types.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CNTException Errors from CClusterItem::DwReadValue().
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CCluster::ReadResTypeExtensions( void )
|
|
{
|
|
DWORD dwStatus;
|
|
CWaitCursor wc;
|
|
|
|
ASSERT( Hkey() != NULL );
|
|
|
|
if ( Hkey() != NULL )
|
|
{
|
|
// Read the Resource Types extension string.
|
|
dwStatus = DwReadValue( CLUSREG_NAME_ADMIN_EXT, CLUSREG_KEYNAME_RESOURCE_TYPES, m_lstrResTypeExtensions );
|
|
if ( ( dwStatus != ERROR_SUCCESS )
|
|
&& ( dwStatus != ERROR_FILE_NOT_FOUND ) )
|
|
{
|
|
ThrowStaticException( dwStatus );
|
|
} // if: error reading the value
|
|
} // if: key is available
|
|
else
|
|
{
|
|
m_lstrResTypeExtensions.RemoveAll();
|
|
} // else: key is not available
|
|
|
|
} //*** CCluster::ReadResTypeExtensions()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::ReadNetworkExtensions
|
|
//
|
|
// Routine Description:
|
|
// Read the extension list for all networks.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CNTException Errors from CClusterItem::DwReadValue().
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CCluster::ReadNetworkExtensions( void )
|
|
{
|
|
DWORD dwStatus;
|
|
CWaitCursor wc;
|
|
|
|
ASSERT( Hkey() != NULL );
|
|
|
|
if ( Hkey() != NULL )
|
|
{
|
|
// Read the Networks extension string.
|
|
dwStatus = DwReadValue( CLUSREG_NAME_ADMIN_EXT, CLUSREG_KEYNAME_NETWORKS, m_lstrNetworkExtensions );
|
|
if ( ( dwStatus != ERROR_SUCCESS )
|
|
&& ( dwStatus != ERROR_FILE_NOT_FOUND ) )
|
|
{
|
|
ThrowStaticException( dwStatus );
|
|
} // if: error reading the value
|
|
} // if: key is available
|
|
else
|
|
{
|
|
m_lstrNetworkExtensions.RemoveAll();
|
|
} // else: key is not available
|
|
|
|
} //*** CCluster::ReadNetworkExtensions()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::ReadNetInterfaceExtensions
|
|
//
|
|
// Routine Description:
|
|
// Read the extension list for all network interfaces.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CNTException Errors from CClusterItem::DwReadValue().
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CCluster::ReadNetInterfaceExtensions( void )
|
|
{
|
|
DWORD dwStatus;
|
|
CWaitCursor wc;
|
|
|
|
ASSERT( Hkey() != NULL );
|
|
|
|
if ( Hkey() != NULL )
|
|
{
|
|
// Read the Network Intefaces extension string.
|
|
dwStatus = DwReadValue( CLUSREG_NAME_ADMIN_EXT, CLUSREG_KEYNAME_NETINTERFACES, m_lstrNetInterfaceExtensions );
|
|
if ( ( dwStatus != ERROR_SUCCESS )
|
|
&& ( dwStatus != ERROR_FILE_NOT_FOUND ) )
|
|
{
|
|
ThrowStaticException( dwStatus );
|
|
} // if: error reading the value
|
|
} // if: key is available
|
|
else
|
|
{
|
|
m_lstrNetInterfaceExtensions.RemoveAll();
|
|
} // else: key is not available
|
|
|
|
} //*** CCluster::ReadNetInterfaceExtensions()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::CollecNetworkPriority
|
|
//
|
|
// Routine Description:
|
|
// Construct the network priority list.
|
|
//
|
|
// Arguments:
|
|
// plpci [IN OUT] List to fill.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CNTException Errors from ClusterOpenEnum() or ClusterEnum().
|
|
// Any exceptions thrown by new or CList::AddTail().
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CCluster::CollectNetworkPriority( IN OUT CNetworkList * plpci )
|
|
{
|
|
DWORD dwStatus;
|
|
HCLUSENUM hclusenum;
|
|
int ienum;
|
|
LPWSTR pwszName = NULL;
|
|
DWORD cchName;
|
|
DWORD cchmacName;
|
|
DWORD dwRetType;
|
|
CNetwork * pciNet;
|
|
CWaitCursor wc;
|
|
|
|
ASSERT_VALID( Pdoc() );
|
|
ASSERT( Hcluster() != NULL );
|
|
|
|
if ( plpci == NULL )
|
|
{
|
|
plpci = m_plpciNetworkPriority;
|
|
} // if: no list specified
|
|
|
|
ASSERT( plpci != NULL );
|
|
|
|
// Remove the previous contents of the list.
|
|
plpci->RemoveAll();
|
|
|
|
if ( Hcluster() != NULL )
|
|
{
|
|
// Open the enumeration.
|
|
hclusenum = ClusterOpenEnum( Hcluster(), (DWORD) CLUSTER_ENUM_INTERNAL_NETWORK );
|
|
if ( hclusenum == NULL )
|
|
{
|
|
ThrowStaticException( GetLastError(), IDS_ENUM_NETWORK_PRIORITY_ERROR, StrName() );
|
|
} // if: error opening the enmeration
|
|
|
|
try
|
|
{
|
|
// Allocate a name buffer.
|
|
cchmacName = 128;
|
|
pwszName = new WCHAR[ cchmacName ];
|
|
if ( pwszName == NULL )
|
|
{
|
|
AfxThrowMemoryException();
|
|
} // if: error allocating the name buffer
|
|
|
|
// Loop through the enumeration and add each network to the list.
|
|
for ( ienum = 0 ; ; ienum++ )
|
|
{
|
|
// Get the next item in the enumeration.
|
|
cchName = cchmacName;
|
|
dwStatus = ClusterEnum( hclusenum, ienum, &dwRetType, pwszName, &cchName );
|
|
if ( dwStatus == ERROR_MORE_DATA )
|
|
{
|
|
delete [] pwszName;
|
|
cchmacName = ++cchName;
|
|
pwszName = new WCHAR[ cchmacName ];
|
|
if ( pwszName == NULL )
|
|
{
|
|
AfxThrowMemoryException();
|
|
} // if: error allocating the name buffer
|
|
dwStatus = ClusterEnum( hclusenum, ienum, &dwRetType, pwszName, &cchName );
|
|
} // if: name buffer was too small
|
|
if ( dwStatus == ERROR_NO_MORE_ITEMS )
|
|
{
|
|
break;
|
|
} // if: done with the enumeraiton
|
|
else if ( dwStatus != ERROR_SUCCESS )
|
|
{
|
|
ThrowStaticException( dwStatus, IDS_ENUM_NETWORK_PRIORITY_ERROR, StrName() );
|
|
} // else if: error getting the next enumeration value
|
|
|
|
ASSERT( dwRetType == CLUSTER_ENUM_INTERNAL_NETWORK );
|
|
|
|
// Find the item in the list of networks on the document.
|
|
pciNet = Pdoc()->LpciNetworks().PciNetworkFromName( pwszName );
|
|
ASSERT_VALID( pciNet );
|
|
|
|
// Add the network to the list.
|
|
if ( pciNet != NULL )
|
|
{
|
|
plpci->AddTail( pciNet );
|
|
} // if: found network in list
|
|
|
|
} // for: each item in the group
|
|
|
|
ClusterCloseEnum( hclusenum );
|
|
|
|
} // try
|
|
catch ( CException * )
|
|
{
|
|
delete [] pwszName;
|
|
ClusterCloseEnum( hclusenum );
|
|
throw;
|
|
} // catch: any exception
|
|
} // if: cluster is available
|
|
|
|
delete [] pwszName;
|
|
|
|
} //*** CCluster::CollecNetworkPriority()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::OnUpdateProperties
|
|
//
|
|
// Routine Description:
|
|
// Determines whether menu items corresponding to ID_FILE_PROPERTIES
|
|
// should be enabled or not.
|
|
//
|
|
// Arguments:
|
|
// pCmdUI [IN OUT] Command routing object.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CCluster::OnUpdateProperties( CCmdUI * pCmdUI )
|
|
{
|
|
pCmdUI->Enable(TRUE);
|
|
|
|
} //*** CCluster::OnUpdateProperties()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::BDisplayProperties
|
|
//
|
|
// Routine Description:
|
|
// Display properties for the object.
|
|
//
|
|
// Arguments:
|
|
// bReadOnly [IN] Don't allow edits to the object properties.
|
|
//
|
|
// Return Value:
|
|
// TRUE OK pressed.
|
|
// FALSE OK not pressed.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CCluster::BDisplayProperties( IN BOOL bReadOnly )
|
|
{
|
|
BOOL bChanged = FALSE;
|
|
CClusterPropSheet sht( AfxGetMainWnd() );
|
|
|
|
// Do this in case this object is deleted while we are operating on it.
|
|
AddRef();
|
|
|
|
// If the object has changed, read it.
|
|
if ( BChanged() )
|
|
{
|
|
ReadItem();
|
|
} // if: object changed
|
|
|
|
// Display the property sheet.
|
|
try
|
|
{
|
|
sht.SetReadOnly( bReadOnly );
|
|
if ( sht.BInit( this, IimgObjectType() ) )
|
|
{
|
|
bChanged = ( ( sht.DoModal() == IDOK ) && ! bReadOnly );
|
|
} // if: initialized successfully
|
|
} // try
|
|
catch ( CException * pe )
|
|
{
|
|
pe->Delete();
|
|
} // catch: CException
|
|
|
|
Release();
|
|
return bChanged;
|
|
|
|
} //*** CCluster::BDisplayProperties()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::SetName
|
|
//
|
|
// Routine Description:
|
|
// Set the name of the cluster.
|
|
//
|
|
// Arguments:
|
|
// pszName [IN] New name of the cluster.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// Any exceptions thrown by WriteItem().
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CCluster::SetName( IN LPCTSTR pszName )
|
|
{
|
|
Rename( pszName );
|
|
|
|
} //*** CCluster::SetName()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::SetDescription
|
|
//
|
|
// Routine Description:
|
|
// Set the description in the cluster database.
|
|
//
|
|
// Arguments:
|
|
// pszDesc [IN] Description to set.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// Any exceptions thrown by WriteItem().
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CCluster::SetDescription( IN LPCTSTR pszDesc )
|
|
{
|
|
ASSERT( Hkey() != NULL );
|
|
|
|
if ( ( Hkey() != NULL ) && ( m_strDescription != pszDesc ) )
|
|
{
|
|
WriteValue( CLUSREG_NAME_CLUS_DESC, NULL, pszDesc );
|
|
m_strDescription = pszDesc;
|
|
} // if: a change occured
|
|
|
|
} //*** CCluster::SetDescription()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::SetQuorumResource
|
|
//
|
|
// Routine Description:
|
|
// Set the quorum resource for the cluster.
|
|
//
|
|
// Arguments:
|
|
// pszResource [IN] Name of resource to make the quorum resource.
|
|
// pszQuorumPath [IN] Path for storing cluster files.
|
|
// nMaxLogSize [IN] Maximum size of the quorum log.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CNTException IDS_SET_QUORUM_RESOURCE_ERROR - errors from
|
|
// SetClusterQuorumResource().
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CCluster::SetQuorumResource(
|
|
IN LPCTSTR pszResource,
|
|
IN LPCTSTR pszQuorumPath,
|
|
IN DWORD nMaxLogSize
|
|
)
|
|
{
|
|
DWORD dwStatus;
|
|
CResource * pciRes;
|
|
CString strRes( pszResource ); // Required if built non-Unicode
|
|
CWaitCursor wc;
|
|
|
|
ASSERT( pszResource != NULL );
|
|
|
|
if ( ( StrQuorumResource() != pszResource )
|
|
|| ( StrQuorumPath() != pszQuorumPath )
|
|
|| ( NMaxQuorumLogSize() != nMaxLogSize ) )
|
|
{
|
|
// Find the resource.
|
|
pciRes = Pdoc()->LpciResources().PciResFromName( pszResource );
|
|
ASSERT_VALID( pciRes );
|
|
ASSERT( pciRes->Hresource() != NULL );
|
|
|
|
if ( pciRes->Hresource() != NULL )
|
|
{
|
|
// Change the quorum resource.
|
|
dwStatus = SetClusterQuorumResource( pciRes->Hresource(), pszQuorumPath, nMaxLogSize );
|
|
if ( dwStatus != ERROR_SUCCESS )
|
|
{
|
|
ThrowStaticException( dwStatus, IDS_SET_QUORUM_RESOURCE_ERROR, pciRes->StrName() );
|
|
} // if: error setting the quorum resource
|
|
|
|
m_strQuorumResource = pszResource;
|
|
m_strQuorumPath = pszQuorumPath;
|
|
m_nMaxQuorumLogSize = nMaxLogSize;
|
|
} // if: resource is available
|
|
} // if: the quorum resource changed
|
|
|
|
} //*** CCluster::SetQuorumResource()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::SetNetworkPriority
|
|
//
|
|
// Routine Description:
|
|
// Set the network priority list.
|
|
//
|
|
// Arguments:
|
|
// rlpci [IN] List of networks in priority order.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// Any exceptions thrown by HNETWORK::new.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CCluster::SetNetworkPriority( IN const CNetworkList & rlpci )
|
|
{
|
|
DWORD dwStatus;
|
|
CWaitCursor wc;
|
|
|
|
ASSERT( Hcluster() != NULL );
|
|
|
|
if ( Hcluster() != NULL )
|
|
{
|
|
BOOL bChanged = TRUE;
|
|
|
|
// Determine if the list has changed.
|
|
if ( rlpci.GetCount() == LpciNetworkPriority().GetCount() )
|
|
{
|
|
POSITION posOld;
|
|
POSITION posNew;
|
|
CNetwork * pciOldNet;
|
|
CNetwork * pciNewNet;
|
|
|
|
bChanged = FALSE;
|
|
|
|
posOld = LpciNetworkPriority().GetHeadPosition();
|
|
posNew = rlpci.GetHeadPosition();
|
|
while ( posOld != NULL )
|
|
{
|
|
pciOldNet = (CNetwork *) LpciNetworkPriority().GetNext( posOld );
|
|
ASSERT_VALID( pciOldNet );
|
|
|
|
ASSERT( posNew != NULL );
|
|
pciNewNet = (CNetwork *) rlpci.GetNext( posNew );
|
|
ASSERT_VALID( pciNewNet );
|
|
|
|
if ( pciOldNet->StrName() != pciNewNet->StrName() )
|
|
{
|
|
bChanged = TRUE;
|
|
break;
|
|
} // if: name is not the same
|
|
} // while: more items in the old list
|
|
} // if: same number of items in the list
|
|
|
|
if ( bChanged )
|
|
{
|
|
HNETWORK * phnetwork = NULL;
|
|
|
|
try
|
|
{
|
|
DWORD ipci;
|
|
POSITION posPci;
|
|
CNetwork * pciNet;
|
|
|
|
// Allocate an array for all the node handles.
|
|
phnetwork = new HNETWORK[ (DWORD) rlpci.GetCount() ];
|
|
if ( phnetwork == NULL )
|
|
{
|
|
ThrowStaticException( GetLastError() );
|
|
} // if: error allocating network handle array
|
|
|
|
// Copy the handle of all the networks in the networks list to the handle aray.
|
|
posPci = rlpci.GetHeadPosition();
|
|
for ( ipci = 0 ; posPci != NULL ; ipci++ )
|
|
{
|
|
pciNet = (CNetwork *) rlpci.GetNext( posPci );
|
|
ASSERT_VALID( pciNet );
|
|
phnetwork[ ipci ] = pciNet->Hnetwork();
|
|
} // while: more networks in the list
|
|
|
|
// Set the property.
|
|
dwStatus = SetClusterNetworkPriorityOrder( Hcluster(), (DWORD) rlpci.GetCount(), phnetwork );
|
|
if ( dwStatus != ERROR_SUCCESS )
|
|
{
|
|
ThrowStaticException( dwStatus, IDS_SET_NET_PRIORITY_ERROR, StrName() );
|
|
} // if: error setting network priority
|
|
|
|
// Update the PCI list.
|
|
m_plpciNetworkPriority->RemoveAll();
|
|
posPci = rlpci.GetHeadPosition();
|
|
while ( posPci != NULL )
|
|
{
|
|
pciNet = (CNetwork *) rlpci.GetNext( posPci );
|
|
m_plpciNetworkPriority->AddTail( pciNet );
|
|
} // while: more items in the list
|
|
} // try
|
|
catch ( CException * )
|
|
{
|
|
delete [] phnetwork;
|
|
throw;
|
|
} // catch: CException
|
|
|
|
delete [] phnetwork;
|
|
|
|
} // if: list changed
|
|
} // if: key is available
|
|
|
|
} //*** CCluster::SetNetworkPriority(CNetworkList*)
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::Rename
|
|
//
|
|
// Routine Description:
|
|
// Change the name of the cluster..
|
|
//
|
|
// Arguments:
|
|
// pszName [IN] New name to give to the cluster.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
// Exceptions Thrown:
|
|
// CNTException Errors returned from SetClusterName().
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CCluster::Rename( IN LPCTSTR pszName )
|
|
{
|
|
DWORD dwStatus;
|
|
CWaitCursor wc;
|
|
|
|
ASSERT( Hcluster() != NULL );
|
|
|
|
if ( StrName() != pszName )
|
|
{
|
|
// Set the name.
|
|
dwStatus = SetClusterName( Hcluster(), pszName );
|
|
if ( dwStatus != ERROR_SUCCESS )
|
|
{
|
|
if ( dwStatus == ERROR_RESOURCE_PROPERTIES_STORED )
|
|
{
|
|
AfxMessageBox( IDS_RESTART_CLUSTER_NAME, MB_OK | MB_ICONEXCLAMATION );
|
|
} // if: properties stored but not in use yet
|
|
else
|
|
{
|
|
ThrowStaticException( dwStatus, IDS_RENAME_CLUSTER_ERROR, StrName(), pszName );
|
|
} // else: error occurred
|
|
} // if: error occurred setting cluster name
|
|
m_strName = pszName;
|
|
} // if: the name changed
|
|
|
|
} //*** CCluster::Rename()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::BIsLabelEditValueValid
|
|
//
|
|
// Routine Description:
|
|
// Validate the label edit value as a cluster name
|
|
//
|
|
// Arguments:
|
|
// pszName [IN] New name to give to the cluster.
|
|
//
|
|
// Return Value:
|
|
// TRUE name is valid
|
|
// FALSE name is invalid
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CCluster::BIsLabelEditValueValid( IN LPCTSTR pszName )
|
|
{
|
|
BOOL bSuccess = TRUE;
|
|
|
|
if ( StrName() != pszName )
|
|
{
|
|
CLRTL_NAME_STATUS cnStatus;
|
|
UINT idsError;
|
|
|
|
// Validate the name.
|
|
if ( ! ClRtlIsNetNameValid( pszName, &cnStatus, FALSE /*CheckIfExists*/ ) )
|
|
{
|
|
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();
|
|
ThrowStaticException( scError, IDS_ERROR_VALIDATING_NETWORK_NAME, pszName );
|
|
}
|
|
default:
|
|
idsError = IDS_INVALID_CLUSTER_NAME;
|
|
break;
|
|
} // switch: cnStatus
|
|
|
|
if ( idsError == IDS_INVALID_CLUSTER_NAME_INVALID_DNS_CHARS )
|
|
{
|
|
int id = AfxMessageBox(IDS_INVALID_CLUSTER_NAME_INVALID_DNS_CHARS, MB_YESNO | MB_DEFBUTTON2 | MB_ICONEXCLAMATION );
|
|
|
|
if ( id == IDNO )
|
|
{
|
|
bSuccess = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bSuccess = FALSE;
|
|
}
|
|
} // if: error validating the name
|
|
} // if: the name changed
|
|
|
|
return bSuccess;
|
|
} //*** CCluster::BIsLabelEditValueValid()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::OnBeginLabelEdit
|
|
//
|
|
// Routine Description:
|
|
// Prepare an edit control in a view for editing the cluster name.
|
|
//
|
|
// Arguments:
|
|
// pedit [IN OUT] Edit control to prepare.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CCluster::OnBeginLabelEdit( IN OUT CEdit * pedit )
|
|
{
|
|
ASSERT_VALID(pedit);
|
|
|
|
pedit->SetLimitText( MAX_CLUSTERNAME_LENGTH );
|
|
pedit->ModifyStyle( 0 /*dwRemove*/, ES_UPPERCASE | ES_OEMCONVERT /*dwAdd*/ );
|
|
|
|
} //*** CCluster::OnBeginLabelEdit()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CCluster::UpdateState
|
|
//
|
|
// Routine Description:
|
|
// Update the current state of the item.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CCluster::UpdateState( void )
|
|
{
|
|
// NOTENOTE: not referneced
|
|
//CClusterAdminApp * papp = GetClusterAdminApp();
|
|
|
|
CString strTitle;
|
|
|
|
GetClusterAdminApp();
|
|
|
|
Trace( g_tagCluster, _T("(%s) - Updating state"), StrName() );
|
|
|
|
// Update the title of the document.
|
|
ASSERT_VALID( Pdoc() );
|
|
try
|
|
{
|
|
Pdoc()->UpdateTitle();
|
|
} // try
|
|
catch ( CException * pe )
|
|
{
|
|
pe->Delete();
|
|
} // catch: CException
|
|
|
|
// Call the base class method.
|
|
CClusterItem::UpdateState();
|
|
|
|
} //*** CCluster::UpdateState()
|