Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2967 lines
80 KiB

/////////////////////////////////////////////////////////////////////////////
//
// 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