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.
 
 
 
 
 
 

1052 lines
27 KiB

//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000-2001 Microsoft Corporation
//
// Module Name:
// QuorumDlg.cpp
//
// Maintained By:
// David Potter (DavidP) 03-APR-2001
//
//////////////////////////////////////////////////////////////////////////////
#include "Pch.h"
#include "QuorumDlg.h"
#include "WizardUtils.h"
#include "WizardHelp.h"
#include "SummaryPage.h"
#include <HtmlHelp.h>
//////////////////////////////////////////////////////////////////////////////
// Context-sensitive help table.
//////////////////////////////////////////////////////////////////////////////
const DWORD g_rgidQuorumDlgHelpIDs[] =
{
IDC_QUORUM_S_QUORUM, IDH_QUORUM_S_QUORUM,
IDC_QUORUM_CB_QUORUM, IDH_QUORUM_S_QUORUM,
0, 0
};
//////////////////////////////////////////////////////////////////////////////
// Static Function Prototypes
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//++
//
// CQuorumDlg::S_HrDisplayModalDialog
//
// Description:
// Display the dialog box.
//
// Arguments:
// hwndParentIn - Parent window for the dialog box.
// pccwIn - CClusCfgWizard pointer for talking to the middle tier.
// pssaOut - array of all the initial IsManaged states
//
// Return Values:
// S_OK - Operation completed successfully.
//
// Remarks:
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CQuorumDlg::S_HrDisplayModalDialog(
HWND hwndParentIn
, CClusCfgWizard * pccwIn
, SStateArray * pssaOut
)
{
TraceFunc( "" );
Assert( pccwIn != NULL );
Assert( pssaOut != NULL );
HRESULT hr = S_OK;
INT_PTR dlgResult = IDOK;
// Display the dialog.
{
CQuorumDlg dlg( pccwIn, pssaOut );
dlgResult = DialogBoxParam(
g_hInstance
, MAKEINTRESOURCE( IDD_QUORUM )
, hwndParentIn
, CQuorumDlg::S_DlgProc
, (LPARAM) &dlg
);
if ( dlgResult == IDOK )
hr = S_OK;
else
hr = S_FALSE;
}
HRETURN( hr );
} //*** CQuorumDlg::S_HrDisplayModalDialog
//////////////////////////////////////////////////////////////////////////////
//++
//
// FIsValidResource
//
// Description:
// Determines whether the resource is a valid selection as a quorum
// resource.
//
// Arguments:
// pResourceIn - the resource in question.
//
// Return Values:
// true - the resource is valid.
// false - the resource is not valid.
//
// Remarks:
// A resource is valid if it is quorum capable and it is not an "unknown"
// quorum.
//
//--
//////////////////////////////////////////////////////////////////////////////
static
bool
FIsValidResource(
IClusCfgManagedResourceInfo * pResourceIn
)
{
TraceFunc( "" );
HRESULT hr = S_OK;
bool fValid = false;
BSTR bstrDeviceID = NULL;
hr = STHR( pResourceIn->IsQuorumCapable() );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
//
// The resource is not quorum capable so there is no reason
// to continue.
//
if ( hr == S_FALSE )
{
goto Cleanup;
} // if:
hr = THR( pResourceIn->GetUID( &bstrDeviceID ) );
if ( FAILED( hr ) )
{
LogMsg( L"[WIZ] FIsValidResource() cannot get the UID for the passed in managed resource. (hr = %#08x)" );
goto Cleanup;
} // if:
TraceMemoryAddBSTR( bstrDeviceID );
//
// If this is the "Unknown Quorum" resource then we don't want to show it
// in the drop down list.
//
if ( NStringCchCompareCase( g_szUnknownQuorumUID, RTL_NUMBER_OF( g_szUnknownQuorumUID ), bstrDeviceID, SysStringLen( bstrDeviceID ) + 1 ) == 0 )
{
goto Cleanup;
} // if:
fValid = true;
Cleanup:
TraceSysFreeString( bstrDeviceID );
RETURN( fValid );
} //*** FIsValidResource
//////////////////////////////////////////////////////////////////////////////
//++
//
// CQuorumDlg::CQuorumDlg
//
// Description:
// Constructor.
//
// Arguments:
// pccwIn - CClusCfgWizard for talking to the middle tier.
// pssaOut - array of all the initial IsManaged states.
//
// Return Values:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
CQuorumDlg::CQuorumDlg(
CClusCfgWizard * pccwIn
, SStateArray * pssaOut
)
: m_pccw( pccwIn )
, m_pssa( pssaOut )
, m_rgpResources( NULL )
, m_cValidResources( 0 )
, m_idxQuorumResource( 0 )
, m_hComboBox( NULL )
, m_fQuorumAlreadySet( false )
{
TraceFunc( "" );
Assert( pccwIn != NULL );
Assert( pssaOut != NULL );
// m_hwnd
m_pccw->AddRef();
TraceFuncExit();
} //*** CQuorumDlg::CQuorumDlg
//////////////////////////////////////////////////////////////////////////////
//++
//
// CQuorumDlg::~CQuorumDlg
//
// Description:
// Destructor.
//
// Arguments:
// None.
//
// Return Values:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
CQuorumDlg::~CQuorumDlg( void )
{
TraceFunc( "" );
DWORD idxResource = 0;
for ( idxResource = 0; idxResource < m_cValidResources; idxResource += 1 )
m_rgpResources[ idxResource ]->Release();
delete [] m_rgpResources;
if ( m_pccw != NULL )
{
m_pccw->Release();
}
TraceFuncExit();
} //*** CQuorumDlg::~CQuorumDlg
//////////////////////////////////////////////////////////////////////////////
//++
//
// CQuorumDlg::S_DlgProc
//
// Description:
// Dialog proc for the Quorum dialog box.
//
// Arguments:
// hwndDlgIn - Dialog box window handle.
// nMsgIn - Message ID.
// wParam - Message-specific parameter.
// lParam - Message-specific parameter.
//
// Return Values:
// TRUE - Message has been handled.
// FALSE - Message has not been handled yet.
//
// Remarks:
// It is expected that this dialog box is invoked by a call to
// DialogBoxParam() with the lParam argument set to the address of the
// instance of this class.
//
//--
//////////////////////////////////////////////////////////////////////////////
INT_PTR
CALLBACK
CQuorumDlg::S_DlgProc(
HWND hwndDlgIn
, UINT nMsgIn
, WPARAM wParam
, LPARAM lParam
)
{
// Don't do TraceFunc because every mouse movement
// will cause this function to be called.
WndMsg( hwndDlgIn, nMsgIn, wParam, lParam );
LRESULT lr = FALSE;
CQuorumDlg * pdlg;
//
// Get a pointer to the class.
//
if ( nMsgIn == WM_INITDIALOG )
{
SetWindowLongPtr( hwndDlgIn, GWLP_USERDATA, lParam );
pdlg = reinterpret_cast< CQuorumDlg * >( lParam );
pdlg->m_hwnd = hwndDlgIn;
}
else
{
pdlg = reinterpret_cast< CQuorumDlg * >( GetWindowLongPtr( hwndDlgIn, GWLP_USERDATA ) );
}
if ( pdlg != NULL )
{
Assert( hwndDlgIn == pdlg->m_hwnd );
switch( nMsgIn )
{
case WM_INITDIALOG:
lr = pdlg->OnInitDialog();
break;
case WM_COMMAND:
lr = pdlg->OnCommand( HIWORD( wParam ), LOWORD( wParam ), reinterpret_cast< HWND >( lParam ) );
break;
case WM_HELP:
WinHelp(
(HWND)((LPHELPINFO) lParam)->hItemHandle,
CLUSCFG_HELP_FILE,
HELP_WM_HELP,
(ULONG_PTR) g_rgidQuorumDlgHelpIDs
);
break;
case WM_CONTEXTMENU:
WinHelp(
(HWND)wParam,
CLUSCFG_HELP_FILE,
HELP_CONTEXTMENU,
(ULONG_PTR) g_rgidQuorumDlgHelpIDs
);
break;
// no default clause needed
} // switch: nMsgIn
} // if: page is specified
return lr;
} //*** CQuorumDlg::S_DlgProc
//////////////////////////////////////////////////////////////////////////////
//++
//
// CQuorumDlg::OnInitDialog
//
// Description:
// Handler for the WM_INITDIALOG message.
//
// Arguments:
// None.
//
// Return Values:
// TRUE Focus has been set.
// FALSE Focus has not been set.
//--
//////////////////////////////////////////////////////////////////////////////
LRESULT
CQuorumDlg::OnInitDialog( void )
{
TraceFunc( "" );
LRESULT lr = TRUE; // did set focus
HRESULT hr = S_OK;
DWORD sc;
DWORD idxResource = 0;
BSTR bstrResourceName = NULL;
//
// create resource list
//
hr = THR( HrCreateResourceList() );
if ( FAILED( hr ) )
{
goto Error;
}
//
// get combo box handle
//
m_hComboBox = GetDlgItem( m_hwnd, IDC_QUORUM_CB_QUORUM );
if ( m_hComboBox == NULL )
{
sc = TW32( GetLastError() );
hr = HRESULT_FROM_WIN32( sc );
goto Error;
}
//
// fill combo box
//
for ( idxResource = 0 ; idxResource < m_cValidResources ; idxResource++ )
{
hr = THR( m_rgpResources[ idxResource ]->GetName( &bstrResourceName ) );
if ( FAILED( hr ) )
{
goto Error;
}
TraceMemoryAddBSTR( bstrResourceName );
sc = (DWORD) SendMessage( m_hComboBox, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>( bstrResourceName ) );
if ( ( sc == CB_ERR ) || ( sc == CB_ERRSPACE ) )
{
hr = HRESULT_FROM_WIN32( TW32( sc ) );
goto Error;
}
TraceSysFreeString( bstrResourceName );
bstrResourceName = NULL;
// - remember which is quorum resource
hr = STHR( m_rgpResources[ idxResource ]->IsQuorumResource() );
if ( FAILED( hr ) )
{
goto Error;
}
else if ( hr == S_OK )
{
m_idxQuorumResource = idxResource;
m_fQuorumAlreadySet = true;
}
} // for: each resource
//
// set combo box selection to current quorum resource
//
sc = (DWORD) SendMessage( m_hComboBox, CB_SETCURSEL, m_idxQuorumResource, 0 );
if ( sc == CB_ERR )
{
hr = HRESULT_FROM_WIN32( TW32( sc ) );
goto Error;
}
//
// Update the buttons based on what is selected.
//
UpdateButtons();
//
// Set focus to the combo box.
//
SetFocus( m_hComboBox );
goto Cleanup;
Error:
HrMessageBoxWithStatus(
m_hwnd
, IDS_ERR_RESOURCE_GATHER_FAILURE_TITLE
, IDS_ERR_RESOURCE_GATHER_FAILURE_TEXT
, hr
, 0
, MB_OK | MB_ICONERROR
, 0
);
EndDialog( m_hwnd, IDCANCEL ); // show message box?
lr = FALSE;
goto Cleanup;
Cleanup:
TraceSysFreeString( bstrResourceName );
RETURN( lr );
} //*** CQuorumDlg::OnInitDialog
//////////////////////////////////////////////////////////////////////////////
//++
//
// CQuorumDlg::OnCommand
//
// Description:
// Handler for the WM_COMMAND message.
//
// Arguments:
// idNotificationIn - Notification code.
// idControlIn - Control ID.
// hwndSenderIn - Handle for the window that sent the message.
//
// Return Values:
// TRUE - Message has been handled.
// FALSE - Message has not been handled yet.
//
//--
//////////////////////////////////////////////////////////////////////////////
LRESULT
CQuorumDlg::OnCommand(
UINT idNotificationIn
, UINT idControlIn
, HWND hwndSenderIn
)
{
TraceFunc( "" );
LRESULT lr = FALSE;
size_t idxCurrentSelection = 0;
HRESULT hr = S_OK;
BOOL fState;
IClusCfgManagedResourceInfo * pQuorum = NULL;
IClusCfgManagedResourceInfo * pCurrent = NULL;
BSTR bstrTemp = NULL;
BOOL bLocalQuorum;
switch ( idControlIn )
{
case IDOK:
//
// get selection from combo box
//
idxCurrentSelection = SendMessage( m_hComboBox, CB_GETCURSEL, 0, 0 );
if ( idxCurrentSelection == CB_ERR )
{
hr = HRESULT_FROM_WIN32( TW32( (DWORD) CB_ERR ) );
goto Error;
}
//
// if original quorum resource is different, or had not been set.
//
if ( ( idxCurrentSelection != m_idxQuorumResource ) || !m_fQuorumAlreadySet )
{
pQuorum = m_rgpResources[ m_idxQuorumResource ];
pCurrent = m_rgpResources[ idxCurrentSelection ];
//
// First, is the new resource Local Quorum? (Special processing -
// unfortunate but necessary.)
//
hr = THR( pCurrent->GetUID( &bstrTemp ) );
if ( FAILED( hr ) )
{
goto Error;
} // if:
bLocalQuorum = ( NStringCchCompareCase( bstrTemp, SysStringLen( bstrTemp ) + 1, CLUS_RESTYPE_NAME_LKQUORUM, RTL_NUMBER_OF( CLUS_RESTYPE_NAME_LKQUORUM ) ) == 0 );
SysFreeString( bstrTemp );
bstrTemp = NULL;
//
// Clear original quorum resource.
//
hr = THR( pQuorum->SetQuorumResource( FALSE ) );
//
// Set the managed state back to it's original state.
//
if ( SUCCEEDED( hr ) )
{
fState = m_pssa->prsArray[ m_idxQuorumResource ].fState;
hr = THR( pQuorum->SetManaged( fState ) );
} // if:
//
// If we successfully ran PrepareToHostQuorum on this resource the last time
// this dialog was up we now need to clean it up.
//
if ( m_pssa->prsArray[ m_idxQuorumResource ].fNeedCleanup )
{
THR( HrCleanupQuorumResource( pQuorum ) );
} // if:
//
// Set new quorum resource.
//
if ( SUCCEEDED( hr ) )
{
//
// This function returns S_FALSE when the resource does not support
// the IClusCfgVerifyQuorum interface. If the resource doesn't
// support the interface then there is no need to clean it up later.
//
hr = STHR( HrInitQuorumResource( pCurrent ) );
if ( FAILED( hr ) )
{
goto Error;
} // if:
if ( hr == S_OK )
{
m_pssa->prsArray[ idxCurrentSelection ].fNeedCleanup = TRUE;
hr = THR( pCurrent->SetQuorumResource( TRUE ) );
} // if:
} // if:
//
// Local Quorum resources should never be SetManaged( TRUE ).
//
if ( SUCCEEDED( hr ) && !bLocalQuorum )
{
hr = THR( m_rgpResources[ idxCurrentSelection ]->SetManaged( TRUE ) );
} // if:
if ( FAILED( hr ) )
{
fState = m_pssa->prsArray[ idxCurrentSelection ].fState;
THR( pCurrent->SetManaged( fState ) );
THR( pCurrent->SetQuorumResource( FALSE ) );
THR( pQuorum->SetQuorumResource( TRUE ) );
THR( pQuorum->SetManaged( bLocalQuorum == FALSE ) );
goto Error;
} // if:
EndDialog( m_hwnd, IDOK );
}
else // (combo box selection is same as original)
{
EndDialog( m_hwnd, IDCANCEL );
}
break;
case IDCANCEL:
EndDialog( m_hwnd, IDCANCEL );
break;
case IDHELP:
HtmlHelp( m_hwnd, L"mscsconcepts.chm::/SAG_MSCS2planning_6.htm", HH_DISPLAY_TOPIC, 0 );
break;
} // switch: idControlIn
goto Cleanup;
Error:
HrMessageBoxWithStatus(
m_hwnd
, IDS_ERR_QUORUM_COMMIT_FAILURE_TITLE
, IDS_ERR_QUORUM_COMMIT_FAILURE_TEXT
, hr
, 0
, MB_OK | MB_ICONERROR
, 0
);
goto Cleanup;
Cleanup:
RETURN( lr );
} //*** CQuorumDlg::OnCommand
//////////////////////////////////////////////////////////////////////////////
//++
//
// CQuorumDlg::HrCreateResourceList
//
// Description:
// Allocates and fills m_rgpResources array with quorum capable and
// joinable resources, and sets m_idxQuorumResource to the index of the
// resource that's currently the quorum resource.
//
// Supposedly at least one quorum capable and joinable resource always
// exists, and exactly one is marked as the quorum resource.
//
// Arguments:
// None.
//
// Return Values:
// S_OK - Success.
// S_FALSE - Didn't find current quorum resource.
// E_OUTOFMEMORY - Couldn't allocate memory for the list.
//
// Other possible error values from called methods.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CQuorumDlg::HrCreateResourceList( void )
{
TraceFunc( "" );
HRESULT hr = S_OK;
IUnknown * punkEnum = NULL;
IEnumClusCfgManagedResources * peccmr = NULL;
DWORD idxResCurrent = 0;
ULONG cFetchedResources = 0;
DWORD cTotalResources = 0;
BOOL fState;
Assert( m_pccw != NULL );
//
// get resource enumerator
//
hr = THR( m_pccw->HrGetClusterChild( CLSID_ManagedResourceType, DFGUID_EnumManageableResources, &punkEnum ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
hr = THR( punkEnum->TypeSafeQI( IEnumClusCfgManagedResources, &peccmr ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// find out how many resources exist
//
hr = THR( peccmr->Count( &cTotalResources ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
//
// allocate memory for resources
//
m_rgpResources = new IClusCfgManagedResourceInfo*[ cTotalResources ];
if ( m_rgpResources == NULL )
{
hr = THR( E_OUTOFMEMORY );
goto Cleanup;
}
for ( idxResCurrent = 0 ; idxResCurrent < cTotalResources ; idxResCurrent++ )
{
m_rgpResources[ idxResCurrent ] = NULL;
}
//
// allocate the m_pssa arrays
//
if ( m_pssa->bInitialized == FALSE )
{
m_pssa->prsArray = new SResourceState[ cTotalResources ];
if ( m_pssa->prsArray == NULL )
{
hr = THR( E_OUTOFMEMORY );
goto Cleanup;
}
for ( idxResCurrent = 0 ; idxResCurrent < cTotalResources ; idxResCurrent++ )
{
m_pssa->prsArray[ idxResCurrent ].fState = FALSE;
m_pssa->prsArray[ idxResCurrent ].fNeedCleanup = FALSE;
}
} // if: m_pssa ! already initialized
//
// copy resources into array
//
hr = THR( peccmr->Next( cTotalResources, m_rgpResources, &cFetchedResources ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
Assert( cFetchedResources == cTotalResources ); // if not, something's wrong with the enum
cTotalResources = min( cTotalResources, cFetchedResources ); // playing it safe
//
// filter out invalid resources
//
for ( idxResCurrent = 0 ; idxResCurrent < cTotalResources ; idxResCurrent++ )
{
if ( !FIsValidResource( m_rgpResources[ idxResCurrent ] ) )
{
m_rgpResources[ idxResCurrent ]->Release();
m_rgpResources[ idxResCurrent ] = NULL;
}
}
//
// compact array; might leave some non-null pointers after end,
// so always use m_cValidResources to determine length hereafter
//
for ( idxResCurrent = 0 ; idxResCurrent < cTotalResources ; idxResCurrent++ )
{
if ( m_rgpResources[ idxResCurrent ] != NULL )
{
m_rgpResources[ m_cValidResources ] = m_rgpResources[ idxResCurrent ];
if ( m_pssa->bInitialized == FALSE )
{
fState = ( m_rgpResources[ m_cValidResources ]->IsManaged() == S_OK ) ? TRUE : FALSE;
m_pssa->prsArray[ m_cValidResources ].fState = fState;
}
m_cValidResources++;
} // if: current element !NULL
} // for: compact the array
if ( m_pssa->bInitialized == FALSE )
{
m_pssa->cCount = m_cValidResources;
m_pssa->bInitialized = TRUE;
}
Cleanup:
if ( m_pssa->bInitialized == FALSE )
{
delete [] m_pssa->prsArray;
m_pssa->prsArray = NULL;
m_pssa->cCount = 0;
}
if ( punkEnum != NULL )
{
punkEnum->Release();
}
if ( peccmr != NULL )
{
peccmr->Release();
}
HRETURN( hr );
} //*** CQuorumDlg::HrCreateResourceList
//////////////////////////////////////////////////////////////////////////////
//++
//
// CQuorumDlg::UpdateButtons
//
// Description:
// Update the OK and Cancel buttons.
//
// Arguments:
// None.
//
// Return Values:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
void
CQuorumDlg::UpdateButtons( void )
{
TraceFunc( "" );
BOOL fEnableOK;
LRESULT lrCurSel;
lrCurSel = SendMessage( GetDlgItem( m_hwnd, IDC_QUORUM_CB_QUORUM ), CB_GETCURSEL, 0, 0 );
fEnableOK = ( lrCurSel != CB_ERR );
EnableWindow( GetDlgItem( m_hwnd, IDOK ), fEnableOK );
TraceFuncExit();
} //*** CQuorumDlg::UpdateButtons
//////////////////////////////////////////////////////////////////////////////
//++
//
// CDetailsDlg::HrInitQuorumResource
//
// Description:
// Initialize the just chosen quorum resource.
//
// Arguments:
// pResourceIn
// The resource that was chosen as the quorum.
//
// Return Values:
// S_OK
// Success.
//
// Other HRESULT failures.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CQuorumDlg::HrInitQuorumResource(
IClusCfgManagedResourceInfo * pResourceIn
)
{
TraceFunc( "" );
Assert( pResourceIn != NULL );
HRESULT hr = S_OK;
IClusCfgVerifyQuorum * piccvq = NULL;
BSTR bstrResource = NULL;
//
// Does this resource implement the IClusCfgVerifyQuorum interface?
//
hr = pResourceIn->TypeSafeQI( IClusCfgVerifyQuorum, &piccvq );
if ( hr == E_NOINTERFACE )
{
hr = S_FALSE;
goto Cleanup;
} // if:
else if ( FAILED( hr ) )
{
goto Cleanup;
} // else if:
hr = THR( pResourceIn->GetName( &bstrResource ) );
if ( FAILED( hr ) )
{
bstrResource = TraceSysAllocString( L"<unknown>" );
} // if:
else
{
TraceMemoryAddBSTR( bstrResource );
} // else:
//
// The resource did implement the IClusCfgVerifyQuorum interface...
//
Assert( ( hr == S_OK ) && ( piccvq != NULL ) );
hr = STHR( piccvq->PrepareToHostQuorumResource() );
if ( FAILED( hr ) )
{
LogMsg( L"[WIZ] PrepareToHostQuorum() failed for resource %ws. (hr = %#08x)", bstrResource, hr );
goto Cleanup;
} // if:
Cleanup:
TraceSysFreeString( bstrResource );
if ( piccvq != NULL )
{
piccvq->Release();
} // if:
HRETURN( hr );
} //*** CQuorumDlg::HrInitQuorumResource
//////////////////////////////////////////////////////////////////////////////
//++
//
// CDetailsDlg::HrCleanupQuorumResource
//
// Description:
// Cleanup the passed in quorum resource.
//
// Arguments:
// pResourceIn
// The resource that used to be selected as the quorum.
//
// Return Values:
// S_OK
// Success.
//
// Other HRESULT failures.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CQuorumDlg::HrCleanupQuorumResource(
IClusCfgManagedResourceInfo * pResourceIn
)
{
TraceFunc( "" );
Assert( pResourceIn != NULL );
HRESULT hr = S_OK;
IClusCfgVerifyQuorum * piccvq = NULL;
BSTR bstrResource = NULL;
//
// Does this resource implement the IClusCfgVerifyQuorum interface?
//
hr = pResourceIn->TypeSafeQI( IClusCfgVerifyQuorum, &piccvq );
if ( hr == E_NOINTERFACE )
{
hr = S_OK;
goto Cleanup;
} // if:
else if ( FAILED( hr ) )
{
goto Cleanup;
} // else if:
hr = THR( pResourceIn->GetName( &bstrResource ) );
if ( FAILED( hr ) )
{
bstrResource = TraceSysAllocString( L"<unknown>" );
} // if:
else
{
TraceMemoryAddBSTR( bstrResource );
} // else:
//
// The resource did implement the IClusCfgVerifyQuorum interface...
//
Assert( ( hr == S_OK ) && ( piccvq != NULL ) );
hr = STHR( piccvq->Cleanup( crCANCELLED ) );
if ( FAILED( hr ) )
{
LogMsg( L"[WIZ] Cleanup() failed for resource %ws. (hr = %#08x)", bstrResource, hr );
goto Cleanup;
} // if:
Cleanup:
TraceSysFreeString( bstrResource );
if ( piccvq != NULL )
{
piccvq->Release();
} // if:
HRETURN( hr );
} //*** CQuorumDlg::HrCleanupQuorumResource