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