Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

2807 lines
64 KiB

//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000-2001 Microsoft Corporation
//
// Module Name:
// CEnumPhysicalDisks.cpp
//
// Description:
// This file contains the definition of the CEnumPhysicalDisks
// class.
//
// The class CEnumPhysicalDisks is the enumeration of cluster
// storage devices. It implements the IEnumClusCfgManagedResources
// interface.
//
// Documentation:
//
// Header File:
// CEnumPhysicalDisks.h
//
// Maintained By:
// Galen Barbee (GalenB) 23-FEB-2000
//
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// Include Files
//////////////////////////////////////////////////////////////////////////////
#include "pch.h"
#include "CEnumPhysicalDisks.h"
#include "CPhysicalDisk.h"
#include <PropList.h>
//////////////////////////////////////////////////////////////////////////////
// Constant Definitions
//////////////////////////////////////////////////////////////////////////////
DEFINE_THISCLASS( "CEnumPhysicalDisks" );
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CEnumPhysicalDisks class
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks::S_HrCreateInstance
//
// Description:
// Create a CEnumPhysicalDisks instance.
//
// Arguments:
// None.
//
// Return Values:
// S_OK
// Success.
//
// E_POINTER
// The passed in ppunk is NULL.
//
// other HRESULTs
// Object creation failed.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CEnumPhysicalDisks::S_HrCreateInstance( IUnknown ** ppunkOut )
{
TraceFunc( "" );
HRESULT hr;
CEnumPhysicalDisks * pccpd = NULL;
if ( ppunkOut == NULL )
{
hr = THR( E_POINTER );
goto Cleanup;
} // if:
pccpd = new CEnumPhysicalDisks();
if ( pccpd == NULL )
{
hr = THR( E_OUTOFMEMORY );
goto Cleanup;
} // if: error allocating object
hr = THR( pccpd->HrInit() );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if: HrInit() failed
hr = THR( pccpd->TypeSafeQI( IUnknown, ppunkOut ) );
Cleanup:
if ( FAILED( hr ) )
{
LogMsg( L"[SRV] CEnumPhysicalDisks::S_HrCreateInstance() failed. (hr = %#08x)", hr );
} // if:
if ( pccpd != NULL )
{
pccpd->Release();
} // if:
HRETURN( hr );
} //*** CEnumPhysicalDisks::S_HrCreateInstance
//////////////////////////////////////////////////////////////////////////////
//++
//
// IUnknown *
// CEnumPhysicalDisks::S_RegisterCatIDSupport
//
// Description:
// Registers/unregisters this class with the categories that it belongs
// to.
//
// Arguments:
// IN ICatRegister * picrIn
// Used to register/unregister our CATID support.
//
// IN BOOL fCreateIn
// When true we are registering the server. When false we are
// un-registering the server.
//
// Return Values:
// S_OK
// Success.
//
// E_INVALIDARG
// The passed in ICatRgister pointer was NULL.
//
// other HRESULTs
// Registration/Unregistration failed.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CEnumPhysicalDisks::S_RegisterCatIDSupport(
ICatRegister * picrIn,
BOOL fCreateIn
)
{
TraceFunc( "" );
HRESULT hr = S_OK;
CATID rgCatIds[ 1 ];
if ( picrIn == NULL )
{
hr = THR( E_INVALIDARG );
goto Cleanup;
} // if:
rgCatIds[ 0 ] = CATID_EnumClusCfgManagedResources;
if ( fCreateIn )
{
hr = THR( picrIn->RegisterClassImplCategories( CLSID_EnumPhysicalDisks, 1, rgCatIds ) );
} // if:
Cleanup:
HRETURN( hr );
} //*** CEnumPhysicalDisks::S_RegisterCatIDSupport
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks::CEnumPhysicalDisks
//
// Description:
// Constructor of the CEnumPhysicalDisks class. This initializes
// the m_cRef variable to 1 instead of 0 to account of possible
// QueryInterface failure in DllGetClassObject.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
CEnumPhysicalDisks::CEnumPhysicalDisks( void )
: m_cRef( 1 )
, m_lcid( LOCALE_NEUTRAL )
, m_fLoadedDevices( false )
{
TraceFunc( "" );
// Increment the count of components in memory so the DLL hosting this
// object cannot be unloaded.
InterlockedIncrement( &g_cObjects );
Assert( m_picccCallback == NULL );
Assert( m_pIWbemServices == NULL );
Assert( m_prgDisks == NULL );
Assert( m_idxNext == 0 );
Assert( m_idxEnumNext == 0 );
Assert( m_bstrNodeName == NULL );
Assert( m_bstrBootDevice == NULL );
Assert( m_bstrSystemDevice == NULL );
Assert( m_bstrBootLogicalDisk == NULL );
Assert( m_bstrSystemLogicalDisk == NULL );
Assert( m_bstrSystemWMIDeviceID == NULL );
Assert( m_cDiskCount == 0 );
TraceFuncExit();
} //*** CEnumPhysicalDisks::CEnumPhysicalDisks
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks::~CEnumPhysicalDisks
//
// Description:
// Desstructor of the CEnumPhysicalDisks class.
//
// Arguments:
// None.
//
// Return Value:
// None.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
CEnumPhysicalDisks::~CEnumPhysicalDisks( void )
{
TraceFunc( "" );
ULONG idx;
if ( m_pIWbemServices != NULL )
{
m_pIWbemServices->Release();
} // if:
if ( m_picccCallback != NULL )
{
m_picccCallback->Release();
} // if:
for ( idx = 0; idx < m_idxNext; idx++ )
{
if ( (*m_prgDisks)[ idx ] != NULL )
{
((*m_prgDisks)[ idx ])->Release();
} // end if:
} // for:
TraceFree( m_prgDisks );
TraceSysFreeString( m_bstrNodeName );
TraceSysFreeString( m_bstrBootDevice );
TraceSysFreeString( m_bstrSystemDevice );
TraceSysFreeString( m_bstrBootLogicalDisk );
TraceSysFreeString( m_bstrSystemLogicalDisk );
TraceSysFreeString( m_bstrSystemWMIDeviceID );
// There's going to be one less component in memory. Decrement component count.
InterlockedDecrement( &g_cObjects );
TraceFuncExit();
} //*** CEnumPhysicalDisks::~CEnumPhysicalDisks
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CEnumPhysicalDisks -- IUnknown interface.
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//++
//
// STDMETHODIMP_( ULONG )
// CEnumPhysicalDisks:: [IUNKNOWN] AddRef
//
// Description:
// Increment the reference count of this object by one.
//
// Arguments:
// None.
//
// Return Value:
// The new reference count.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_( ULONG )
CEnumPhysicalDisks::AddRef( void )
{
TraceFunc( "[IUnknown]" );
InterlockedIncrement( & m_cRef );
RETURN( m_cRef );
} //*** CEnumPhysicalDisks::AddRef
//////////////////////////////////////////////////////////////////////////////
//++
//
// STDMETHODIMP_( ULONG )
// CEnumPhysicalDisks:: [IUNKNOWN] Release
//
// Description:
// Decrement the reference count of this object by one.
//
// Arguments:
// None.
//
// Return Value:
// The new reference count.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_( ULONG )
CEnumPhysicalDisks::Release( void )
{
TraceFunc( "[IUnknown]" );
LONG cRef;
cRef = InterlockedDecrement( &m_cRef );
if ( cRef == 0 )
{
TraceDo( delete this );
} // if: reference count equal to zero
RETURN( cRef );
} //*** CEnumPhysicalDisks::Release
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks:: [INKNOWN] QueryInterface
//
// Description:
// Query this object for the passed in interface.
//
// Arguments:
// IN REFIID riid,
// Id of interface requested.
//
// OUT void ** ppv
// 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.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CEnumPhysicalDisks::QueryInterface( REFIID riid, void ** ppv )
{
TraceQIFunc( riid, ppv );
HRESULT hr = E_NOINTERFACE;
if ( IsEqualIID( riid, IID_IUnknown ) )
{
*ppv = static_cast< IEnumClusCfgManagedResources * >( this );
hr = S_OK;
} // if: IUnknown
else if ( IsEqualIID( riid, IID_IEnumClusCfgManagedResources ) )
{
*ppv = TraceInterface( __THISCLASS__, IEnumClusCfgManagedResources, this, 0 );
hr = S_OK;
} // else if:
else if ( IsEqualIID( riid, IID_IClusCfgWbemServices ) )
{
*ppv = TraceInterface( __THISCLASS__, IClusCfgWbemServices, this, 0 );
hr = S_OK;
} // else if:
else if ( IsEqualIID( riid, IID_IClusCfgInitialize ) )
{
*ppv = TraceInterface( __THISCLASS__, IClusCfgInitialize, this, 0 );
hr = S_OK;
} // else if:
if ( SUCCEEDED( hr ) )
{
((IUnknown *) *ppv)->AddRef( );
} // if: success
QIRETURN_IGNORESTDMARSHALLING( hr, riid );
} //*** CEnumPhysicalDisks::QueryInterface
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CEnumPhysicalDisks -- IClusCfgWbemServices interface.
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks::SetWbemServices
//
// Description:
// Set the WBEM services provider.
//
// Arguments:
// IN IWbemServices pIWbemServicesIn
//
// Return Value:
// S_OK
// Success
//
// E_POINTER
// The pIWbemServicesIn param is NULL.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CEnumPhysicalDisks::SetWbemServices( IWbemServices * pIWbemServicesIn )
{
TraceFunc( "[IClusCfgWbemServices]" );
HRESULT hr = S_OK;
if ( pIWbemServicesIn == NULL )
{
hr = THR( E_POINTER );
STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_SetWbemServices_Enum_PhysDisk, IDS_ERROR_NULL_POINTER, hr );
goto Cleanup;
} // if:
m_pIWbemServices = pIWbemServicesIn;
m_pIWbemServices->AddRef();
hr = THR( HrGetSystemDevice( &m_bstrSystemDevice ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( HrConvertDeviceVolumeToLogicalDisk( m_bstrSystemDevice, &m_bstrSystemLogicalDisk ) );
//
// system volume is an EFI volume on IA64 and won't have a logical disk.
//
if ( HRESULT_CODE( hr ) == ERROR_INVALID_FUNCTION )
{
hr = THR( HrConvertDeviceVolumeToWMIDeviceID( m_bstrSystemDevice, &m_bstrSystemWMIDeviceID ) );
Assert( m_bstrSystemLogicalDisk == NULL );
Assert( m_bstrSystemWMIDeviceID != NULL );
} // if:
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( HrGetBootLogicalDisk( &m_bstrBootLogicalDisk ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = STHR( HrIsLogicalDiskNTFS( m_bstrBootLogicalDisk ) );
if ( hr == S_FALSE )
{
STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_Boot_Partition_Not_NTFS, IDS_WARNING_BOOT_PARTITION_NOT_NTFS, hr );
hr = S_OK;
} // if:
Cleanup:
HRETURN( hr );
} //*** CEnumPhysicalDisks::SetWbemServices
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CEnumPhysicalDisks -- IClusCfgInitialize interface.
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks::Initialize
//
// Description:
// Initialize this component.
//
// Arguments:
// IN IUknown * punkCallbackIn
//
// IN LCID lcidIn
//
// Return Value:
// S_OK
// Success
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CEnumPhysicalDisks::Initialize(
IUnknown * punkCallbackIn,
LCID lcidIn
)
{
TraceFunc( "[IClusCfgInitialize]" );
Assert( m_picccCallback == NULL );
HRESULT hr = S_OK;
m_lcid = lcidIn;
if ( punkCallbackIn == NULL )
{
hr = THR( E_POINTER );
goto Cleanup;
} // if:
hr = THR( punkCallbackIn->TypeSafeQI( IClusCfgCallback, &m_picccCallback ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( HrGetComputerName( ComputerNameNetBIOS, &m_bstrNodeName ) );
Cleanup:
HRETURN( hr );
} //*** CEnumPhysicalDisks::Initialize
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CEnumPhysicalDisks -- IEnumClusCfgManagedResources interface.
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks::Next
//
// Description:
//
// Arguments:
//
// Return Value:
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CEnumPhysicalDisks::Next(
ULONG cNumberRequestedIn,
IClusCfgManagedResourceInfo ** rgpManagedResourceInfoOut,
ULONG * pcNumberFetchedOut
)
{
TraceFunc( "[IEnumClusCfgManagedResources]" );
HRESULT hr = S_FALSE;
ULONG cFetched = 0;
IClusCfgManagedResourceInfo * pccsdi;
IUnknown * punk;
ULONG ulStop;
if ( rgpManagedResourceInfoOut == NULL )
{
hr = THR( E_POINTER );
STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_Next_Enum_PhysDisk, IDS_ERROR_NULL_POINTER, hr );
goto Cleanup;
} // if:
if ( !m_fLoadedDevices )
{
hr = THR( HrLoadEnum() );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
} // if:
ulStop = min( cNumberRequestedIn, ( m_idxNext - m_idxEnumNext ) );
for ( hr = S_OK; ( cFetched < ulStop ) && ( m_idxEnumNext < m_idxNext ); m_idxEnumNext++ )
{
punk = (*m_prgDisks)[ m_idxEnumNext ];
if ( punk != NULL )
{
hr = THR( punk->TypeSafeQI( IClusCfgManagedResourceInfo, &pccsdi ) );
if ( FAILED( hr ) )
{
break;
} // if:
rgpManagedResourceInfoOut[ cFetched++ ] = pccsdi;
} // if:
} // for:
if ( FAILED( hr ) )
{
m_idxEnumNext -= cFetched;
while ( cFetched != 0 )
{
(rgpManagedResourceInfoOut[ --cFetched ])->Release();
} // for:
goto Cleanup;
} // if:
if ( cFetched < cNumberRequestedIn )
{
hr = S_FALSE;
} // if:
Cleanup:
if ( pcNumberFetchedOut != NULL )
{
*pcNumberFetchedOut = cFetched;
} // if:
HRETURN( hr );
} //*** CEnumPhysicalDisks::Next
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks::Skip
//
// Description:
//
// Arguments:
//
// Return Value:
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CEnumPhysicalDisks::Skip( ULONG cNumberToSkipIn )
{
TraceFunc( "[IEnumClusCfgManagedResources]" );
HRESULT hr = S_OK;
m_idxEnumNext += cNumberToSkipIn;
if ( m_idxEnumNext >= m_idxNext )
{
m_idxEnumNext = m_idxNext;
hr = STHR( S_FALSE );
} // if:
HRETURN( hr );
} //*** CEnumPhysicalDisks::Skip
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks::Reset
//
// Description:
//
// Arguments:
//
// Return Value:
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CEnumPhysicalDisks::Reset( void )
{
TraceFunc( "[IEnumClusCfgManagedResources]" );
m_idxEnumNext = 0;
HRETURN( S_OK );
} //*** CEnumPhysicalDisks::Reset
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks::Clone
//
// Description:
//
// Arguments:
//
// Return Value:
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CEnumPhysicalDisks::Clone(
IEnumClusCfgManagedResources ** ppEnumClusCfgStorageDevicesOut
)
{
TraceFunc( "[IEnumClusCfgManagedResources]" );
HRESULT hr = S_OK;
if ( ppEnumClusCfgStorageDevicesOut == NULL )
{
hr = THR( E_POINTER );
STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_Clone_Enum_PhysDisk, IDS_ERROR_NULL_POINTER, hr );
goto Cleanup;
} // if:
hr = THR( E_NOTIMPL );
Cleanup:
HRETURN( hr );
} //*** CEnumPhysicalDisks::Clone
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks::Count
//
// Description:
// Return the count of items in the Enum.
//
// Arguments:
//
// Return Value:
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CEnumPhysicalDisks::Count( DWORD * pnCountOut )
{
TraceFunc( "[IEnumClusCfgManagedResources]" );
HRESULT hr = S_OK;
if ( pnCountOut == NULL )
{
hr = THR( E_POINTER );
goto Cleanup;
} // if:
if ( !m_fLoadedDevices )
{
hr = THR( HrLoadEnum() );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
} // if:
*pnCountOut = m_cDiskCount;
Cleanup:
HRETURN( hr );
} //*** CEnumPhysicalDisks::Count
//*************************************************************************//
/////////////////////////////////////////////////////////////////////////////
// CEnumPhysicalDisks class -- Private Methods.
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks::HrInit
//
// Description:
// Initialize this component.
//
// Arguments:
// None.
//
// Return Value:
//
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CEnumPhysicalDisks::HrInit( void )
{
TraceFunc( "" );
HRESULT hr = S_OK;
HRETURN( hr );
} //*** CEnumPhysicalDisks::HrInit
/////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks::HrGetDisks
//
// Description:
//
// Arguments:
//
//
// Return Value:
//
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CEnumPhysicalDisks::HrGetDisks( void )
{
TraceFunc( "" );
HRESULT hr = S_FALSE;
BSTR bstrClass;
IEnumWbemClassObject * pDisks = NULL;
ULONG ulReturned;
IWbemClassObject * pDisk = NULL;
bstrClass = TraceSysAllocString( L"Win32_DiskDrive" );
if ( bstrClass == NULL )
{
goto OutOfMemory;
} // if:
hr = THR( m_pIWbemServices->CreateInstanceEnum( bstrClass, WBEM_FLAG_SHALLOW, NULL, &pDisks ) );
if ( FAILED( hr ) )
{
STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_WMI_Phys_Disks_Qry_Failed, IDS_ERROR_WMI_PHYS_DISKS_QRY_FAILED, hr );
goto Cleanup;
} // if:
for ( ; ; )
{
hr = pDisks->Next( WBEM_INFINITE, 1, &pDisk, &ulReturned );
if ( ( hr == S_OK ) && ( ulReturned == 1 ) )
{
hr = STHR( HrLogDiskInfo( pDisk ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = STHR( IsDiskSCSI( pDisk ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
if ( hr == S_OK )
{
hr = STHR( HrCreateAndAddDiskToArray( pDisk ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
} // if:
pDisk->Release();
pDisk = NULL;
} // if:
else if ( ( hr == S_FALSE ) && ( ulReturned == 0 ) )
{
hr = S_OK;
break;
} // else if:
else
{
STATUS_REPORT_STRING( TASKID_Major_Find_Devices, TASKID_Minor_WQL_Disk_Qry_Next_Failed, IDS_ERROR_WQL_QRY_NEXT_FAILED, bstrClass, hr );
goto Cleanup;
} // else:
} // for:
m_idxEnumNext = 0;
m_fLoadedDevices = TRUE;
goto Cleanup;
OutOfMemory:
hr = THR( E_OUTOFMEMORY );
STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_HrGetDisks, IDS_ERROR_OUTOFMEMORY, hr );
Cleanup:
if ( pDisk != NULL )
{
pDisk->Release();
} // if:
if ( pDisks != NULL )
{
pDisks->Release();
} // if:
TraceSysFreeString( bstrClass );
HRETURN( hr );
} //*** CEnumPhysicalDisks::HrGetDisks
/////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks::HrCreateAndAddDiskToArray
//
// Description:
// Create a IClusCfgStorageDevice object and add the passed in disk to
// the array of punks that holds the disks.
//
// Arguments:
//
//
// Return Value:
// S_OK
// Success
//
// E_OUTOFMEMORY
// Couldn't allocate memeory.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CEnumPhysicalDisks::HrCreateAndAddDiskToArray( IWbemClassObject * pDiskIn )
{
TraceFunc( "" );
HRESULT hr = S_FALSE;
IUnknown * punk = NULL;
IClusCfgSetWbemObject * piccswo = NULL;
bool fRetainObject = true;
hr = THR( CPhysicalDisk::S_HrCreateInstance( &punk ) );
if ( FAILED( hr ) )
{
goto Exit;
} // if:
punk = TraceInterface( L"CPhysicalDisk", IUnknown, punk, 1 );
hr = THR( HrSetInitialize( punk, m_picccCallback, m_lcid ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( HrSetWbemServices( punk, m_pIWbemServices ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( punk->TypeSafeQI( IClusCfgSetWbemObject, &piccswo ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = STHR( piccswo->SetWbemObject( pDiskIn, &fRetainObject ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
if ( fRetainObject )
{
hr = THR( HrAddDiskToArray( punk ) );
} // if:
Cleanup:
if ( piccswo != NULL )
{
piccswo->Release();
} // if:
punk->Release();
Exit:
HRETURN( hr );
} //*** CEnumPhysicalDisks::HrCreateAndAddDiskToArray
/////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks::HrPruneSystemDisks
//
// Description:
// Prune all system disks from the list. System disks are disks that
// are booted, are running the OS, or have page files.
//
// Arguments:
//
//
// Return Value:
// S_OK
// Success
//
// E_OUTOFMEMORY
// Couldn't allocate memeory.
//
// Remarks:
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CEnumPhysicalDisks::HrPruneSystemDisks( void )
{
TraceFunc( "" );
HRESULT hr = S_OK;
ULONG idx;
ULONG ulSCSIBus;
ULONG ulSCSIPort;
IClusCfgPhysicalDiskProperties * piccpdp = NULL;
IUnknown * punk;
ULONG cRemoved = 0;
ULONG cTemp = 0;
bool fSystemAndBootTheSame = ( m_bstrSystemLogicalDisk != NULL ) ? ( m_bstrBootLogicalDisk[ 0 ] == m_bstrSystemLogicalDisk[ 0 ] ) : false;
WCHAR szPageFileDisks[ 26 ];
int cPageFileDisks = 0;
int idxPageFileDisk;
bool fPruneBus = false;
hr = STHR( HrIsSystemBusManaged() );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
//
// If the system bus is not managed then we need to prune the disks on those buses
// that contain system, boot, and pagefile disks.
//
if ( hr == S_FALSE )
{
fPruneBus = true;
} // if:
//
// Prune the disks on the system buses. If the system disks are IDE they won't
// be in the list.
//
//
// Find the boot disk
//
hr = STHR( HrFindDiskWithLogicalDisk( m_bstrBootLogicalDisk[ 0 ], &idx ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
if ( hr == S_OK )
{
//
// Should we prune the whole bus, or just the boot disk itself?
//
if ( fPruneBus )
{
hr = THR( HrGetSCSIInfo( idx, &ulSCSIBus, &ulSCSIPort ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_Pruning_Boot_Disk_Bus, IDS_INFO_PRUNING_BOOTDISK_BUS, hr );
hr = THR( HrPruneDisks( ulSCSIBus, ulSCSIPort, &cTemp, IDS_INFO_BOOTDISK_PRUNED ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
cRemoved += cTemp;
} // if:
else
{
RemoveDiskFromArray( idx );
cRemoved++;
} // else:
} // if:
//
// Prune the system disk bus if it is not the same as the boot disk bus.
//
if ( !fSystemAndBootTheSame )
{
if ( m_bstrSystemLogicalDisk != NULL )
{
Assert( m_bstrSystemWMIDeviceID == NULL );
hr = STHR( HrFindDiskWithLogicalDisk( m_bstrSystemLogicalDisk[ 0 ], &idx ) );
} // if:
else
{
Assert( m_bstrSystemLogicalDisk == NULL );
hr = STHR( HrFindDiskWithWMIDeviceID( m_bstrSystemWMIDeviceID, &idx ) );
} // else:
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
if ( hr == S_OK )
{
//
// Should we prune the whole bus, or just the system disk itself?
//
if ( fPruneBus )
{
hr = THR( HrGetSCSIInfo( idx, &ulSCSIBus, &ulSCSIPort ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_Pruning_System_Disk_Bus, IDS_INFO_PRUNING_SYSTEMDISK_BUS, hr );
hr = THR( HrPruneDisks( ulSCSIBus, ulSCSIPort, &cTemp, IDS_INFO_SYSTEMDISK_PRUNED ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
cRemoved += cTemp;
} // if:
else
{
RemoveDiskFromArray( idx );
cRemoved++;
} // else:
} // if:
} // if:
//
// Prune the bus with disks that have paging files.
//
hr = THR( HrGetPageFileLogicalDisks( m_picccCallback, m_pIWbemServices, szPageFileDisks, &cPageFileDisks ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
if ( cPageFileDisks > 0 )
{
for ( idxPageFileDisk = 0; idxPageFileDisk < cPageFileDisks; idxPageFileDisk++ )
{
hr = STHR( HrFindDiskWithLogicalDisk( szPageFileDisks[ idxPageFileDisk ], &idx ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
if ( hr == S_OK )
{
//
// Should we prune the whole bus, or just the system disk itself?
//
if ( fPruneBus )
{
hr = THR( HrGetSCSIInfo( idx, &ulSCSIBus, &ulSCSIPort ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_Pruning_PageFile_Disk_Bus, IDS_INFO_PRUNING_PAGEFILEDISK_BUS, hr );
hr = THR( HrPruneDisks( ulSCSIBus, ulSCSIPort, &cTemp, IDS_INFO_PAGEFILEDISK_PRUNED ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
cRemoved += cTemp;
} // if:
else
{
RemoveDiskFromArray( idx );
cRemoved++;
} // else:
} // if:
} // for:
} // if:
//
// Last ditch effort to properly set the managed state of the remaining disks.
//
for ( idx = 0; ( cRemoved < m_idxNext ) && ( idx < m_idxNext ); idx++ )
{
punk = (*m_prgDisks)[ idx ]; // don't ref
if ( punk != NULL )
{
hr = THR( punk->TypeSafeQI( IClusCfgPhysicalDiskProperties, &piccpdp ) );
if ( FAILED( hr ) )
{
LOG_STATUS_REPORT( L"Could not query for the IClusCfgPhysicalDiskProperties interface.", hr );
goto Cleanup;
} // if:
//
// Give the disk a chance to figure out for itself if it should be managed.
//
hr = STHR( piccpdp->CanBeManaged() );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
piccpdp->Release();
piccpdp = NULL;
} // if:
} // for:
//
// Minor optimization. If we removed all of the elements reset the enum next to 0.
//
if ( cRemoved == m_idxNext )
{
m_idxNext = 0;
} // if:
hr = S_OK;
Cleanup:
if ( piccpdp != NULL )
{
piccpdp->Release();
} // if:
HRETURN( hr );
} //*** CEnumPhysicalDisks::HrPruneSystemDisks
/////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks::IsDiskSCSI
//
// Description:
//
// Arguments:
//
//
// Return Value:
// S_OK
// Disk is SCSI.
//
// S_FALSE
// Disk is not SCSI.
//
// E_OUTOFMEMORY
// Couldn't allocate memeory.
//
// Remarks:
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CEnumPhysicalDisks::IsDiskSCSI( IWbemClassObject * pDiskIn )
{
TraceFunc( "" );
Assert( pDiskIn != NULL );
HRESULT hr;
VARIANT var;
VariantInit( &var );
hr = THR( HrGetWMIProperty( pDiskIn, L"InterfaceType", VT_BSTR, &var ) );
if ( SUCCEEDED( hr ) )
{
if ( ( wcscmp( L"SCSI", var.bstrVal ) == 0 ) )
{
hr = S_OK;
} // if:
else
{
hr = S_FALSE;
} // else:
} // if:
VariantClear( &var );
HRETURN( hr );
} //*** CEnumPhysicalDisks::IsDiskSCSI
/////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks:HrAddDiskToArray
//
// Description:
// Add the passed in disk to the array of punks that holds the disks.
//
// Arguments:
//
//
// Return Value:
// S_OK
// Success
//
// E_OUTOFMEMORY
// Couldn't allocate memeory.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CEnumPhysicalDisks::HrAddDiskToArray( IUnknown * punkIn )
{
TraceFunc( "" );
Assert( punkIn != NULL );
HRESULT hr = S_OK;
IUnknown * ((*prgpunks)[]) = NULL;
prgpunks = (IUnknown *((*)[])) TraceReAlloc( m_prgDisks, sizeof( IUnknown * ) * ( m_idxNext + 1 ), HEAP_ZERO_MEMORY );
if ( prgpunks == NULL )
{
hr = THR( E_OUTOFMEMORY );
STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_HrAddDiskToArray, IDS_ERROR_OUTOFMEMORY, hr );
goto Cleanup;
} // if:
m_prgDisks = prgpunks;
(*m_prgDisks)[ m_idxNext++ ] = punkIn;
punkIn->AddRef();
m_cDiskCount += 1;
Cleanup:
HRETURN( hr );
} //*** CEnumPhysicalDisks::HrAddDiskToArray
/////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks:HrFixupDisks
//
// Description:
// Tweak the disks to better reflect how they are managed by this node.
//
// Arguments:
// None.
//
// Return Value:
// S_OK
// Success.
//
// Win32 Error
// something failed.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CEnumPhysicalDisks::HrFixupDisks( void )
{
TraceFunc( "" );
HRESULT hr;
ULONG idx;
IUnknown * punk = NULL;
IClusCfgManagedResourceInfo * piccmri = NULL;
//
// KB: 14-JUN-2000 GalenB
//
// Clear the managed bit on all remaing disks. These bits will be turned
// back on for the disks this node owns. That happens in
// HrNodeResourceCallback().
//
//
// BUGBUG: 02-MAY-2001 GalenB
//
// Hmmm... Maybe clearing the managed state from all disks is a mistake. What if we
// have new disks that are not already in the cluster for this clustered node?
//
for ( idx = 0; idx < m_idxNext; idx++ )
{
punk = (*m_prgDisks)[ idx ]; // don't ref
if ( punk != NULL )
{
hr = THR( punk->TypeSafeQI( IClusCfgManagedResourceInfo, &piccmri ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( piccmri->SetManaged( false ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
piccmri->Release();
piccmri = NULL;
} // if:
} // for:
hr = THR( HrEnumNodeResources( m_bstrNodeName ) );
Cleanup:
if ( piccmri != NULL )
{
piccmri->Release();
} // if:
HRETURN( hr );
} //*** CEnumPhysicalDisks::HrFixupDisks
/////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks:HrNodeResourceCallback
//
// Description:
// Called by CClusterUtils::HrEnumNodeResources() when it finds a
// resource for this node.
//
// Arguments:
//
//
// Return Value:
// S_OK
// Success.
//
// Win32 Error
// something failed.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CEnumPhysicalDisks::HrNodeResourceCallback(
HCLUSTER hClusterIn,
HRESOURCE hResourceIn
)
{
TraceFunc( "" );
HRESULT hr = S_OK;
CLUS_SCSI_ADDRESS csa;
DWORD dwSignature;
BOOL fIsQuorum;
BSTR bstrResourceName = NULL;
hr = STHR( HrIsResourceOfType( hResourceIn, L"Physical Disk" ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
//
// If this resource is not a physical disk then we simply want to
// skip it.
//
if ( hr == S_FALSE )
{
goto Cleanup;
} // if:
hr = STHR( HrIsCoreResource( hResourceIn ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
fIsQuorum = ( hr == S_OK );
hr = THR( HrGetClusterDiskInfo( hClusterIn, hResourceIn, &csa, &dwSignature ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( HrGetClusterProperties( hResourceIn, &bstrResourceName ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( HrSetThisDiskToBeManaged( csa.TargetId, csa.Lun, fIsQuorum, bstrResourceName, dwSignature ) );
Cleanup:
TraceSysFreeString( bstrResourceName );
HRETURN( hr );
} //*** CEnumPhysicalDisks::HrNodeResourceCallback
/////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks:HrGetClusterDiskInfo
//
// Description:
//
//
// Arguments:
//
//
// Return Value:
// S_OK
// Success.
//
// Win32 Error
// something failed.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CEnumPhysicalDisks::HrGetClusterDiskInfo(
HCLUSTER hClusterIn,
HRESOURCE hResourceIn,
CLUS_SCSI_ADDRESS * pcsaOut,
DWORD * pdwSignatureOut
)
{
TraceFunc( "" );
HRESULT hr = S_OK;
DWORD sc;
CClusPropValueList cpvl;
CLUSPROP_BUFFER_HELPER cbhValue = { NULL };
sc = TW32( cpvl.ScGetResourceValueList( hResourceIn, CLUSCTL_RESOURCE_STORAGE_GET_DISK_INFO ) );
if ( sc != ERROR_SUCCESS )
{
goto MakeHr;
} // if:
sc = TW32( cpvl.ScMoveToFirstValue() );
if ( sc != ERROR_SUCCESS )
{
goto MakeHr;
} // if:
for ( ; ; )
{
cbhValue = cpvl;
switch ( cbhValue.pSyntax->dw )
{
case CLUSPROP_SYNTAX_PARTITION_INFO :
{
break;
} // case: CLUSPROP_SYNTAX_PARTITION_INFO
case CLUSPROP_SYNTAX_DISK_SIGNATURE :
{
*pdwSignatureOut = cbhValue.pDiskSignatureValue->dw;
break;
} // case: CLUSPROP_SYNTAX_DISK_SIGNATURE
case CLUSPROP_SYNTAX_SCSI_ADDRESS :
{
pcsaOut->dw = cbhValue.pScsiAddressValue->dw;
break;
} // case: CLUSPROP_SYNTAXscSI_ADDRESS
case CLUSPROP_SYNTAX_DISK_NUMBER :
{
break;
} // case: CLUSPROP_SYNTAX_DISK_NUMBER
} // switch:
sc = cpvl.ScMoveToNextValue();
if ( sc == ERROR_SUCCESS )
{
continue;
} // if:
if ( sc == ERROR_NO_MORE_ITEMS )
{
break;
} // if: error occurred moving to the next value
TW32( sc );
goto MakeHr;
} // for:
goto Cleanup;
MakeHr:
hr = HRESULT_FROM_WIN32( sc );
Cleanup:
HRETURN( hr );
} //*** CEnumPhysicalDisks::HrGetClusterDiskInfo
/////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks:HrSetThisDiskToBeManaged
//
// Description:
//
//
// Arguments:
//
//
// Return Value:
// S_OK
// Success.
//
// Win32 Error
// something failed.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CEnumPhysicalDisks::HrSetThisDiskToBeManaged(
ULONG ulSCSITidIn
, ULONG ulSCSILunIn
, BOOL fIsQuorumIn
, BSTR bstrResourceNameIn
, DWORD dwSignatureIn
)
{
TraceFunc( "" );
HRESULT hr = S_OK;
ULONG idx;
IUnknown * punk = NULL;
IClusCfgManagedResourceInfo * piccmri = NULL;
WCHAR sz[ 64 ];
BSTR bstrUID = NULL;
DWORD dwSignature;
IClusCfgPhysicalDiskProperties * piccpdp = NULL;
_snwprintf( sz, ARRAYSIZE( sz ), L"SCSI Tid %ld, SCSI Lun %ld", ulSCSITidIn, ulSCSILunIn );
//
// KB: 15-JUN-2000 GalenB
//
// Find the disk that has the passes in TID and Lun and set it
// to be managed.
//
for ( idx = 0; idx < m_idxNext; idx++ )
{
punk = (*m_prgDisks)[ idx ]; // don't ref
if ( punk != NULL )
{
hr = THR( punk->TypeSafeQI( IClusCfgManagedResourceInfo, &piccmri ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( piccmri->GetUID( &bstrUID ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
TraceMemoryAddBSTR( bstrUID );
if ( _wcsicmp( bstrUID, sz ) == 0 )
{
hr = THR( piccmri->TypeSafeQI( IClusCfgPhysicalDiskProperties, &piccpdp ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( piccpdp->HrGetSignature( &dwSignature ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( piccpdp->HrSetFriendlyName( bstrResourceNameIn ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
piccpdp->Release();
piccpdp = NULL;
//
// May want to do more with this later...
//
Assert( dwSignatureIn == dwSignature );
hr = THR( piccmri->SetManaged( TRUE ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( piccmri->SetQuorumedDevice( fIsQuorumIn ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
break;
} // if:
TraceSysFreeString( bstrUID );
bstrUID = NULL;
piccmri->Release();
piccmri = NULL;
} // if:
} // for:
Cleanup:
if ( piccpdp != NULL )
{
piccpdp->Release();
} // if:
if ( piccmri != NULL )
{
piccmri->Release();
} // if:
TraceSysFreeString( bstrUID );
HRETURN( hr );
} //*** CEnumPhysicalDisks::HrSetThisDiskToBeManaged
/////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks:HrFindDiskWithLogicalDisk
//
// Description:
// Find the disk with the passed in logical disk ID.
//
// Arguments:
// None.
//
// Return Value:
// S_OK
// Success. Found the disk.
//
// S_FALSE
// Success. Did not find the disk.
//
// Win32 Error
// something failed.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CEnumPhysicalDisks::HrFindDiskWithLogicalDisk(
WCHAR cLogicalDiskIn,
ULONG * pidxDiskOut
)
{
TraceFunc( "" );
Assert( pidxDiskOut != NULL );
HRESULT hr = S_OK;
IClusCfgPhysicalDiskProperties * piccpdp = NULL;
ULONG idx;
bool fFoundIt = false;
IUnknown * punk;
for ( idx = 0; idx < m_idxNext; idx++ )
{
punk = (*m_prgDisks)[ idx ]; // don't ref
if ( punk != NULL )
{
hr = THR( punk->TypeSafeQI( IClusCfgPhysicalDiskProperties, &piccpdp ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = STHR( piccpdp->IsThisLogicalDisk( cLogicalDiskIn ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
if ( hr == S_OK )
{
fFoundIt = true;
break;
} // if:
piccpdp->Release();
piccpdp = NULL;
} // if:
} // for:
if ( !fFoundIt )
{
hr = S_FALSE;
} // if:
if ( pidxDiskOut != NULL )
{
*pidxDiskOut = idx;
} // if:
Cleanup:
if ( piccpdp != NULL )
{
piccpdp->Release();
} // if:
HRETURN( hr );
} //*** CEnumPhysicalDisks::HrFindDiskWithLogicalDisk
/////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks:HrGetSCSIInfo
//
// Description:
// Get the SCSI info for the disk at the passed in index.
//
// Arguments:
// None.
//
// Return Value:
// S_OK
// Success.
//
// Win32 Error
// something failed.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CEnumPhysicalDisks::HrGetSCSIInfo(
ULONG idxDiskIn,
ULONG * pulSCSIBusOut,
ULONG * pulSCSIPortOut
)
{
TraceFunc( "" );
Assert( pulSCSIBusOut != NULL );
Assert( pulSCSIPortOut != NULL );
HRESULT hr = S_OK;
IClusCfgPhysicalDiskProperties * piccpdp = NULL;
hr = THR( ((*m_prgDisks)[ idxDiskIn ])->TypeSafeQI( IClusCfgPhysicalDiskProperties, &piccpdp ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( piccpdp->HrGetSCSIBus( pulSCSIBusOut ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( piccpdp->HrGetSCSIPort( pulSCSIPortOut ) );
Cleanup:
if ( piccpdp != NULL )
{
piccpdp->Release();
} // if:
HRETURN( hr );
} //*** CEnumPhysicalDisks::HrGetSCSIInfo
/////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks:HrPruneDisks
//
// Description:
// Get the SCSI info for the disk at the passed in index.
//
// Arguments:
// None.
//
// Return Value:
// S_OK
// Success.
//
// Win32 Error
// something failed.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CEnumPhysicalDisks::HrPruneDisks(
ULONG ulSCSIBusIn
, ULONG ulSCSIPortIn
, ULONG * pulRemovedOut
, int nMsgId
)
{
TraceFunc( "" );
Assert( pulRemovedOut != NULL );
HRESULT hr = S_OK;
IClusCfgPhysicalDiskProperties * piccpdp = NULL;
ULONG idx;
IUnknown * punk;
ULONG ulSCSIBus;
ULONG ulSCSIPort;
ULONG cRemoved = 0;
for ( idx = 0; idx < m_idxNext; idx++ )
{
punk = (*m_prgDisks)[ idx ]; // don't ref
if ( punk != NULL )
{
hr = THR( punk->TypeSafeQI( IClusCfgPhysicalDiskProperties, &piccpdp ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( piccpdp->HrGetSCSIBus( &ulSCSIBus ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( piccpdp->HrGetSCSIPort( &ulSCSIPort ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
if ( ( ulSCSIBusIn == ulSCSIBus ) && ( ulSCSIPortIn == ulSCSIPort ) )
{
BSTR bstr = NULL;
IClusCfgManagedResourceInfo * piccmri = NULL;
LogPrunedDisk( punk, ulSCSIBusIn, ulSCSIPortIn );
THR( ((*m_prgDisks)[ idx ])->TypeSafeQI( IClusCfgManagedResourceInfo, &piccmri ) );
THR( piccmri->GetName( &bstr ) );
if ( piccmri != NULL )
{
piccmri->Release();
} // if:
TraceMemoryAddBSTR( bstr );
STATUS_REPORT_STRING( TASKID_Major_Find_Devices, TASKID_Minor_Pruned_Disk_From_Bus, nMsgId, bstr != NULL ? bstr : L"????", hr );
RemoveDiskFromArray( idx );
cRemoved++;
TraceSysFreeString( bstr );
} // if:
piccpdp->Release();
piccpdp = NULL;
} // if:
} // for:
if ( pulRemovedOut != NULL )
{
*pulRemovedOut = cRemoved;
} // if:
Cleanup:
if ( piccpdp != NULL )
{
piccpdp->Release();
} // if:
HRETURN( hr );
} //*** CEnumPhysicalDisks::HrPruneDisks
/////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks:LogPrunedDisk
//
// Description:
// Get the SCSI info for the disk at the passed in index.
//
// Arguments:
// None.
//
// Return Value:
// S_OK
// Success.
//
// Win32 Error
// something failed.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
void
CEnumPhysicalDisks::LogPrunedDisk(
IUnknown * punkIn,
ULONG ulSCSIBusIn,
ULONG ulSCSIPortIn
)
{
TraceFunc( "" );
Assert( punkIn != NULL );
HRESULT hr = S_OK;
IClusCfgManagedResourceInfo * piccmri = NULL;
IClusCfgPhysicalDiskProperties * piccpdp = NULL;
BSTR bstrName = NULL;
BSTR bstrUID = NULL;
BSTR bstr = NULL;
hr = THR( punkIn->TypeSafeQI( IClusCfgManagedResourceInfo, &piccmri ) );
if ( SUCCEEDED( hr ) )
{
hr = THR( piccmri->GetUID( &bstrUID ) );
piccmri->Release();
} // if:
if ( FAILED( hr ) )
{
bstrUID = TraceSysAllocString( L"<Unknown>" );
} // if:
else
{
TraceMemoryAddBSTR( bstrUID );
} // else:
hr = THR( punkIn->TypeSafeQI( IClusCfgPhysicalDiskProperties, &piccpdp ) );
if ( SUCCEEDED( hr ) )
{
hr = THR( piccpdp->HrGetDeviceID( &bstrName ) );
piccpdp->Release();
} // if:
if ( FAILED( hr ) )
{
bstrName = TraceSysAllocString( L"<Unknown>" );
} // if:
hr = THR( HrFormatStringIntoBSTR(
L"Pruning SCSI disk '%1!ws!', on Bus '%2!d!' and Port '%3!d!'; at '%4!ws!'"
, &bstr
, bstrName
, ulSCSIBusIn
, ulSCSIPortIn
, bstrUID
) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
LOG_STATUS_REPORT( bstr, hr );
Cleanup:
TraceSysFreeString( bstrName );
TraceSysFreeString( bstrUID );
TraceSysFreeString( bstr );
TraceFuncExit();
} //*** CEnumPhysicalDisks::LogPrunedDisk
/////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks:HrIsLogicalDiskNTFS
//
// Description:
// Is the passed in logical disk NTFS?
//
// Arguments:
// bstrLogicalDiskIn
//
// Return Value:
// S_OK
// The disk is NTFS.
//
// S_FALSE
// The disk is not NTFS.
//
// Win32 Error
// something failed.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CEnumPhysicalDisks::HrIsLogicalDiskNTFS( BSTR bstrLogicalDiskIn )
{
TraceFunc1( "bstrLogicalDiskIn = '%ls'", bstrLogicalDiskIn == NULL ? L"<null>" : bstrLogicalDiskIn );
Assert( bstrLogicalDiskIn != NULL );
HRESULT hr = S_OK;
IWbemClassObject * pLogicalDisk = NULL;
BSTR bstrPath = NULL;
WCHAR sz[ 64 ];
VARIANT var;
size_t cch;
VariantInit( &var );
cch = wcslen( bstrLogicalDiskIn );
if ( cch > 3 )
{
hr = THR( E_INVALIDARG );
STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_HrIsLogicalDiskNTFS_InvalidArg, IDS_ERROR_INVALIDARG, hr );
goto Cleanup;
} // if:
//
// truncate off any trailing \'s
//
if ( bstrLogicalDiskIn[ cch - 1 ] == L'\\' )
{
bstrLogicalDiskIn[ cch - 1 ] = '\0';
} // if:
//
// If we got just the logical disk without the trailing colon...
//
if ( wcslen( bstrLogicalDiskIn ) == 1 )
{
_snwprintf( sz, ARRAYSIZE( sz ), L"Win32_LogicalDisk.DeviceID=\"%s:\"", bstrLogicalDiskIn );
} // if:
else
{
_snwprintf( sz, ARRAYSIZE( sz ), L"Win32_LogicalDisk.DeviceID=\"%s\"", bstrLogicalDiskIn );
} // else:
bstrPath = TraceSysAllocString( sz );
if ( bstrPath == NULL )
{
hr = THR( E_OUTOFMEMORY );
STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_HrIsLogicalDiskNTFS, IDS_ERROR_OUTOFMEMORY, hr );
} // if:
hr = THR( m_pIWbemServices->GetObject( bstrPath, WBEM_FLAG_RETURN_WBEM_COMPLETE, NULL, &pLogicalDisk, NULL ) );
if ( FAILED( hr ) )
{
STATUS_REPORT_STRING( TASKID_Major_Find_Devices, TASKID_Minor_WMI_Get_LogicalDisk_Failed, IDS_ERROR_WMI_GET_LOGICALDISK_FAILED, bstrLogicalDiskIn, hr );
goto Cleanup;
} // if:
hr = THR( HrGetWMIProperty( pLogicalDisk, L"FileSystem", VT_BSTR, &var ) );
if (FAILED( hr ) )
{
goto Cleanup;
} // if:
CharUpper( var.bstrVal );
if ( wcscmp( var.bstrVal, L"NTFS" ) != 0 )
{
hr = S_FALSE;
} // if:
Cleanup:
if ( pLogicalDisk != NULL )
{
pLogicalDisk->Release();
} // if:
VariantClear( &var );
TraceSysFreeString( bstrPath );
HRETURN( hr );
} //*** CEnumPhysicalDisks::HrIsLogicalDiskNTFS
/////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks:HrLogDiskInfo
//
// Description:
// Write the info about this disk into the log.
//
// Arguments:
// pDiskIn
//
// Return Value:
// S_OK
//
// Win32 Error
// something failed.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CEnumPhysicalDisks::HrLogDiskInfo( IWbemClassObject * pDiskIn )
{
TraceFunc( "" );
Assert( pDiskIn != NULL );
HRESULT hr = S_OK;
VARIANT varDeviceID;
VARIANT varSCSIBus;
VARIANT varSCSIPort;
VARIANT varSCSILun;
VARIANT varSCSITid;
BSTR bstr = NULL;
VariantInit( &varDeviceID );
VariantInit( &varSCSIBus );
VariantInit( &varSCSIPort );
VariantInit( &varSCSILun );
VariantInit( &varSCSITid );
hr = THR( HrGetWMIProperty( pDiskIn, L"DeviceID", VT_BSTR, &varDeviceID ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = STHR( IsDiskSCSI( pDiskIn ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
//
// Disk is SCSI...
//
if ( hr == S_OK )
{
hr = THR( HrGetWMIProperty( pDiskIn, L"SCSIBus", VT_I4, &varSCSIBus ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( HrGetWMIProperty( pDiskIn, L"SCSITargetId", VT_I4, &varSCSITid ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( HrGetWMIProperty( pDiskIn, L"SCSILogicalUnit", VT_I4, &varSCSILun ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( HrGetWMIProperty( pDiskIn, L"SCSIPort", VT_I4, &varSCSIPort ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( HrFormatStringIntoBSTR(
L"Found SCSI disk '%1!ws!' on Bus '%2!d!' and Port '%3!d!'; at TID '%4!d!' and LUN '%5!d!'"
, &bstr
, varDeviceID.bstrVal
, varSCSIBus.iVal
, varSCSIPort.iVal
, varSCSITid.iVal
, varSCSILun.iVal
) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
LOG_STATUS_REPORT( bstr, hr );
} // if:
else
{
STATUS_REPORT_STRING( TASKID_Major_Find_Devices, TASKID_Minor_Found_Non_SCSI_Disk, IDS_ERROR_FOUND_NON_SCSI_DISK, varDeviceID.bstrVal, hr );
} // else:
Cleanup:
VariantClear( &varDeviceID );
VariantClear( &varSCSIBus );
VariantClear( &varSCSIPort );
VariantClear( &varSCSILun );
VariantClear( &varSCSITid );
TraceSysFreeString( bstr );
HRETURN( hr );
} //*** CEnumPhysicalDisks::HrLogDiskInfo
/////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks:HrFindDiskWithWMIDeviceID
//
// Description:
// Find the disk with the passed in WMI device ID.
//
// Arguments:
// None.
//
// Return Value:
// S_OK
// Success. Found the disk.
//
// S_FALSE
// Success. Did not find the disk.
//
// Win32 Error
// something failed.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CEnumPhysicalDisks::HrFindDiskWithWMIDeviceID(
BSTR bstrWMIDeviceIDIn,
ULONG * pidxDiskOut
)
{
TraceFunc( "" );
Assert( pidxDiskOut != NULL );
HRESULT hr = S_OK;
IClusCfgPhysicalDiskProperties * piccpdp = NULL;
ULONG idx;
bool fFoundIt = false;
IUnknown * punk;
BSTR bstrDeviceID = NULL;
for ( idx = 0; idx < m_idxNext; idx++ )
{
punk = (*m_prgDisks)[ idx ]; // don't ref
if ( punk != NULL )
{
hr = THR( punk->TypeSafeQI( IClusCfgPhysicalDiskProperties, &piccpdp ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = STHR( piccpdp->HrGetDeviceID( &bstrDeviceID ) );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
if ( wcscmp( bstrWMIDeviceIDIn, bstrDeviceID ) == 0 )
{
fFoundIt = true;
break;
} // if:
piccpdp->Release();
piccpdp = NULL;
TraceSysFreeString( bstrDeviceID );
bstrDeviceID = NULL;
} // if:
} // for:
if ( !fFoundIt )
{
hr = S_FALSE;
} // if:
if ( pidxDiskOut != NULL )
{
*pidxDiskOut = idx;
} // if:
Cleanup:
if ( piccpdp != NULL )
{
piccpdp->Release();
} // if:
TraceSysFreeString( bstrDeviceID );
HRETURN( hr );
} //*** CEnumPhysicalDisks::HrFindDiskWithWMIDeviceID
/////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks:HrIsSystemBusManaged
//
// Description:
// Is the system bus managed by the cluster service?
//
// Arguments:
// None.
//
// Return Value:
// S_OK
// Success. The system bus is managed.
//
// S_FALSE
// Success. The system bus is not managed.
//
// Win32 Error
// something failed.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CEnumPhysicalDisks::HrIsSystemBusManaged( void )
{
TraceFunc( "" );
HRESULT hr = S_FALSE;
DWORD sc;
HKEY hKey = NULL;
DWORD dwData;
DWORD cbData = sizeof( dwData );
sc = RegOpenKeyEx( HKEY_LOCAL_MACHINE, L"SYSTEM\\CURRENTCONTROLSET\\SERVICES\\ClusSvc\\Parameters", 0, KEY_READ, &hKey );
if ( sc == ERROR_FILE_NOT_FOUND )
{
goto Cleanup; // not yet a cluster node. Return S_FALSE.
} // if:
if ( sc != ERROR_SUCCESS )
{
TW32( sc );
LogMsg( L"[SRV] RegOpenKeyEx() failed. (hr = %#08x)", hr );
goto Win32Error;
} // if:
sc = RegQueryValueEx( hKey, L"ManageDisksOnSystemBuses", NULL, NULL, (LPBYTE) &dwData, &cbData );
if ( sc == ERROR_FILE_NOT_FOUND )
{
goto Cleanup; // value not found. Return S_FALSE.
} // if:
if ( sc != ERROR_SUCCESS )
{
TW32( sc );
LogMsg( L"[SRV] RegQueryValueEx() failed. (hr = %#08x)", hr );
goto Win32Error;
} // if:
if ( dwData > 0 )
{
hr = S_OK;
} // if:
goto Cleanup;
Win32Error:
hr = HRESULT_FROM_WIN32( sc );
Cleanup:
if ( hKey != NULL )
{
RegCloseKey( hKey );
} // if:
HRETURN( hr );
} //*** CEnumPhysicalDisks::HrIsSystemBusManaged
/////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks:HrGetClusterProperties
//
// Description:
// Return the asked for cluster properties.
//
// Arguments:
//
//
// Return Value:
// S_OK
// Success.
//
// Win32 Error
// something failed.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CEnumPhysicalDisks::HrGetClusterProperties(
HRESOURCE hResourceIn
, BSTR * pbstrResourceNameOut
)
{
TraceFunc( "" );
Assert( pbstrResourceNameOut != NULL );
HRESULT hr = S_OK;
CClusPropList cpl;
CLUSPROP_BUFFER_HELPER cpbh;
DWORD sc;
sc = TW32( cpl.ScGetResourceProperties( hResourceIn, CLUSCTL_RESOURCE_GET_RO_COMMON_PROPERTIES ) );
if ( sc != ERROR_SUCCESS )
{
goto MakeHr;
} // if:
sc = TW32( cpl.ScMoveToPropertyByName( L"Name" ) );
if ( sc != ERROR_SUCCESS )
{
goto MakeHr;
} // if:
cpbh = cpl.CbhCurrentValue();
Assert( cpbh.pSyntax->dw == CLUSPROP_SYNTAX_LIST_VALUE_SZ );
if ( ( cpbh.pStringValue->sz != NULL ) && ( wcscmp( cpbh.pStringValue->sz, L"" ) != 0 ) )
{
*pbstrResourceNameOut = TraceSysAllocString( cpbh.pStringValue->sz );
if ( *pbstrResourceNameOut == NULL )
{
hr = THR( E_OUTOFMEMORY );
goto Cleanup;
} // if:
} // if:
else
{
hr = THR( E_UNEXPECTED );
LOG_STATUS_REPORT( L"The name of a physical disk resource was empty!", hr );
} // else:
goto Cleanup;
MakeHr:
hr = HRESULT_FROM_WIN32( sc );
Cleanup:
HRETURN( hr );
} //*** CEnumPhysicalDisks::HrGetClusterProperties
/////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks::RemoveDiskFromArray
//
// Description:
// Release the disk at the specified index in the array and decrease the disk count.
//
// Arguments:
// idxDiskIn - the index of the disk to remove; must be less than the array size.
//
// Return Value:
// None.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
void
CEnumPhysicalDisks::RemoveDiskFromArray( ULONG idxDiskIn )
{
TraceFunc( "" );
Assert( idxDiskIn < m_idxNext );
((*m_prgDisks)[ idxDiskIn ])->Release();
(*m_prgDisks)[ idxDiskIn ] = NULL;
m_cDiskCount -= 1;
TraceFuncExit();
} //*** CEnumPhysicalDisks::RemoveDiskFromArray
/////////////////////////////////////////////////////////////////////////////
//++
//
// CEnumPhysicalDisks::HrLoadEnum
//
// Description:
// Load the enum and filter out any devices that don't belong.
//
// Arguments:
// None.
//
// Return Value:
// S_OK
// Success.
//
// Other HRESULT errors.
//
// Remarks:
// None.
//
//--
//////////////////////////////////////////////////////////////////////////////
HRESULT
CEnumPhysicalDisks::HrLoadEnum( void )
{
TraceFunc( "" );
HRESULT hr = S_OK;
hr = THR( HrGetDisks() );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = THR( HrPruneSystemDisks() );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
hr = STHR( HrIsNodeClustered() );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
if ( hr == S_OK )
{
hr = THR( HrFixupDisks() );
if ( FAILED( hr ) )
{
goto Cleanup;
} // if:
} // if:
hr = S_OK; // could have been S_FALSE
Cleanup:
HRETURN( hr );
} //*** CEnumPysicalDisks::HrLoadEnum