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