1778 lines
58 KiB
C++
1778 lines
58 KiB
C++
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 2000-2001 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
// TaskGatherInformation.cpp
|
|
//
|
|
// Description:
|
|
// CTaskGatherInformation implementation.
|
|
//
|
|
// Maintained By:
|
|
// Galen Barbee (GalenB) 02-FEB-2000
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "pch.h"
|
|
#include "TaskGatherInformation.h"
|
|
#include "ManagedDevice.h"
|
|
#include "ManagedNetwork.h"
|
|
|
|
DEFINE_THISCLASS("CTaskGatherInformation")
|
|
|
|
#define MINIMUM_STORAGE_SIZE 5
|
|
|
|
//
|
|
// Failure code.
|
|
//
|
|
|
|
#define SSR_TGI_FAILED( _major, _minor, _hr ) \
|
|
{ \
|
|
HRESULT hrTemp; \
|
|
BSTR bstrNotification = NULL; \
|
|
hrTemp = THR( HrLoadStringIntoBSTR( g_hInstance, IDS_ERR_TGI_FAILED_TRY_TO_REANALYZE, &bstrNotification ) ); \
|
|
hrTemp = THR( SendStatusReport( m_bstrNodeName, _major, _minor, 0, 1, 1, _hr, bstrNotification ) ); \
|
|
if ( bstrNotification != NULL ) \
|
|
{ \
|
|
TraceSysFreeString( bstrNotification ); \
|
|
} \
|
|
if ( FAILED( hrTemp ) )\
|
|
{ \
|
|
_hr = hrTemp; \
|
|
} \
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Static function prototypes
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static HRESULT HrTotalManagedResourceCount( IEnumClusCfgManagedResources * pResourceEnumIn, IEnumClusCfgNetworks * pNetworkEnumIn, DWORD * pnCountOut );
|
|
|
|
|
|
//****************************************************************************
|
|
//
|
|
// Constructor / Destructor
|
|
//
|
|
//****************************************************************************
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// HRESULT
|
|
// CTaskGatherInformation::S_HrCreateInstance(
|
|
// IUnknown ** punkOut
|
|
// )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CTaskGatherInformation::S_HrCreateInstance(
|
|
IUnknown ** ppunkOut
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
Assert( ppunkOut != NULL );
|
|
|
|
HRESULT hr;
|
|
|
|
CTaskGatherInformation * ptgi = new CTaskGatherInformation;
|
|
if ( ptgi != NULL )
|
|
{
|
|
hr = THR( ptgi->HrInit() );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = THR( ptgi->TypeSafeQI( IUnknown, ppunkOut ) );
|
|
TraceMoveToMemoryList( *ppunkOut, g_GlobalMemoryList );
|
|
}
|
|
|
|
ptgi->Release();
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** CTaskGatherInformation::S_HrCreateInstance()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CTaskGatherInformation::CTaskGatherInformation( void )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
CTaskGatherInformation::CTaskGatherInformation( void )
|
|
: m_cRef( 1 )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
InterlockedIncrement( &g_cObjects );
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CTaskGatherInformation::CTaskGatherInformation()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// STDMETHODIMP
|
|
// CTaskGatherInformation::HrInit( void )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CTaskGatherInformation::HrInit( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
// IUnknown stuff
|
|
Assert( m_cRef == 1 );
|
|
|
|
// IDoTask / ITaskGatherInformation
|
|
Assert( m_cookieCompletion == NULL );
|
|
Assert( m_cookieNode == NULL );
|
|
Assert( m_pcccb == NULL );
|
|
Assert( m_fJoining == FALSE );
|
|
Assert( m_cResources == 0 );
|
|
|
|
Assert( m_pom == NULL );
|
|
Assert( m_pccs == NULL );
|
|
Assert( m_bstrNodeName == NULL );
|
|
|
|
Assert( m_ulQuorumDiskSize == 0 );
|
|
Assert( m_pccmriQuorum == NULL );
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** CTaskGatherInformation::HrInit()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CTaskGatherInformation::~CTaskGatherInformation()
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
CTaskGatherInformation::~CTaskGatherInformation( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
if ( m_pcccb != NULL )
|
|
{
|
|
m_pcccb->Release();
|
|
}
|
|
|
|
if ( m_pom != NULL )
|
|
{
|
|
m_pom->Release();
|
|
}
|
|
|
|
if ( m_pccs != NULL )
|
|
{
|
|
m_pccs->Release();
|
|
}
|
|
|
|
if ( m_bstrNodeName != NULL )
|
|
{
|
|
TraceSysFreeString( m_bstrNodeName );
|
|
}
|
|
|
|
InterlockedDecrement( &g_cObjects );
|
|
|
|
TraceFuncExit();
|
|
|
|
} //*** CTaskGatherInformation::~CTaskGatherInformation()
|
|
|
|
|
|
//****************************************************************************
|
|
//
|
|
// IUnknown
|
|
//
|
|
//****************************************************************************
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// STDMETHODIMP
|
|
// CTaskGatherInformation::QueryInterface(
|
|
// REFIID riidIn,
|
|
// LPVOID * ppvOut
|
|
// )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CTaskGatherInformation::QueryInterface(
|
|
REFIID riidIn,
|
|
LPVOID * ppvOut
|
|
)
|
|
{
|
|
TraceQIFunc( riidIn, ppvOut );
|
|
|
|
HRESULT hr = E_NOINTERFACE;
|
|
|
|
if ( IsEqualIID( riidIn, IID_IUnknown ) )
|
|
{
|
|
*ppvOut = static_cast< ITaskGatherInformation * >( this );
|
|
hr = S_OK;
|
|
} // if: IUnknown
|
|
else if ( IsEqualIID( riidIn, IID_ITaskGatherInformation ) )
|
|
{
|
|
*ppvOut = TraceInterface( __THISCLASS__, ITaskGatherInformation, this, 0 );
|
|
hr = S_OK;
|
|
} // else if: ITaskGatherInformation
|
|
|
|
else if ( IsEqualIID( riidIn, IID_IDoTask ) )
|
|
{
|
|
*ppvOut = TraceInterface( __THISCLASS__, IDoTask, this, 0 );
|
|
hr = S_OK;
|
|
} // else if: IDoTask
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
((IUnknown *) *ppvOut)->AddRef();
|
|
} // if: success
|
|
|
|
QIRETURN_IGNORESTDMARSHALLING( hr, riidIn );
|
|
|
|
} //*** CTaskGatherInformation::QueryInterface()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// STDMETHODIMP_( ULONG )
|
|
// CTaskGatherInformation::AddRef( void )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP_( ULONG )
|
|
CTaskGatherInformation::AddRef( void )
|
|
{
|
|
TraceFunc( "[IUnknown]" );
|
|
|
|
InterlockedIncrement( &m_cRef );
|
|
|
|
RETURN( m_cRef );
|
|
|
|
} //*** CTaskGatherInformation::AddRef()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// STDMETHODIMP_( ULONG )
|
|
// CTaskGatherInformation::Release( void )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP_( ULONG )
|
|
CTaskGatherInformation::Release( void )
|
|
{
|
|
TraceFunc( "[IUnknown]" );
|
|
|
|
LONG cRef;
|
|
|
|
InterlockedDecrement( &m_cRef );
|
|
cRef = m_cRef;
|
|
|
|
if ( cRef == 0 )
|
|
{
|
|
TraceDo( delete this );
|
|
}
|
|
|
|
RETURN( cRef );
|
|
|
|
} //*** CTaskGatherInformation::Release()
|
|
|
|
|
|
//****************************************************************************
|
|
//
|
|
// ITaskGatherInformation
|
|
//
|
|
//****************************************************************************
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// STDMETHODIMP
|
|
// CTaskGatherInformation::BeginTask( void )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CTaskGatherInformation::BeginTask( void )
|
|
{
|
|
TraceFunc( "[IDoTask]" );
|
|
|
|
HRESULT hr;
|
|
LPWSTR psz;
|
|
|
|
BSTR bstrNotification = NULL;
|
|
|
|
IServiceProvider * psp = NULL;
|
|
IUnknown * punk = NULL;
|
|
IConnectionPointContainer * pcpc = NULL;
|
|
IConnectionPoint * pcp = NULL;
|
|
INotifyUI * pnui = NULL;
|
|
IConnectionManager * pcm = NULL;
|
|
IStandardInfo * psi = NULL;
|
|
IClusCfgCapabilities * pccc = NULL;
|
|
|
|
IEnumClusCfgManagedResources * peccmr = NULL;
|
|
IEnumClusCfgNetworks * pen = NULL;
|
|
|
|
DWORD cTotalResources = 0;
|
|
|
|
TraceInitializeThread( L"TaskGatherInformation" );
|
|
|
|
//
|
|
// Make sure we weren't "reused"
|
|
//
|
|
|
|
Assert( m_cResources == 0 );
|
|
|
|
//
|
|
// Gather the manager we need to complete our tasks.
|
|
//
|
|
|
|
hr = THR( CoCreateInstance( CLSID_ServiceManager,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
TypeSafeParams( IServiceProvider, &psp )
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_CoCreate_ServiceManager, hr );
|
|
goto Cleanup;
|
|
}
|
|
|
|
hr = THR( psp->TypeSafeQS( CLSID_ObjectManager,
|
|
IObjectManager,
|
|
&m_pom
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_QS_ObjectManager, hr );
|
|
goto Cleanup;
|
|
}
|
|
|
|
hr = THR( psp->TypeSafeQS( CLSID_NotificationManager,
|
|
IConnectionPointContainer,
|
|
&pcpc
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_QS_NotificationManager, hr );
|
|
goto Cleanup;
|
|
}
|
|
|
|
hr = THR( pcpc->FindConnectionPoint( IID_INotifyUI, &pcp ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_FindConnectionPoint, hr );
|
|
goto Cleanup;
|
|
}
|
|
|
|
pcp = TraceInterface( L"CTaskGatherInformation!IConnectionPoint", IConnectionPoint, pcp, 1 );
|
|
|
|
hr = THR( pcp->TypeSafeQI( INotifyUI, &pnui ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_QI_pnui, hr );
|
|
goto Cleanup;
|
|
}
|
|
|
|
pnui = TraceInterface( L"CTaskGatherInformation!INotifyUI", INotifyUI, pnui, 1 );
|
|
|
|
hr = THR( psp->TypeSafeQS( CLSID_ClusterConnectionManager,
|
|
IConnectionManager,
|
|
&pcm
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_QS_ClusterConnectionManager, hr );
|
|
goto Cleanup;
|
|
}
|
|
|
|
// release promptly
|
|
psp->Release();
|
|
psp = NULL;
|
|
|
|
//
|
|
// Ask the object manager for the name of the node.
|
|
//
|
|
|
|
hr = THR( m_pom->GetObject( DFGUID_StandardInfo,
|
|
m_cookieNode,
|
|
&punk
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_GetObject_StandardInfo, hr );
|
|
goto Cleanup;
|
|
}
|
|
|
|
hr = THR( punk->TypeSafeQI( IStandardInfo, &psi ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_GetObject_StandardInfo_QI, hr );
|
|
goto Cleanup;
|
|
}
|
|
|
|
psi = TraceInterface( L"TaskGatherInformation!IStandardInfo", IStandardInfo, psi, 1 );
|
|
|
|
punk->Release();
|
|
punk = NULL;
|
|
|
|
hr = THR( psi->GetName( &m_bstrNodeName ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_GetName, hr );
|
|
goto Cleanup;
|
|
}
|
|
|
|
TraceMemoryAddBSTR( m_bstrNodeName );
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Create progress message and tell the UI layer our progress
|
|
// for checking the node's cluster feasibility.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
hr = THR( HrLoadStringIntoBSTR( g_hInstance,
|
|
IDS_TASKID_MINOR_CHECKING_NODE_CLUSTER_FEASIBILITY,
|
|
&bstrNotification
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_LoadString, hr );
|
|
goto Cleanup;
|
|
}
|
|
|
|
hr = THR( SendStatusReport( m_bstrNodeName,
|
|
TASKID_Major_Check_Node_Feasibility,
|
|
TASKID_Minor_Checking_Node_Cluster_Feasibility,
|
|
0,
|
|
2,
|
|
0,
|
|
S_OK,
|
|
bstrNotification
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto ClusterFeasibilityError;
|
|
|
|
//
|
|
// Ask the connection manager for a connection to the node.
|
|
//
|
|
|
|
hr = THRE( pcm->GetConnectionToObject( m_cookieNode, &punk ), HR_S_RPC_S_CLUSTER_NODE_DOWN );
|
|
if ( hr != S_OK )
|
|
{
|
|
THR( HrLoadStringIntoBSTR( g_hInstance,
|
|
IDS_TASKID_MINOR_FAILED_TO_CONNECT_TO_NODE,
|
|
&bstrNotification
|
|
) );
|
|
|
|
THR( SendStatusReport( m_bstrNodeName,
|
|
TASKID_Major_Check_Node_Feasibility,
|
|
TASKID_Minor_Checking_Node_Cluster_Feasibility,
|
|
0,
|
|
2,
|
|
2,
|
|
hr,
|
|
bstrNotification
|
|
) );
|
|
// don't care about error from here - we are returning an error.
|
|
|
|
//
|
|
// If we failed to get a connection to the node, we delete the
|
|
// node from the configuration.
|
|
//
|
|
THR( m_pom->RemoveObject( m_cookieNode ) );
|
|
// don't care if there is an error because we can't fix it!
|
|
|
|
goto ClusterFeasibilityError;
|
|
}
|
|
|
|
hr = THR( punk->TypeSafeQI( IClusCfgServer, &m_pccs ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_GetConnectionToObject_QI_m_pccs, hr );
|
|
goto ClusterFeasibilityError;
|
|
}
|
|
|
|
punk->Release();
|
|
punk = NULL;
|
|
|
|
//
|
|
// Tell the UI layer we're done connecting to the node.
|
|
//
|
|
|
|
hr = THR( SendStatusReport( m_bstrNodeName,
|
|
TASKID_Major_Check_Node_Feasibility,
|
|
TASKID_Minor_Checking_Node_Cluster_Feasibility,
|
|
0, // min
|
|
2, // max
|
|
1, // current
|
|
S_OK,
|
|
NULL // don't update string
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Ask the node if it can be clustered.
|
|
//
|
|
|
|
hr = THR( m_pccs->TypeSafeQI( IClusCfgCapabilities, &pccc ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_QI_pccc, hr );
|
|
goto ClusterFeasibilityError;
|
|
}
|
|
|
|
hr = STHR( pccc->CanNodeBeClustered() );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_CanNodeBeClustered, hr );
|
|
goto ClusterFeasibilityError;
|
|
}
|
|
|
|
if ( hr == S_FALSE )
|
|
{
|
|
//
|
|
// Tell the UI layer that this node doesn't want to be clustered. Note that
|
|
// we don't put anything in the UI, only to the log. It is the responsibility
|
|
// of the "blocking" component to tell the UI layer the reasons.
|
|
//
|
|
|
|
hr = THR( SendStatusReport( NULL,
|
|
TASKID_Major_Client_And_Server_Log,
|
|
TASKID_Minor_Can_Node_Be_Clustered_Failed,
|
|
0, // min
|
|
1, // max
|
|
1, // current
|
|
ERROR_NODE_CANNOT_BE_CLUSTERED,
|
|
m_bstrNodeName
|
|
) );
|
|
// don't care about the error.
|
|
|
|
hr = THR( HRESULT_FROM_WIN32( ERROR_NODE_CANNOT_BE_CLUSTERED ) );
|
|
goto ClusterFeasibilityError;
|
|
}
|
|
|
|
//
|
|
// Tell the UI layer we're done checking the node's cluster feasibility.
|
|
//
|
|
|
|
hr = THR( SendStatusReport( m_bstrNodeName,
|
|
TASKID_Major_Check_Node_Feasibility,
|
|
TASKID_Minor_Checking_Node_Cluster_Feasibility,
|
|
0, // min
|
|
2, // max
|
|
2, // current
|
|
S_OK,
|
|
NULL // don't update string
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Create progress message and tell the UI layer our progress
|
|
// for gathering managed device info.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
hr = THR( HrLoadStringIntoBSTR( g_hInstance,
|
|
IDS_TASKID_MINOR_GATHERING_MANAGED_DEVICES,
|
|
&bstrNotification
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_LoadString, hr );
|
|
goto FindDevicesError;
|
|
}
|
|
|
|
hr = THR( SendStatusReport( m_bstrNodeName,
|
|
TASKID_Major_Find_Devices,
|
|
TASKID_Minor_Gathering_Managed_Devices,
|
|
0,
|
|
2,
|
|
0,
|
|
S_OK,
|
|
bstrNotification
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto FindDevicesError;
|
|
|
|
hr = THR( m_pccs->GetManagedResourcesEnum( &peccmr ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
hr = THR( m_pccs->GetNetworksEnum( &pen ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
hr = THR( HrTotalManagedResourceCount( peccmr, pen, &cTotalResources ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Start gathering the managed resources.
|
|
//
|
|
|
|
hr = THR( HrGatherResources( peccmr, cTotalResources ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Tell the UI layer we're done with gathering the resources.
|
|
//
|
|
|
|
hr = THR( SendStatusReport( m_bstrNodeName,
|
|
TASKID_Major_Find_Devices,
|
|
TASKID_Minor_Gathering_Managed_Devices,
|
|
0, // min
|
|
2, // max
|
|
1, // current
|
|
S_OK,
|
|
NULL // don't update string
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Now gather the networks from the node.
|
|
//
|
|
|
|
hr = THR( HrGatherNetworks( pen, cTotalResources ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Tell the UI layer we're done with gathering the networks.
|
|
//
|
|
|
|
hr = THR( SendStatusReport( m_bstrNodeName,
|
|
TASKID_Major_Find_Devices,
|
|
TASKID_Minor_Gathering_Managed_Devices,
|
|
0, // min
|
|
2, // max
|
|
2, // current
|
|
S_OK,
|
|
NULL // don't update string
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
Cleanup:
|
|
TraceSysFreeString( bstrNotification );
|
|
|
|
if ( psp != NULL )
|
|
{
|
|
psp->Release();
|
|
}
|
|
if ( punk != NULL )
|
|
{
|
|
punk->Release();
|
|
}
|
|
if ( pcp != NULL )
|
|
{
|
|
pcp->Release();
|
|
}
|
|
if ( pcpc != NULL )
|
|
{
|
|
pcpc->Release();
|
|
}
|
|
if ( m_pom != NULL )
|
|
{
|
|
HRESULT hr2;
|
|
IUnknown * punk;
|
|
|
|
hr2 = THR( m_pom->GetObject( DFGUID_StandardInfo,
|
|
m_cookieCompletion,
|
|
&punk
|
|
) );
|
|
if ( SUCCEEDED( hr2 ) )
|
|
{
|
|
IStandardInfo * psi;
|
|
|
|
hr2 = THR( punk->TypeSafeQI( IStandardInfo, &psi ) );
|
|
punk->Release();
|
|
|
|
if ( SUCCEEDED( hr2 ) )
|
|
{
|
|
hr2 = THR( psi->SetStatus( hr ) );
|
|
psi->Release();
|
|
}
|
|
else
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_GetObject_QI_Failed, hr );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_BeginTask_GetObject_Failed, hr );
|
|
}
|
|
}
|
|
if ( pnui != NULL )
|
|
{
|
|
THR( pnui->ObjectChanged( m_cookieCompletion ) );
|
|
pnui->Release();
|
|
}
|
|
if ( pcm != NULL )
|
|
{
|
|
pcm->Release();
|
|
}
|
|
if ( psi != NULL )
|
|
{
|
|
psi->Release();
|
|
}
|
|
if ( pccc != NULL )
|
|
{
|
|
pccc->Release();
|
|
}
|
|
|
|
if ( peccmr != NULL )
|
|
{
|
|
peccmr->Release();
|
|
}
|
|
|
|
if ( pen != NULL )
|
|
{
|
|
pen->Release();
|
|
}
|
|
|
|
HRETURN( hr );
|
|
|
|
ClusterFeasibilityError:
|
|
THR( SendStatusReport( m_bstrNodeName,
|
|
TASKID_Major_Check_Node_Feasibility,
|
|
TASKID_Minor_Checking_Node_Cluster_Feasibility,
|
|
0,
|
|
2,
|
|
2,
|
|
hr,
|
|
NULL
|
|
) );
|
|
goto Cleanup;
|
|
|
|
FindDevicesError:
|
|
THR( SendStatusReport( m_bstrNodeName,
|
|
TASKID_Major_Find_Devices,
|
|
TASKID_Minor_Gathering_Managed_Devices,
|
|
0,
|
|
2,
|
|
2,
|
|
hr,
|
|
NULL
|
|
) );
|
|
goto Cleanup;
|
|
|
|
} //*** CTaskGatherInformation::BeginTask()
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// STDMETHODIMP
|
|
// CTaskGatherInformation::StopTask( void )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CTaskGatherInformation::StopTask( void )
|
|
{
|
|
TraceFunc( "[IDoTask]" );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** CTaskGatherInformation::StopTask
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// STDMETHODIMP
|
|
// CTaskGatherInformation::SetCompletionCookie(
|
|
// OBJECTCOOKIE cookieIn
|
|
// )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CTaskGatherInformation::SetCompletionCookie(
|
|
OBJECTCOOKIE cookieIn
|
|
)
|
|
{
|
|
TraceFunc( "[ITaskGatherInformation]" );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
m_cookieCompletion = cookieIn;
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** CTaskGatherInformation::SetCompletionCookie()
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// STDMETHODIMP
|
|
// CTaskGatherInformation::SetNodeCookie(
|
|
// OBJECTCOOKIE cookieIn
|
|
// )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CTaskGatherInformation::SetNodeCookie(
|
|
OBJECTCOOKIE cookieIn
|
|
)
|
|
{
|
|
TraceFunc( "[ITaskGatherInformation]" );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
m_cookieNode = cookieIn;
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** CTaskGatherInformation::SetNodeCookie()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// STDMETHODIMP
|
|
// CTaskGatherInformation::SetJoining( void )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CTaskGatherInformation::SetJoining( void )
|
|
{
|
|
TraceFunc( "[ITaskGatherInformation]" );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
m_fJoining = TRUE;
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** CTaskGatherInformation::SetJoining()
|
|
|
|
|
|
//****************************************************************************
|
|
//
|
|
// IClusCfgCallback
|
|
//
|
|
//****************************************************************************
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// STDMETHODIMP
|
|
// CTaskGatherInformation::SendStatusReport(
|
|
// BSTR bstrNodeNameIn,
|
|
// CLSID clsidTaskMajorIn,
|
|
// CLSID clsidTaskMinorIn,
|
|
// ULONG ulMinIn,
|
|
// ULONG ulMaxIn,
|
|
// ULONG ulCurrentIn,
|
|
// HRESULT hrStatusIn,
|
|
// BSTR bstrDescriptionIn
|
|
// )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CTaskGatherInformation::SendStatusReport(
|
|
BSTR bstrNodeNameIn,
|
|
CLSID clsidTaskMajorIn,
|
|
CLSID clsidTaskMinorIn,
|
|
ULONG ulMinIn,
|
|
ULONG ulMaxIn,
|
|
ULONG ulCurrentIn,
|
|
HRESULT hrStatusIn,
|
|
BSTR bstrDescriptionIn
|
|
)
|
|
{
|
|
TraceFunc( "[IClusCfgCallback]" );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
IServiceProvider * psp = NULL;
|
|
IConnectionPointContainer * pcpc = NULL;
|
|
IConnectionPoint * pcp = NULL;
|
|
FILETIME ft;
|
|
|
|
if ( m_pcccb == NULL )
|
|
{
|
|
//
|
|
// Collect the manager we need to complete this task.
|
|
//
|
|
|
|
hr = THR( CoCreateInstance( CLSID_ServiceManager,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
TypeSafeParams( IServiceProvider, &psp )
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
hr = THR( psp->TypeSafeQS( CLSID_NotificationManager,
|
|
IConnectionPointContainer,
|
|
&pcpc
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
hr = THR( pcpc->FindConnectionPoint( IID_IClusCfgCallback, &pcp ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
pcp = TraceInterface( L"CTaskGatherInformation!IConnectionPoint", IConnectionPoint, pcp, 1 );
|
|
|
|
hr = THR( pcp->TypeSafeQI( IClusCfgCallback, &m_pcccb ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
m_pcccb = TraceInterface( L"CTaskGatherInformation!IClusCfgCallback", IClusCfgCallback, m_pcccb, 1 );
|
|
|
|
psp->Release();
|
|
psp = NULL;
|
|
}
|
|
|
|
GetSystemTimeAsFileTime( &ft );
|
|
|
|
//
|
|
// Send the message!
|
|
//
|
|
|
|
hr = THR( m_pcccb->SendStatusReport( bstrNodeNameIn,
|
|
clsidTaskMajorIn,
|
|
clsidTaskMinorIn,
|
|
ulMinIn,
|
|
ulMaxIn,
|
|
ulCurrentIn,
|
|
hrStatusIn,
|
|
bstrDescriptionIn,
|
|
&ft,
|
|
NULL
|
|
) );
|
|
|
|
Cleanup:
|
|
if ( psp != NULL )
|
|
{
|
|
psp->Release();
|
|
}
|
|
if ( pcpc != NULL )
|
|
{
|
|
pcpc->Release();
|
|
}
|
|
if ( pcp != NULL )
|
|
{
|
|
pcp->Release();
|
|
}
|
|
|
|
HRETURN( hr );
|
|
|
|
} //*** CTaskGatherInformation::SendStatusReport()
|
|
|
|
|
|
//****************************************************************************
|
|
//
|
|
// Private
|
|
//
|
|
//****************************************************************************
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// HRESULT
|
|
// CTaskGatherInformation::HrGatherResources( IEnumClusCfgManagedResources * pResourceEnumIn, DWORD cTotalResourcesIn )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CTaskGatherInformation::HrGatherResources( IEnumClusCfgManagedResources * pResourceEnumIn, DWORD cTotalResourcesIn )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr = S_OK;
|
|
ULONG celt;
|
|
|
|
OBJECTCOOKIE cookieDummy;
|
|
|
|
ULONG celtFetched = 0;
|
|
BSTR bstrName = NULL;
|
|
BSTR bstrNotification = NULL;
|
|
BOOL fFoundQuorumDevice = FALSE;
|
|
BSTR bstrQuorumDeviceName = NULL;
|
|
|
|
IEnumClusCfgPartitions * peccp = NULL;
|
|
IClusCfgManagedResourceInfo * pccmriNew = NULL;
|
|
IClusCfgManagedResourceInfo * pccmri[ 10 ] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
|
|
|
if ( pResourceEnumIn == NULL )
|
|
{
|
|
hr = THR( E_POINTER );
|
|
goto Error;
|
|
}
|
|
|
|
//
|
|
// Initialize some stuff.
|
|
//
|
|
|
|
m_ulQuorumDiskSize = ULONG_MAX;
|
|
Assert( m_pccmriQuorum == NULL );
|
|
|
|
//
|
|
// Enumerate the next 10 resources.
|
|
//
|
|
while ( hr == S_OK )
|
|
{
|
|
//
|
|
// KB: GPease 27-JUL-2000
|
|
// We decided to enumerate one at a time because WMI is
|
|
// taking so long on the server side that the UI needs
|
|
// some kind of feedback. Having the server send a
|
|
// message back seemed to be expensive especially
|
|
// since grabbing 10 at a time was supposed to save
|
|
// us bandwidth on the wire.
|
|
//
|
|
//hr = STHR( pResourceEnumIn->Next( 10, pccmri, &celtFetched ) );
|
|
hr = STHR( pResourceEnumIn->Next( 1, pccmri, &celtFetched ) );
|
|
if ( hr == S_FALSE && celtFetched == 0 )
|
|
break; // exit loop
|
|
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherResources_EnumResources_Next, hr );
|
|
goto Error;
|
|
}
|
|
|
|
//
|
|
// Loop thru the resource gather information out of each of them
|
|
// and then release them.
|
|
//
|
|
for( celt = 0; celt < celtFetched; celt ++ )
|
|
{
|
|
UINT uIdMessage = IDS_TASKID_MINOR_FOUND_DEVICE;
|
|
IGatherData * pgd;
|
|
IUnknown * punk;
|
|
|
|
Assert( pccmri[ celt ] != NULL );
|
|
|
|
// get the name of the resource
|
|
hr = THR( pccmri[ celt ]->GetUID( &bstrName ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherResources_EnumResources_GetUID, hr );
|
|
goto Error;
|
|
}
|
|
|
|
TraceMemoryAddBSTR( bstrName );
|
|
|
|
// make sure the object manager generates a cookie for it.
|
|
hr = STHR( m_pom->FindObject( CLSID_ManagedResourceType,
|
|
m_cookieNode,
|
|
bstrName,
|
|
DFGUID_ManagedResource,
|
|
&cookieDummy,
|
|
&punk
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherResources_EnumResources_FindObject, hr );
|
|
goto Error;
|
|
}
|
|
|
|
TraceSysFreeString( bstrName );
|
|
bstrName = NULL;
|
|
|
|
hr = THR( punk->TypeSafeQI( IClusCfgManagedResourceInfo, &pccmriNew ) );
|
|
punk->Release(); // release promptly
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherResources_EnumResources_FindObject_QI_pccmriNew, hr );
|
|
goto Error;
|
|
}
|
|
|
|
//
|
|
// The Object Manager created a new object. Initialize it.
|
|
//
|
|
|
|
// find the IGatherData interface
|
|
hr = THR( pccmriNew->TypeSafeQI( IGatherData, &pgd ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherResources_EnumResources_FindObject_QI_pgd, hr );
|
|
goto Error;
|
|
}
|
|
|
|
// have the new object gather all information it needs
|
|
hr = THR( pgd->Gather( m_cookieNode, pccmri[ celt ] ) );
|
|
pgd->Release(); // release promptly
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherResources_EnumResources_Gather, hr );
|
|
goto Error;
|
|
}
|
|
|
|
// figure out if the device is capable of being a quorum device.
|
|
hr = STHR( pccmriNew->IsQuorumCapable() );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherResources_EnumResources_IsQuorumCapable, hr );
|
|
goto Error;
|
|
}
|
|
if ( hr == S_OK )
|
|
{
|
|
uIdMessage = IDS_TASKID_MINOR_FOUND_QUORUM_CAPABLE_DEVICE;
|
|
|
|
//
|
|
// If we aren't joining, then figure out if this resource is a better
|
|
// quorum resource than one previously encountered.
|
|
//
|
|
|
|
if ( !m_fJoining )
|
|
{
|
|
ULONG ulMegaBytes;
|
|
|
|
// don't wrap - this can fail with NO_INTERFACE
|
|
hr = pccmri[ celt ]->TypeSafeQI( IEnumClusCfgPartitions, &peccp );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
while ( SUCCEEDED( hr ) )
|
|
{
|
|
ULONG celtDummy;
|
|
IClusCfgPartitionInfo * pccpi;
|
|
|
|
hr = STHR( peccp->Next( 1, &pccpi, &celtDummy ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherResources_EnumResources_EnumPartitions_Next, hr );
|
|
goto Error;
|
|
}
|
|
|
|
if ( hr == S_FALSE )
|
|
break; // exit condition
|
|
|
|
hr = THR( pccpi->GetSize( &ulMegaBytes ) );
|
|
pccpi->Release(); // release promptly
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherResources_EnumResources_EnumPartitions_GetSize, hr );
|
|
goto Error;
|
|
}
|
|
|
|
//
|
|
// Does this partition meet the minimum requirements for a quorum resource?
|
|
// And is it smaller than the last selected quorum resource?
|
|
//
|
|
|
|
if ( ( ulMegaBytes >= MINIMUM_STORAGE_SIZE ) && ( ulMegaBytes < m_ulQuorumDiskSize ) )
|
|
{
|
|
if ( m_pccmriQuorum != pccmriNew )
|
|
{
|
|
// Set the new device as quorum
|
|
hr = THR( pccmriNew->SetQuorumedDevice( TRUE ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherResources_EnumResources_EnumPartitions_SetNEWQuorumedDevice, hr );
|
|
goto Error;
|
|
}
|
|
|
|
if ( m_pccmriQuorum != NULL )
|
|
{
|
|
// delete the old quorum device name
|
|
TraceSysFreeString( bstrQuorumDeviceName );
|
|
bstrQuorumDeviceName = NULL;
|
|
|
|
// Unset the old device
|
|
hr = THR( m_pccmriQuorum->SetQuorumedDevice( FALSE ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherResources_EnumResources_EnumPartitions_SetOLDQuorumedDevice, hr );
|
|
goto Error;
|
|
}
|
|
|
|
// Release the interface
|
|
m_pccmriQuorum->Release();
|
|
}
|
|
|
|
hr = THR( pccmriNew->GetUID( &bstrQuorumDeviceName ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherResources_EnumResources_EnumPartitions_GetUID, hr );
|
|
goto Error;
|
|
}
|
|
|
|
TraceMemoryAddBSTR( bstrQuorumDeviceName );
|
|
|
|
m_pccmriQuorum = pccmriNew;
|
|
m_pccmriQuorum->AddRef();
|
|
}
|
|
|
|
m_ulQuorumDiskSize = ulMegaBytes;
|
|
|
|
fFoundQuorumDevice = TRUE;
|
|
|
|
} // if: partition meets requirements and is smaller.
|
|
|
|
} // while: success
|
|
|
|
peccp->Release();
|
|
peccp = NULL;
|
|
|
|
} // if: storage capabile
|
|
else
|
|
{
|
|
if ( hr != E_NOINTERFACE )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherResources_EnumResources_QI_peccp, hr );
|
|
THR( hr );
|
|
goto Error;
|
|
}
|
|
|
|
if ( uIdMessage == IDS_TASKID_MINOR_FOUND_QUORUM_CAPABLE_DEVICE )
|
|
{
|
|
//
|
|
// If it doesn't support enumerating the partitions, then we don't
|
|
// consider it a candidate for being a quorum resource.
|
|
//
|
|
|
|
uIdMessage = IDS_TASKID_MINOR_FOUND_DEVICE;
|
|
}
|
|
|
|
} // else: failed
|
|
|
|
} // if: not joining
|
|
else
|
|
{
|
|
//
|
|
// If we are joining, then a quorum device had to be found
|
|
// already.
|
|
//
|
|
|
|
//
|
|
// BUGBUG: 08-MAY-2001 GalenB
|
|
//
|
|
// We are not setting bstrQuorumDeviceName to something if we are joining. This causes the message
|
|
// "Setting quorum device to '(NULL)' to appear in the logs and the UI. Where is the quorum when
|
|
// we are adding a node to the cluster?
|
|
//
|
|
// A more complete fix is to find the current quorum device and get its name.
|
|
//
|
|
fFoundQuorumDevice = TRUE;
|
|
|
|
} // else: joining
|
|
} // if: quorum capable
|
|
|
|
// send the UI layer a report
|
|
m_cResources ++;
|
|
|
|
// grab the name to display in the UI
|
|
hr = THR( pccmriNew->GetName( &bstrName ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherResources_EnumResources_GetName, hr );
|
|
goto Error;
|
|
}
|
|
|
|
TraceMemoryAddBSTR( bstrName );
|
|
|
|
hr = THR( HrFormatMessageIntoBSTR( g_hInstance, uIdMessage, &bstrNotification, bstrName ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherResources_EnumResources_FormatMessage, hr );
|
|
goto Error;
|
|
}
|
|
|
|
hr = THR( SendStatusReport( m_bstrNodeName,
|
|
TASKID_Major_Find_Devices,
|
|
TASKID_Minor_Update_Progress,
|
|
0,
|
|
cTotalResourcesIn,
|
|
m_cResources,
|
|
S_OK,
|
|
bstrNotification
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
// Cleanup for the next resource.
|
|
TraceSysFreeString( bstrName );
|
|
bstrName = NULL;
|
|
|
|
pccmriNew->Release();
|
|
pccmriNew = NULL;
|
|
|
|
// release the interface
|
|
pccmri[ celt ]->Release();
|
|
pccmri[ celt ] = NULL;
|
|
} // for: celt
|
|
} // while: hr
|
|
|
|
//
|
|
// Update UI layer about the quorum device.
|
|
//
|
|
|
|
//
|
|
// BUGUG: 08-MAY-2001 GalenB
|
|
//
|
|
// Testing that bstrQuorumDeviceName has something in it before showing this in the UI.
|
|
// When adding nodes this variable is not being set and was causing a status report
|
|
// with a NULL name to be shown in the UI.
|
|
//
|
|
if ( fFoundQuorumDevice )
|
|
{
|
|
if ( bstrQuorumDeviceName != NULL )
|
|
{
|
|
Assert( m_fJoining == FALSE );
|
|
|
|
THR( HrLoadStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_FOUND_QUORUM_CAPABLE_RESOURCE, &bstrNotification ) );
|
|
THR( SendStatusReport( m_bstrNodeName,
|
|
TASKID_Major_Find_Devices,
|
|
TASKID_Minor_Found_Quorum_Capable_Resource,
|
|
0,
|
|
1,
|
|
1,
|
|
S_OK,
|
|
bstrNotification
|
|
) );
|
|
|
|
TraceSysFreeString( bstrNotification );
|
|
bstrNotification = NULL;
|
|
|
|
THR( HrFormatStringIntoBSTR( g_hInstance, IDS_TASKID_MINOR_MARKING_QUORUM_CAPABLE_RESOURCE, &bstrNotification, bstrQuorumDeviceName ) );
|
|
hr = THR( SendStatusReport( m_bstrNodeName,
|
|
TASKID_Major_Find_Devices,
|
|
TASKID_Minor_Marking_Quorum_Capable_Resource,
|
|
0,
|
|
1,
|
|
1,
|
|
S_OK,
|
|
bstrNotification
|
|
) );
|
|
} // if: we have a quorum device to show
|
|
}
|
|
else
|
|
{
|
|
if ( m_fJoining )
|
|
{
|
|
//
|
|
// If joining, stop the user.
|
|
//
|
|
|
|
hr = THR( HrFormatMessageIntoBSTR( g_hInstance,
|
|
IDS_TASKID_MINOR_NO_QUORUM_CAPABLE_DEVICE_FOUND,
|
|
&bstrNotification,
|
|
m_bstrNodeName
|
|
) );
|
|
|
|
hr = THR( SendStatusReport( m_bstrNodeName,
|
|
TASKID_Major_Find_Devices,
|
|
TASKID_Minor_No_Quorum_Capable_Device_Found,
|
|
0,
|
|
1,
|
|
1,
|
|
HRESULT_FROM_WIN32( TW32( ERROR_QUORUM_DISK_NOT_FOUND ) ),
|
|
bstrNotification
|
|
) );
|
|
// error checked below
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If forming, just warn the user.
|
|
//
|
|
|
|
hr = THR( HrFormatMessageIntoBSTR( g_hInstance,
|
|
IDS_TASKID_MINOR_FORCED_LOCAL_QUORUM,
|
|
&bstrNotification
|
|
) );
|
|
|
|
hr = THR( SendStatusReport( m_bstrNodeName,
|
|
TASKID_Major_Find_Devices,
|
|
TASKID_Minor_No_Quorum_Capable_Device_Found,
|
|
0,
|
|
1,
|
|
1,
|
|
MAKE_HRESULT( SEVERITY_SUCCESS, FACILITY_WIN32, ERROR_QUORUM_DISK_NOT_FOUND ),
|
|
bstrNotification
|
|
) );
|
|
// error checked below
|
|
}
|
|
} // else: no quorum detected.
|
|
|
|
//
|
|
// Check error and do the appropriate thing.
|
|
//
|
|
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherResources_Failed, hr );
|
|
goto Cleanup;
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
Cleanup:
|
|
TraceSysFreeString( bstrName );
|
|
TraceSysFreeString( bstrNotification );
|
|
TraceSysFreeString( bstrQuorumDeviceName );
|
|
|
|
if ( peccp != NULL )
|
|
{
|
|
peccp->Release();
|
|
}
|
|
if ( pccmriNew != NULL )
|
|
{
|
|
pccmriNew->Release();
|
|
}
|
|
for( celt = 0; celt < 10; celt ++ )
|
|
{
|
|
if ( pccmri[ celt ] != NULL )
|
|
{
|
|
pccmri[ celt ]->Release();
|
|
}
|
|
} // for: celt
|
|
|
|
HRETURN( hr );
|
|
|
|
Error:
|
|
//
|
|
// Tell the UI layer we're done will gathering and what the resulting
|
|
// status was.
|
|
//
|
|
THR( SendStatusReport( m_bstrNodeName,
|
|
TASKID_Major_Find_Devices,
|
|
TASKID_Minor_Gathering_Managed_Devices,
|
|
0,
|
|
2,
|
|
2,
|
|
hr,
|
|
bstrNotification
|
|
) );
|
|
goto Cleanup;
|
|
|
|
} //*** CTaskGatherInformation::HrGatherResources()
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// HRESULT
|
|
// CTaskGatherInformation::HrGatherNetworks( IEnumClusCfgNetworks * pNetworkEnumIn, DWORD cTotalResourcesIn )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CTaskGatherInformation::HrGatherNetworks( IEnumClusCfgNetworks * pNetworkEnumIn, DWORD cTotalResourcesIn )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr = S_OK;
|
|
ULONG celt;
|
|
|
|
OBJECTCOOKIE cookieDummy;
|
|
|
|
ULONG celtFetched = 0;
|
|
ULONG celtFound = 0;
|
|
BSTR bstrName = NULL;
|
|
BSTR bstrNotification = NULL;
|
|
|
|
IClusCfgNetworkInfo * pccniLocal = NULL;
|
|
IClusCfgNetworkInfo * pccni[ 10 ] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
|
|
|
|
//
|
|
// Enumerate the next 10 networks.
|
|
//
|
|
while ( hr == S_OK )
|
|
{
|
|
//
|
|
// KB: GPease 27-JUL-2000
|
|
// We decided to enumerate one at a time because WMI is
|
|
// taking so long on the server side that the UI needs
|
|
// some kind of feedback. Having the server send a
|
|
// message back seemed to be expensive especially
|
|
// since grabbing 10 at a time was supposed to save
|
|
// us bandwidth on the wire.
|
|
//
|
|
//hr = STHR( pNetworkEnumIn->Next( 10, pccni, &celtFetched ) );
|
|
hr = STHR( pNetworkEnumIn->Next( 1, pccni, &celtFetched ) );
|
|
if ( hr == S_FALSE && celtFetched == 0 )
|
|
break; // exit loop
|
|
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherNetworks_EnumNetworks_Next, hr );
|
|
goto Error;
|
|
}
|
|
|
|
//
|
|
// Loop thru the networks gather information out of each of them
|
|
// and then release them.
|
|
//
|
|
for( celt = 0; celt < celtFetched; celt ++ )
|
|
{
|
|
IGatherData * pgd;
|
|
IUnknown * punk;
|
|
|
|
Assert( pccni[ celt ] != NULL );
|
|
|
|
// get the name of the resource
|
|
hr = THR( pccni[ celt ]->GetUID( &bstrName ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherNetworks_EnumNetworks_GetUID, hr );
|
|
goto Error;
|
|
}
|
|
|
|
TraceMemoryAddBSTR( bstrName );
|
|
|
|
// make sure the object manager generates a cookie for it.
|
|
hr = STHR( m_pom->FindObject( CLSID_NetworkType,
|
|
m_cookieNode,
|
|
bstrName,
|
|
DFGUID_NetworkResource,
|
|
&cookieDummy,
|
|
&punk
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherNetworks_EnumNetworks_FindObject, hr );
|
|
goto Error;
|
|
}
|
|
|
|
//
|
|
// The Object Manager created a new object. Initialize it.
|
|
//
|
|
|
|
// find the IGatherData interface
|
|
hr = THR( punk->TypeSafeQI( IClusCfgNetworkInfo, &pccniLocal ) );
|
|
punk->Release(); // release promptly
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherNetworks_EnumNetworks_FindObject_QI_pccniLocal, hr );
|
|
goto Error;
|
|
}
|
|
|
|
// find the IGatherData interface
|
|
hr = THR( pccniLocal->TypeSafeQI( IGatherData, &pgd ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherNetworks_EnumNetworks_FindObject_QI_pgd, hr );
|
|
goto Error;
|
|
}
|
|
|
|
// have the new object gather all information it needs
|
|
hr = THR( pgd->Gather( m_cookieNode, pccni[ celt ] ) );
|
|
pgd->Release(); // release promptly
|
|
if ( hr == E_UNEXPECTED )
|
|
{
|
|
hr = THR( HrFormatStringIntoBSTR( g_hInstance,
|
|
IDS_TASKID_MINOR_DUPLICATE_NETWORKS_FOUND,
|
|
&bstrNotification,
|
|
bstrName
|
|
) );
|
|
|
|
hr = THR( SendStatusReport( m_bstrNodeName,
|
|
TASKID_Major_Find_Devices,
|
|
TASKID_Minor_Duplicate_Networks_Found,
|
|
0,
|
|
cTotalResourcesIn,
|
|
m_cResources + 1, // the resource number it would have been
|
|
HRESULT_FROM_WIN32( ERROR_CLUSTER_NETWORK_EXISTS ),
|
|
bstrNotification
|
|
) );
|
|
hr = THR( HRESULT_FROM_WIN32( ERROR_CLUSTER_NETWORK_EXISTS ) );
|
|
goto Cleanup;
|
|
}
|
|
else if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherNetworks_EnumNetworks_Gather, hr );
|
|
goto Error;
|
|
}
|
|
|
|
TraceSysFreeString( bstrName );
|
|
bstrName = NULL;
|
|
|
|
// send the UI layer a report
|
|
m_cResources ++;
|
|
|
|
hr = THR( pccniLocal->GetName( &bstrName ) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherNetworks_EnumNetworks_GetName, hr );
|
|
goto Error;
|
|
}
|
|
|
|
TraceMemoryAddBSTR( bstrName );
|
|
|
|
hr = THR( HrFormatMessageIntoBSTR( g_hInstance,
|
|
IDS_TASKID_MINOR_FOUND_DEVICE,
|
|
&bstrNotification,
|
|
bstrName
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherNetworks_EnumNetworks_FormatMessage, hr );
|
|
goto Error;
|
|
}
|
|
|
|
hr = THR( SendStatusReport( m_bstrNodeName,
|
|
TASKID_Major_Find_Devices,
|
|
TASKID_Minor_Update_Progress,
|
|
0,
|
|
cTotalResourcesIn,
|
|
m_cResources,
|
|
S_OK,
|
|
bstrNotification
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
// found a Network Interface, increment the counter
|
|
celtFound++;
|
|
|
|
// clean up before next pass
|
|
TraceSysFreeString( bstrName );
|
|
bstrName = NULL;
|
|
|
|
// release the interface
|
|
pccni[ celt ]->Release();
|
|
pccni[ celt ] = NULL;
|
|
|
|
pccniLocal->Release();
|
|
pccniLocal = NULL;
|
|
|
|
} // for: celt
|
|
|
|
} // while: hr
|
|
|
|
// Check how many interfaces have been found. Should be at
|
|
// least 2 to avoid single point of failure. If not, warn.
|
|
if ( celtFound < 2 )
|
|
{
|
|
hr = THR( HrFormatMessageIntoBSTR( g_hInstance,
|
|
IDS_TASKID_MINOR_ONLY_ONE_NETWORK,
|
|
&bstrNotification
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
SSR_TGI_FAILED( TASKID_Major_Client_And_Server_Log, TASKID_Minor_GatherNetworks_EnumNetworks_FormatMessage, hr );
|
|
goto Error;
|
|
}
|
|
|
|
hr = THR( SendStatusReport( m_bstrNodeName,
|
|
TASKID_Major_Find_Devices,
|
|
TASKID_Minor_Only_One_Network,
|
|
0,
|
|
1,
|
|
1,
|
|
S_FALSE,
|
|
bstrNotification
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
Cleanup:
|
|
if ( bstrName != NULL )
|
|
{
|
|
TraceSysFreeString( bstrName );
|
|
}
|
|
if ( bstrNotification != NULL )
|
|
{
|
|
TraceSysFreeString( bstrNotification );
|
|
}
|
|
if ( pccniLocal != NULL )
|
|
{
|
|
pccniLocal->Release();
|
|
}
|
|
for( celt = 0; celt < 10; celt ++ )
|
|
{
|
|
if ( pccni[ celt ] != NULL )
|
|
{
|
|
pccni[ celt ]->Release();
|
|
}
|
|
} // for: celt
|
|
|
|
HRETURN( hr );
|
|
|
|
Error:
|
|
//
|
|
// Tell the UI layer we're done will gathering and what the resulting
|
|
// status was.
|
|
//
|
|
THR( SendStatusReport( m_bstrNodeName,
|
|
TASKID_Major_Find_Devices,
|
|
TASKID_Minor_Gathering_Managed_Devices,
|
|
0,
|
|
2,
|
|
2,
|
|
hr,
|
|
bstrNotification
|
|
) );
|
|
goto Cleanup;
|
|
|
|
} //*** CTaskGatherInformation::HrGatherNetworks()
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Static function implementations
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
static HRESULT HrTotalManagedResourceCount( IEnumClusCfgManagedResources * pResourceEnumIn, IEnumClusCfgNetworks * pNetworkEnumIn, DWORD * pnCountOut )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
DWORD cResources = 0;
|
|
DWORD cNetworks = 0;
|
|
HRESULT hr = S_OK;
|
|
|
|
if ( ( pResourceEnumIn == NULL ) || ( pNetworkEnumIn == NULL ) || ( pnCountOut == NULL ) )
|
|
{
|
|
hr = THR( E_POINTER );
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Ask the resource enumerator how many resources its collection has.
|
|
//
|
|
|
|
hr = THR(pResourceEnumIn->Count( &cResources ));
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Ask the network enumerator how many networks its collection has.
|
|
//
|
|
|
|
hr = pNetworkEnumIn->Count( &cNetworks );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
*pnCountOut = cResources + cNetworks;
|
|
|
|
Cleanup:
|
|
|
|
HRETURN( hr );
|
|
|
|
}
|
|
|