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

2301 lines
56 KiB

//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000-2002 Microsoft Corporation
//
// Module Name:
// TaskCommitClusterChanges.cpp
//
// Description:
// CTaskCommitClusterChanges implementation.
//
// Maintained By:
// Galen Barbee (GalenB) 02-FEB-2000
//
//////////////////////////////////////////////////////////////////////////////
#include "Pch.h"
#include "TaskCommitClusterChanges.h"
DEFINE_THISCLASS("CTaskCommitClusterChanges")
// ************************************************************************
//
// Constructor / Destructor
//
// ************************************************************************
//////////////////////////////////////////////////////////////////////////////
//
// HRESULT
// CTaskCommitClusterChanges::S_HrCreateInstance(
// IUnknown ** ppunkOut
// )
//
//////////////////////////////////////////////////////////////////////////////
HRESULT
CTaskCommitClusterChanges::S_HrCreateInstance(
IUnknown ** ppunkOut
)
{
TraceFunc( "" );
HRESULT hr = S_OK;
CTaskCommitClusterChanges * ptccc = NULL;
Assert( ppunkOut != NULL );
if ( ppunkOut == NULL )
{
hr = THR( E_POINTER );
goto Cleanup;
}
ptccc = new CTaskCommitClusterChanges;
if ( ptccc == NULL )
{
hr = THR( E_OUTOFMEMORY );
goto Cleanup;
}
hr = THR( ptccc->HrInit() );
if ( FAILED( hr ) )
{
goto Cleanup;
}
hr = THR( ptccc->TypeSafeQI( IUnknown, ppunkOut ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
Cleanup:
if ( ptccc != NULL )
{
ptccc->Release();
}
HRETURN( hr );
} //*** CTaskCommitClusterChanges::S_HrCreateInstance
//////////////////////////////////////////////////////////////////////////////
//
// CTaskCommitClusterChanges::CTaskCommitClusterChanges
//
//////////////////////////////////////////////////////////////////////////////
CTaskCommitClusterChanges::CTaskCommitClusterChanges( void )
: m_cRef( 1 )
{
TraceFunc( "" );
InterlockedIncrement( &g_cObjects );
TraceFuncExit();
} //*** CTaskCommitClusterChanges::CTaskCommitClusterChanges
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskCommitClusterChanges::HrInit
//
// Description:
// Initialize the object.
//
// Arguments:
// None.
//
// Return Values:
// S_OK - Success.
// Other HRESULTs.
//
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CTaskCommitClusterChanges::HrInit( void )
{
TraceFunc( "" );
HRESULT hr = S_OK;
// IUnknown stuff
Assert( m_cRef == 1 );
// IDoTask / ITaskCommitClusterChanges
Assert( m_cookie == 0 );
Assert( m_pcccb == NULL );
Assert( m_pcookies == NULL );
Assert( m_cNodes == 0 );
Assert( m_event == NULL );
Assert( m_cookieCluster == NULL );
Assert( m_cookieFormingNode == NULL );
Assert( m_punkFormingNode == NULL );
Assert( m_bstrClusterName == NULL );
Assert( m_bstrClusterBindingString == NULL );
Assert( m_pccc == NULL );
Assert( m_ulIPAddress == 0 );
Assert( m_ulSubnetMask == 0 );
Assert( m_bstrNetworkUID == 0 );
Assert( m_fStop == FALSE );
Assert( m_pen == NULL );
Assert( m_pnui == NULL );
Assert( m_pom == NULL );
Assert( m_ptm == NULL );
Assert( m_pcm == NULL );
// INotifyUI
Assert( m_cNodes == 0 );
Assert( m_hrStatus == S_OK );
hr = THR( HrCoCreateInternalInstance(
CLSID_ClusCfgCredentials
, NULL
, CLSCTX_INPROC_SERVER
, IID_IClusCfgCredentials
, reinterpret_cast< void ** >( &m_pccc )
) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
hr = THR( HrGetComputerName(
ComputerNameDnsHostname
, &m_bstrNodeName
, TRUE // fBestFitIn
) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
Cleanup:
HRETURN( hr );
} //*** CTaskCommitClusterChanges::HrInit
//////////////////////////////////////////////////////////////////////////////
//
// CTaskCommitClusterChanges::~CTaskCommitClusterChanges
//
//////////////////////////////////////////////////////////////////////////////
CTaskCommitClusterChanges::~CTaskCommitClusterChanges( void )
{
TraceFunc( "" );
// m_cRef
// m_cookie
if ( m_pcccb != NULL )
{
m_pcccb->Release();
}
if ( m_pcookies != NULL )
{
TraceFree( m_pcookies );
}
// m_cNodes
if ( m_event != NULL )
{
CloseHandle( m_event );
}
// m_cookieCluster
// m_cookieFormingNode
if ( m_punkFormingNode != NULL )
{
m_punkFormingNode->Release();
}
TraceSysFreeString( m_bstrClusterName );
TraceSysFreeString( m_bstrClusterBindingString );
// m_ulIPAddress
// m_ulSubnetMask
TraceSysFreeString( m_bstrNetworkUID );
TraceSysFreeString( m_bstrNodeName );
if ( m_pen != NULL )
{
m_pen->Release();
}
if ( m_pccc != NULL )
{
m_pccc->Release();
}
if ( m_pnui != NULL )
{
m_pnui->Release();
}
if ( m_pom != NULL )
{
m_pom->Release();
}
if ( m_ptm != NULL )
{
m_ptm->Release();
}
if ( m_pcm != NULL )
{
m_pcm->Release();
}
// m_cSubTasksDone
// m_hrStatus
// m_lLockCallback
InterlockedDecrement( &g_cObjects );
TraceFuncExit();
} //*** CTaskCommitClusterChanges::~CTaskCommitClusterChanges
// ************************************************************************
//
// IUnknown
//
// ************************************************************************
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskCommitClusterChanges::QueryInterface
//
// Description:
// Query this object for the passed in interface.
//
// Arguments:
// riidIn
// Id of interface requested.
//
// ppvOut
// Pointer to the requested interface.
//
// Return Value:
// S_OK
// If the interface is available on this object.
//
// E_NOINTERFACE
// If the interface is not available.
//
// E_POINTER
// ppvOut was NULL.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CTaskCommitClusterChanges::QueryInterface(
REFIID riidIn
, LPVOID * ppvOut
)
{
TraceQIFunc( riidIn, ppvOut );
HRESULT hr = S_OK;
//
// Validate arguments.
//
Assert( ppvOut != NULL );
if ( ppvOut == NULL )
{
hr = THR( E_POINTER );
goto Cleanup;
}
//
// Handle known interfaces.
//
if ( IsEqualIID( riidIn, IID_IUnknown ) )
{
*ppvOut = static_cast< ITaskCommitClusterChanges * >( this );
} // if: IUnknown
else if ( IsEqualIID( riidIn, IID_ITaskCommitClusterChanges ) )
{
*ppvOut = TraceInterface( __THISCLASS__, ITaskCommitClusterChanges, this, 0 );
} // else if: ITaskCommitClusterChanges
else if ( IsEqualIID( riidIn, IID_IDoTask ) )
{
*ppvOut = TraceInterface( __THISCLASS__, IDoTask, this, 0 );
} // else if: IDoTask
else if ( IsEqualIID( riidIn, IID_INotifyUI ) )
{
*ppvOut = TraceInterface( __THISCLASS__, INotifyUI, this, 0 );
} // else if: INotifyUI
else if ( IsEqualIID( riidIn, IID_IClusCfgCallback ) )
{
*ppvOut = TraceInterface( __THISCLASS__, IClusCfgCallback, this, 0 );
} // else if: IClusCfgCallback
else
{
*ppvOut = NULL;
hr = E_NOINTERFACE;
}
//
// Add a reference to the interface if successful.
//
if ( SUCCEEDED( hr ) )
{
((IUnknown *) *ppvOut)->AddRef();
} // if: success
Cleanup:
QIRETURN_IGNORESTDMARSHALLING( hr, riidIn );
} //*** CTaskCommitClusterChanges::QueryInterface
//////////////////////////////////////////////////////////////////////////////
//
// STDMETHODIMP_(ULONG)
// CTaskCommitClusterChanges::AddRef
//
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_( ULONG )
CTaskCommitClusterChanges::AddRef( void )
{
TraceFunc( "[IUnknown]" );
InterlockedIncrement( &m_cRef );
CRETURN( m_cRef );
} //*** CTaskCommitClusterChanges::AddRef
//////////////////////////////////////////////////////////////////////////////
//
// STDMETHODIMP_(ULONG)
// CTaskCommitClusterChanges::Release
//
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_( ULONG )
CTaskCommitClusterChanges::Release( void )
{
TraceFunc( "[IUnknown]" );
LONG cRef;
cRef = InterlockedDecrement( &m_cRef );
if ( cRef == 0 )
{
TraceDo( delete this );
}
CRETURN( cRef );
} //*** CTaskCommitClusterChanges::Release
// ************************************************************************
//
// IDoTask / ITaskCommitClusterChanges
//
// ************************************************************************
//////////////////////////////////////////////////////////////////////////////
//
// STDMETHODIMP
// CTaskCommitClusterChanges::BeginTask
//
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CTaskCommitClusterChanges::BeginTask( void )
{
TraceFunc( "[IDoTask]" );
HRESULT hr;
OBJECTCOOKIE cookieDummy;
IServiceProvider * psp = NULL;
IUnknown * punk = NULL;
IConnectionPointContainer * pcpc = NULL;
IConnectionPoint * pcp = NULL;
TraceInitializeThread( L"TaskCommitClusterChanges" );
LogMsg( L"[MT] [CTaskCommitClusterChanges] Beginning task..." );
//
// Gather the managers we need to complete the 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;
}
pcpc = TraceInterface( L"CTaskCommitClusterChanges!IConnectionPointContainer", IConnectionPointContainer, pcpc, 1 );
hr = THR( pcpc->FindConnectionPoint( IID_INotifyUI, &pcp ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
pcp = TraceInterface( L"CTaskCommitClusterChanges!IConnectionPoint", IConnectionPoint, pcp, 1 );
hr = THR( pcp->TypeSafeQI( INotifyUI, &m_pnui ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
// TraceMoveFromMemoryList( m_pnui, g_GlobalMemoryList );
m_pnui = TraceInterface( L"CTaskCommitClusterChanges!INotifyUI", INotifyUI, m_pnui, 1 );
hr = THR( psp->TypeSafeQS( CLSID_TaskManager, ITaskManager, &m_ptm ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
hr = THR( psp->TypeSafeQS( CLSID_ObjectManager, IObjectManager, &m_pom ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
hr = THR( psp->TypeSafeQS( CLSID_ClusterConnectionManager, IConnectionManager, &m_pcm ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// Release the service manager.
//
psp->Release();
psp = NULL;
//
// Get the enum of the nodes.
//
hr = THR( m_pom->FindObject( CLSID_NodeType,
m_cookieCluster,
NULL,
DFGUID_EnumCookies,
&cookieDummy,
&punk
) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
Assert( m_pen == NULL );
hr = THR( punk->TypeSafeQI( IEnumCookies, &m_pen ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// Compare and push information to the nodes.
//
hr = THR( HrCompareAndPushInformationToNodes() );
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// Gather information about the cluster we are to form/join.
//
hr = THR( HrGatherClusterInformation() );
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// Check to see if we need to "form" a cluster first.
//
if ( m_punkFormingNode != NULL )
{
hr = THR( HrFormFirstNode() );
if ( FAILED( hr ) )
{
goto Cleanup;
}
} // if: m_punkFormingNode
//
// Join the additional nodes.
//
hr = THR( HrAddJoiningNodes() );
if ( FAILED( hr ) )
{
goto Cleanup;
}
Cleanup:
if ( m_cookie != 0 )
{
if ( m_pom != NULL )
{
HRESULT hr2;
IUnknown * punkTemp = NULL;
hr2 = THR( m_pom->GetObject( DFGUID_StandardInfo,
m_cookie,
&punkTemp
) );
if ( SUCCEEDED( hr2 ) )
{
IStandardInfo * psi;
hr2 = THR( punkTemp->TypeSafeQI( IStandardInfo, &psi ) );
punkTemp->Release();
punkTemp = NULL;
if ( SUCCEEDED( hr2 ) )
{
hr2 = THR( psi->SetStatus( hr ) );
psi->Release();
}
} // if: ( SUCCEEDED( hr2 ) )
} // if: ( m_pom != NULL )
if ( m_pnui != NULL )
{
// Signal that the task completed.
THR( m_pnui->ObjectChanged( m_cookie ) );
}
} // if: ( m_cookie != 0 )
if ( punk != NULL )
{
punk->Release();
}
if ( psp != NULL )
{
psp->Release();
}
if ( pcpc != NULL )
{
pcpc->Release();
}
if ( pcp != NULL )
{
pcp->Release();
}
LogMsg( L"[MT] [CTaskCommitClusterChanges] Exiting task. The task was%ws cancelled. (hr = %#08x)", m_fStop == FALSE ? L" not" : L"", hr );
HRETURN( hr );
} //*** CTaskCommitClusterChanges::BeginTask
//////////////////////////////////////////////////////////////////////////////
//
// STDMETHODIMP
// CTaskCommitClusterChanges::StopTask
//
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CTaskCommitClusterChanges::StopTask( void )
{
TraceFunc( "[IDoTask]" );
HRESULT hr = S_OK;
m_fStop = TRUE;
LogMsg( L"[MT] [CTaskCommitClusterChanges] Calling StopTask() on all remaining sub-tasks." );
THR( HrNotifyAllTasksToStop() );
HRETURN( hr );
} //*** CTaskCommitClusterChanges::StopTask
//////////////////////////////////////////////////////////////////////////////
//
// STDMETHODIMP
// CTaskCommitClusterChanges::SetCookie(
// OBJECTCOOKIE cookieIn
// )
//
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CTaskCommitClusterChanges::SetCookie(
OBJECTCOOKIE cookieIn
)
{
TraceFunc( "[ITaskCommitClusterChanges]" );
HRESULT hr = S_OK;
m_cookie = cookieIn;
HRETURN( hr );
} //*** CTaskCommitClusterChanges::SetCookie
//////////////////////////////////////////////////////////////////////////////
//
// STDMETHODIMP
// CTaskCommitClusterChanges::SetClusterCookie(
// OBJECTCOOKIE cookieClusterIn
// )
//
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CTaskCommitClusterChanges::SetClusterCookie(
OBJECTCOOKIE cookieClusterIn
)
{
TraceFunc( "[ITaskCommitClusterChanges]" );
HRESULT hr = S_OK;
m_cookieCluster = cookieClusterIn;
HRETURN( hr );
} //*** CTaskCommitClusterChanges::SetClusterCookie
//////////////////////////////////////////////////////////////////////////////
//
// STDMETHODIMP
// CTaskCommitClusterChanges::SetJoining
//
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CTaskCommitClusterChanges::SetJoining( void )
{
TraceFunc( "[ITaskCommitClusterChanges]" );
HRESULT hr = S_OK;
m_fJoining = TRUE;
HRETURN( hr );
} //*** CTaskCommitClusterChanges::SetJoining
//****************************************************************************
//
// IClusCfgCallback
//
//****************************************************************************
//////////////////////////////////////////////////////////////////////////////
//
// STDMETHODIMP
// CTaskCommitClusterChanges::SendStatusReport(
// LPCWSTR pcszNodeNameIn
// , CLSID clsidTaskMajorIn
// , CLSID clsidTaskMinorIn
// , ULONG ulMinIn
// , ULONG ulMaxIn
// , ULONG ulCurrentIn
// , HRESULT hrStatusIn
// , LPCWSTR pcszDescriptionIn
// , FILETIME * pftTimeIn
// , LPCWSTR pcszReferenceIn
// )
//
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CTaskCommitClusterChanges::SendStatusReport(
LPCWSTR pcszNodeNameIn
, CLSID clsidTaskMajorIn
, CLSID clsidTaskMinorIn
, ULONG ulMinIn
, ULONG ulMaxIn
, ULONG ulCurrentIn
, HRESULT hrStatusIn
, LPCWSTR pcszDescriptionIn
, FILETIME * pftTimeIn
, LPCWSTR pcszReferenceIn
)
{
TraceFunc( "[IClusCfgCallback]" );
Assert( pcszNodeNameIn != NULL );
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"CConfigurationConnection!IConnectionPoint", IConnectionPoint, pcp, 1 );
hr = THR( pcp->TypeSafeQI( IClusCfgCallback, &m_pcccb ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
m_pcccb = TraceInterface( L"CConfigurationConnection!IClusCfgCallback", IClusCfgCallback, m_pcccb, 1 );
psp->Release();
psp = NULL;
}
if ( pftTimeIn == NULL )
{
GetSystemTimeAsFileTime( &ft );
pftTimeIn = &ft;
} // if:
//
// Send the message!
//
hr = THR( m_pcccb->SendStatusReport(
pcszNodeNameIn != NULL ? pcszNodeNameIn : m_bstrNodeName
, clsidTaskMajorIn
, clsidTaskMinorIn
, ulMinIn
, ulMaxIn
, ulCurrentIn
, hrStatusIn
, pcszDescriptionIn
, pftTimeIn
, pcszReferenceIn
) );
if ( m_fStop == TRUE )
{
hr = E_ABORT;
} // if:
Cleanup:
if ( psp != NULL )
{
psp->Release();
}
if ( pcpc != NULL )
{
pcpc->Release();
}
if ( pcp != NULL )
{
pcp->Release();
}
HRETURN( hr );
} //*** CTaskCommitClusterChanges::SendStatusReport
//****************************************************************************
//
// INotifyUI
//
//****************************************************************************
//////////////////////////////////////////////////////////////////////////////
//
// STDMETHODIMP
// CTaskCommitClusterChanges::ObjectChanged(
// OBJECTCOOKIE cookieIn
// )
//
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CTaskCommitClusterChanges::ObjectChanged(
OBJECTCOOKIE cookieIn
)
{
TraceFunc( "[INotifyUI]" );
BOOL fSuccess;
ULONG idx;
HRESULT hr = S_OK;
LogMsg( L"[TaskCommitClusterChanges] Looking for the completion cookie %u.", cookieIn );
for ( idx = 0; idx < m_cNodes; idx ++ )
{
if ( cookieIn == m_pcookies[ idx ] )
{
LogMsg( L"[TaskCommitClusterChanges] Clearing completion cookie %u at array index %u", cookieIn, idx );
// don't care if this fails, but it really shouldn't
THR( HrRemoveTaskFromTrackingList( cookieIn ) );
//
// Make sure it won't be signalled twice.
//
m_pcookies[ idx ] = NULL;
InterlockedIncrement( reinterpret_cast< long * >( &m_cSubTasksDone ) );
if ( m_cSubTasksDone == m_cNodes )
{
//
// Signal the event if all the nodes are done.
//
fSuccess = SetEvent( m_event );
if ( ! fSuccess )
{
hr = HRESULT_FROM_WIN32( TW32( GetLastError() ) );
goto Cleanup;
} // if:
} // if: all done
break;
} // if: matched cookie
} // for: each cookie in the list
goto Cleanup;
Cleanup:
HRETURN( hr );
} //*** CTaskCommitClusterChanges::ObjectChanged
//****************************************************************************
//
// Private
//
//****************************************************************************
//////////////////////////////////////////////////////////////////////////////
//
// HRESULT
// CTaskCommitClusterChanges::HrCompareAndPushInformationToNodes
//
//////////////////////////////////////////////////////////////////////////////
HRESULT
CTaskCommitClusterChanges::HrCompareAndPushInformationToNodes( void )
{
TraceFunc( "" );
HRESULT hr = S_OK;
DWORD dwCookie = 0;
DWORD sc;
ULONG cNodes;
ULONG celtDummy;
OBJECTCOOKIE cookieNode;
OBJECTCOOKIE * pcookies = NULL;
BOOL fDeterminedForming = FALSE;
BSTR bstrNodeName = NULL;
BSTR bstrNotification = NULL;
IUnknown * punk = NULL;
IClusCfgNodeInfo * pccni = NULL;
IConnectionPoint * pcp = NULL;
IStandardInfo * psi = NULL;
ITaskCompareAndPushInformation * ptcapi = NULL;
//
// Tell the UI layer that we are starting to connect to the nodes.
//
hr = THR( SendStatusReport( m_bstrNodeName,
TASKID_Major_Update_Progress, // just twiddle the icon
TASKID_Major_Reanalyze,
1,
1,
1,
S_OK,
NULL,
NULL,
NULL
) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// Count the number of nodes.
//
hr = THR( m_pen->Count( &m_cNodes ) );
if ( FAILED( hr ) )
{
goto Error;
}
//
// Create an event to signal when all the "push" tasks have been
// completed.
//
m_event = CreateEvent( NULL, TRUE, FALSE, NULL );
if ( m_event == NULL )
{
hr = THR( HRESULT_FROM_WIN32( GetLastError() ) );
goto Error;
}
//
// Register with the Notification Manager to get notified.
//
hr = THR( m_pnui->TypeSafeQI( IConnectionPoint, &pcp ) );
if ( FAILED( hr ) )
{
goto Error;
}
hr = THR( pcp->Advise( static_cast< INotifyUI * >( this ), &dwCookie ) );
if ( FAILED( hr ) )
{
goto Error;
}
//
// Allocate a buffer to collect cookies
//
m_pcookies = reinterpret_cast< OBJECTCOOKIE * >( TraceAlloc( HEAP_ZERO_MEMORY, m_cNodes * sizeof( OBJECTCOOKIE ) ) );
if ( m_pcookies == NULL )
{
hr = THR( E_OUTOFMEMORY );
goto Cleanup;
}
//
// This copy is to find out the status of the subtasks.
//
pcookies = reinterpret_cast< OBJECTCOOKIE * >( TraceAlloc( HEAP_ZERO_MEMORY, m_cNodes * sizeof( OBJECTCOOKIE ) ) );
if ( pcookies == NULL )
{
hr = THR( E_OUTOFMEMORY );
goto Cleanup;
}
//
// Loop thru the nodes, creating cookies and compare data for that node.
//
Assert( hr == S_OK );
for ( cNodes = 0; ( ( hr == S_OK ) && ( m_fStop == FALSE ) ); cNodes ++ )
{
//
// Grab the next node.
//
hr = STHR( m_pen->Next( 1, &cookieNode, &celtDummy ) );
if ( hr == S_FALSE )
{
break;
} // if:
if ( FAILED( hr ) )
{
goto Error;
} // if:
//
// Get the object for this node cookie.
//
hr = THR( m_pom->GetObject( DFGUID_NodeInformation, cookieNode, &punk ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( punk->TypeSafeQI( IClusCfgNodeInfo, &pccni ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
punk->Release();
punk = NULL;
//
// Get the nodes name. We are using this to distinguish one nodes
// completion cookie from another. It might also make debugging
// easier (??).
//
hr = THR( HrRetrieveCookiesName( m_pom, cookieNode, &bstrNodeName ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
//
// Update the notification in case something goes wrong.
//
hr = THR( HrFormatMessageIntoBSTR( g_hInstance, IDS_TASKID_MINOR_CONNECTING_TO_NODES, &bstrNotification, bstrNodeName ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// Create a completion cookie.
//
// KB: These will probably be the same cookie from TaskAnalyzeCluster.
//
// Wrap this because we're just generating a cookie
hr = THR( m_pom->FindObject( IID_NULL, m_cookieCluster, bstrNodeName, IID_NULL, &m_pcookies[ cNodes ], &punk ) );
Assert( punk == NULL );
if ( FAILED( hr ) )
{
goto Error;
}
//
// This copy is for determining the status of the sub-tasks.
//
pcookies[ cNodes ] = m_pcookies[ cNodes ];
//
// Figure out if this node is already part of a cluster.
//
hr = STHR( pccni->IsMemberOfCluster() );
if ( FAILED( hr ) )
{
goto Error;
}
//
// Figure out the forming node.
//
if ( ( m_punkFormingNode == NULL ) // no forming node selected
&& ( fDeterminedForming == FALSE ) // no forming node determined
&& ( hr == S_FALSE ) // node isn't a member of a cluster
)
{
//
// If it isn't a member of a cluster, select it as the forming node.
//
Assert( m_punkFormingNode == NULL );
hr = THR( pccni->TypeSafeQI( IUnknown, &m_punkFormingNode ) );
if ( FAILED( hr ) )
{
goto Error;
}
//
// Retrieve the cookie for the forming node.
//
// Wrap this because all Nodes should be in the database by now.
hr = THR( m_pom->FindObject( CLSID_NodeType,
m_cookieCluster,
bstrNodeName,
IID_NULL,
&m_cookieFormingNode,
&punk // dummy
) );
Assert( punk == NULL );
if ( FAILED( hr ) )
{
goto Error;
}
//
// Set this flag to once a node has been determined to be the
// forming node to keep other nodes from being selected.
//
fDeterminedForming = TRUE;
} // if: forming node not found yet
else if ( hr == S_OK ) // node is a member of a cluster
{
//
// Figured out that this node has already formed therefore there
// shouldn't be a "forming node." "Unselect" the forming node by
// releasing the punk and setting it to NULL.
//
if ( m_punkFormingNode != NULL )
{
m_punkFormingNode->Release();
m_punkFormingNode = NULL;
}
//
// Set this flag to once a node has been determined to be the
// forming node to keep other nodes from being selected.
//
fDeterminedForming = TRUE;
} // else:
//
// Create a task to gather this nodes information.
//
hr = THR( m_ptm->CreateTask( TASK_CompareAndPushInformation, &punk ) );
if ( FAILED( hr ) )
{
goto Error;
}
hr = THR( punk->TypeSafeQI( ITaskCompareAndPushInformation, &ptcapi ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// Set the tasks completion cookie.
//
LogMsg( L"[TaskCommitClusterChanges] Setting completion cookie %u at array index %u into the compare and push information task for node %ws", m_pcookies[ cNodes ], cNodes, bstrNodeName );
hr = THR( ptcapi->SetCompletionCookie( m_pcookies[ cNodes ] ) );
if ( FAILED( hr ) )
{
goto Error;
}
//
// Tell it what node it is suppose to gather information from.
//
hr = THR( ptcapi->SetNodeCookie( cookieNode ) );
if ( FAILED( hr ) )
{
goto Error;
}
//
// Submit the task.
//
hr = THR( m_ptm->SubmitTask( ptcapi ) );
if ( FAILED( hr ) )
{
goto Error;
}
hr = THR( HrAddTaskToTrackingList( punk, m_pcookies[ cNodes ] ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
punk->Release();
punk = NULL;
//
// Cleanup for the next node.
//
pccni->Release();
pccni = NULL;
TraceSysFreeString( bstrNodeName );
bstrNodeName = NULL;
ptcapi->Release();
ptcapi = NULL;
} // for: looping thru nodes
Assert( cNodes == m_cNodes );
if ( m_fStop == TRUE )
{
goto Cleanup;
} // if:
//
// Now wait for the work to be done.
//
sc = (DWORD) -1;
Assert( sc != WAIT_OBJECT_0 );
while ( ( sc != WAIT_OBJECT_0 ) && ( m_fStop == FALSE ) )
{
MSG msg;
while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
sc = MsgWaitForMultipleObjectsEx( 1,
&m_event,
INFINITE,
QS_ALLEVENTS | QS_ALLINPUT | QS_ALLPOSTMESSAGE,
0
);
} // while: sc == WAIT_OBJECT_0
//
// Check the status to make sure everyone was happy, if not abort the task.
//
for( cNodes = 0; cNodes < m_cNodes; cNodes ++ )
{
HRESULT hrStatus;
hr = THR( m_pom->GetObject( DFGUID_StandardInfo, pcookies[ cNodes ], &punk ) );
if ( FAILED( hr ) )
{
goto Error;
}
hr = THR( punk->TypeSafeQI( IStandardInfo, &psi ) );
punk->Release();
punk = NULL;
if ( FAILED( hr ) )
{
goto Error;
}
hr = THR( psi->GetStatus( &hrStatus ) );
if ( FAILED( hr ) )
{
goto Error;
}
if ( hrStatus != S_OK )
{
hr = hrStatus;
goto Cleanup;
}
} // for: each node
hr = S_OK;
Cleanup:
Assert( punk == NULL );
if ( pcookies != NULL )
{
for ( cNodes = 0; cNodes < m_cNodes; cNodes++ )
{
if ( pcookies[ cNodes ] != NULL )
{
THR( m_pom->RemoveObject( pcookies[ cNodes ] ) );
}
} // for: each node
TraceFree( pcookies );
} // if: cookiees were allocated
TraceSysFreeString( bstrNodeName );
TraceSysFreeString( bstrNotification );
if ( ptcapi != NULL )
{
ptcapi->Release();
}
if ( pcp != NULL )
{
if ( dwCookie != 0 )
{
THR( pcp->Unadvise( dwCookie ) );
}
pcp->Release();
}
if ( pccni != NULL )
{
pccni->Release();
}
if ( psi != NULL )
{
psi->Release();
}
HRETURN( hr );
Error:
//
// Tell the UI layer about the failure.
//
THR( HrSendStatusReport(
m_bstrNodeName
, TASKID_Major_Reanalyze
, TASKID_Minor_Inconsistant_MiddleTier_Database
, 0
, 1
, 1
, hr
, IDS_TASKID_MINOR_INCONSISTANT_MIDDLETIER_DATABASE
) );
goto Cleanup;
} //*** CTaskCommitClusterChanges::HrCompareAndPushInformationToNodes
//////////////////////////////////////////////////////////////////////////////
//
// HRESULT
// CTaskCommitClusterChanges::HrGatherClusterInformation
//
//////////////////////////////////////////////////////////////////////////////
HRESULT
CTaskCommitClusterChanges::HrGatherClusterInformation( void )
{
TraceFunc( "" );
HRESULT hr;
IUnknown * punk = NULL;
IClusCfgClusterInfo * pccci = NULL;
IClusCfgCredentials * piccc = NULL;
IClusCfgNetworkInfo * pccni = NULL;
//
// Ask the object manager for the cluster configuration object.
//
hr = THR( m_pom->GetObject( DFGUID_ClusterConfigurationInfo, m_cookieCluster, &punk ) );
if ( FAILED( hr ) )
{
goto Error;
}
hr = THR( punk->TypeSafeQI( IClusCfgClusterInfo, &pccci ) );
if ( FAILED( hr ) )
{
goto Error;
}
//
// Gather common properties.
//
hr = THR( pccci->GetName( &m_bstrClusterName ) );
if ( FAILED( hr ) )
{
goto Error;
}
TraceMemoryAddBSTR( m_bstrClusterName );
hr = STHR( pccci->GetBindingString( &m_bstrClusterBindingString ) );
if ( FAILED( hr ) )
{
goto Error;
} // if:
TraceMemoryAddBSTR( m_bstrClusterBindingString );
LogMsg( L"[MT] Cluster binding string is {%ws}.", m_bstrClusterBindingString );
hr = THR( pccci->GetClusterServiceAccountCredentials( &piccc ) );
if ( FAILED( hr ) )
{
goto Error;
}
hr = THR( m_pccc->AssignFrom( piccc ) );
if ( FAILED( hr ) )
{
goto Error;
}
hr = THR( pccci->GetIPAddress( &m_ulIPAddress ) );
if ( FAILED( hr ) )
{
goto Error;
}
hr = THR( pccci->GetSubnetMask( &m_ulSubnetMask ) );
if ( FAILED( hr ) )
{
goto Error;
}
hr = THR( pccci->GetNetworkInfo( &pccni ) );
if ( FAILED( hr ) )
{
goto Error;
}
hr = THR( pccni->GetUID( &m_bstrNetworkUID ) );
if ( FAILED( hr ) )
{
goto Error;
}
TraceMemoryAddBSTR( m_bstrNetworkUID );
Cleanup:
if ( punk != NULL )
{
punk->Release();
}
if ( pccni != NULL )
{
pccni->Release();
}
if ( piccc != NULL )
{
piccc->Release();
}
if ( pccci != NULL )
{
pccci->Release();
}
HRETURN( hr );
Error:
//
// Tell the UI layer about the failure.
//
THR( HrSendStatusReport(
m_bstrClusterName
, TASKID_Major_Reanalyze
, TASKID_Minor_Inconsistant_MiddleTier_Database
, 0
, 1
, 1
, hr
, IDS_TASKID_MINOR_INCONSISTANT_MIDDLETIER_DATABASE
) );
goto Cleanup;
} //*** CTaskCommitClusterChanges::HrGatherClusterInformation
//////////////////////////////////////////////////////////////////////////////
//
// HRESULT
// CTaskCommitClusterChanges::HrFormFirstNode
//
//////////////////////////////////////////////////////////////////////////////
HRESULT
CTaskCommitClusterChanges::HrFormFirstNode( void )
{
TraceFunc( "" );
HRESULT hr = S_OK;
ULONG celtDummy;
BSTR bstrNodeName = NULL;
BSTR bstrUID = NULL;
IUnknown * punk = NULL;
IClusCfgCredentials * piccc = NULL;
IClusCfgNodeInfo * pccni = NULL;
IClusCfgClusterInfo * pccci = NULL;
IClusCfgServer * pccs = NULL;
IEnumClusCfgNetworks * peccn = NULL;
IClusCfgNetworkInfo * pccneti = NULL;
//
// TODO: gpease 25-MAR-2000
// Figure out what additional work to do here.
//
//
// Get the name of the node.
//
hr = THR( m_pom->GetObject( DFGUID_NodeInformation, m_cookieFormingNode, &punk ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
hr = THR( punk->TypeSafeQI( IClusCfgNodeInfo, &pccni ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
punk->Release();
punk = NULL;
hr = THR( pccni->GetName( &bstrNodeName ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
TraceMemoryAddBSTR( bstrNodeName );
pccni->Release();
pccni = NULL;
//
// Create notification string.
//
//
// Update the UI layer telling it that we are about to start.
//
hr = THR( HrSendStatusReport(
bstrNodeName
, TASKID_Major_Configure_Cluster_Services
, TASKID_Minor_Forming_Node
, 0
, 2
, 0
, S_OK
, IDS_TASKID_MINOR_FORMING_NODE
) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// Ask the Connection Manager for a connection to the node.
//
hr = THR( m_pcm->GetConnectionToObject( m_cookieFormingNode, &punk ) );
if ( FAILED( hr ) )
{
goto Error;
}
hr = THR( punk->TypeSafeQI( IClusCfgServer, &pccs ) );
if ( FAILED( hr ) )
{
goto Error;
}
punk->Release();
punk = NULL;
//
// Get the node info interface.
//
hr = THR( pccs->GetClusterNodeInfo( &pccni ) );
if ( FAILED( hr ) )
{
goto Error;
}
//
// Retrieve the server's Cluster Configuration Object..
//
hr = THR( pccni->GetClusterConfigInfo( &pccci ) );
if ( FAILED( hr ) )
{
goto Error;
}
//
// Put the properties into the remoted object.
//
hr = THR( pccci->SetName( m_bstrClusterName ) );
if ( FAILED( hr ) )
{
goto Error;
}
hr = STHR( pccci->SetBindingString( m_bstrClusterBindingString ) );
if ( FAILED( hr ) )
{
goto Error;
}
hr = THR( pccci->GetClusterServiceAccountCredentials( &piccc ) );
if ( FAILED( hr ) )
{
goto Error;
}
hr = THR( m_pccc->AssignTo( piccc ) );
if( FAILED( hr ) )
{
goto Error;
}
hr = THR( pccci->SetIPAddress( m_ulIPAddress ) );
if ( FAILED( hr ) )
{
goto Error;
}
hr = THR( pccci->SetSubnetMask( m_ulSubnetMask ) );
if ( FAILED( hr ) )
{
goto Error;
}
//
// Find the network that matches the UID of network to host the
// IP address.
//
hr = THR( pccs->GetNetworksEnum( &peccn ) );
if ( FAILED( hr ) )
{
goto Error;
}
Assert( hr == S_OK );
while ( hr == S_OK )
{
hr = STHR( peccn->Next( 1, &pccneti, &celtDummy ) );
if ( hr == S_FALSE )
{
//
// Somehow, there isn't a network that matches the UID of the
// network. How did we get this far?
//
hr = THR( E_UNEXPECTED );
goto Error;
}
if ( FAILED( hr ) )
{
goto Error;
}
hr = THR( pccneti->GetUID( &bstrUID ) );
if ( FAILED( hr ) )
{
goto Error;
}
TraceMemoryAddBSTR( bstrUID );
if ( NBSTRCompareCase( bstrUID, m_bstrNetworkUID ) == 0 )
{
//
// Found the network!
//
break;
}
TraceSysFreeString( bstrUID );
bstrUID = NULL;
pccneti->Release();
pccneti = NULL;
} // while: hr == S_OK
hr = THR( pccci->SetNetworkInfo( pccneti ) );
if ( FAILED( hr ) )
{
goto Error;
}
//
// Configure that node to create a cluster
//
hr = THR( pccci->SetCommitMode( cmCREATE_CLUSTER ) );
if ( FAILED( hr ) )
{
goto Error;
}
//
// Update the UI layer telling it that we are making progress.
//
hr = THR( SendStatusReport( bstrNodeName,
TASKID_Major_Configure_Cluster_Services,
TASKID_Minor_Forming_Node,
0,
2,
1,
hr,
NULL, // don't need to update string
NULL,
NULL
) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// Commit this node!
//
hr = THR( pccs->CommitChanges() );
if ( FAILED( hr ) )
{
goto Error;
}
Cleanup:
//
// Update the UI layer telling it that we are finished.
//
THR( SendStatusReport( bstrNodeName,
TASKID_Major_Configure_Cluster_Services,
TASKID_Minor_Forming_Node,
0,
2,
2,
hr,
NULL, // don't need to update string
NULL,
NULL
) );
if ( punk != NULL )
{
punk->Release();
}
TraceSysFreeString( bstrNodeName );
TraceSysFreeString( bstrUID );
if ( pccneti != NULL )
{
pccneti->Release();
}
if ( peccn != NULL )
{
peccn->Release();
}
if ( piccc != NULL )
{
piccc->Release();
}
if ( pccni != NULL )
{
pccni->Release();
}
if ( pccci != NULL )
{
pccci->Release();
}
if ( pccs != NULL )
{
pccs->Release();
}
HRETURN( hr );
Error:
//
// Tell the UI layer about the failure.
//
THR( SendStatusReport( bstrNodeName,
TASKID_Major_Configure_Cluster_Services,
TASKID_Minor_Forming_Node,
0,
2,
2,
hr,
NULL, // don't need to update string
NULL,
NULL
) );
goto Cleanup;
} //*** CTaskCommitClusterChanges::HrFormFirstNode
//////////////////////////////////////////////////////////////////////////////
//
// HRESULT
// CTaskCommitClusterChanges::HrAddJoiningNodes
//
//////////////////////////////////////////////////////////////////////////////
HRESULT
CTaskCommitClusterChanges::HrAddJoiningNodes( void )
{
TraceFunc( "" );
HRESULT hr = S_OK;
ULONG cNodes;
ULONG celtDummy;
OBJECTCOOKIE cookieNode;
BSTR bstrNodeName = NULL;
IClusCfgNodeInfo * pccni = NULL;
IUnknown * punkNode = NULL;
//
// Reset the enum to use again.
//
hr = THR( m_pen->Reset() );
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// Loop thru the nodes, adding all joining nodes, skipping the forming node (if any).
//
Assert( hr == S_OK );
for( cNodes = 0; ( ( hr == S_OK ) && ( m_fStop == FALSE ) ); cNodes ++ )
{
//
// Cleanup
//
if ( punkNode != NULL )
{
punkNode->Release();
punkNode = NULL;
} // if:
if ( pccni != NULL )
{
pccni->Release();
pccni = NULL;
} // if:
TraceSysFreeString( bstrNodeName );
bstrNodeName = NULL;
//
// Grab the next node.
//
hr = STHR( m_pen->Next( 1, &cookieNode, &celtDummy ) );
if ( hr == S_FALSE )
{
break;
}
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// Get the name of the node ffrom the cookies standard info, Once we have a node
// name it's okay to goto error instead of cleanup.
//
hr = THR( HrRetrieveCookiesName( m_pom, cookieNode, &bstrNodeName ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
//
// Get the node object for the cookie.
//
// While the argument list says it returns an IUnknown pointer, it
// actually calls into QueryInterface requesting an IClusCfgNodeInfo
// interface.
hr = THR( m_pom->GetObject(
DFGUID_NodeInformation
, cookieNode
, reinterpret_cast< IUnknown ** >( &pccni )
) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
// Get an IUnknown pointer for use in the comparison to determine
// whether this is the forming node or not. This is necessary because
// in the comparison below, we need to compare the exact same
// interface that was set into m_punkFormingNode, which was an
// IUnknown interface.
hr = THR( pccni->TypeSafeQI( IUnknown, &punkNode ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// Check cluster membership.
//
hr = STHR( pccni->IsMemberOfCluster() );
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// If the node is already clustered then skip it.
//
if ( hr == S_OK )
{
continue;
}
//
// KB: We only need the punk's address to see if the objects are the
// same COM object by comparing the IUnknown interfaces.
//
// If the addresses are the same then skip it since we already "formed" in
// HrCompareAndPushInformationToNodes() above.
//
if ( m_punkFormingNode == punkNode )
{
continue;
}
hr = THR( HrAddAJoiningNode( bstrNodeName, cookieNode ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
} // for: looping thru nodes a second time.
Assert( cNodes == m_cNodes );
hr = S_OK;
Cleanup:
TraceSysFreeString( bstrNodeName );
if ( pccni != NULL )
{
pccni->Release();
}
if ( punkNode != NULL )
{
punkNode->Release();
}
HRETURN( hr );
} //*** CTaskCommitClusterChanges::HrAddJoiningNodes
//////////////////////////////////////////////////////////////////////////////
//
// HRESULT
// CTaskCommitClusterChanges::HrAddAJoiningNode(
// BSTR bstrNameIn,
// OBJECTCOOKIE cookieIn
// )
//
//////////////////////////////////////////////////////////////////////////////
HRESULT
CTaskCommitClusterChanges::HrAddAJoiningNode(
BSTR bstrNameIn,
OBJECTCOOKIE cookieIn
)
{
TraceFunc( "" );
HRESULT hr;
IUnknown * punk = NULL;
IClusCfgCredentials * piccc = NULL;
IClusCfgNodeInfo * pccni = NULL;
IClusCfgClusterInfo * pccci = NULL;
IClusCfgServer * pccs = NULL;
//
// Create the notification string
//
//
// Tell UI layer we are about to start this.
//
hr = THR( HrSendStatusReport(
bstrNameIn
, TASKID_Major_Configure_Cluster_Services
, TASKID_Minor_Joining_Node
, 0
, 2
, 0
, S_OK
, IDS_TASKID_MINOR_JOINING_NODE
) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// Connect to the node.
//
hr = THR( m_pcm->GetConnectionToObject( cookieIn,
&punk
) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
hr = THR( punk->TypeSafeQI( IClusCfgServer, &pccs ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// Get the node info interface.
//
hr = THR( pccs->GetClusterNodeInfo( &pccni ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// Retrieve the server's Cluster Configuration Object..
//
hr = THR( pccni->GetClusterConfigInfo( &pccci ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// Put the properties into the remoted object.
//
hr = THR( pccci->SetName( m_bstrClusterName ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
hr = THR( pccci->SetBindingString( m_bstrClusterBindingString ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
hr = THR( pccci->GetClusterServiceAccountCredentials( &piccc ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
hr = THR( m_pccc->AssignTo( piccc ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
hr = THR( pccci->SetIPAddress( m_ulIPAddress ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
hr = THR( pccci->SetSubnetMask( m_ulSubnetMask ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// Set this node to add itself to a cluster
//
hr = THR( pccci->SetCommitMode( cmADD_NODE_TO_CLUSTER ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// Tell the UI layer we are making progess.... the server will then send messages
// indicating what it is doing.
//
hr = THR( SendStatusReport( bstrNameIn,
TASKID_Major_Configure_Cluster_Services,
TASKID_Minor_Joining_Node,
0,
2,
1,
S_OK,
NULL, // don't need to update string
NULL,
NULL
) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// Commit this node!
//
hr = THR( pccs->CommitChanges() );
if ( FAILED( hr ) )
{
goto Cleanup;
}
Cleanup:
THR( SendStatusReport( bstrNameIn,
TASKID_Major_Configure_Cluster_Services,
TASKID_Minor_Joining_Node,
0,
2,
2,
hr,
NULL, // don't need to update string
NULL,
NULL
) );
if ( punk != NULL )
{
punk->Release();
}
if ( piccc != NULL )
{
piccc->Release();
}
if ( pccci != NULL )
{
pccci->Release();
}
if ( pccs != NULL )
{
pccs->Release();
}
if ( pccni != NULL )
{
pccni->Release();
}
HRETURN( hr );
} //*** CTaskCommitClusterChanges::HrAddAJoiningNode
//////////////////////////////////////////////////////////////////////////////
//
// HRESULT
// CTaskCommitClusterChanges::HrSendStatusReport(
// LPCWSTR pcsNodeNameIn
// , CLSID clsidMajorIn
// , CLSID clsidMinorIn
// , ULONG ulMinIn
// , ULONG ulMaxIn
// , ULONG ulCurrentIn
// , HRESULT hrIn
// , int nDescriptionIdIn
// )
//
//////////////////////////////////////////////////////////////////////////////
HRESULT
CTaskCommitClusterChanges::HrSendStatusReport(
LPCWSTR pcszNodeNameIn
, CLSID clsidMajorIn
, CLSID clsidMinorIn
, ULONG ulMinIn
, ULONG ulMaxIn
, ULONG ulCurrentIn
, HRESULT hrIn
, int nDescriptionIdIn
)
{
TraceFunc( "" );
HRESULT hr = S_OK;
BSTR bstr = NULL;
hr = THR( HrLoadStringIntoBSTR( g_hInstance, nDescriptionIdIn, &bstr ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( SendStatusReport( pcszNodeNameIn, clsidMajorIn, clsidMinorIn, ulMinIn, ulMaxIn, ulCurrentIn, hrIn, bstr, NULL, NULL ) );
Cleanup:
TraceSysFreeString( bstr );
HRETURN( hr );
} //*** CTaskCommitClusterChanges::HrSendStatusReport