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.
 
 
 
 
 
 

2214 lines
67 KiB

/////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1997-2002 Microsoft Corporation
//
// Module Name:
// ClusResG.cpp
//
// Description:
// Implementation of the resource group 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 * iidCClusResGroup[] =
{
&IID_ISClusResGroup
};
static const IID * iidCClusResGroups[] =
{
&IID_ISClusResGroups
};
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CClusResGroup class
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::CClusResGroup
//
// Description:
// Constructor.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CClusResGroup::CClusResGroup( void )
{
m_hGroup = NULL;
m_pClusRefObject = NULL;
m_pClusterResources = NULL;
m_pPreferredOwnerNodes = NULL;
m_pCommonProperties = NULL;
m_pPrivateProperties = NULL;
m_pCommonROProperties = NULL;
m_pPrivateROProperties = NULL;
m_piids = (const IID *) iidCClusResGroup;
m_piidsSize = ARRAYSIZE( iidCClusResGroup );
} //*** CClusResGroup::CClusResGroup()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::~CClusResGroup
//
// Description:
// Destructor.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CClusResGroup::~CClusResGroup( void )
{
// m_hGroup will be auto released
if ( m_pClusterResources != NULL )
{
m_pClusterResources->Release();
m_pClusterResources = NULL;
}
if ( m_pPreferredOwnerNodes != NULL )
{
m_pPreferredOwnerNodes->Release();
m_pPreferredOwnerNodes = NULL;
}
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_pClusRefObject != NULL )
{
m_pClusRefObject->Release();
m_pClusRefObject = NULL;
}
} //*** CClusResGroup::~CClusResGroup()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::Create
//
// Description:
// Finish the heavy weight construction.
//
// Arguments:
// pClusRefObject [IN] - Wraps the cluster handle.
// bstrGroupName [IN] - The name of this group.
//
// Return Value:
// S_OK if successful, E_POINTER, or Win32 error as HRESULT.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusResGroup::Create(
IN ISClusRefObject * pClusRefObject,
IN BSTR bstrGroupName
)
{
ASSERT( pClusRefObject != NULL );
ASSERT( bstrGroupName != NULL );
HRESULT _hr = E_POINTER;
if ( ( pClusRefObject != NULL ) && ( bstrGroupName != NULL ) )
{
m_pClusRefObject = pClusRefObject;
m_pClusRefObject->AddRef();
HCLUSTER _hCluster = 0;
_hr = m_pClusRefObject->get_Handle((ULONG_PTR *) &_hCluster);
if ( SUCCEEDED( _hr ) )
{
HGROUP hGroup = ::CreateClusterGroup( _hCluster, bstrGroupName );
if ( hGroup == 0 )
{
DWORD _sc = GetLastError();
_hr = HRESULT_FROM_WIN32( _sc );
}
else
{
m_hGroup = CRefCountedHandle<GroupHandle>::Create(hGroup);
if (m_hGroup == 0)
{
DWORD _sc = GetLastError();
::CloseClusterGroup(hGroup);
_hr = HRESULT_FROM_WIN32( _sc );
}
else
{
m_bstrGroupName = bstrGroupName;
_hr = S_OK;
}
}
}
}
/*
if ( _hr == S_OK )
{
OutputDebugStringW( L"CClusResGroup::Create() succeeded.\n" );
} // if: success!
else
{
WCHAR sz[ 256 ];
_snwprintf( sz, RTL_NUMBER_OF( sz ), L"CClusResGroup::Create() failed. (hr = %#08x)\n", _hr );
OutputDebugStringW( sz );
} // else: failure...
*/
return _hr;
} //*** CClusResGroup::Create()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::Open
//
// Description:
// Open the passed group on the cluster.
//
// Arguments:
// pClusRefObject [IN] - Wraps the cluster handle.
// bstrGroupName [IN] - The name of this group.
//
// Return Value:
// S_OK if successful, E_POINTER, or Win32 error as HRESULT.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusResGroup::Open(
IN ISClusRefObject * pClusRefObject,
IN BSTR bstrGroupName
)
{
ASSERT( pClusRefObject != NULL );
ASSERT( bstrGroupName != NULL );
HRESULT _hr = E_POINTER;
if ( ( pClusRefObject != NULL ) && ( bstrGroupName != NULL ) )
{
m_pClusRefObject = pClusRefObject;
m_pClusRefObject->AddRef();
HCLUSTER _hCluster = NULL;
_hr = m_pClusRefObject->get_Handle( (ULONG_PTR *) &_hCluster );
if ( SUCCEEDED( _hr ) )
{
HGROUP hGroup = ::OpenClusterGroup( _hCluster, bstrGroupName );
if ( hGroup == NULL )
{
DWORD _sc = GetLastError();
_hr = HRESULT_FROM_WIN32( _sc );
}
else
{
m_hGroup = CRefCountedHandle<GroupHandle>::Create(hGroup);
if ( m_hGroup == NULL )
{
DWORD _sc = GetLastError();
::CloseClusterGroup(hGroup);
_hr = HRESULT_FROM_WIN32( _sc );
}
else
{
m_bstrGroupName = bstrGroupName;
_hr = S_OK;
}
}
}
}
return _hr;
} //*** CClusResGroup::Open()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::GetProperties
//
// Description:
// Creates a property collection for this object type (Resource Group).
//
// 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 CClusResGroup::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 = pProperties;
}
else
{
m_pPrivateProperties = pProperties;
}
}
else
{
if ( bReadOnly )
{
m_pCommonROProperties = pProperties;
}
else
{
m_pCommonProperties = pProperties;
}
}
}
}
}
}
}
return _hr;
} //*** CClusResGroup::GetProperties()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::get_Handle
//
// Description:
// Returns the handle to this object (Group).
//
// Arguments:
// phandle [OUT] - Catches the handle.
//
// Return Value:
// S_OK if successful, or E_POINTER if not.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroup::get_Handle( OUT ULONG_PTR * phandle )
{
//ASSERT( phandle != NULL );
HRESULT _hr = E_POINTER;
if ( phandle != NULL )
{
*phandle = (ULONG_PTR)m_hGroup->get_Handle();
_hr = S_OK;
}
return _hr;
} //*** CClusResGroup::get_Handle()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::Close
//
// Description:
// Close the handle to the cluster object (Group).
//
// Arguments:
// None.
//
// Return Value:
// S_OK if successful, or Win32 error as HRESULT if not.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroup::Close( void )
{
if ( m_pClusRefObject )
{
m_pClusRefObject->Release();
m_pClusRefObject = NULL;
}
// SmartPointer will deref the handle properly when assigned NULL
m_hGroup = NULL;
return S_OK;
} //*** CClusResGroup::Close()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::put_Name
//
// Description:
// Change the name of this object (Group).
//
// Arguments:
// bstrGroupName [IN] - The new name.
//
// Return Value:
// S_OK if successful, E_POINTER, or Win32 error as HRESULT if not.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroup::put_Name( IN BSTR bstrGroupName )
{
//ASSERT( bstrGroupName != NULL );
HRESULT _hr = E_POINTER;
if ( bstrGroupName != NULL )
{
DWORD _sc = ::SetClusterGroupName( m_hGroup->get_Handle(), bstrGroupName );
if ( _sc == ERROR_SUCCESS )
{
m_bstrGroupName = bstrGroupName;
}
_hr = HRESULT_FROM_WIN32( _sc );
}
return _hr;
} //*** CClusResGroup::put_Name()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::get_Name
//
// Description:
// Return the name of this object (Resource Group).
//
// Arguments:
// pbstrGroupName [OUT] - Catches the name of this object.
//
// Return Value:
// S_OK if successful, or E_POINTER if not.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroup::get_Name( OUT BSTR * pbstrGroupName )
{
//ASSERT( pbstrGroupName != NULL );
HRESULT _hr = E_POINTER;
if ( pbstrGroupName != NULL )
{
*pbstrGroupName = m_bstrGroupName.Copy();
_hr = S_OK;
}
return _hr;
} //*** CClusResGroup::get_Name()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::get_State
//
// Description:
// Returns the current cluster group state for this group.
//
// Arguments:
// pcgsState [OUT] - Catches the cluster group state.
//
// Return Value:
// S_OK if successful, E_POINTER, or Win32 error as HRESULT if not.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroup::get_State( OUT CLUSTER_GROUP_STATE * pcgsState )
{
//ASSERT( pcgsState != NULL );
HRESULT _hr = E_POINTER;
if ( pcgsState != NULL )
{
CLUSTER_GROUP_STATE _cgsState = ::WrapGetClusterGroupState( m_hGroup->get_Handle(), NULL );
if ( _cgsState == ClusterGroupStateUnknown )
{
DWORD _sc = GetLastError();
_hr = HRESULT_FROM_WIN32( _sc );
}
else
{
*pcgsState = _cgsState;
_hr = S_OK;
}
}
return _hr;
} //*** CClusResGroup::get_State()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::get_OwnerNode
//
// Description:
// Returns the owner node for this group. The owner node is the node
// where the group is currently online.
//
// Arguments:
// ppOwnerNode [OUT[ - Catches the owner node interface.
//
// Return Value:
// S_OK if successful, E_POINTER, or Win32 error as HRESULT if not.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroup::get_OwnerNode( OUT ISClusNode ** ppOwnerNode )
{
//ASSERT( ppOwnerNode != NULL );
HRESULT _hr = E_POINTER;
if ( ppOwnerNode != NULL )
{
DWORD _sc = 0;
PWCHAR pwszNodeName = NULL;
CLUSTER_GROUP_STATE cgs = ClusterGroupStateUnknown;
cgs = WrapGetClusterGroupState( m_hGroup->get_Handle(), &pwszNodeName );
if ( cgs != ClusterGroupStateUnknown )
{
CComObject<CClusNode> * pNode = NULL;
*ppOwnerNode = NULL;
_hr = CComObject<CClusNode>::CreateInstance( &pNode );
if ( SUCCEEDED( _hr ) )
{
CSmartPtr< ISClusRefObject > ptrRefObject( m_pClusRefObject );
BSTR bstr = NULL;
bstr = SysAllocString( pwszNodeName );
if ( bstr == NULL )
{
_hr = E_OUTOFMEMORY;
}
else
{
pNode->AddRef();
_hr = pNode->Open( ptrRefObject, bstr );
if ( SUCCEEDED( _hr ) )
{
_hr = pNode->QueryInterface( IID_ISClusNode, (void **) ppOwnerNode );
}
pNode->Release();
SysFreeString( bstr );
}
}
::LocalFree( pwszNodeName );
}
else
{
_sc = GetLastError();
_hr = HRESULT_FROM_WIN32( _sc );
}
}
return _hr;
} //*** CClusResGroup::get_OwnerNode()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::get_Resources
//
// Description:
// Returns the collection of resources that belong to this group.
//
// Arguments:
// ppClusterGroupResources [OUT] - Catches the collection.
//
// Return Value:
// S_OK if successful, E_POINTER, or other HRESULT error if not.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroup::get_Resources(
OUT ISClusResGroupResources ** ppClusterGroupResources
)
{
return ::HrCreateResourceCollection< CClusResGroupResources, ISClusResGroupResources, CRefcountedHGROUP >(
&m_pClusterResources,
m_hGroup,
ppClusterGroupResources,
IID_ISClusResGroupResources,
m_pClusRefObject
);
} //*** CClusResGroup::get_Resources()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::get_PreferredOwnerNodes
//
// Description:
// Returns the collection of preferred owner nodes for this group.
//
// Arguments:
// ppOwnerNodes [OUT] - Catches the collection.
//
// Return Value:
// S_OK if successful, E_POINTER, or other HRESULT error if not.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroup::get_PreferredOwnerNodes(
ISClusResGroupPreferredOwnerNodes ** ppOwnerNodes
)
{
return ::HrCreateResourceCollection< CClusResGroupPreferredOwnerNodes, ISClusResGroupPreferredOwnerNodes, CRefcountedHGROUP >(
&m_pPreferredOwnerNodes,
m_hGroup,
ppOwnerNodes,
IID_ISClusResGroupPreferredOwnerNodes,
m_pClusRefObject
);
} //*** CClusResGroup::get_PreferredOwnerNodes()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::Delete
//
// Description:
// Removes this object (Resource Group) from the cluster.
//
// Arguments:
// None.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroup::Delete( void )
{
DWORD _sc = ERROR_INVALID_HANDLE;
if ( m_hGroup != NULL )
{
_sc = DeleteClusterGroup( m_hGroup->get_Handle() );
if ( _sc == ERROR_SUCCESS )
{
m_hGroup = NULL;
}
}
/*
if ( _sc == ERROR_SUCCESS )
{
OutputDebugStringW( L"CClusResGroup::Delete() succeeded.\n" );
} // if: success
else
{
WCHAR sz[ 256 ];
_snwprintf( sz, RTL_NUMBER_OF( sz ), L"CClusResGroup::Delete() failed. (handle = %d) (sc = %#08x)\n", m_hGroup->get_Handle(), _sc );
OutputDebugStringW( sz );
} // else: failure...
*/
return HRESULT_FROM_WIN32( _sc );
} //*** CClusResGroup::Delete()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::Online
//
// Description:
// Bring this group online on the passed in node, or on to the node
// it is currently offline if no node is specified.
//
// Arguments:
// varTimeout [IN] - How long in seconds to wait for the group to
// come online.
// varNode [IN] - Node to bring the group online.
// pvarPending [OUT] - Catches the pending state. True if we timed
// out before the group came completely online.
//
// Return Value:
// S_OK if successful, or other Win32 error as HRESULT.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroup::Online(
IN VARIANT varTimeout,
IN VARIANT varNode,
OUT VARIANT * pvarPending
)
{
//ASSERT( pNode != NULL );
//ASSERT( pvarPending != NULL );
HRESULT _hr = E_POINTER;
if ( pvarPending != NULL )
{
_hr = ::VariantChangeTypeEx( &varTimeout, &varTimeout, LOCALE_SYSTEM_DEFAULT, 0, VT_I4 );
if ( SUCCEEDED( _hr ) )
{
HNODE _hNode = NULL;
HCLUSTER _hCluster = NULL;
CComObject< CClusNode > * _pcnNode = NULL;
ISClusNode * _piscNode = NULL;
pvarPending->vt = VT_BOOL;
pvarPending->boolVal = VARIANT_FALSE;
_hr = m_pClusRefObject->get_Handle( (ULONG_PTR *) &_hCluster );
if ( SUCCEEDED( _hr ) )
{
if ( varNode.vt == ( VT_VARIANT | VT_BYREF ) )
{
if ( varNode.pvarVal != NULL )
{
IDispatch * _pidNode = varNode.pvarVal->pdispVal;
_hr = _pidNode->QueryInterface( IID_ISClusNode, (void **) &_piscNode );
if ( SUCCEEDED( _hr ) )
{
_hr = _piscNode->get_Handle( (ULONG_PTR *) &_hNode );
_piscNode->Release();
} // if: did we get the ISClusNode interface?
} // if: we have a variant value pointer
} // if: was the option parameter present?
else if ( varNode.vt == VT_DISPATCH )
{
IDispatch * _pidNode = varNode.pdispVal;
_hr = _pidNode->QueryInterface( IID_ISClusNode, (void **) &_piscNode );
if ( SUCCEEDED( _hr ) )
{
_hr = _piscNode->get_Handle( (ULONG_PTR *) &_hNode );
_piscNode->Release();
} // if: did we get the ISClusNode interface?
} // else if: we have a dispatch variant
else if ( varNode.vt == VT_BSTR )
{
_hr = CComObject< CClusNode >::CreateInstance( &_pcnNode );
if ( SUCCEEDED( _hr ) )
{
_pcnNode->AddRef();
_hr = _pcnNode->Open( m_pClusRefObject, ( varNode.vt & VT_BYREF) ? (*varNode.pbstrVal) : varNode.bstrVal );
if ( SUCCEEDED( _hr ) )
{
_hr = _pcnNode->get_Handle( (ULONG_PTR *) &_hNode );
} // if:
} // if:
} // else if: we have a string variant
else if ( varNode.vt == VT_EMPTY )
{
_hNode = NULL;
} // else if: it is empty
else if ( ( varNode.vt == VT_ERROR ) && ( varNode.scode == DISP_E_PARAMNOTFOUND ) )
{
_hNode = NULL;
} // else if: the optional parameter was not specified
else
{
_hr = ::VariantChangeTypeEx( &varNode, &varNode, LOCALE_SYSTEM_DEFAULT, 0, VT_I4 );
if ( SUCCEEDED( _hr ) )
{
if ( varNode.lVal != 0 )
{
_hr = E_INVALIDARG;
} // if: this is not zero then we cannot accept this parameter format. If varNode.lVal was zero then we could assume it was a NULL arg...
} // if: coerce to a long
} // else: the node variant could be invalid -- check for a zero, and if found treat it like a NULL...
if ( SUCCEEDED( _hr ) )
{
BOOL bPending = FALSE;
_hr = ::HrWrapOnlineClusterGroup(
_hCluster,
m_hGroup->get_Handle(),
_hNode,
varTimeout.lVal,
(long *) &bPending
);
if ( SUCCEEDED( _hr ) )
{
if ( bPending )
{
pvarPending->boolVal = VARIANT_TRUE;
} // if: pending?
} // if: online succeeded
} // if: we have a node handle
} // if: get_Handle() -- cluster handle
if ( _pcnNode != NULL )
{
_pcnNode->Release();
} // if: did we create a node?
} // if: wasn't the right type
} //if: pvarPending != NULL
return _hr;
} //*** CClusResGroup::Online()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::Move
//
// Description:
// Move this group to the passed in node, or to the best available node
// if no node was passed, and restore its online state.
//
// Arguments:
// varTimeout [IN] - How long in seconds to wait for the group to
// come move and complete stat restoration.
// varNode [IN] - Node to move the group to.
// pvarPending [OUT] - Catches the pending state. True if we timed
// out before the group came completely online.
//
// Return Value:
// S_OK if successful, or other Win32 error as HRESULT.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroup::Move(
IN VARIANT varTimeout,
IN VARIANT varNode,
OUT VARIANT * pvarPending
)
{
//ASSERT( pNode != NULL );
//ASSERT( pvarPending != NULL );
HRESULT _hr = E_POINTER;
if ( pvarPending != NULL )
{
_hr = ::VariantChangeTypeEx( &varTimeout, &varTimeout, LOCALE_SYSTEM_DEFAULT, 0, VT_I4 );
if ( SUCCEEDED( _hr ) )
{
HNODE _hNode = NULL;
HCLUSTER _hCluster = NULL;
CComObject< CClusNode > * _pcnNode = NULL;
ISClusNode * _piscNode = NULL;
pvarPending->vt = VT_BOOL;
pvarPending->boolVal = VARIANT_FALSE;
_hr = m_pClusRefObject->get_Handle( (ULONG_PTR *) &_hCluster );
if ( SUCCEEDED( _hr ) )
{
if ( varNode.vt == ( VT_VARIANT | VT_BYREF ) )
{
ASSERT( varNode.pvarVal != NULL );
VARIANT * _pvar = varNode.pvarVal;
if ( _pvar->vt == VT_DISPATCH )
{
IDispatch * _pidNode = _pvar->pdispVal;
_hr = _pidNode->QueryInterface( IID_ISClusNode, (void **) &_piscNode );
if ( SUCCEEDED( _hr ) )
{
_hr = _piscNode->get_Handle( (ULONG_PTR *) &_hNode );
_piscNode->Release();
} // if: did we get the ISClusNode interface?
} // if: variant value point is to an IDispatch
else if ( _pvar->vt == VT_BSTR )
{
_hr = CComObject< CClusNode >::CreateInstance( &_pcnNode );
if ( SUCCEEDED( _hr ) )
{
_pcnNode->AddRef();
_hr = _pcnNode->Open( m_pClusRefObject, _pvar->bstrVal );
if ( SUCCEEDED( _hr ) )
{
_hr = _pcnNode->get_Handle( (ULONG_PTR *) &_hNode );
} // if:
} // if:
} // else if:
} // if: was the option parameter present?
else if ( varNode.vt == VT_DISPATCH )
{
IDispatch * _pidNode = varNode.pdispVal;
_hr = _pidNode->QueryInterface( IID_ISClusNode, (void **) &_piscNode );
if ( SUCCEEDED( _hr ) )
{
_hr = _piscNode->get_Handle( (ULONG_PTR *) &_hNode );
_piscNode->Release();
} // if: did we get the ISClusNode interface?
} // else if: we have a dispatch variant
else if ( varNode.vt == VT_BSTR )
{
_hr = CComObject< CClusNode >::CreateInstance( &_pcnNode );
if ( SUCCEEDED( _hr ) )
{
_pcnNode->AddRef();
_hr = _pcnNode->Open( m_pClusRefObject, ( varNode.vt & VT_BYREF) ? (*varNode.pbstrVal) : varNode.bstrVal );
if ( SUCCEEDED( _hr ) )
{
_hr = _pcnNode->get_Handle( (ULONG_PTR *) &_hNode );
} // if:
} // if:
} // else if: we have a string variant
else if ( varNode.vt == VT_EMPTY )
{
_hNode = NULL;
} // else if: it is empty
else if ( ( varNode.vt == VT_ERROR ) && ( varNode.scode == DISP_E_PARAMNOTFOUND ) )
{
_hNode = NULL;
} // else if: the optional parameter was not specified
else
{
_hr = ::VariantChangeTypeEx( &varNode, &varNode, LOCALE_SYSTEM_DEFAULT, 0, VT_I4 );
if ( SUCCEEDED( _hr ) )
{
if ( varNode.lVal != 0 )
{
_hr = E_INVALIDARG;
} // if: this is not zero then we cannot accept this parameter format. If varNode.lVal was zero then we could assume it was a NULL arg...
} // if: coerce to a long
} // else: the node variant could be invalid -- check for a zero, and if found treat it like a NULL...
if ( SUCCEEDED( _hr ) )
{
BOOL bPending = FALSE;
_hr = ::HrWrapMoveClusterGroup(
_hCluster,
m_hGroup->get_Handle(),
_hNode,
varTimeout.lVal,
(long *) &bPending
);
if ( SUCCEEDED( _hr ) )
{
if ( bPending )
{
pvarPending->boolVal = VARIANT_TRUE;
} // if: pending?
} // if: Move group succeeded
} // if: we have all handles
} // if: get_Handle() -- cluster handle
if ( _pcnNode != NULL )
{
_pcnNode->Release();
} // if: did we create a node?
} // if: wasn't the right type
} //if: pvarPending != NULL
return _hr;
} //*** CClusResGroup::Move()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::Offline
//
// Description:
// Take the group offline.
//
// Arguments:
// varTimeout [IN] - How long in seconds to wait for the group to
// go offline.
// pvarPending [OUT] - Catches the pending state. True if we timed
// out before the group came completely online.
//
// Return Value:
// S_OK if successful, or other Win32 error as HRESULT.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroup::Offline(
IN VARIANT varTimeout,
OUT VARIANT * pvarPending
)
{
//ASSERT( nTimeout >= 0 );
//ASSERT( pvarPending != NULL );
HRESULT _hr = E_POINTER;
if ( pvarPending != NULL )
{
_hr = ::VariantChangeTypeEx( &varTimeout, &varTimeout, LOCALE_SYSTEM_DEFAULT, 0, VT_I4 );
if ( SUCCEEDED( _hr ) )
{
HCLUSTER _hCluster;
pvarPending->vt = VT_BOOL;
pvarPending->boolVal = VARIANT_FALSE;
_hr = m_pClusRefObject->get_Handle( (ULONG_PTR *) &_hCluster );
if ( SUCCEEDED( _hr ) )
{
BOOL bPending = FALSE;
_hr = ::HrWrapOfflineClusterGroup( _hCluster, m_hGroup->get_Handle(),
varTimeout.lVal, (long *) &bPending );
if ( SUCCEEDED( _hr ) )
{
if ( bPending )
{
pvarPending->boolVal = VARIANT_TRUE;
} // if: pending?
} // if: offline group succeeded
} // if: get_Handle() -- cluster handle
} // if: wasn't the right type
} //if: pvarPending != NULL
return _hr;
} //*** CClusResGroup::Offline()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::get_CommonProperties
//
// Description:
// Get this object's (Resource Group) common properties collection.
//
// Arguments:
// ppProperties [OUT] - Catches the properties collection.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroup::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;
} //*** CClusResGroup::get_CommonProperties()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::get_PrivateProperties
//
// Description:
// Get this object's (Resource Group) private properties collection.
//
// Arguments:
// ppProperties [OUT] - Catches the properties collection.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroup::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;
} //*** CClusResGroup::get_PrivateProperties()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::get_CommonROProperties
//
// Description:
// Get this object's (Resource Group) common read only properties collection.
//
// Arguments:
// ppProperties [OUT] - Catches the properties collection.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroup::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;
} //*** CClusResGroup::get_CommonROProperties()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::get_PrivateROProperties
//
// Description:
// Get this object's (Resource Group) private read only properties collection.
//
// Arguments:
// ppProperties [OUT] - Catches the properties collection.
//
// Return Value:
// S_OK if successful, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroup::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;
} //*** CClusResGroup::get_PrivateROProperties()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::get_Cluster
//
// Description:
// Returns the cluster object for the cluster where this group lives.
//
// Arguments:
// ppCluster [OUT] - Catches the cluster object.
//
// Return Value:
// S_OK if successful, E_POINTER, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroup::get_Cluster( OUT ISCluster ** ppCluster )
{
return ::HrGetCluster( ppCluster, m_pClusRefObject );
} //*** CClusResGroup::get_Cluster()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::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 HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusResGroup::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_GROUP_GET_RO_PRIVATE_PROPERTIES
: CLUSCTL_GROUP_GET_RO_COMMON_PROPERTIES;
}
else
{
_dwControlCode = bPrivate
? CLUSCTL_GROUP_GET_PRIVATE_PROPERTIES
: CLUSCTL_GROUP_GET_COMMON_PROPERTIES;
}
_sc = rcplPropList.ScGetGroupProperties( m_hGroup->get_Handle(), _dwControlCode );
_hr = HRESULT_FROM_WIN32( _sc );
return _hr;
} //*** CClusResGroup::HrLoadProperties()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroup::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:
// S_OK if successful, or other Win32 error as HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
DWORD CClusResGroup::ScWriteProperties(
const CClusPropList & rcplPropList,
BOOL bPrivate
)
{
DWORD dwControlCode = bPrivate ? CLUSCTL_GROUP_SET_PRIVATE_PROPERTIES : CLUSCTL_GROUP_SET_COMMON_PROPERTIES;
DWORD nBytesReturned = 0;
DWORD _sc = ERROR_SUCCESS;
_sc = ClusterGroupControl(
m_hGroup->get_Handle(),
NULL,
dwControlCode,
rcplPropList,
rcplPropList.CbBufferSize(),
0,
0,
&nBytesReturned
);
return _sc;
} //*** CClusResGroup::ScWriteProperties()
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CClusResGroups class
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroups::CClusResGroups
//
// Description:
// Constructor.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CClusResGroups::CClusResGroups( void )
{
m_pClusRefObject = NULL;
m_piids = (const IID *) iidCClusResGroups;
m_piidsSize = ARRAYSIZE( iidCClusResGroups );
} //*** CClusResGroups::CClusResGroups()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroups::~CClusResGroups
//
// Description:
// Destructor.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
CClusResGroups::~CClusResGroups( void )
{
Clear();
if ( m_pClusRefObject != NULL )
{
m_pClusRefObject->Release();
m_pClusRefObject = NULL;
}
} //*** CClusResGroups::~CClusResGroups()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroups::Create
//
// Description:
// Finish the heavy weight construction.
//
// Arguments:
// pClusRefObject [IN] - Wraps the cluster handle.
// pwszNodeName [IN] - Optional node name. If this argument
// is supplied then this is a collection of
// groups that are owned by that node.
//
// Return Value:
// S_OK if successful, or E_POINTER if not.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusResGroups::Create(
IN ISClusRefObject * pClusRefObject,
IN LPCWSTR pwszNodeName
)
{
ASSERT( pClusRefObject != NULL );
//ASSERT( pwszNodeName != NULL );
HRESULT _hr = E_POINTER;
if ( ( pClusRefObject != NULL ) /*&& ( pwszNodeName != NULL )*/ )
{
m_pClusRefObject= pClusRefObject;
m_pClusRefObject->AddRef();
m_bstrNodeName = pwszNodeName;
_hr = S_OK;
}
return _hr;
} //*** CClusResGroups::Create()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroups::FindItem
//
// Description:
// Find the passed in group in the collection.
//
// Arguments:
// pszGroupName [IN] - The name of the group to find.
// pnIndex [OUT] - Catches the index of the group.
//
// Return Value:
// S_OK if successful, E_POINTER, or E_INVALIDARG if the group was
// not found.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusResGroups::FindItem(
IN LPWSTR pszGroupName,
OUT ULONG * pnIndex
)
{
//ASSERT( pszGroupName != NULL );
//ASSERT( pnIndex != NULL );
HRESULT _hr = E_POINTER;
if ( ( pszGroupName != NULL ) && ( pnIndex != NULL ) )
{
CComObject<CClusResGroup> * pGroup = NULL;
int nMax = m_ResourceGroups.size();
_hr = E_INVALIDARG;
for( int i = 0; i < nMax; i++ )
{
pGroup = m_ResourceGroups[ i ];
if ( pGroup && ( lstrcmpi( pszGroupName, pGroup->Name() ) == 0 ) )
{
*pnIndex = i;
_hr = S_OK;
break;
}
}
}
return _hr;
} //*** CClusResGroups::FindItem()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroups::FindItem
//
// Description:
// Find the passed in group in the collection.
//
// Arguments:
// pResourceGroup [IN] - The group to find.
// pnIndex [OUT] - Catches the index of the group.
//
// Return Value:
// S_OK if successful, E_POINTER, or E_INVALIDARG is the group was
// not found.
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusResGroups::FindItem(
IN ISClusResGroup * pResourceGroup,
OUT ULONG * pnIndex
)
{
//ASSERT( pResourceGroup != NULL );
//ASSERT( pnIndex != NULL );
HRESULT _hr = E_POINTER;
if ( ( pResourceGroup != NULL ) && ( pnIndex != NULL ) )
{
CComBSTR _bstrName;
_hr = pResourceGroup->get_Name( &_bstrName );
if ( SUCCEEDED( _hr ) )
{
_hr = FindItem( _bstrName, pnIndex );
}
}
return _hr;
} //*** CClusResGroups::FindItem()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroups::GetIndex
//
// Description:
// Get the index from the passed in variant.
//
// Arguments:
// varIndex [IN] - Hold the index. This is a one based number,
// or the name of the group as a string.
// pnIndex [OUT] - Catches the zero based index in the collection.
//
// Return Value:
// S_OK if successful, E_POINTER, or E_INVALIDARG if the index is out
// of range.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusResGroups::GetIndex(
IN VARIANT varIndex,
OUT ULONG * pnIndex
)
{
//ASSERT( pnIndex != NULL );
HRESULT _hr = E_POINTER;
if ( pnIndex != NULL )
{
CComVariant v;
ULONG nIndex = 0;
*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_ResourceGroups.size() )
{
*pnIndex = nIndex;
}
else
{
_hr = E_INVALIDARG;
}
}
}
return _hr;
} //*** CClusResGroups::GetIndex()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroups::RemoveAt
//
// Description:
// Remove the object (Group) at the passed in index/position from the
// collection.
//
// Arguments:
// nPos [IN] - Index of the object to remove.
//
// Return Value:
// S_OK if successful, or E_INVALIDARG is the index is out of range.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusResGroups::RemoveAt( IN size_t pos )
{
CComObject<CClusResGroup> * pResourceGroup = NULL;
ResourceGroupList::iterator first = m_ResourceGroups.begin();
ResourceGroupList::iterator last = m_ResourceGroups.end();
HRESULT _hr = E_INVALIDARG;
for ( size_t t = 0; ( t < pos ) && ( first != last ); t++, first++ );
if ( first != last )
{
pResourceGroup = *first;
if ( pResourceGroup )
{
pResourceGroup->Release();
}
m_ResourceGroups.erase( first );
_hr = S_OK;
}
return _hr;
} //*** CClusResGroups::RemoveAt()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroups::get_Count
//
// Description:
// Returns the count of elements (Groups) in the collection.
//
// Arguments:
// plCount [OUT] - Catches the count.
//
// Return Value:
// S_OK if successful, or E_POINTER if not.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroups::get_Count( OUT long * plCount )
{
//ASSERT( plCount != NULL );
HRESULT _hr = E_POINTER;
if ( plCount != NULL )
{
*plCount = m_ResourceGroups.size();
_hr = S_OK;
}
return _hr;
} //*** CClusResGroups::get_Count()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroups::Clear
//
// Description:
// Clean out the vector of ClusResGroup objects.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
//--
/////////////////////////////////////////////////////////////////////////////
void CClusResGroups::Clear( void )
{
::ReleaseAndEmptyCollection< ResourceGroupList, CComObject< CClusResGroup > >( m_ResourceGroups );
} //*** CClusResGroups::Clear()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroups::get_Item
//
// Description:
// Returns the object (Group) at the passed in index.
//
// Arguments:
// varIndex [IN] - Hold the index. This is a one based number, or
// a string that is the name of the group to get.
// ppProperty [OUT] - Catches the property.
//
// Return Value:
// S_OK if successful, E_POINTER, or E_INVALIDARG if the index is out
// of range, or other HRESULT error.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroups::get_Item(
IN VARIANT varIndex,
OUT ISClusResGroup ** ppResourceGroup
)
{
//ASSERT( ppResourceGroup != NULL );
HRESULT _hr = E_POINTER;
if ( ppResourceGroup != NULL )
{
CComObject<CClusResGroup> * pGroup = NULL;
// Zero the out param
*ppResourceGroup = NULL;
ULONG nIndex = 0;
_hr = GetIndex( varIndex, &nIndex );
if ( SUCCEEDED( _hr ) )
{
pGroup = m_ResourceGroups[ nIndex ];
_hr = pGroup->QueryInterface( IID_ISClusResGroup, (void **) ppResourceGroup );
}
}
/*
if ( _hr == S_OK )
{
OutputDebugStringW( L"CClusResGroups::get_Item() succeeded.\n" );
} // if: success!
else
{
WCHAR sz[ 256 ];
_snwprintf( sz, RTL_NUMBER_OF( sz ), L"CClusResGroups::get_Item() failed. (hr = %#08x)\n", _hr );
OutputDebugStringW( sz );
} // else: failure...
*/
return _hr;
} //*** CClusResGroups::get_Item()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroups::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 CClusResGroups::get__NewEnum(
IUnknown ** ppunk
)
{
return ::HrNewIDispatchEnum< ResourceGroupList, CComObject< CClusResGroup > >( ppunk, m_ResourceGroups );
} //*** CClusResGroups::get__NewEnum()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroups::CreateItem
//
// Description:
// Create a new object (Group) and add it to the collection.
//
// Arguments:
// bstrResourceGroupName [IN] - The name of the new group.
// ppResourceGroup [OUT] - Catches the new object.
//
// Return Value:
// S_OK if successful, E_POINTER, or Win32 error as HRESULT.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroups::CreateItem(
IN BSTR bstrResourceGroupName,
OUT ISClusResGroup ** ppResourceGroup
)
{
//ASSERT( bstrResourceGroupName != NULL );
//ASSERT( ppResourceGroup != NULL );
HRESULT _hr = E_POINTER;
if ( ( bstrResourceGroupName != NULL ) && ( ppResourceGroup != NULL ) )
{
ULONG nIndex;
*ppResourceGroup = NULL;
_hr = FindItem( bstrResourceGroupName, &nIndex );
if ( FAILED( _hr ) )
{
CComObject< CClusResGroup > * pResourceGroup = NULL;
_hr = CComObject< CClusResGroup >::CreateInstance( &pResourceGroup );
if ( SUCCEEDED( _hr ) )
{
CSmartPtr< ISClusRefObject > ptrRefObject( m_pClusRefObject );
CSmartPtr< CComObject< CClusResGroup > > ptrGroup( pResourceGroup );
_hr = ptrGroup->Create( ptrRefObject, bstrResourceGroupName );
if ( SUCCEEDED( _hr ) )
{
_hr = ptrGroup->QueryInterface( IID_ISClusResGroup, (void **) ppResourceGroup );
if ( SUCCEEDED( _hr ) )
{
ptrGroup->AddRef();
m_ResourceGroups.insert( m_ResourceGroups.end(), ptrGroup );
}
}
}
} // if: group already exists
else
{
CComObject< CClusResGroup > * pResourceGroup = NULL;
pResourceGroup = m_ResourceGroups[ nIndex ];
_hr = pResourceGroup->QueryInterface( IID_ISClusResGroup, (void **) ppResourceGroup );
}
}
/*
if ( _hr == S_OK )
{
OutputDebugStringW( L"ClusResGroups::CreateItem() succeeded.\n" );
} // if: success!
else
{
WCHAR sz[ 256 ];
_snwprintf( sz, RTL_NUMBER_OF( sz ), L"Error creating group. (hr = %#08x)\n", _hr );
OutputDebugStringW( sz );
} // else: failure...
*/
return _hr;
} //*** CClusResGroups::CreateItem()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroups::DeleteItem
//
// Description:
// Deletes the object (group) at the passed in index.
//
// Arguments:
// varIndex [IN] - The index of the object to delete.
//
// Return Value:
// S_OK if successful, E_INVALIDARG, or Win32 error as HRESULT.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroups::DeleteItem( IN VARIANT varIndex )
{
HRESULT _hr = S_OK;
ULONG nIndex = 0;
_hr = GetIndex( varIndex, &nIndex );
if ( SUCCEEDED( _hr ) )
{
ISClusResGroup * pResourceGroup = (ISClusResGroup *) m_ResourceGroups[ nIndex ];
// Delete the resource group.
_hr = pResourceGroup->Delete();
if ( SUCCEEDED( _hr ) )
{
RemoveAt( nIndex );
}
}
/*
if ( _hr == S_OK )
{
OutputDebugStringW( L"CClusResGroups::DeleteItem() succeeded.\n" );
} // if: success!
else
{
WCHAR sz[ 128 ];
_snwprintf( sz, RTL_NUMBER_OF( sz ), L"CClusResGroups::DeleteItem() failed. (hr = %#08x)\n", _hr );
OutputDebugStringW( sz );
} // else: failure...
*/
return _hr;
} //*** CClusResGroups::DeleteItem()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroups::Refresh
//
// Description:
// Load the collection from the cluster.
//
// Arguments:
// None.
//
// Return Value:
// S_OK is successful, or Win32 error as HRESULT if not.
//
//--
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CClusResGroups::Refresh( void )
{
Clear();
if ( m_pClusRefObject == NULL )
{
return E_POINTER;
} // if: we have a cluster handle wrapper
if ( m_bstrNodeName == (BSTR) NULL )
{
return RefreshCluster();
} // if: this collection is for a cluster
else
{
return RefreshNode();
} // else: this collection is for a node
} //*** CClusResGroups::Refresh()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroups::RefreshCluster
//
// Description:
// Load all of the groups in the cluster into this collection.
//
// Arguments:
// None.
//
// Return Value:
// S_OK is successful, or Win32 error as HRESULT if not.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusResGroups::RefreshCluster( void )
{
HCLUSTER _hCluster = NULL;
HRESULT _hr;
ASSERT( m_pClusRefObject != NULL );
_hr = m_pClusRefObject->get_Handle( (ULONG_PTR *) &_hCluster );
if ( SUCCEEDED( _hr ) )
{
HCLUSENUM hEnum = NULL;
DWORD _sc = ERROR_SUCCESS;
hEnum = ::ClusterOpenEnum( _hCluster, CLUSTER_ENUM_GROUP );
if ( hEnum != NULL )
{
DWORD dwType;
LPWSTR pwszName = NULL;
CComObject< CClusResGroup > * pResourceGroup = NULL;
int nIndex;
for( nIndex = 0, _hr = S_OK; SUCCEEDED( _hr ); nIndex++ )
{
_sc = ::WrapClusterEnum( hEnum, nIndex, &dwType, &pwszName );
if ( _sc == ERROR_NO_MORE_ITEMS)
{
_hr = S_OK;
break;
} // if: Enumerator is empty. Time to leave...
else if ( _sc == ERROR_SUCCESS )
{
_hr = CComObject< CClusResGroup >::CreateInstance( &pResourceGroup );
if ( SUCCEEDED( _hr ) )
{
CSmartPtr< ISClusRefObject > ptrRefObject( m_pClusRefObject );
CSmartPtr< CComObject< CClusResGroup > > ptrGroup( pResourceGroup );
BSTR bstr = NULL;
bstr = SysAllocString( pwszName );
if ( bstr == NULL )
{
_hr = E_OUTOFMEMORY;
} // if: failed to allocate a bstr
else
{
_hr = ptrGroup->Open( ptrRefObject, bstr );
if ( SUCCEEDED( _hr ) )
{
ptrGroup->AddRef();
m_ResourceGroups.insert( m_ResourceGroups.end(), ptrGroup );
} // if: successfully opened the group
else if ( HRESULT_CODE( _hr ) == ERROR_GROUP_NOT_FOUND )
{
//
// It is possible for the group to have been deleted from the cluster
// in the time between creating the enum and opening the group. When
// that happens we need to simply skip that group and continue
// enumerating.
//
_hr = S_FALSE; // success code to keep us in the loop
} // else if: the cluster group was not found
SysFreeString( bstr );
} // else: successfully allocated a bstr
} // if: successfully created an instance of a group object
::LocalFree( pwszName );
pwszName = NULL;
} // else if: successfully got a group from the enumerator
else
{
_hr = HRESULT_FROM_WIN32( _sc );
} // else: failed to get a group from the enumerator
} // for: each group in the enumerator
::ClusterCloseEnum( hEnum ) ;
} // if: successfully created the groups enumerator
else
{
_sc = GetLastError();
_hr = HRESULT_FROM_WIN32( _sc );
} // else: failed to create the groups enumerator
} // if: successfully got the cluster handle
return _hr;
} //*** CClusResGroups::RefreshCluster()
/////////////////////////////////////////////////////////////////////////////
//++
//
// CClusResGroups::RefreshNode
//
// Description:
// Load all of the groups owned by the node at m_bstrNodeName.
//
// Arguments:
// None.
//
// Return Value:
// S_OK is successful, or Win32 error as HRESULT if not.
//
//--
/////////////////////////////////////////////////////////////////////////////
HRESULT CClusResGroups::RefreshNode( void )
{
HCLUSTER _hCluster = NULL;
HRESULT _hr;
ASSERT( m_pClusRefObject != NULL );
_hr = m_pClusRefObject->get_Handle( (ULONG_PTR *) &_hCluster );
if ( SUCCEEDED( _hr ) )
{
HCLUSENUM hEnum = NULL;
DWORD _sc = ERROR_SUCCESS;
hEnum = ::ClusterOpenEnum( _hCluster, CLUSTER_ENUM_GROUP );
if ( hEnum != NULL )
{
DWORD dwType;
LPWSTR pwszName = NULL;
LPWSTR pwszNodeName = NULL;
CComObject< CClusResGroup > * pResourceGroup = NULL;
CLUSTER_GROUP_STATE cgs = ClusterGroupStateUnknown;
int _nIndex;
for( _nIndex = 0, _hr = S_OK; SUCCEEDED( _hr ); _nIndex++ )
{
_sc = ::WrapClusterEnum( hEnum, _nIndex, &dwType, &pwszName );
if ( _sc == ERROR_NO_MORE_ITEMS )
{
_hr = S_OK;
break;
} // if: enum is empty. Time to leave...
else if ( _sc == ERROR_SUCCESS )
{
_hr = CComObject< CClusResGroup >::CreateInstance( &pResourceGroup );
if ( SUCCEEDED( _hr ) )
{
CSmartPtr< ISClusRefObject > ptrRefObject( m_pClusRefObject );
CSmartPtr< CComObject< CClusResGroup > > ptrGroup( pResourceGroup );
BSTR bstr = NULL;
bstr = SysAllocString( pwszName );
if ( bstr == NULL )
{
_hr = E_OUTOFMEMORY;
} // if: could not allocate a bstr
else
{
_hr = ptrGroup->Open( ptrRefObject, bstr );
if ( SUCCEEDED( _hr ) )
{
cgs = WrapGetClusterGroupState( ptrGroup->Hgroup(), &pwszNodeName );
if ( cgs != ClusterGroupStateUnknown )
{
if ( lstrcmpi( m_bstrNodeName, pwszNodeName ) == 0 )
{
ptrGroup->AddRef();
m_ResourceGroups.insert( m_ResourceGroups.end(), ptrGroup );
} // if: the group is owned by this node
::LocalFree( pwszNodeName );
pwszNodeName = NULL;
} // if: the group state is not unknown
} // if: the group was opened
else if ( HRESULT_CODE( _hr ) == ERROR_GROUP_NOT_FOUND )
{
//
// It is possible for the group to have been deleted from the cluster
// in the time between creating the enum and opening the group. When
// that happens we need to simply skip that group and continue
// enumerating.
//
_hr = S_FALSE; // success code to keep us in the loop
} // else if: the cluster group was not found
SysFreeString( bstr );
} // else: could allocated a bstr
} // if: sucessfully created a group object instance
::LocalFree( pwszName );
pwszName = NULL;
} // else if: successfully got a group from the enumerator
else
{
_hr = HRESULT_FROM_WIN32( _sc );
} // else: failed to get a group from the enumerator
} // for: each group in the enumerator
::ClusterCloseEnum( hEnum );
} // if: successfully created a group enumerator
else
{
_sc = GetLastError();
_hr = HRESULT_FROM_WIN32( _sc );
} // else: failed to create a group enumerator
} // if: got the cluster handle from the ref counted container
/*
if ( _hr == S_OK )
{
OutputDebugStringW( L"CClusResGroups::RefreshNode() succeeded.\n" );
} // if: success!
else
{
WCHAR sz[ 128 ];
_snwprintf( sz, RTL_NUMBER_OF( sz ), L"CClusResGroups::RefreshNode() failed. (hr = %#08x)\n", _hr );
OutputDebugStringW( sz );
} // else: failure...
*/
return _hr;
} //*** CClusResGroups::RefreshNode()