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.
 
 
 
 
 
 

1463 lines
45 KiB

//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000-2002 Microsoft Corporation
//
// Module Name:
// TaskAnalyzeCluster.cpp
//
// Description:
// CTaskAnalyzeCluster implementation.
//
// Maintained By:
// Galen Barbee (GalenB) 03-FEB-2000
//
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// Include Files
//////////////////////////////////////////////////////////////////////////////
#include "Pch.h"
#include "TaskAnalyzeCluster.h"
//////////////////////////////////////////////////////////////////////////////
// Constant Definitions
//////////////////////////////////////////////////////////////////////////////
DEFINE_THISCLASS( "CTaskAnalyzeCluster" )
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CTaskAnalyzeCluster class
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::S_HrCreateInstance
//
// Description:
// Create a CTaskAnalyzeCluster instance.
//
// Arguments:
// ppunkOut
//
// Return Values:
// S_OK
// Success.
//
// Other HRESULT as failure.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CTaskAnalyzeCluster::S_HrCreateInstance(
IUnknown ** ppunkOut
)
{
TraceFunc( "" );
Assert( ppunkOut != NULL );
HRESULT hr = S_OK;
CTaskAnalyzeCluster * ptac = NULL;
if ( ppunkOut == NULL )
{
hr = THR( E_POINTER );
goto Cleanup;
} // if:
ptac = new CTaskAnalyzeCluster;
if ( ptac == NULL )
{
hr = THR( E_OUTOFMEMORY );
goto Cleanup;
} // if:
hr = THR( ptac->HrInit() );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( ptac->TypeSafeQI( IUnknown, ppunkOut ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
Cleanup:
if ( ptac != NULL )
{
ptac->Release();
} // if:
HRETURN( hr );
} //*** CTaskAnalyzeCluster::S_HrCreateInstance
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::CTaskAnalyzeCluster
//
// Description:
// Constructor
//
// Arguments:
// None.
//
// Return Values:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
CTaskAnalyzeCluster::CTaskAnalyzeCluster( void )
{
TraceFunc( "" );
TraceFuncExit();
} //*** CTaskAnalyzeCluster::CTaskAnalyzeCluster
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::~CTaskAnalyzeCluster
//
// Description:
// Destructor
//
// Arguments:
// None.
//
// Return Values:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
CTaskAnalyzeCluster::~CTaskAnalyzeCluster( void )
{
TraceFunc( "" );
TraceFuncExit();
} //*** CTaskAnalyzeCluster::~CTaskAnalyzeCluster
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CTaskAnalyzeCluster - IUknkown interface.
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::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.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CTaskAnalyzeCluster::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;
} // if:
//
// Handle known interfaces.
//
if ( IsEqualIID( riidIn, IID_IUnknown ) )
{
*ppvOut = static_cast< ITaskAnalyzeCluster * >( this );
} // if: IUnknown
else if ( IsEqualIID( riidIn, IID_ITaskAnalyzeCluster ) )
{
*ppvOut = TraceInterface( __THISCLASS__, ITaskAnalyzeCluster, this, 0 );
} // else if: ITaskAnalyzeCluster
else if ( IsEqualIID( riidIn, IID_IDoTask ) )
{
*ppvOut = TraceInterface( __THISCLASS__, IDoTask, this, 0 );
} // else if: IDoTask
else if ( IsEqualIID( riidIn, IID_IClusCfgCallback ) )
{
*ppvOut = TraceInterface( __THISCLASS__, IClusCfgCallback, this, 0 );
} // else if: IClusCfgCallback
else if ( IsEqualIID( riidIn, IID_INotifyUI ) )
{
*ppvOut = TraceInterface( __THISCLASS__, INotifyUI, this, 0 );
} // else if: INotifyUI
else
{
*ppvOut = NULL;
hr = E_NOINTERFACE;
} // else:
//
// Add a reference to the interface if successful.
//
if ( SUCCEEDED( hr ) )
{
((IUnknown *) *ppvOut)->AddRef();
} // if: success
Cleanup:
QIRETURN_IGNORESTDMARSHALLING( hr, riidIn );
} //*** CTaskAnalyzeCluster::QueryInterface
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::AddRef
//
// Description:
// Increment the reference count of this object by one.
//
// Arguments:
// None.
//
// Return Value:
// The new reference count.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_( ULONG )
CTaskAnalyzeCluster::AddRef( void )
{
TraceFunc( "[IUnknown]" );
ULONG c = UlAddRef();
CRETURN( c );
} //*** CTaskAnalyzeCluster::AddRef
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::Release
//
// Description:
// Decrement the reference count of this object by one.
//
// Arguments:
// None.
//
// Return Value:
// The new reference count.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_( ULONG )
CTaskAnalyzeCluster::Release( void )
{
TraceFunc( "[IUnknown]" );
ULONG c = UlRelease();
CRETURN( c );
} //*** CTaskAnalyzeCluster::Release
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CTaskAnalyzeCluster - IDoTask/ITaskAnalyzeCluster interface.
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::BeginTask
//
// Description:
// Task entry point.
//
// Arguments:
// None.
//
// Return Value:
// S_OK
// Success
//
// HRESULT failure.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CTaskAnalyzeCluster::BeginTask( void )
{
TraceFunc( "[IDoTask]" );
HRESULT hr = THR( HrBeginTask() );
HRETURN( hr );
} //*** CTaskAnalyzeCluster::BeginTask
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::StopTask
//
// Description:
// Stop task entry point.
//
// Arguments:
// None.
//
// Return Value:
// S_OK
// Success
//
// HRESULT failure.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CTaskAnalyzeCluster::StopTask( void )
{
TraceFunc( "[IDoTask]" );
HRESULT hr = THR( HrStopTask() );
HRETURN( hr );
} //*** CTaskAnalyzeCluster::StopTask
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::SetJoiningMode
//
// Description:
// Tell this task whether we are joining nodes to the cluster?
//
// Arguments:
// None.
//
// Return Value:
// S_OK
// Success
//
// HRESULT failure.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CTaskAnalyzeCluster::SetJoiningMode( void )
{
TraceFunc( "[ITaskAnalyzeCluster]" );
HRESULT hr = THR( HrSetJoiningMode() );
HRETURN( hr );
} //*** CTaskAnalyzeCluster::SetJoiningMode
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::SetCookie
//
// Description:
// Receive the completion cookier from the task creator.
//
// Arguments:
// cookieIn
// The completion cookie to send back to the creator when this
// task is complete.
//
// Return Value:
// S_OK
// Success
//
// HRESULT failure.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CTaskAnalyzeCluster::SetCookie(
OBJECTCOOKIE cookieIn
)
{
TraceFunc( "[ITaskAnalyzeCluster]" );
HRESULT hr = THR( HrSetCookie( cookieIn ) );
HRETURN( hr );
} //*** CTaskAnalyzeCluster::SetCookie
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::SetClusterCookie
//
// Description:
// Receive the object manager cookie of the cluster that we are going
// to analyze.
//
// Arguments:
// cookieClusterIn
// The cookie for the cluster to work on.
//
// Return Value:
// S_OK
// Success
//
// HRESULT failure.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CTaskAnalyzeCluster::SetClusterCookie(
OBJECTCOOKIE cookieClusterIn
)
{
TraceFunc( "[ITaskAnalyzeCluster]" );
HRESULT hr = THR( HrSetClusterCookie( cookieClusterIn ) );
HRETURN( hr );
} //*** CTaskAnalyzeCluster::SetClusterCookie
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::HrCompareDriveLetterMappings
//
// Description:
// Compare the drive letter mappings on each node to make sure there
// are no conflicts. Specifically, verify that the system disk on each
// node does not conflict with storage devices that could be failed over
// to that node.
//
// Arguments:
// None.
//
// Return Values:
// S_OK - Operation completed successfully.
// Other HRESULTs.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CTaskAnalyzeCluster::HrCompareDriveLetterMappings( void )
{
TraceFunc( "" );
HRESULT hr = S_OK;
HRESULT hrDriveConflictError = S_OK;
HRESULT hrDriveConflictWarning = S_OK;
OBJECTCOOKIE cookieDummy;
OBJECTCOOKIE cookieClusterNode;
DWORD idxCurrentNode;
DWORD cNodes;
ULONG celtDummy;
int idxDLM;
BSTR bstrOuterNodeName = NULL;
BSTR bstrInnerNodeName = NULL;
BSTR bstrMsg = NULL;
BSTR bstrMsgREF = NULL;
IUnknown * punk = NULL;
IEnumCookies * pecNodes = NULL;
IClusCfgNodeInfo * pccniOuter = NULL;
IClusCfgNodeInfo * pccniInner = NULL;
SDriveLetterMapping dlmOuter;
SDriveLetterMapping dlmInner;
hr = THR( HrSendStatusReport(
CTaskAnalyzeClusterBase::m_bstrClusterName
, TASKID_Major_Check_Cluster_Feasibility
, TASKID_Minor_Check_DriveLetter_Mappings
, 0
, 1
, 0
, hr
, IDS_TASKID_MINOR_CHECK_DRIVELETTER_MAPPINGS
) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
//
// Get the node cookie enumerator.
//
hr = THR( CTaskAnalyzeClusterBase::m_pom->FindObject( CLSID_NodeType, CTaskAnalyzeClusterBase::m_cookieCluster, NULL, DFGUID_EnumCookies, &cookieDummy, &punk ) );
if ( FAILED( hr ) )
{
SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CompareDriveLetterMappings_Find_Object, hr );
goto Cleanup;
}
hr = THR( punk->TypeSafeQI( IEnumCookies, &pecNodes ) );
if ( FAILED( hr ) )
{
SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_CompareDriveLetterMappings_Find_Object_QI, hr );
goto Cleanup;
}
//pecNodes = TraceInterface( L"CTaskAnalyzeCluster!IEnumCookies", IEnumCookies, pecNodes, 1 );
punk->Release();
punk = NULL;
//
// If there is only one node, just exit this function.
//
hr = THR( pecNodes->Count( &cNodes ) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
if ( cNodes == 1 )
{
goto Cleanup;
}
//
// Loop through the enumerator to compare each node with every other node.
// This requires an outer loop and an inner loop.
//
for ( idxCurrentNode = 0 ;; idxCurrentNode++ )
{
//
// Cleanup.
//
if ( pccniOuter != NULL )
{
pccniOuter->Release();
pccniOuter = NULL;
}
TraceSysFreeString( bstrOuterNodeName );
bstrOuterNodeName = NULL;
//
// Skip to the next node. This is necessary since there is only one
// enumerator for both the outer and inner loop.
//
if ( idxCurrentNode > 0 )
{
// Reset back to the first item in the enumerator.
hr = STHR( pecNodes->Reset() );
if ( FAILED( hr ) )
{
SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Reset_Node_Enumerator, hr );
goto Cleanup;
}
// Skip to the current node.
hr = STHR( pecNodes->Skip( idxCurrentNode ) );
if ( FAILED( hr ) )
{
SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Skip_To_Node, hr );
goto Cleanup;
}
if ( hr == S_FALSE )
{
//
// Reached the end of the list.
//
hr = S_OK;
break;
}
} // if: not at first node
//
// Find the next node.
//
hr = STHR( pecNodes->Next( 1, &cookieClusterNode, &celtDummy ) );
if ( FAILED( hr ) )
{
SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Find_Outer_Node_Next, hr );
goto Cleanup;
}
if ( hr == S_FALSE )
{
//
// Reached the end of the list.
//
hr = S_OK;
break;
}
//
// Retrieve the node information.
//
hr = THR( CTaskAnalyzeClusterBase::m_pom->GetObject( DFGUID_NodeInformation, cookieClusterNode, &punk ) );
if ( FAILED( hr ) )
{
SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Outer_NodeInfo_FindObject, hr );
goto Cleanup;
}
hr = THR( punk->TypeSafeQI( IClusCfgNodeInfo, &pccniOuter ) );
if ( FAILED( hr ) )
{
SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Outer_NodeInfo_FindObject_QI, hr );
goto Cleanup;
}
//pccniOuter = TraceInterface( L"CTaskAnalyzeCluster!IClusCfgNodeInfo", IClusCfgNodeInfo, pccni, 1 );
punk->Release();
punk = NULL;
//
// Get the drive letter mappings for the outer node.
//
hr = THR( pccniOuter->GetDriveLetterMappings( &dlmOuter ) );
if ( FAILED( hr ) )
{
SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Outer_NodeInfo_GetDLM, hr );
goto Cleanup;
}
//
// Get the name of the node.
//
hr = THR( pccniOuter->GetName( &bstrOuterNodeName ) );
if ( FAILED( hr ) )
{
SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Outer_GetNodeName, hr );
goto Cleanup;
}
TraceMemoryAddBSTR( bstrOuterNodeName );
//
// Loop through all the other nodes in the cluster.
//
for ( ;; )
{
//
// Cleanup.
//
if ( pccniInner != NULL )
{
pccniInner->Release();
pccniInner = NULL;
}
TraceSysFreeString( bstrInnerNodeName );
bstrInnerNodeName = NULL;
//
// Find the next node.
//
hr = STHR( pecNodes->Next( 1, &cookieClusterNode, &celtDummy ) );
if ( FAILED( hr ) )
{
SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Find_Inner_Node_Next, hr );
goto Cleanup;
}
if ( hr == S_FALSE )
{
//
// Reached the end of the list.
//
hr = S_OK;
break;
}
//
// Retrieve the node information.
//
hr = THR( CTaskAnalyzeClusterBase::m_pom->GetObject( DFGUID_NodeInformation, cookieClusterNode, &punk ) );
if ( FAILED( hr ) )
{
SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Inner_NodeInfo_FindObject, hr );
goto Cleanup;
}
hr = THR( punk->TypeSafeQI( IClusCfgNodeInfo, &pccniInner ) );
if ( FAILED( hr ) )
{
SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Inner_NodeInfo_FindObject_QI, hr );
goto Cleanup;
}
//pccniInner = TraceInterface( L"CTaskAnalyzeCluster!IClusCfgNodeInfo", IClusCfgNodeInfo, pccni, 1 );
punk->Release();
punk = NULL;
//
// Get the drive letter mappings for the inner node.
//
hr = THR( pccniInner->GetDriveLetterMappings( &dlmInner ) );
if ( FAILED( hr ) )
{
SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Inner_NodeInfo_GetDLM, hr );
goto Cleanup;
}
//
// Get the name of the node.
//
hr = THR( pccniInner->GetName( &bstrInnerNodeName ) );
if ( FAILED( hr ) )
{
SSR_ANALYSIS_FAILED( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_Compare_Drive_Letter_Mappings_Inner_GetNodeName, hr );
goto Cleanup;
}
TraceMemoryAddBSTR( bstrInnerNodeName );
//
// Loop through the drive letter mappings to make sure that there
// are no conflicts between the two machines.
//
for ( idxDLM = 0 ; idxDLM < 26 ; idxDLM++ )
{
if ( dlmOuter.dluDrives[ idxDLM ] == dluSYSTEM )
{
CLSID clsidMinorId;
hr = THR( CoCreateGuid( &clsidMinorId ) );
if ( FAILED( hr ) )
{
clsidMinorId = IID_NULL;
}
switch ( dlmInner.dluDrives[ idxDLM ] )
{
case dluFIXED_DISK:
case dluREMOVABLE_DISK:
{
LPCWSTR pwszMsg;
LPCWSTR pwszMsgREF;
hrDriveConflictError = HRESULT_FROM_WIN32( ERROR_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT );
hr = THR( HrFormatStringIntoBSTR(
g_hInstance
, IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_ERROR
, &bstrMsg
, bstrOuterNodeName
, L'A' + idxDLM // construct the drive letter
, bstrInnerNodeName
) );
if ( bstrMsg == NULL )
{
pwszMsg = L"System drive conflicts.";
}
else
{
pwszMsg = bstrMsg;
}
hr = THR( HrFormatStringIntoBSTR(
g_hInstance
, IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_ERROR_REF
, &bstrMsgREF
) );
if ( bstrMsgREF == NULL )
{
pwszMsgREF = L"System drive conflicts. Make sure there is no drive letter conflict between these nodes and re-run the cluster setup.";
}
else
{
pwszMsgREF = bstrMsgREF;
}
hr = THR( SendStatusReport(
CTaskAnalyzeClusterBase::m_bstrClusterName
, TASKID_Minor_Check_DriveLetter_Mappings
, clsidMinorId
, 0
, 1
, 1
, hrDriveConflictError
, pwszMsg
, NULL
, pwszMsgREF
) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
break;
} // case: fixed disk or removable disk
case dluCOMPACT_DISC:
case dluNETWORK_DRIVE:
case dluRAM_DISK:
{
LPCWSTR pwszMsg;
LPCWSTR pwszMsgREF;
UINT ids = 0;
hrDriveConflictWarning = MAKE_HRESULT( 0, FACILITY_WIN32, ERROR_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT );
if ( dlmInner.dluDrives[ idxDLM ] == dluCOMPACT_DISC )
{
ids = IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_CD_WARNING;
} // if: ( dlmInner.dluDrives[ idxDLM ] == dluCOMPACT_DISC )
else if ( dlmInner.dluDrives[ idxDLM ] == dluNETWORK_DRIVE )
{
ids = IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_NET_WARNING;
} // if: ( dlmInner.dluDrives[ idxDLM ] == dluNETWORK_DRIVE )
else if ( dlmInner.dluDrives[ idxDLM ] == dluRAM_DISK )
{
ids = IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_RAM_WARNING;
} // if: ( dlmInner.dluDrives[ idxDLM ] == dluRAM_DISK )
Assert( ids != 0 );
hr = THR( HrFormatStringIntoBSTR(
g_hInstance
, ids
, &bstrMsg
, bstrOuterNodeName
, L'A' + idxDLM // construct the drive letter
, bstrInnerNodeName
) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
if ( bstrMsg == NULL )
{
pwszMsg = L"System drive conflicts.";
}
else
{
pwszMsg = bstrMsg;
}
hr = THR( HrFormatStringIntoBSTR(
g_hInstance
, IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_WARNING_REF
, &bstrMsgREF
) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
if ( bstrMsgREF == NULL )
{
pwszMsgREF = L"System drive conflicts. It is recommended not to have any drive letter conflicts between nodes.";
}
else
{
pwszMsgREF = bstrMsgREF;
}
hr = THR( SendStatusReport(
CTaskAnalyzeClusterBase::m_bstrClusterName
, TASKID_Minor_Check_DriveLetter_Mappings
, clsidMinorId
, 0
, 1
, 1
, hrDriveConflictWarning
, pwszMsg
, NULL
, pwszMsgREF
) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
break;
} // case: compact disc, network drive, or ram disk
} // switch: inner drive letter usage
} // if: outer node drive is a system drive
if ( dlmInner.dluDrives[ idxDLM ] == dluSYSTEM )
{
CLSID clsidMinorId;
hr = THR( CoCreateGuid( &clsidMinorId ) );
if ( FAILED( hr ) )
{
clsidMinorId = IID_NULL;
}
switch ( dlmOuter.dluDrives[ idxDLM ] )
{
case dluFIXED_DISK:
case dluREMOVABLE_DISK:
{
LPCWSTR pwszMsg;
LPCWSTR pwszMsgREF;
hrDriveConflictError = HRESULT_FROM_WIN32( ERROR_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT );
hr = THR( HrFormatStringIntoBSTR(
g_hInstance
, IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_ERROR
, &bstrMsg
, bstrInnerNodeName
, L'A' + idxDLM // construct the drive letter
, bstrOuterNodeName
) );
if ( bstrMsg == NULL )
{
pwszMsg = L"System drive conflicts.";
}
else
{
pwszMsg = bstrMsg;
}
hr = THR( HrFormatStringIntoBSTR(
g_hInstance
, IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_ERROR_REF
, &bstrMsgREF
) );
if ( bstrMsgREF == NULL )
{
pwszMsgREF = L"System drive conflicts. Make sure there is no drive letter conflict between these nodes and re-run the cluster setup.";
}
else
{
pwszMsgREF = bstrMsgREF;
}
hr = THR( SendStatusReport(
CTaskAnalyzeClusterBase::m_bstrClusterName
, TASKID_Minor_Check_DriveLetter_Mappings
, clsidMinorId
, 0
, 1
, 1
, hrDriveConflictError
, pwszMsg
, NULL
, pwszMsgREF
) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
break;
} // case: fixed disk or removable disk
case dluCOMPACT_DISC:
case dluNETWORK_DRIVE:
case dluRAM_DISK:
{
LPCWSTR pwszMsg;
LPCWSTR pwszMsgREF;
UINT ids = 0;
hrDriveConflictWarning = MAKE_HRESULT( 0, FACILITY_WIN32, ERROR_CLUSCFG_SYSTEM_DISK_DRIVE_LETTER_CONFLICT );
if ( dlmOuter.dluDrives[ idxDLM ] == dluCOMPACT_DISC )
{
ids = IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_CD_WARNING;
} // if: ( dlmOuter.dluDrives[ idxDLM ] == dluCOMPACT_DISC )
else if ( dlmOuter.dluDrives[ idxDLM ] == dluNETWORK_DRIVE )
{
ids = IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_NET_WARNING;
} // if: ( dlmOuter.dluDrives[ idxDLM ] == dluNETWORK_DRIVE )
else if ( dlmOuter.dluDrives[ idxDLM ] == dluRAM_DISK )
{
ids = IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_RAM_WARNING;
} // if: ( dlmOuter.dluDrives[ idxDLM ] == dluRAM_DISK )
Assert( ids != 0 );
hr = THR( HrFormatStringIntoBSTR(
g_hInstance
, ids
, &bstrMsg
, bstrInnerNodeName
, L'A' + idxDLM // construct the drive letter
, bstrOuterNodeName
) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
if ( bstrMsg == NULL )
{
pwszMsg = L"System drive conflicts.";
}
else
{
pwszMsg = bstrMsg;
}
hr = THR( HrFormatStringIntoBSTR(
g_hInstance
, IDS_TASKID_MINOR_SYSTEM_DRIVE_LETTER_CONFLICT_WARNING_REF
, &bstrMsgREF
) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
if ( bstrMsgREF == NULL )
{
pwszMsgREF = L"System drive conflicts. It is recommended not to have any drive letter conflicts between nodes.";
}
else
{
pwszMsgREF = bstrMsgREF;
}
hr = THR( SendStatusReport(
CTaskAnalyzeClusterBase::m_bstrClusterName
, TASKID_Minor_Check_DriveLetter_Mappings
, clsidMinorId
, 0
, 1
, 1
, hrDriveConflictWarning
, pwszMsg
, NULL
, pwszMsgREF
) );
if ( FAILED( hr ) )
{
goto Cleanup;
}
break;
} // case: compact disc, network drive, or ram disk
} // switch: outer drive letter usage
} // if: inner node drive is a system drive
} // for: each drive letter mapping
} // for ever: inner node loop
} // for ever: outer node loop
Cleanup:
THR( HrSendStatusReport(
CTaskAnalyzeClusterBase::m_bstrClusterName
, TASKID_Major_Check_Cluster_Feasibility
, TASKID_Minor_Check_DriveLetter_Mappings
, 0
, 1
, 1
, hr
, IDS_TASKID_MINOR_CHECK_DRIVELETTER_MAPPINGS
) );
TraceSysFreeString( bstrOuterNodeName );
TraceSysFreeString( bstrInnerNodeName );
TraceSysFreeString( bstrMsg );
TraceSysFreeString( bstrMsgREF );
if ( pecNodes != NULL )
{
pecNodes->Release();
}
if ( pccniOuter != NULL )
{
pccniOuter->Release();
}
if ( pccniInner != NULL )
{
pccniInner->Release();
}
if ( punk != NULL )
{
punk->Release();
}
//
// Set the return value if an error or warning occurred.
// An error will override a warning.
//
if ( hrDriveConflictError != S_OK )
{
hr = hrDriveConflictError;
}
else if ( hrDriveConflictWarning != S_OK )
{
hr = hrDriveConflictWarning;
}
HRETURN( hr );
} //*** CTaskAnalyzeCluster::HrCompareDriveLetterMappings
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::HrCreateNewResourceInCluster
//
// Description:
// Create a new resource in the cluster configuration since there was
// not a match to the resource already in the cluster.
//
// Arguments:
// pccmriIn
//
// Return Value:
// S_OK
// Success.
//
// Other HRESULT error.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CTaskAnalyzeCluster::HrCreateNewResourceInCluster(
IClusCfgManagedResourceInfo * pccmriIn
, BSTR bstrNodeResNameIn
, BSTR * pbstrNodeResUIDInout
, BSTR bstrNodeNameIn
)
{
TraceFunc( "" );
Assert( pccmriIn != NULL );
Assert( pbstrNodeResUIDInout != NULL );
HRESULT hr = S_OK;
IClusCfgManagedResourceInfo * pccmriNew = NULL;
//
// Need to create a new object.
//
hr = THR( HrCreateNewManagedResourceInClusterConfiguration( pccmriIn, &pccmriNew ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
//
// Display the name of the node's resource in the log.
//
LogMsg(
L"[MT] Created object for resource '%ws' ('%ws') from node '%ws' in the cluster configuration."
, bstrNodeResNameIn
, *pbstrNodeResUIDInout
, bstrNodeNameIn
);
//
// If this is the quorum resource, remember it.
//
hr = STHR( pccmriNew->IsQuorumResource() );
if ( hr == S_OK )
{
//
// Remember the quorum device's UID.
//
Assert( m_bstrQuorumUID == NULL );
m_bstrQuorumUID = *pbstrNodeResUIDInout;
*pbstrNodeResUIDInout = NULL;
} // if:
hr = S_OK;
Cleanup:
if ( pccmriNew != NULL )
{
pccmriNew->Release();
} // if:
HRETURN( hr );
} //*** CTaskAnalyzeCluster::HrCreateNewResourceInCluster
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::HrCreateNewResourceInCluster
//
// Description:
// Create a new resource in the cluster configuration since there was
// not a match to the resource already in the cluster.
//
// Arguments:
// pccmriIn
// The source object.
//
// ppccmriOut
// The new object that was created.
//
// Return Value:
// S_OK
// Success.
//
// Other HRESULT error.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CTaskAnalyzeCluster::HrCreateNewResourceInCluster(
IClusCfgManagedResourceInfo * pccmriIn
, IClusCfgManagedResourceInfo ** ppccmriOut
)
{
TraceFunc( "" );
Assert( pccmriIn != NULL );
Assert( ppccmriOut != NULL );
HRESULT hr = S_OK;
//
// Need to create a new object.
//
hr = THR( HrCreateNewManagedResourceInClusterConfiguration( pccmriIn, ppccmriOut ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
//
// If the resource is manageable in a cluster then we should set it
// to be managed so it will be created by PostConfig.
//
hr = STHR( (*ppccmriOut)->IsManagedByDefault() );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
if ( hr == S_OK )
{
hr = THR( (*ppccmriOut)->SetManaged( TRUE ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
} // if:
hr = S_OK;
Cleanup:
HRETURN( hr );
} //*** CTaskAnalyzeCluster::HrCreateNewResourceInCluster
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::HrFixupErrorCode
//
// Description:
// Do any fix ups needed for the passed in error code and return the
// fixed up value. The default implementation is to do no fixups.
//
// Arguments:
// hrIn
// The error code to fix up.
//
// Return Value:
// The passed in error code.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CTaskAnalyzeCluster::HrFixupErrorCode(
HRESULT hrIn
)
{
TraceFunc( "" );
HRETURN( hrIn );
} //*** CTaskAnalyzeCluster::HrFixupErrorCode
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::GetNodeCannotVerifyQuorumStringRefId
//
// Description:
// Return the correct string ids for the message that is displayed
// to the user when there isn't a quorum resource.
//
// Arguments:
// pdwRefIdOut
// The reference text to show the user.
//
// Return Value:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
void
CTaskAnalyzeCluster::GetNodeCannotVerifyQuorumStringRefId(
DWORD * pdwRefIdOut
)
{
TraceFunc( "" );
Assert( pdwRefIdOut != NULL );
*pdwRefIdOut = IDS_TASKID_MINOR_NODE_CANNOT_ACCESS_QUORUM_ERROR_REF;
TraceFuncExit();
} //*** CTaskAnalyzeCluster::GetNodeCannotVerifyQuorumStringRefId
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::GetNoCommonQuorumToAllNodesStringIds
//
// Description:
// Return the correct string ids for the message that is displayed
// to the user when there isn't a common to all nodes quorum resource.
//
// Arguments:
// pdwMessageIdOut
// The message to show the user.
//
// pdwRefIdOut
// The reference text to show the user.
//
// Return Value:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
void
CTaskAnalyzeCluster::GetNoCommonQuorumToAllNodesStringIds(
DWORD * pdwMessageIdOut
, DWORD * pdwRefIdOut
)
{
TraceFunc( "" );
Assert( pdwMessageIdOut != NULL );
Assert( pdwRefIdOut != NULL );
*pdwMessageIdOut = IDS_TASKID_MINOR_MISSING_COMMON_QUORUM_RESOURCE_ERROR;
*pdwRefIdOut = IDS_TASKID_MINOR_MISSING_COMMON_QUORUM_RESOURCE_ERROR_REF;
TraceFuncExit();
} //*** CTaskAnalyzeCluster::GetNoCommonQuorumToAllNodesStringIds
//////////////////////////////////////////////////////////////////////////////
//++
//
// CTaskAnalyzeCluster::HrShowLocalQuorumWarning
//
// Description:
// Send the warning about forcing local quorum to the UI.
//
// Arguments:
// None.
//
// Return Value:
// S_OK
// The SSR was done properly.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CTaskAnalyzeCluster::HrShowLocalQuorumWarning( void )
{
TraceFunc( "" );
HRESULT hr = S_OK;
hr = THR( HrSendStatusReport(
CTaskAnalyzeClusterBase::m_bstrClusterName
, TASKID_Minor_Finding_Common_Quorum_Device
, TASKID_Minor_Forced_Local_Quorum
, 1
, 1
, 1
, MAKE_HRESULT( SEVERITY_SUCCESS, FACILITY_WIN32, ERROR_QUORUM_DISK_NOT_FOUND )
, IDS_TASKID_MINOR_FORCED_LOCAL_QUORUM
) );
HRETURN( hr );
} //*** CTaskAnalyzeCluster::HrShowLocalQuorumWarning