|
|
/////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1997-2002 Microsoft Corporation
//
// Module Name:
// ClusNode.cpp
//
// Description:
// Implementation of the node classes for the MSCLUS automation classes.
//
// Author:
// Charles Stacy Harris (stacyh) 28-Feb-1997
// Galen Barbee (galenb) July 1998
//
// Revision History:
// July 1998 GalenB Maaaaaajjjjjjjjjoooooorrrr clean up
//
// Notes:
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ClusterObject.h"
#include "property.h"
#include "clusres.h"
#include "clusresg.h"
#include "clusneti.h"
#include "clusnode.h"
/////////////////////////////////////////////////////////////////////////////
// Global variables
/////////////////////////////////////////////////////////////////////////////
static const IID * iidCClusNode[] = { &IID_ISClusNode };
static const IID * iidCClusNodes[] = { &IID_ISClusNodes };
static const IID * iidCClusResGroupPreferredOwnerNodes[] = { &IID_ISClusResGroupPreferredOwnerNodes };
static const IID * iidCClusResPossibleOwnerNodes[] = { &IID_ISClusResPossibleOwnerNodes };
static const IID * iidCClusResTypePossibleOwnerNodes[] = { &IID_ISClusResTypePossibleOwnerNodes };
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CClusNode class
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNode::CClusNode
//
// Description:
// Constructor.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CClusNode::CClusNode( void ) { m_hNode = NULL; m_pClusRefObject = NULL; m_pResourceGroups = NULL; m_pCommonProperties = NULL; m_pPrivateProperties = NULL; m_pCommonROProperties = NULL; m_pPrivateROProperties = NULL; m_pNetInterfaces = NULL;
m_piids = (const IID *) iidCClusNode; m_piidsSize = ARRAYSIZE( iidCClusNode );
} //*** CClusNode::CClusNode()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNode::~CClusNode
//
// Description:
// Destructor.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CClusNode::~CClusNode( void ) { if ( m_hNode != NULL ) { ::CloseClusterNode( m_hNode ); m_hNode = NULL; } // if:
if ( m_pResourceGroups != NULL ) { m_pResourceGroups->Release(); m_pResourceGroups = NULL; } // if:
if ( m_pCommonProperties != NULL ) { m_pCommonProperties->Release(); m_pCommonProperties = NULL; } // if: release the property collection
if ( m_pPrivateProperties != NULL ) { m_pPrivateProperties->Release(); m_pPrivateProperties = NULL; } // if: release the property collection
if ( m_pCommonROProperties != NULL ) { m_pCommonROProperties->Release(); m_pCommonROProperties = NULL; } // if: release the property collection
if ( m_pPrivateROProperties != NULL ) { m_pPrivateROProperties->Release(); m_pPrivateROProperties = NULL; } // if: release the property collection
if ( m_pNetInterfaces != NULL ) { m_pNetInterfaces->Release(); m_pNetInterfaces = NULL; } // if:
if ( m_pClusRefObject != NULL ) { m_pClusRefObject->Release(); m_pClusRefObject = NULL; } // if:
} //*** CClusNode::~CClusNode()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNode::Open
//
// Description:
// Retrieve this object's (Node) data from the cluster.
//
// Arguments:
// pClusRefObject [IN] - Wraps the cluster handle.
// bstrNodeName [IN] - The name of the node to open.
//
// Return Value:
// S_OK if successful, E_POINTER, or other Win32 error as HRESULT.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusNode::Open( IN ISClusRefObject * pClusRefObject, IN BSTR bstrNodeName ) { ASSERT( pClusRefObject != NULL ); ASSERT( bstrNodeName != NULL);
HRESULT _hr = E_POINTER;
if ( ( pClusRefObject != NULL ) && ( bstrNodeName != NULL ) ) { m_pClusRefObject = pClusRefObject; m_pClusRefObject->AddRef();
HCLUSTER hCluster = NULL;
_hr = m_pClusRefObject->get_Handle( (ULONG_PTR *) &hCluster ); if ( SUCCEEDED( _hr ) ) { m_hNode = ::OpenClusterNode( hCluster, bstrNodeName ); if ( m_hNode == 0 ) { DWORD _sc = GetLastError();
_hr = HRESULT_FROM_WIN32( _sc ); } // if: the node failed to open
else { m_bstrNodeName = bstrNodeName; _hr = S_OK; } // else: we opened the node
} // if: we have a cluster handle
} // if: non NULL args
return _hr;
} //*** CClusNode::Open()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNode::GetProperties
//
// Description:
// Creates a property collection for this object type (Node).
//
// Arguments:
// ppProperties [OUT] - Catches the newly created collection.
// bPrivate [IN] - Are these private properties? Or Common?
// bReadOnly [IN] - Are these read only properties?
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusNode::GetProperties( ISClusProperties ** ppProperties, BOOL bPrivate, BOOL bReadOnly ) { //ASSERT( ppProperties != NULL );
HRESULT _hr = E_POINTER;
if ( ppProperties != NULL ) { CComObject< CClusProperties > * pProperties = NULL;
*ppProperties = NULL;
_hr = CComObject< CClusProperties >::CreateInstance( &pProperties ); if ( SUCCEEDED( _hr ) ) { CSmartPtr< CComObject< CClusProperties > > ptrProperties( pProperties );
_hr = ptrProperties->Create( this, bPrivate, bReadOnly ); if ( SUCCEEDED( _hr ) ) { _hr = ptrProperties->Refresh(); if ( SUCCEEDED( _hr ) ) { _hr = ptrProperties->QueryInterface( IID_ISClusProperties, (void **) ppProperties ); if ( SUCCEEDED( _hr ) ) { ptrProperties->AddRef();
if ( bPrivate ) { if ( bReadOnly ) { m_pPrivateROProperties = ptrProperties; } else { m_pPrivateProperties = ptrProperties; } } else { if ( bReadOnly ) { m_pCommonROProperties = ptrProperties; } else { m_pCommonProperties = ptrProperties; } } } } } } } // if: non NULL args
return _hr;
} //*** CClusNode::GetProperties()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNode::get_Handle
//
// Description:
// Get the native handle for this object (Node).
//
// Arguments:
// phandle [OUT] - Catches the handle.
//
// Return Value:
// S_OK if successful, or E_POINTER.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusNode::get_Handle( OUT ULONG_PTR * phandle ) { //ASSERT( phandle != NULL );
ASSERT( m_hNode != NULL );
HRESULT _hr = E_POINTER;
if ( phandle != NULL ) { if ( m_hNode != NULL ) { *phandle = (ULONG_PTR) m_hNode; _hr = S_OK; } // if: node handle not NULL
} // if: argument no NULL
return _hr;
} //*** CClusNode::get_Handle()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNode::Close
//
// Description:
// Close this object (Node).
//
// Arguments:
// None.
//
// Return Value:
// S_OK if successful, or other Win32 error as HRESULT.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusNode::Close( void ) { HRESULT _hr = S_FALSE;
if ( m_hNode != NULL ) { if ( ::CloseClusterNode( m_hNode ) ) { m_hNode = NULL; _hr = S_OK; } else { DWORD _sc = GetLastError();
_hr = HRESULT_FROM_WIN32( _sc ); } }
return _hr;
} //*** CClusNode::Close()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNode::get_Name
//
// Description:
// Return the name of this object (Node).
//
// Arguments:
// pbstrNodeName [OUT] - Catches the name of this object.
//
// Return Value:
// S_OK if successful, E_POINTER, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusNode::get_Name( BSTR * pbstrNodeName ) { //ASSERT( pbstrNodeName != NULL );
HRESULT _hr = E_POINTER;
if ( pbstrNodeName != NULL ) { *pbstrNodeName = m_bstrNodeName.Copy(); _hr = S_OK; }
return _hr;
} //*** CClusNode::get_Name()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNode::get_NodeID
//
// Description:
// Get the ID of this node.
//
// Arguments:
// pbstrNodeID [OUT] - Catches the node id.
//
// Return Value:
// S_OK if successful, E_POINTER, or other Win32 error as HRESULT.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusNode::get_NodeID( OUT BSTR * pbstrNodeID ) { //ASSERT( pbstrNodeID != NULL );
HRESULT _hr = E_POINTER;
if ( pbstrNodeID != NULL ) { LPWSTR pwszNodeID; DWORD dwRet = ERROR_SUCCESS;
dwRet = ::WrapGetClusterNodeId( m_hNode, &pwszNodeID ); if ( dwRet == ERROR_SUCCESS ) { *pbstrNodeID = ::SysAllocString( pwszNodeID ); if ( *pbstrNodeID == NULL ) { _hr = E_OUTOFMEMORY; }
::LocalFree( pwszNodeID ); } // if: got node ID...
_hr = HRESULT_FROM_WIN32( dwRet ); }
return _hr;
} //*** CClusNode::get_NodeID()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNode::get_State
//
// Description:
// Get the current state of the cluster node. Up/down/paused, etc.
//
// Arguments:
// pState [OUT] - Catches the node state.
//
// Return Value:
// S_OK if successful, E_POINTER, or other Win32 error as HRESULT.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusNode::get_State( OUT CLUSTER_NODE_STATE * pState ) { //ASSERT( pState != NULL );
HRESULT _hr = E_POINTER;
if ( pState != NULL ) { CLUSTER_NODE_STATE cns;
cns = ::GetClusterNodeState( m_hNode ); if ( cns == ClusterNodeStateUnknown ) { DWORD _sc = GetLastError();
_hr = HRESULT_FROM_WIN32( _sc ); } else { *pState = cns; _hr = S_OK; } }
return _hr;
} //*** CClusNode::get_State()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNode::Pause
//
// Description:
// Pause this cluster node.
//
// Arguments:
// None.
//
// Return Value:
// S_OK if successful, E_POINTER, or other Win32 error as HRESULT.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusNode::Pause( void ) { HRESULT _hr = E_POINTER;
if ( m_hNode != NULL ) { DWORD _sc = ::PauseClusterNode( m_hNode );
_hr = HRESULT_FROM_WIN32( _sc ); }
return _hr;
} //*** CClusNode::Pause()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNode::Resume
//
// Description:
// Resume this paused cluster node.
//
// Arguments:
// None.
//
// Return Value:
// S_OK if successful, E_POINTER, or other Win32 error as HRESULT.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusNode::Resume( void ) { HRESULT _hr = E_POINTER;
if ( m_hNode != NULL ) { DWORD _sc = ::ResumeClusterNode( m_hNode );
_hr = HRESULT_FROM_WIN32( _sc ); }
return _hr;
} //*** CClusNode::Resume()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNode::Evict
//
// Description:
// Evict this node from the cluster.
//
// Arguments:
// None.
//
// Return Value:
// S_OK if successful, E_POINTER, or other Win32 error as HRESULT.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusNode::Evict( void ) { HRESULT _hr = E_POINTER;
if ( m_hNode != NULL ) { DWORD _sc = ::EvictClusterNode( m_hNode );
_hr = HRESULT_FROM_WIN32( _sc ); }
return _hr;
} //*** CClusNode::Evict()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNode::get_ResourceGroups
//
// Description:
// Get the collection of groups that are active on this node.
//
// Arguments:
// ppResourceGroups [OUT] - Catches the collection of groups.
//
// Return Value:
// S_OK if successful, E_POINTER, or other Win32 error as HRESULT.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusNode::get_ResourceGroups( OUT ISClusResGroups ** ppResourceGroups ) { return ::HrCreateResourceCollection< CClusResGroups, ISClusResGroups, CComBSTR >( &m_pResourceGroups, m_bstrNodeName, ppResourceGroups, IID_ISClusResGroups, m_pClusRefObject );
} //*** CClusNode::get_ResourceGroups()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNode::get_CommonProperties
//
// Description:
// Get this object's (Node) common properties collection.
//
// Arguments:
// ppProperties [OUT] - Catches the properties collection.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusNode::get_CommonProperties( OUT ISClusProperties ** ppProperties ) { //ASSERT( ppProperties != NULL );
HRESULT _hr = E_POINTER;
if ( ppProperties != NULL ) { if ( m_pCommonProperties ) { _hr = m_pCommonProperties->QueryInterface( IID_ISClusProperties, (void **) ppProperties ); } else { _hr = GetProperties( ppProperties, FALSE, FALSE ); } }
return _hr;
} //*** CClusNode::get_CommonProperties()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNode::get_PrivateProperties
//
// Description:
// Get this object's (Node) private properties collection.
//
// Arguments:
// ppProperties [OUT] - Catches the properties collection.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusNode::get_PrivateProperties( OUT ISClusProperties ** ppProperties ) { //ASSERT( ppProperties != NULL );
HRESULT _hr = E_POINTER;
if ( ppProperties != NULL ) { if ( m_pPrivateProperties ) { _hr = m_pPrivateProperties->QueryInterface( IID_ISClusProperties, (void **) ppProperties ); } else { _hr = GetProperties( ppProperties, TRUE, FALSE ); } }
return _hr;
} //*** CClusNode::get_PrivateProperties()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNode::get_CommonROProperties
//
// Description:
// Get this object's (Node) common read only properties collection.
//
// Arguments:
// ppProperties [OUT] - Catches the properties collection.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusNode::get_CommonROProperties( OUT ISClusProperties ** ppProperties ) { //ASSERT( ppProperties != NULL );
HRESULT _hr = E_POINTER;
if ( ppProperties != NULL ) { if ( m_pCommonROProperties ) { _hr = m_pCommonROProperties->QueryInterface( IID_ISClusProperties, (void **) ppProperties ); } else { _hr = GetProperties( ppProperties, FALSE, TRUE ); } }
return _hr;
} //*** CClusNode::get_CommonROProperties()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNode::get_PrivateROProperties
//
// Description:
// Get this object's (Node) private read only properties collection.
//
// Arguments:
// ppProperties [OUT] - Catches the properties collection.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusNode::get_PrivateROProperties( OUT ISClusProperties ** ppProperties ) { //ASSERT( ppProperties != NULL );
HRESULT _hr = E_POINTER;
if ( ppProperties != NULL ) { if ( m_pPrivateROProperties ) { _hr = m_pPrivateROProperties->QueryInterface( IID_ISClusProperties, (void **) ppProperties ); } else { _hr = GetProperties( ppProperties, TRUE, TRUE ); } }
return _hr;
} //*** CClusNode::get_PrivateROProperties()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNode::get_NetInterfaces
//
// Description:
// Get this object's (Node) network interfaces collection.
//
// Arguments:
// ppNetInterfaces [OUT] - Catches the network interfaces collection.
//
// Return Value:
// S_OK if successful, E_POINTER, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusNode::get_NetInterfaces( OUT ISClusNodeNetInterfaces ** ppNetInterfaces ) { return ::HrCreateResourceCollection< CClusNodeNetInterfaces, ISClusNodeNetInterfaces, HNODE >( &m_pNetInterfaces, m_hNode, ppNetInterfaces, IID_ISClusNodeNetInterfaces, m_pClusRefObject );
} //*** CClusNode::get_NetInterfaces()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNode::get_Cluster
//
// Description:
// Returns the parent cluster of this node.
//
// Arguments:
// ppCluster [OUT] - Catches the cluster parent.
//
// Return Value:
// S_OK if successful, E_POINTER, or other Win32 error as HRESULT.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusNode::get_Cluster( OUT ISCluster ** ppCluster ) { return ::HrGetCluster( ppCluster, m_pClusRefObject );
} //*** CClusNode::get_Cluster()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNode::HrLoadProperties
//
// Description:
// This virtual function does the actual load of the property list from
// the cluster.
//
// Arguments:
// rcplPropList [IN OUT] - The property list to load.
// bReadOnly [IN] - Load the read only properties?
// bPrivate [IN] - Load the common or the private properties?
//
// Return Value:
// S_OK if successful, or other Win32 error as HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusNode::HrLoadProperties( IN OUT CClusPropList & rcplPropList, IN BOOL bReadOnly, IN BOOL bPrivate ) { HRESULT _hr = S_FALSE; DWORD _dwControlCode = 0; DWORD _sc = ERROR_SUCCESS;
if ( bReadOnly ) { _dwControlCode = bPrivate ? CLUSCTL_NODE_GET_RO_PRIVATE_PROPERTIES : CLUSCTL_NODE_GET_RO_COMMON_PROPERTIES; } else { _dwControlCode = bPrivate ? CLUSCTL_NODE_GET_PRIVATE_PROPERTIES : CLUSCTL_NODE_GET_COMMON_PROPERTIES; }
_sc = rcplPropList.ScGetNodeProperties( m_hNode, _dwControlCode );
_hr = HRESULT_FROM_WIN32( _sc );
return _hr;
} //*** CClusNode::HrLoadProperties()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNode::ScWriteProperties
//
// Description:
// This virtual function does the actual saving of the property list to
// the cluster.
//
// Arguments:
// rcplPropList [IN] - The property list to save.
// bPrivate [IN] - Save the common or the private properties?
//
// Return Value:
// ERROR_SUCCESS if successful, or other Win32 error if not.
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD CClusNode::ScWriteProperties( const CClusPropList & rcplPropList, BOOL bPrivate ) { DWORD dwControlCode = bPrivate ? CLUSCTL_NODE_SET_PRIVATE_PROPERTIES : CLUSCTL_NODE_SET_COMMON_PROPERTIES; DWORD nBytesReturned = 0; DWORD _sc = ERROR_SUCCESS;
_sc = ClusterNodeControl( m_hNode, NULL, dwControlCode, rcplPropList, rcplPropList.CbBufferSize(), 0, 0, &nBytesReturned );
return _sc;
} //*** CClusNode::ScWriteProperties()
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CNodes class
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//++
//
// CNodes::CNodes
//
// Description:
// Constructor. This class implements functionality common to all node
// collections.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CNodes::CNodes( void ) { m_pClusRefObject = NULL;
} //*** CNodes::CNodes()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CNodes::~CNodes
//
// Description:
// Desctructor.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CNodes::~CNodes( void ) { Clear();
if ( m_pClusRefObject != NULL ) { m_pClusRefObject->Release(); m_pClusRefObject = NULL; } // if:
} //*** CNodes::~CNodes()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CNodes::Create
//
// Description:
// Finish creating the object by doing things that cannot be done in
// a light weight constructor.
//
// Arguments:
// pClusRefObject [IN] - Wraps the cluster handle.
//
// Return Value:
// S_OK if successful or E_POINTER if not.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CNodes::Create( IN ISClusRefObject * pClusRefObject ) { ASSERT( pClusRefObject != NULL );
HRESULT _hr = E_POINTER;
if ( pClusRefObject != NULL ) { m_pClusRefObject = pClusRefObject; m_pClusRefObject->AddRef(); _hr = S_OK; }
return _hr;
} //*** CNodes::Create()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CNodes::Clear
//
// Description:
// Release the objects in the vector and clean up the vector.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CNodes::Clear( void ) { ::ReleaseAndEmptyCollection< NodeList, CComObject< CClusNode > >( m_Nodes );
} //*** CNodes::Clear()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CNodes::FindItem
//
// Description:
// Find the passed in node in the vector and return its index.
//
// Arguments:
// pwszNodeName [IN] - The node to find.
// pnIndex [OUT] - Catches the node's index.
//
// Return Value:
// S_OK if successful, E_POINTER, or E_INVALIDARG.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CNodes::FindItem( IN LPWSTR pwszNodeName, OUT UINT * pnIndex ) { //ASSERT( pwszNodeName != NULL );
//ASSERT( pnIndex != NULL );
HRESULT _hr = E_POINTER;
if ( ( pwszNodeName != NULL ) && ( pnIndex != NULL ) ) { _hr = E_INVALIDARG;
if ( ! m_Nodes.empty() ) { CComObject< CClusNode > * pNode = NULL; NodeList::iterator first = m_Nodes.begin(); NodeList::iterator last = m_Nodes.end(); UINT _iIndex;
for ( _iIndex = 0; first != last; first++, _iIndex++ ) { pNode = *first;
if ( pNode && ( lstrcmpi( pwszNodeName, pNode->Name() ) == 0 ) ) { *pnIndex = _iIndex; _hr = S_OK; break; } } } // if:
}
return _hr;
} //*** CNodes::FindItem( pwszNodeName )
/////////////////////////////////////////////////////////////////////////////
//++
//
// CNodes::FindItem
//
// Description:
// Find the passed in node in the vector and return its index.
//
// Arguments:
// pClusterNode [IN] - The node to find.
// pnIndex [OUT] - Catches the node's index.
//
// Return Value:
// S_OK if successful, E_POINTER, or E_INVALIDARG.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CNodes::FindItem( IN ISClusNode * pClusterNode, OUT UINT * pnIndex ) { //ASSERT( pClusterNode != NULL );
//ASSERT( pnIndex != NULL );
HRESULT _hr = E_POINTER;
if ( ( pClusterNode != NULL ) && ( pnIndex != NULL ) ) { CComBSTR bstrName;
_hr = pClusterNode->get_Name( &bstrName ); if ( SUCCEEDED( _hr ) ) { _hr = FindItem( bstrName, pnIndex ); } }
return _hr;
} //*** CNodes::FindItem( pClusterNode )
/////////////////////////////////////////////////////////////////////////////
//++
//
// CNodes::GetIndex
//
// Description:
// Convert the passed in variant index into the real index in the
// collection.
//
// Arguments:
// varIndex [IN] - The index to convert.
// pnIndex [OUT] - Catches the index.
//
// Return Value:
// S_OK if successful, E_POINTER, or E_INVALIDARG.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CNodes::GetIndex( IN VARIANT varIndex, OUT UINT * pnIndex ) { //ASSERT( pnIndex != NULL );
HRESULT _hr = E_POINTER;
if ( pnIndex != NULL ) { UINT nIndex = 0; CComVariant v;
*pnIndex = 0;
v.Copy( &varIndex );
// Check to see if the index is a number.
_hr = v.ChangeType( VT_I4 ); if ( SUCCEEDED( _hr ) ) { nIndex = v.lVal; nIndex--; // Adjust index to be 0 relative instead of 1 relative
} else { // Check to see if the index is a string.
_hr = v.ChangeType( VT_BSTR ); if ( SUCCEEDED( _hr ) ) { // Search for the string.
_hr = FindItem( v.bstrVal, &nIndex ); } }
// We found an index, now check the range.
if ( SUCCEEDED( _hr ) ) { if ( nIndex < m_Nodes.size() ) { *pnIndex = nIndex; } else { _hr = E_INVALIDARG; } } }
return _hr;
} //*** CNodes::GetIndex()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CNodes::GetItem
//
// Description:
// Return the item (Node) by name.
//
// Arguments:
// pwszNodeName [IN] - The name of the item requested.
// ppClusterNode [OUT] - Catches the item.
//
// Return Value:
// S_OK if successful, E_POINTER, or E_INVALIDARG.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CNodes::GetItem( IN LPWSTR pwszNodeName, OUT ISClusNode ** ppClusterNode ) { //ASSERT( pwszNodeName != NULL );
//ASSERT( ppClusterNode != NULL );
HRESULT _hr = E_POINTER;
if ( ( pwszNodeName != NULL ) && ( ppClusterNode != NULL ) ) { CComObject< CClusNode > * pNode = NULL; NodeList::iterator first = m_Nodes.begin(); NodeList::iterator last = m_Nodes.end();
_hr = E_INVALIDARG;
for ( ; first != last; first++ ) { pNode = *first;
if ( pNode && ( lstrcmpi( pwszNodeName, pNode->Name() ) == 0 ) ) { _hr = pNode->QueryInterface( IID_ISClusNode, (void **) ppClusterNode ); break; } } }
return _hr;
} //*** CNodes::GetItem()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CNodes::GetItem
//
// Description:
// Return the item (Node) by index.
//
// Arguments:
// nIndex [IN] - The name of the item requested.
// ppClusterNode [OUT] - Catches the item.
//
// Return Value:
// S_OK if successful, E_POINTER, or E_INVALIDARG.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CNodes::GetItem( IN UINT nIndex, OUT ISClusNode ** ppClusterNode ) { //ASSERT( ppClusterNode != NULL );
HRESULT _hr = E_POINTER;
if ( ppClusterNode != NULL ) { //
// Automation collections are 1-relative for languages like VB.
// We are 0-relative internally.
//
if ( ( --nIndex ) < m_Nodes.size() ) { CComObject< CClusNode > * pNode = m_Nodes[ nIndex ];
_hr = pNode->QueryInterface( IID_ISClusNode, (void **) ppClusterNode ); } else { _hr = E_INVALIDARG; } }
return _hr;
} //*** CNodes::GetItem()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CNodes::GetNodeItem
//
// Description:
// Return the object (Node) at the passed in index.
//
// Arguments:
// varIndex [IN] - Contains the index requested.
// ppClusterNode [OUT] - Catches the item.
//
// Return Value:
// S_OK if successful, E_POINTER, or E_INVALIDARG.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CNodes::GetNodeItem( IN VARIANT varIndex, OUT ISClusNode ** ppClusterNode ) { //ASSERT( ppClusterNode != NULL );
HRESULT _hr = E_POINTER;
if ( ppClusterNode != NULL ) { CComObject<CClusNode> * pNode = NULL; UINT nIndex = 0;
*ppClusterNode = NULL;
_hr = GetIndex( varIndex, &nIndex ); if ( SUCCEEDED( _hr ) ) { pNode = m_Nodes[ nIndex ]; _hr = pNode->QueryInterface( IID_ISClusNode, (void **) ppClusterNode ); } }
return _hr;
} //*** CNodes::GetNodeItem()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CNodes::InsertAt
//
// Description:
// Insert the passed in node into the node list.
//
// Arguments:
// pClusNode [IN] - The node to add.
// pos [IN] - The position to insert the node at.
//
// Return Value:
// E_POINTER, E_INVALIDARG, or S_OK if successful.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CNodes::InsertAt( CComObject< CClusNode > * pClusNode, size_t pos ) { //ASSERT( pClusNode != NULL );
HRESULT _hr = E_POINTER;
if ( pClusNode != NULL ) { if ( pos < m_Nodes.size() ) { NodeList::iterator first = m_Nodes.begin(); NodeList::iterator last = m_Nodes.end(); size_t _iIndex;
for ( _iIndex = 0; ( _iIndex < pos ) && ( first != last ); _iIndex++, first++ ) { } // for:
m_Nodes.insert( first, pClusNode ); pClusNode->AddRef(); _hr = S_OK; } else { _hr = E_INVALIDARG; } }
return _hr;
} //*** CNodes::InsertAt()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CNodes::RemoveAt
//
// Description:
// Remove the object from the vector at the passed in position.
//
// Arguments:
// pos [IN] - the position of the object to remove.
//
// Return Value:
// S_OK if successful, or E_INVALIDARG if the position is out of range.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CNodes::RemoveAt( size_t pos ) { CComObject<CClusNode> * pNode = NULL; NodeList::iterator first = m_Nodes.begin(); NodeList::const_iterator last = m_Nodes.end(); HRESULT _hr = E_INVALIDARG; size_t _iIndex;
for ( _iIndex = 0; ( _iIndex < pos ) && ( first != last ); _iIndex++, first++ ) { } // for:
if ( first != last ) { pNode = *first; if ( pNode ) { pNode->Release(); }
m_Nodes.erase( first ); _hr = S_OK; }
return _hr;
} //*** CNodes::RemoveAt()
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CClusNodes class
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNodes::CClusNodes
//
// Description:
// Constructor.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CClusNodes::CClusNodes( void ) { m_piids = (const IID *) iidCClusNodes; m_piidsSize = ARRAYSIZE( iidCClusNodes );
} //*** CClusNodes::CClusNodes()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNodes::~CClusNodes
//
// Description:
// destructor.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CClusNodes::~CClusNodes( void ) { Clear();
} //*** CClusNodes::~CClusNodes()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNodes::get_Count
//
// Description:
// Return the count of objects (Nodes) in the collection.
//
// Arguments:
// plCount [OUT] - Catches the count.
//
// Return Value:
// S_OK if successful, or E_POINTER.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusNodes::get_Count( OUT long * plCount ) { //ASSERT( plCount != NULL );
HRESULT _hr = E_POINTER;
if ( plCount != NULL ) { *plCount = m_Nodes.size(); _hr = S_OK; }
return _hr;
} //*** CClusNodes::get_Count()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNodes::get_Item
//
// Description:
// Return the object (Node) at the passed in index.
//
// Arguments:
// varIndex [IN] - Contains the index requested.
// ppClusterNode [OUT] - Catches the item.
//
// Return Value:
// S_OK if successful, E_POINTER, or E_INVALIDARG.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusNodes::get_Item( IN VARIANT varIndex, OUT ISClusNode ** ppClusterNode ) { //ASSERT( ppClusterNode != NULL );
HRESULT _hr = E_POINTER;
if ( ppClusterNode != NULL ) { _hr = GetNodeItem(varIndex, ppClusterNode); } // if: args are not NULL
return _hr;
} //*** CClusNodes::get_Item()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNodes::get__NewEnum
//
// Description:
// Create and return a new enumeration for this collection.
//
// Arguments:
// ppunk [OUT] - Catches the new enumeration.
//
// Return Value:
// S_OK if successful, E_POINTER, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusNodes::get__NewEnum( IUnknown ** ppunk ) { return ::HrNewIDispatchEnum< NodeList, CComObject< CClusNode > >( ppunk, m_Nodes );
} //*** CClusNodes::get__NewEnum()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusNodes::Refresh
//
// Description:
// Load the collection from the cluster database.
//
// Arguments:
// None.
//
// Return Value:
// S_OK if successful, E_POINTER, or Win32 error as HRESULT.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusNodes::Refresh( void ) { HCLUSENUM hEnum = NULL; HCLUSTER hCluster = NULL; DWORD _sc = ERROR_SUCCESS; HRESULT _hr = S_OK;
ASSERT( m_pClusRefObject != NULL );
_hr = m_pClusRefObject->get_Handle( (ULONG_PTR *) &hCluster ); if ( SUCCEEDED( _hr ) ) { hEnum = ::ClusterOpenEnum( hCluster, CLUSTER_ENUM_NODE ); if ( hEnum != NULL ) { int _nIndex = 0; DWORD dwType; LPWSTR pszName = NULL; CComObject< CClusNode > * pNode = NULL;
Clear();
for( _nIndex = 0, _hr = S_OK; SUCCEEDED( _hr ); _nIndex++ ) { _sc = ::WrapClusterEnum( hEnum, _nIndex, &dwType, &pszName ); if ( _sc == ERROR_NO_MORE_ITEMS ) { _hr = S_OK; break; } else if ( _sc == ERROR_SUCCESS ) { _hr = CComObject< CClusNode >::CreateInstance( &pNode ); if ( SUCCEEDED( _hr ) ) { CSmartPtr< ISClusRefObject > ptrRefObject( m_pClusRefObject ); CSmartPtr< CComObject< CClusNode > > ptrNode( pNode ); BSTR bstr = NULL;
bstr = SysAllocString( pszName ); if ( bstr == NULL ) { _hr = E_OUTOFMEMORY; } else { _hr = ptrNode->Open( ptrRefObject, bstr ); if ( SUCCEEDED( _hr ) ) { ptrNode->AddRef(); m_Nodes.insert( m_Nodes.end(), ptrNode ); } else if ( HRESULT_CODE( _hr ) == ERROR_CLUSTER_NODE_NOT_FOUND ) { //
// It is possible for the node to have been deleted from the cluster
// in the time between creating the enum and opening the node. When
// that happens we need to simply skip that node and continue
// enumerating.
//
_hr = S_FALSE; // success code to keep us in the loop
} // else if: the cluster node was not found
SysFreeString( bstr ); } }
::LocalFree( pszName ); pszName = NULL; } else { _hr = HRESULT_FROM_WIN32( _sc ); } }
::ClusterCloseEnum( hEnum ); } else { _sc = GetLastError(); _hr = HRESULT_FROM_WIN32( _sc ); } }
return _hr;
} //*** CClusNodes::Refresh()
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CClusResGroupPreferredOwnerNodes class
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroupPreferredOwnerNodes::CClusResGroupPreferredOwnerNodes
//
// Description:
// Constructor.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CClusResGroupPreferredOwnerNodes::CClusResGroupPreferredOwnerNodes( void ) { m_bModified = FALSE; m_piids = (const IID *) iidCClusResGroupPreferredOwnerNodes; m_piidsSize = ARRAYSIZE( iidCClusResGroupPreferredOwnerNodes );
} //*** CClusResGroupPreferredOwnerNodes::CClusResGroupPreferredOwnerNodes()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroupPreferredOwnerNodes::~CClusResGroupPreferredOwnerNodes
//
// Description:
// destructor.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CClusResGroupPreferredOwnerNodes::~CClusResGroupPreferredOwnerNodes( void ) { Clear();
} //*** CClusResGroupPreferredOwnerNodes::~CClusResGroupPreferredOwnerNodes()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroupPreferredOwnerNodes::Create
//
// Description:
// Finish creating the object by doing things that cannot be done in
// a light weight constructor.
//
// Arguments:
// pClusRefObject [IN] - Wraps the cluster handle.
// hGroup [IN] - Group the collection belongs to.
//
// Return Value:
// S_OK if successful or E_POINTER if not.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusResGroupPreferredOwnerNodes::Create( IN ISClusRefObject * pClusRefObject, IN CRefcountedHGROUP hGroup ) { HRESULT _hr = E_POINTER;
_hr = CNodes::Create( pClusRefObject ); if ( SUCCEEDED( _hr ) ) { m_hGroup = hGroup; } // if:
return _hr;
} //*** CClusResGroupPreferredOwnerNodes::Create()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroupPreferredOwnerNodes::get_Count
//
// Description:
// Return the count of objects (Nodes) in the collection.
//
// Arguments:
// plCount [OUT] - Catches the count.
//
// Return Value:
// S_OK if successful, or E_POINTER.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroupPreferredOwnerNodes::get_Count( OUT long * plCount ) { //ASSERT( plCount != NULL );
HRESULT _hr = E_POINTER;
if ( plCount != NULL ) { *plCount = m_Nodes.size(); _hr = S_OK; }
return _hr;
} //*** CClusResGroupPreferredOwnerNodes::get_Count()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroupPreferredOwnerNodes::get_Item
//
// Description:
// Return the object (Node) at the passed in index.
//
// Arguments:
// varIndex [IN] - Contains the index requested.
// ppClusterNode [OUT] - Catches the item.
//
// Return Value:
// S_OK if successful, E_POINTER, or E_INVALIDARG.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroupPreferredOwnerNodes::get_Item( IN VARIANT varIndex, OUT ISClusNode ** ppClusterNode ) { //ASSERT( ppClusterNode != NULL );
HRESULT _hr = E_POINTER;
if ( ppClusterNode != NULL ) { _hr = GetNodeItem( varIndex, ppClusterNode ); }
return _hr;
} //*** CClusResGroupPreferredOwnerNodes::get_Item()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroupPreferredOwnerNodes::get__NewEnum
//
// Description:
// Create and return a new enumeration for this collection.
//
// Arguments:
// ppunk [OUT] - Catches the new enumeration.
//
// Return Value:
// S_OK if successful, E_POINTER, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroupPreferredOwnerNodes::get__NewEnum( IUnknown ** ppunk ) { return ::HrNewIDispatchEnum< NodeList, CComObject< CClusNode > >( ppunk, m_Nodes );
} //*** CClusResGroupPreferredOwnerNodes::get__NewEnum()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroupPreferredOwnerNodes::Refresh
//
// Description:
// Loads the resource group preferred owner node collection from the
// cluster.
//
// Arguments:
// None.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroupPreferredOwnerNodes::Refresh( void ) { HRESULT _hr = S_OK; HGROUPENUM hEnum = NULL; DWORD _sc = ERROR_SUCCESS;
hEnum = ::ClusterGroupOpenEnum( m_hGroup->get_Handle(), CLUSTER_GROUP_ENUM_NODES ); if ( hEnum != NULL ) { int _nIndex = 0; DWORD dwType = 0; LPWSTR pszName = NULL; CComObject< CClusNode > * pNode = NULL;
Clear(); m_bModified = FALSE;
for( _nIndex = 0, _hr = S_OK; SUCCEEDED( _hr ); _nIndex++ ) { _sc = WrapClusterGroupEnum( hEnum, _nIndex, &dwType, &pszName ); if ( _sc == ERROR_NO_MORE_ITEMS ) { _hr = S_OK; break; } else if ( _sc == ERROR_SUCCESS ) { _hr = CComObject< CClusNode >::CreateInstance( &pNode ); if ( SUCCEEDED( _hr ) ) { CSmartPtr< ISClusRefObject > ptrRefObject( m_pClusRefObject ); CSmartPtr< CComObject< CClusNode > > ptrNode( pNode ); BSTR bstr = NULL;
bstr = SysAllocString( pszName ); if ( bstr == NULL ) { _hr = E_OUTOFMEMORY; } else { _hr = ptrNode->Open( ptrRefObject, bstr ); if ( SUCCEEDED( _hr ) ) { ptrNode->AddRef(); m_Nodes.insert( m_Nodes.end(), ptrNode ); } else if ( HRESULT_CODE( _hr ) == ERROR_CLUSTER_NODE_NOT_FOUND ) { //
// It is possible for the node to have been deleted from the cluster
// in the time between creating the enum and opening the node. When
// that happens we need to simply skip that node and continue
// enumerating.
//
_hr = S_FALSE; // success code to keep us in the loop
} // else if: the cluster node was not found
SysFreeString( bstr ); } }
::LocalFree( pszName ); pszName = NULL; } else { _hr = HRESULT_FROM_WIN32( _sc ); } }
::ClusterGroupCloseEnum( hEnum ); } else { _sc = GetLastError(); _hr = HRESULT_FROM_WIN32( _sc ); }
return _hr;
} //*** CClusResGroupPreferredOwnerNodes::Refresh()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroupPreferredOwnerNodes::InsertItem
//
// Description:
// Insert the node into the groups preferred owners list.
//
// Arguments:
// pNode [IN] - Node to add to the preferred owners list.
// nPosition [IN] - Where in the list to insert the node.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroupPreferredOwnerNodes::InsertItem( IN ISClusNode * pNode, IN long nPosition ) { //ASSERT( pNode != NULL );
HRESULT _hr = E_POINTER;
if ( pNode != NULL ) { UINT _nIndex = 0;
_hr = FindItem( pNode, &_nIndex ); if ( FAILED( _hr ) ) { _hr = E_INVALIDARG;
if ( nPosition > 0 ) { SSIZE_T pos = (SSIZE_T) nPosition - 1; // convert to zero base
if ( pos >= 0 ) { CComObject< CClusNode > * _pNode = NULL;
_hr = pNode->QueryInterface( IID_CClusNode, (void **) &_pNode ); if ( SUCCEEDED( _hr ) ) { if ( ( m_Nodes.empty() ) || ( pos == 0 ) ) { _pNode->AddRef(); m_Nodes.insert( m_Nodes.begin(), _pNode ); } // if: list is empty or the insert index is zero then insert at the beginning
else if ( pos >= m_Nodes.size() ) { _pNode->AddRef(); m_Nodes.insert( m_Nodes.end(), _pNode ); } // else if: pos equals the end, append
else { _hr = InsertAt( _pNode, pos ); } // else: try to insert it where is belongs
m_bModified = TRUE; pNode->Release(); } // if:
} // if: index is greater than zero
} // if: nPosition must be greater than zero!
} // if: node was not already in the collection
else { _hr = E_INVALIDARG; } // else: node was already in the collectoin
}
return _hr;
} //*** CClusResGroupPreferredOwnerNodes::InsertItem()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroupPreferredOwnerNodes::AddItem
//
// Description:
// Add the node into the groups preferred owners list.
//
// Arguments:
// pNode [IN] - Node to add to the preferred owners list.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroupPreferredOwnerNodes::AddItem( IN ISClusNode * pNode ) { //ASSERT( pNode != NULL );
HRESULT _hr = E_POINTER;
if ( pNode != NULL ) { UINT _nIndex = 0;
_hr = FindItem( pNode, &_nIndex ); if ( FAILED( _hr ) ) { CComObject< CClusNode > * _pNode = NULL;
_hr = pNode->QueryInterface( IID_CClusNode, (void **) &_pNode ); if ( SUCCEEDED( _hr ) ) { m_Nodes.insert( m_Nodes.end(), _pNode ); m_bModified = TRUE; } // if:
} // if: node was not found in the collection already
else { _hr = E_INVALIDARG; } // esle: node was found
}
return _hr;
} //*** CClusResGroupPreferredOwnerNodes::AddItem()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroupPreferredOwnerNodes::RemoveItem
//
// Description:
// Remove the item at the passed in index.
//
// Arguments:
// varIndex [IN] - The index of the item to remove.
//
// Return Value:
// S_OK if successful, E_POINTER, or E_INVALIDARG.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroupPreferredOwnerNodes::RemoveItem( IN VARIANT varIndex ) { HRESULT _hr = S_OK;
UINT _nIndex = 0;
_hr = GetIndex( varIndex, &_nIndex ); if ( SUCCEEDED( _hr ) ) { _hr = RemoveAt( _nIndex ); if ( SUCCEEDED( _hr ) ) { m_bModified = TRUE; } // if:
} // if:
return _hr;
} //*** CClusResGroupPreferredOwnerNodes::RemoveItem()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroupPreferredOwnerNodes::get_Modified
//
// Description:
// Has this collection been modified?
//
// Arguments:
// pvarModified [OUT] - Catches the modified state.
//
// Return Value:
// S_OK if successful, or E_POINTER.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroupPreferredOwnerNodes::get_Modified( OUT VARIANT * pvarModified ) { //ASSERT( pvarModified != NULL );
HRESULT _hr = E_POINTER;
if ( pvarModified != NULL ) { pvarModified->vt = VT_BOOL;
if ( m_bModified ) { pvarModified->boolVal = VARIANT_TRUE; } // if: the collection has been modified.
else { pvarModified->boolVal = VARIANT_FALSE; } // else: the collection has not been modified.
_hr = S_OK; }
return _hr;
} //*** CClusResGroupPreferredOwnerNodes::get_Modified()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroupPreferredOwnerNodes::SaveChanges
//
// Description:
// Saves the changes to this collection of preferred owner nodes to
// the cluster database.
//
// Arguments:
// None.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroupPreferredOwnerNodes::SaveChanges( void ) { HRESULT _hr = S_OK;
if ( m_bModified ) { size_t _cNodes; HNODE * _phNodes = NULL;
_cNodes = m_Nodes.size();
_phNodes = new HNODE [ _cNodes ]; if ( _phNodes != NULL ) { NodeList::const_iterator _itCurrent = m_Nodes.begin(); NodeList::const_iterator _itLast = m_Nodes.end(); size_t _iIndex; DWORD _sc = ERROR_SUCCESS; CComObject< CClusNode > * _pOwnerNode = NULL;
ZeroMemory( _phNodes, _cNodes * sizeof( HNODE ) );
for ( _iIndex = 0; _itCurrent != _itLast; _itCurrent++, _iIndex++ ) { _pOwnerNode = *_itCurrent; _phNodes[ _iIndex ] = _pOwnerNode->RhNode(); } // for:
_sc = ::SetClusterGroupNodeList( m_hGroup->get_Handle(), _cNodes, _phNodes );
_hr = HRESULT_FROM_WIN32( _sc ); if ( SUCCEEDED( _hr ) ) { m_bModified = FALSE; } // if:
delete [] _phNodes; } else { _hr = E_OUTOFMEMORY; } }
return _hr;
} //*** CClusResGroupPreferredOwnerNodes::SaveChanges()
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CClusResPossibleOwnerNodes class
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResPossibleOwnerNodes::CClusResPossibleOwnerNodes
//
// Description:
// Constructor.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CClusResPossibleOwnerNodes::CClusResPossibleOwnerNodes( void ) { m_piids = (const IID *) iidCClusResPossibleOwnerNodes; m_piidsSize = ARRAYSIZE( iidCClusResPossibleOwnerNodes );
} //*** CClusResPossibleOwnerNodes::CClusResPossibleOwnerNodes()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResPossibleOwnerNodes::~CClusResPossibleOwnerNodes
//
// Description:
// destructor.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CClusResPossibleOwnerNodes::~CClusResPossibleOwnerNodes( void ) { Clear();
} //*** CClusResPossibleOwnerNodes::~CClusResPossibleOwnerNodes()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResPossibleOwnerNodes::Create
//
// Description:
// Finish creating the object by doing things that cannot be done in
// a light weight constructor.
//
// Arguments:
// pClusRefObject [IN] - Wraps the cluster handle.
// hResource [IN] - Resource the collection belongs to.
//
// Return Value:
// S_OK if successful or E_POINTER if not.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusResPossibleOwnerNodes::Create( IN ISClusRefObject * pClusRefObject, IN HRESOURCE hResource ) { HRESULT _hr = E_POINTER;
_hr = CNodes::Create( pClusRefObject ); if ( SUCCEEDED( _hr ) ) { m_hResource = hResource; } // if:
return _hr;
} //*** CClusResPossibleOwnerNodes::Create()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResPossibleOwnerNodes::get_Count
//
// Description:
// Return the count of objects (Nodes) in the collection.
//
// Arguments:
// plCount [OUT] - Catches the count.
//
// Return Value:
// S_OK if successful, or E_POINTER.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResPossibleOwnerNodes::get_Count( OUT long * plCount ) { //ASSERT( plCount != NULL );
HRESULT _hr = E_POINTER;
if ( plCount != NULL ) { *plCount = m_Nodes.size(); _hr = S_OK; }
return _hr;
} //*** CClusResPossibleOwnerNodes::get_Count()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResPossibleOwnerNodes::get_Item
//
// Description:
// Return the object (Node) at the passed in index.
//
// Arguments:
// varIndex [IN] - Contains the index requested.
// ppClusterNode [OUT] - Catches the item.
//
// Return Value:
// S_OK if successful, E_POINTER, or E_INVALIDARG.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResPossibleOwnerNodes::get_Item( IN VARIANT varIndex, OUT ISClusNode ** ppClusterNode ) { //ASSERT( ppClusterNode != NULL );
HRESULT _hr = E_POINTER;
if ( ppClusterNode != NULL ) { _hr = GetNodeItem( varIndex, ppClusterNode ); }
return _hr;
} //*** CClusResPossibleOwnerNodes::get_Item()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResPossibleOwnerNodes::get__NewEnum
//
// Description:
// Create and return a new enumeration for this collection.
//
// Arguments:
// ppunk [OUT] - Catches the new enumeration.
//
// Return Value:
// S_OK if successful, E_POINTER, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResPossibleOwnerNodes::get__NewEnum( IUnknown ** ppunk ) { return ::HrNewIDispatchEnum< NodeList, CComObject< CClusNode > >( ppunk, m_Nodes );
} //*** CClusResPossibleOwnerNodes::get__NewEnum()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResPossibleOwnerNodes::Refresh
//
// Description:
// Load the collection from the cluster database.
//
// Arguments:
// None.
//
// Return Value:
// S_OK if successful, E_POINTER, or Win32 error as HRESULT.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResPossibleOwnerNodes::Refresh( void ) { HRESULT _hr = S_OK; HRESENUM hEnum = NULL; DWORD _sc = ERROR_SUCCESS;
hEnum = ::ClusterResourceOpenEnum( m_hResource, CLUSTER_RESOURCE_ENUM_NODES ); if ( hEnum != NULL ) { int _nIndex = 0; DWORD dwType; LPWSTR pszName = NULL; CComObject< CClusNode > * pNode = NULL;
Clear();
m_bModified = FALSE;
for( _nIndex = 0, _hr = S_OK; SUCCEEDED( _hr ); _nIndex++ ) { _sc = ::WrapClusterResourceEnum( hEnum, _nIndex, &dwType, &pszName ); if ( _sc == ERROR_NO_MORE_ITEMS ) { _hr = S_OK; break; } else if ( _sc == ERROR_SUCCESS ) { _hr = CComObject< CClusNode >::CreateInstance( &pNode ); if ( SUCCEEDED( _hr ) ) { CSmartPtr< ISClusRefObject > ptrRefObject( m_pClusRefObject ); CSmartPtr< CComObject< CClusNode > > ptrNode( pNode ); BSTR bstr = NULL;
bstr = SysAllocString( pszName ); if ( bstr == NULL ) { _hr = E_OUTOFMEMORY; } else { _hr = ptrNode->Open( ptrRefObject, bstr ); if ( SUCCEEDED( _hr ) ) { ptrNode->AddRef(); m_Nodes.insert( m_Nodes.end(), ptrNode ); } else if ( HRESULT_CODE( _hr ) == ERROR_CLUSTER_NODE_NOT_FOUND ) { //
// It is possible for the node to have been deleted from the cluster
// in the time between creating the enum and opening the node. When
// that happens we need to simply skip that node and continue
// enumerating.
//
_hr = S_FALSE; // success code to keep us in the loop
} // else if: the cluster node was not found
SysFreeString( bstr ); } }
::LocalFree( pszName ); pszName = NULL; } else { _hr = HRESULT_FROM_WIN32( _sc ); } }
::ClusterResourceCloseEnum( hEnum ); } else { _sc = GetLastError(); _hr = HRESULT_FROM_WIN32( _sc ); }
return _hr;
} //*** CClusResPossibleOwnerNodes::Refresh()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResPossibleOwnerNodes::AddItem
//
// Description:
// Add the passed in node to this resource's list of possible owners.
//
// Arguments:
// pNode [IN] - The node to add to the list.
//
// Return Value:
// S_OK if successful, E_POINTER, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResPossibleOwnerNodes::AddItem( ISClusNode * pNode ) { //ASSERT( pNode != NULL );
HRESULT _hr = E_POINTER;
if ( pNode != NULL ) { // Fail if duplicate
UINT _nIndex = 0;
_hr = FindItem( pNode, &_nIndex ); if ( SUCCEEDED( _hr ) ) { _hr = E_INVALIDARG; } else { CComObject< CClusNode > * _pNode = NULL;
_hr = pNode->QueryInterface( IID_CClusNode, (void **) &_pNode ); if ( SUCCEEDED( _hr ) ) { DWORD _sc = ERROR_SUCCESS;
_sc = ::AddClusterResourceNode( m_hResource, _pNode->RhNode() ); if ( _sc == ERROR_SUCCESS ) { _pNode->AddRef(); m_Nodes.insert( m_Nodes.end(), _pNode );
m_bModified = TRUE; } // if:
_hr = HRESULT_FROM_WIN32( _sc );
pNode->Release(); } // if:
} }
return _hr;
} //*** CClusResPossibleOwnerNodes::AddItem()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResPossibleOwnerNodes::RemoveItem
//
// Description:
// Remove the node at the passed in index from this resource's list of
// possible owners.
//
// Arguments:
// varIndex [IN] - holds the index of the node to remove.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResPossibleOwnerNodes::RemoveItem( VARIANT varIndex ) { HRESULT _hr = S_OK; UINT _nIndex = 0;
_hr = GetIndex( varIndex, &_nIndex ); if ( SUCCEEDED( _hr ) ) { CComObject< CClusNode> * _pNode = m_Nodes[ _nIndex ]; DWORD _sc = ERROR_SUCCESS;
_sc = ::RemoveClusterResourceNode( m_hResource, _pNode->RhNode() ); _hr = HRESULT_FROM_WIN32( _sc ); if ( SUCCEEDED( _hr ) ) { RemoveAt( _nIndex ); m_bModified = TRUE; } // if:
} // if:
return _hr;
} //*** CClusResPossibleOwnerNodes::RemoveItem()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResPossibleOwnerNodes::get_Modified
//
// Description:
// Has this collection been modified?
//
// Arguments:
// pvarModified [OUT] - Catches the modified state.
//
// Return Value:
// S_OK if successful, or E_POINTER.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResPossibleOwnerNodes::get_Modified( OUT VARIANT * pvarModified ) { //ASSERT( pvarModified != NULL );
HRESULT _hr = E_POINTER;
if ( pvarModified != NULL ) { pvarModified->vt = VT_BOOL;
if ( m_bModified ) { pvarModified->boolVal = VARIANT_TRUE; } // if: the collection has been modified.
else { pvarModified->boolVal = VARIANT_FALSE; } // else: the collection has not been modified.
_hr = S_OK; }
return _hr;
} //*** CClusResPossibleOwnerNodes::get_Modified()
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CClusResTypePossibleOwnerNodes class
/////////////////////////////////////////////////////////////////////////////
#if CLUSAPI_VERSION >= 0x0500
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResTypePossibleOwnerNodes::CClusResTypePossibleOwnerNodes
//
// Description:
// Constructor.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CClusResTypePossibleOwnerNodes::CClusResTypePossibleOwnerNodes( void ) { m_piids = (const IID *) iidCClusResTypePossibleOwnerNodes; m_piidsSize = ARRAYSIZE( iidCClusResTypePossibleOwnerNodes );
} //*** CClusResTypePossibleOwnerNodes::CClusResTypePossibleOwnerNodes()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResTypePossibleOwnerNodes::~CClusResTypePossibleOwnerNodes
//
// Description:
// destructor.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CClusResTypePossibleOwnerNodes::~CClusResTypePossibleOwnerNodes( void ) { Clear();
} //*** CClusResTypePossibleOwnerNodes::~CClusResTypePossibleOwnerNodes()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResTypePossibleOwnerNodes::Create
//
// Description:
// Finish creating the object by doing things that cannot be done in
// a light weight constructor.
//
// Arguments:
// pClusRefObject [IN] - Wraps the cluster handle.
// bstrResTypeName [IN] - Resource type name the collection belongs to.
//
// Return Value:
// S_OK if successful or E_POINTER if not.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusResTypePossibleOwnerNodes::Create( IN ISClusRefObject * pClusRefObject, IN BSTR bstrResTypeName ) { HRESULT _hr = E_POINTER;
_hr = CNodes::Create( pClusRefObject ); if ( SUCCEEDED( _hr ) ) { m_bstrResTypeName = bstrResTypeName; } // if:
return _hr;
} //*** CClusResTypePossibleOwnerNodes::Create()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResTypePossibleOwnerNodes::get_Count
//
// Description:
// Return the count of objects (Nodes) in the collection.
//
// Arguments:
// plCount [OUT] - Catches the count.
//
// Return Value:
// S_OK if successful, or E_POINTER.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResTypePossibleOwnerNodes::get_Count( OUT long * plCount ) { //ASSERT( plCount != NULL );
HRESULT _hr = E_POINTER;
if ( plCount != NULL ) { *plCount = m_Nodes.size(); _hr = S_OK; }
return _hr;
} //*** CClusResTypePossibleOwnerNodes::get_Count()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResTypePossibleOwnerNodes::get_Item
//
// Description:
// Return the object (Node) at the passed in index.
//
// Arguments:
// varIndex [IN] - Contains the index requested.
// ppClusterNode [OUT] - Catches the item.
//
// Return Value:
// S_OK if successful, E_POINTER, or E_INVALIDARG.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResTypePossibleOwnerNodes::get_Item( IN VARIANT varIndex, OUT ISClusNode ** ppClusterNode ) { //ASSERT( ppClusterNode != NULL );
HRESULT _hr = E_POINTER;
if ( ppClusterNode != NULL ) { _hr = GetNodeItem( varIndex, ppClusterNode ); }
return _hr;
} //*** CClusResTypePossibleOwnerNodes::get_Item()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResTypePossibleOwnerNodes::get__NewEnum
//
// Description:
// Create and return a new enumeration for this collection.
//
// Arguments:
// ppunk [OUT] - Catches the new enumeration.
//
// Return Value:
// S_OK if successful, E_POINTER, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResTypePossibleOwnerNodes::get__NewEnum( OUT IUnknown ** ppunk ) { return ::HrNewIDispatchEnum< NodeList, CComObject< CClusNode > >( ppunk, m_Nodes );
} //*** CClusResTypePossibleOwnerNodes::get__NewEnum()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResTypePossibleOwnerNodes::Refresh
//
// Description:
// Load the resource type possible owner nodes collection from the
// cluster.
//
// Arguments:
// None.
//
// Return Value:
// S_OK if successful, or Win32 error ad HRESULT.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResTypePossibleOwnerNodes::Refresh( void ) { HRESULT _hr = S_OK; HRESTYPEENUM hEnum = NULL; DWORD _sc = ERROR_SUCCESS; HCLUSTER hCluster = NULL;
_hr = m_pClusRefObject->get_Handle( (ULONG_PTR *) &hCluster ); if ( SUCCEEDED( _hr ) ) { hEnum = ::ClusterResourceTypeOpenEnum( hCluster, m_bstrResTypeName, CLUSTER_RESOURCE_TYPE_ENUM_NODES ); if ( hEnum != NULL ) { int _nIndex = 0; DWORD dwType; LPWSTR pszName = NULL; CComObject< CClusNode > * pNode = NULL;
Clear();
for ( _nIndex = 0, _hr = S_OK; SUCCEEDED( _hr ); _nIndex++ ) { _sc = ::WrapClusterResourceTypeEnum( hEnum, _nIndex, &dwType, &pszName ); if ( _sc == ERROR_NO_MORE_ITEMS ) { _hr = S_OK; break; } else if ( _sc == ERROR_SUCCESS ) { _hr = CComObject< CClusNode >::CreateInstance( &pNode ); if ( SUCCEEDED( _hr ) ) { CSmartPtr< ISClusRefObject > ptrRefObject( m_pClusRefObject ); CSmartPtr< CComObject< CClusNode > > ptrNode( pNode ); BSTR bstr = NULL;
bstr = SysAllocString( pszName ); if ( bstr == NULL ) { _hr = E_OUTOFMEMORY; } else { _hr = ptrNode->Open( ptrRefObject, bstr ); if ( SUCCEEDED( _hr ) ) { ptrNode->AddRef(); m_Nodes.insert( m_Nodes.end(), ptrNode ); } else if ( HRESULT_CODE( _hr ) == ERROR_CLUSTER_NODE_NOT_FOUND ) { //
// It is possible for the node to have been deleted from the cluster
// in the time between creating the enum and opening the node. When
// that happens we need to simply skip that node and continue
// enumerating.
//
_hr = S_FALSE; // success code to keep us in the loop
} // else if: the cluster node was not found
SysFreeString( bstr ); } }
::LocalFree( pszName ); pszName = NULL; } // else if: no error
else { _hr = HRESULT_FROM_WIN32( _sc ); } // else: error from WrapClusterResourceTypeEnum
} // for: repeat until error
::ClusterResourceTypeCloseEnum( hEnum ); } else { _sc = GetLastError(); _hr = HRESULT_FROM_WIN32( _sc ); } } // if: we have a cluster handle
return _hr;
} //*** CClusResTypePossibleOwnerNodes::Refresh()
#endif // CLUSAPI_VERSION >= 0x0500
|