///////////////////////////////////////////////////////////////////////////// // // Copyright (c) 1999-2002 Microsoft Corporation // // Module Name: // ClusDisk.cpp // // Description: // Implementation of the cluster disk class for the MSCLUS // automation classes. // // Author: // Galen Barbee (galenb) 11-Feb-1999 // // Revision History: // // Notes: // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #if CLUSAPI_VERSION >= 0x0500 #include #else #include "PropList.h" #endif // CLUSAPI_VERSION >= 0x0500 #include "ClusDisk.h" ///////////////////////////////////////////////////////////////////////////// // Global variables ///////////////////////////////////////////////////////////////////////////// static const IID * iidCClusDisk[] = { &IID_ISClusDisk }; static const IID * iidCClusDisks[] = { &IID_ISClusDisks }; static const IID * iidCClusScsiAddress[] = { &IID_ISClusScsiAddress }; //*************************************************************************// ///////////////////////////////////////////////////////////////////////////// // CClusDisk class ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// //++ // // CClusDisk::CClusDisk // // Description: // Constructor. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// CClusDisk::CClusDisk( void ) { m_pPartitions = NULL; m_dwSignature = 0; m_dwDiskNumber = 0; m_piids = (const IID *) iidCClusDisk; m_piidsSize = ARRAYSIZE( iidCClusDisk ); } //*** CClusDisk::CClusDisk() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusDisk::~CClusDisk // // Description: // Destructor. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// CClusDisk::~CClusDisk( void ) { if ( m_pPartitions != NULL ) { m_pPartitions->Release(); } // if: } //*** CClusDisk::~CClusDisk() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusDisk::Create // // Description: // Finish creating this object. This method get the value list from // the passed in physical disk resource handle. // // Arguments: // hResource [IN] - Handle to the physical disk resource. // // Return Value: // S_OK if successful, or Win32 error wrapped in HRESULT. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusDisk::Create( IN HRESOURCE hResource ) { HRESULT _hr = E_POINTER; DWORD _sc = ERROR_SUCCESS; CClusPropValueList _cpvl; _sc = _cpvl.ScGetResourceValueList( hResource, CLUSCTL_RESOURCE_STORAGE_GET_DISK_INFO ); _hr = HRESULT_FROM_WIN32( _sc ); if ( SUCCEEDED( _hr ) ) { _sc = _cpvl.ScMoveToFirstValue(); _hr = HRESULT_FROM_WIN32( _sc ); if ( SUCCEEDED( _hr ) ) { CLUSPROP_BUFFER_HELPER _cbhValue = { NULL }; CComObject< CClusPartitions > * pPartitions = NULL; if ( m_pPartitions != NULL ) { m_pPartitions->Release(); m_pPartitions = NULL; } // if: clean up any old partitions collection _hr = CComObject< CClusPartitions >::CreateInstance( &pPartitions ); if ( SUCCEEDED( _hr ) ) { CSmartPtr< CComObject< CClusPartitions > > ptrPartitions( pPartitions ); m_pPartitions = ptrPartitions; ptrPartitions->AddRef(); do { _cbhValue = _cpvl; switch ( _cbhValue.pSyntax->dw ) { case CLUSPROP_SYNTAX_PARTITION_INFO : { _hr = ptrPartitions->HrCreateItem( _cbhValue.pPartitionInfoValue ); break; } // case: CLUSPROP_SYNTAX_PARTITION_INFO case CLUSPROP_SYNTAX_DISK_SIGNATURE : { m_dwSignature = _cbhValue.pDiskSignatureValue->dw; break; } // case: CLUSPROP_SYNTAX_DISK_SIGNATURE case CLUSPROP_SYNTAX_SCSI_ADDRESS : { m_csaScsiAddress.dw = _cbhValue.pScsiAddressValue->dw; break; } // case: CLUSPROP_SYNTAX_SCSI_ADDRESS case CLUSPROP_SYNTAX_DISK_NUMBER : { m_dwDiskNumber = _cbhValue.pDiskNumberValue->dw; break; } // case: CLUSPROP_SYNTAX_DISK_NUMBER } // switch: // // Move to the next value. // _sc = _cpvl.ScMoveToNextValue(); if ( _sc == ERROR_NO_MORE_ITEMS ) { _hr = S_OK; break; } // if: error occurred moving to the next value _hr = HRESULT_FROM_WIN32( _sc ); } while ( SUCCEEDED( _hr ) ); // do-while: there are no errors } // if: created the partition collection } // if: move to first value ok } // if: get the value list ok return _hr; } //*** CClusDisk::Create() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusDisk::HrCreate // // Description: // Finish creating this object. This method parses a passed in value // list to get the values for the physical disk object. // // Arguments: // rcpvl [IN OUT] - Value list to parse. // pbEndFound [OUT] - Did find the end of the value list? // // Return Value: // S_OK, or Win32 error code wrapped in an HRESULT. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusDisk::HrCreate( IN OUT CClusPropValueList & rcpvl, OUT BOOL * pbEndFound ) { DWORD _sc = ERROR_SUCCESS; CLUSPROP_BUFFER_HELPER _cbhValue = { NULL }; CComObject< CClusPartitions > * pPartitions = NULL; HRESULT _hr = S_FALSE; if ( m_pPartitions != NULL ) { m_pPartitions->Release(); m_pPartitions = NULL; } // if: clean up any old partitions collection _hr = CComObject< CClusPartitions >::CreateInstance( &pPartitions ); if ( SUCCEEDED( _hr ) ) { CSmartPtr< CComObject< CClusPartitions > > ptrPartitions( pPartitions ); m_pPartitions = ptrPartitions; ptrPartitions->AddRef(); _cbhValue = rcpvl; do { switch ( _cbhValue.pSyntax->dw ) { case CLUSPROP_SYNTAX_DISK_SIGNATURE : { m_dwSignature = _cbhValue.pDiskSignatureValue->dw; break; } // case: CLUSPROP_SYNTAX_DISK_SIGNATURE case CLUSPROP_SYNTAX_PARTITION_INFO : { _hr = ptrPartitions->HrCreateItem( _cbhValue.pPartitionInfoValue ); break; } // case: CLUSPROP_SYNTAX_PARTITION_INFO case CLUSPROP_SYNTAX_SCSI_ADDRESS : { m_csaScsiAddress.dw = _cbhValue.pScsiAddressValue->dw; break; } // case: CLUSPROP_SYNTAX_SCSI_ADDRESS case CLUSPROP_SYNTAX_DISK_NUMBER : { m_dwDiskNumber = _cbhValue.pDiskNumberValue->dw; break; } // case: CLUSPROP_SYNTAX_DISK_NUMBER } // switch: // // Move to the next value. // _sc = rcpvl.ScMoveToNextValue(); if ( _sc == ERROR_NO_MORE_ITEMS ) { _hr = S_OK; *pbEndFound = TRUE; break; } // if: error occurred moving to the next value _cbhValue = rcpvl; if ( _cbhValue.pSyntax->dw == CLUSPROP_SYNTAX_DISK_SIGNATURE ) { _hr = HRESULT_FROM_WIN32( _sc ); break; } // if: exit if another signature is found before the end of the list is seen _hr = HRESULT_FROM_WIN32( _sc ); } while ( SUCCEEDED( _hr ) ); // do-while: there are no errors } // if: the patitions collection can be created return _hr; } //*** CClusDisk::HrCreate() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusDisk::get_Signature // // Description: // Get the disk signature. // // Arguments: // plSignature [OUT] - catches the signature. // // Return Value: // S_OK if successful, or E_POINTER // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusDisk::get_Signature( OUT long * plSignature ) { //ASSERT( plSignature != NULL ); HRESULT _hr = E_POINTER; if ( plSignature != NULL ) { *plSignature = static_cast< long >( m_dwSignature ); _hr = S_OK; } return _hr; } //*** CClusDisk::get_Signature() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusDisk::get_ScsiAddress // // Description: // Get the disk's SCSI address. // // Arguments: // ppScsiAddress [OUT] - catches the SCSI address.. // // Return Value: // S_OK if successful, or E_POINTER // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusDisk::get_ScsiAddress( OUT ISClusScsiAddress ** ppScsiAddress ) { //ASSERT( ppScsiAddress != NULL ); HRESULT _hr = E_POINTER; if ( ppScsiAddress != NULL ) { CComObject< CClusScsiAddress > * _pScsiAddress = NULL; _hr = CComObject< CClusScsiAddress >::CreateInstance( &_pScsiAddress ); if ( SUCCEEDED( _hr ) ) { CSmartPtr< CComObject< CClusScsiAddress > > _ptrScsiAddress( _pScsiAddress ); _hr = _ptrScsiAddress->Create( m_csaScsiAddress ); if ( SUCCEEDED( _hr ) ) { _hr = _ptrScsiAddress->QueryInterface( IID_ISClusScsiAddress, (void **) ppScsiAddress ); } // if: } // if: } // if: return _hr; } //*** CClusDisk::get_ScsiAddress() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusDisk::get_DiskNumber // // Description: // Get the disk number. // // Arguments: // plDiskNumber [OUT] - catches the disk number. // // Return Value: // S_OK if successful, or E_POINTER // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusDisk::get_DiskNumber( OUT long * plDiskNumber ) { //ASSERT( plDiskNumber != NULL ); HRESULT _hr = E_POINTER; if ( plDiskNumber != NULL ) { *plDiskNumber = static_cast< long >( m_dwDiskNumber ); _hr = S_OK; } return _hr; } //*** CClusDisk::get_DiskNumber() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusDisk::get_Partitions // // Description: // Get the disk partitions. // // Arguments: // ppPartitions [OUT] - catches the partitions collection. // // Return Value: // S_OK if successful, or E_POINTER // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusDisk::get_Partitions( OUT ISClusPartitions ** ppPartitions ) { //ASSERT( ppPartitions != NULL ); ASSERT( m_pPartitions != NULL ); HRESULT _hr = E_POINTER; if ( ppPartitions != NULL ) { if ( ppPartitions != NULL ) { _hr = m_pPartitions->QueryInterface( IID_ISClusPartitions, (void **) ppPartitions ); } // if: } // if: return _hr; } //*** CClusDisk::get_Partitions() //*************************************************************************// ///////////////////////////////////////////////////////////////////////////// // CClusDisks class ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// //++ // // CClusDisks::CClusDisks // // Description: // Constructor. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// CClusDisks::CClusDisks( void ) { m_pClusRefObject = NULL; m_piids = (const IID *) iidCClusDisks; m_piidsSize = ARRAYSIZE( iidCClusDisks ); } //*** CClusDisks::CClusDisks() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusDisks::~CClusDisks // // Description: // Destructor. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// CClusDisks::~CClusDisks( void ) { Clear(); if ( m_pClusRefObject != NULL ) { m_pClusRefObject->Release(); m_pClusRefObject = NULL; } // if: do we have a pointer to the cluster handle wrapper? } //*** CClusDisks::~CClusDisks() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusDisks::Create // // Description: // Complete the heavy weight construction, // // Arguments: // rpvl [IN] - Property value list. // // Return Value: // E_NOTIMPL // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusDisks::Create( IN const CClusPropValueList &rpvl ) { HRESULT _hr = E_NOTIMPL; return _hr; } //*** CClusDisks::Create() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusDisks::GetIndex // // Description: // Convert the passed in 1 based index into a 0 based index. // // Arguments: // varIndex [IN] - holds the 1 based index. // pnIndex [OUT] - catches the 0 based index. // // Return Value: // S_OK if successful, E_POINTER, or E_INVALIDARG if out of range. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusDisks::GetIndex( IN VARIANT varIndex, OUT UINT * pnIndex ) { //ASSERT( pnIndex != NULL ); HRESULT _hr = E_POINTER; if ( pnIndex != NULL ) { CComVariant v; UINT nIndex = 0; *pnIndex = 0; v.Copy( &varIndex ); // Check to see if the index is a number. _hr = v.ChangeType( VT_I4 ); if ( SUCCEEDED( _hr ) ) { nIndex = v.lVal; nIndex--; // Adjust index to be 0 relative instead of 1 relative if ( nIndex < m_dvDisks.size() ) { *pnIndex = nIndex; } else { _hr = E_INVALIDARG; } } } return _hr; } //*** CClusDisks::GetIndex() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusDisks::get_Count // // Description: // Get the count of objects in the collection. // // Arguments: // plCount [OUT] - Catches the count. // // Return Value: // S_OK if successful or E_POINTER. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusDisks::get_Count( OUT long * plCount ) { //ASSERT( plCount != NULL ); HRESULT _hr = E_POINTER; if ( plCount != NULL ) { *plCount = m_dvDisks.size(); _hr = S_OK; } return _hr; } //*** CClusDisks::get_Count() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusDisks::Clear // // Description: // Empty the vector of disks. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CClusDisks::Clear( void ) { ::ReleaseAndEmptyCollection< DiskVector, CComObject< CClusDisk > >( m_dvDisks ); } //*** CClusDisks::Clear() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusDisks::get_Item // // Description: // Get the item (disk) at the passed in index. // // Arguments: // varIndex [IN] - Contains the index requested. // ppbstrRegistryKey [OUT] - Catches the key. // // Return Value: // S_OK if successful, E_POINTER, or other HRESULT error. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusDisks::get_Item( IN VARIANT varIndex, OUT ISClusDisk ** ppDisk ) { //ASSERT( ppDisk != NULL ); HRESULT _hr = E_POINTER; if ( ppDisk != NULL ) { CComObject< CClusDisk > * pDisk = NULL; // Zero the out param *ppDisk = NULL; UINT nIndex = 0; _hr = GetIndex( varIndex, &nIndex ); if ( SUCCEEDED( _hr ) ) { pDisk = m_dvDisks[ nIndex ]; _hr = pDisk->QueryInterface( IID_ISClusDisk, (void **) ppDisk ); } } return _hr; } //*** CClusDisks::get_Item() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusDisks::get__NewEnum // // Description: // Create and return a new enumeration for this collection. // // Arguments: // ppunk [OUT] - Catches the new enumeration. // // Return Value: // S_OK if successful, E_POINTER, or other HRESULT error. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusDisks::get__NewEnum( OUT IUnknown ** ppunk ) { return ::HrNewIDispatchEnum< DiskVector, CComObject< CClusDisk > >( ppunk, m_dvDisks ); } //*** CClusDisks::get__NewEnum() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusDisks::Create // // Description: // Finish creating the object by doing things that cannot be done in // a light weight constructor. // // Arguments: // pClusRefObject [IN] - Wraps the cluster handle. // bstrResTypeName [IN] - The resource type this collection is for. // // Return Value: // S_OK if successful, or E_POINTER if not. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusDisks::Create( IN ISClusRefObject * pClusRefObject, IN BSTR bstrResTypeName ) { ASSERT( pClusRefObject != NULL ); HRESULT _hr = E_POINTER; if ( pClusRefObject != NULL ) { m_pClusRefObject = pClusRefObject; m_pClusRefObject->AddRef(); m_bstrResTypeName = bstrResTypeName; _hr = S_OK; } return _hr; } //*** CClusDisks::Create() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusDisks::Refresh // // Description: // Load the collection from the cluster database. // // Arguments: // None. // // Return Value: // S_OK if successful, or Win32 error as HRESULT if not. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusDisks::Refresh( void ) { HRESULT _hr = S_OK; DWORD _sc = ERROR_SUCCESS; HCLUSTER _hCluster = NULL; BOOL _bEndFound = FALSE; _hr = m_pClusRefObject->get_Handle( (ULONG_PTR *) &_hCluster ); if ( SUCCEEDED( _hr ) ) { CClusPropValueList _cpvl; _sc = _cpvl.ScGetResourceTypeValueList( _hCluster, m_bstrResTypeName, CLUSCTL_RESOURCE_TYPE_STORAGE_GET_AVAILABLE_DISKS ); _hr = HRESULT_FROM_WIN32( _sc ); if ( SUCCEEDED( _hr ) ) { Clear(); _sc = _cpvl.ScMoveToFirstValue(); _hr = HRESULT_FROM_WIN32( _sc ); if ( SUCCEEDED( _hr ) ) { CLUSPROP_BUFFER_HELPER _cbhValue = { NULL }; do { _cbhValue = _cpvl; if ( _cbhValue.pSyntax->dw == CLUSPROP_SYNTAX_DISK_SIGNATURE ) { _hr = HrCreateDisk( _cpvl, &_bEndFound ); } // if: value list MUST start with signature! } while ( ! _bEndFound ); // do-while: there are values in the list } // if: we moved to the first value } // if: the value list of available disks was retrieved } // if: we have a cluster handle return _hr; } //*** CClusDisks::Refresh() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusDisks::HrCreateDisk // // Description: // Create a CClusDisk object from the passed in value list and add it // to the collection. This method assumes that the value list's curent // value is the disk signature. // // Arguments: // rcpvl [IN OUT] - The value list to parse. // pbEndFound [IN] - Catches the end of list state. // // Return Value: // S_OK, if successful, Win32 error code wrapped in an HRESULT. // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusDisks::HrCreateDisk( IN OUT CClusPropValueList & rcpvl, OUT BOOL * pbEndFound ) { CComObject< CClusDisk > * _pDisk = NULL; HRESULT _hr = S_FALSE; _hr = CComObject< CClusDisk >::CreateInstance( &_pDisk ); if ( SUCCEEDED( _hr ) ) { CSmartPtr< CComObject< CClusDisk > > _ptrDisk( _pDisk ); _hr = _ptrDisk->HrCreate( rcpvl, pbEndFound ); if ( SUCCEEDED( _hr ) ) { m_dvDisks.insert( m_dvDisks.end(), _pDisk ); _ptrDisk->AddRef(); } // if: } // if: return _hr; } //*** CClusDisks::HrCreateDisk() //*************************************************************************// ///////////////////////////////////////////////////////////////////////////// // CClusScsiAddress class ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// //++ // // CClusScsiAddress::CClusScsiAddress // // Description: // Constructor. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// CClusScsiAddress::CClusScsiAddress( void ) { m_piids = (const IID *) iidCClusScsiAddress; m_piidsSize = ARRAYSIZE( iidCClusScsiAddress ); } //*** CClusScsiAddress::CClusScsiAddress() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusScsiAddress::Create // // Description: // Finish creating this object. // // Arguments: // pcpi [IN] - points to the CLUS_PARTITION_INFO struct. // // Return Value: // S_OK if successful, or E_POINTER // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CClusScsiAddress::Create( IN const CLUS_SCSI_ADDRESS & rcsa ) { m_csa = rcsa; return S_OK; } //*** CClusScsiAddress::Create() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusScsiAddress::get_PortNumber // // Description: // Get the disk's port number. // // Arguments: // pvarPortNumber [OUT] - catches the port number. // // Return Value: // S_OK if successful, or E_POINTER // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusScsiAddress::get_PortNumber( OUT VARIANT * pvarPortNumber ) { //ASSERT( pvarPortNumber != NULL ); HRESULT _hr = E_POINTER; if ( pvarPortNumber != NULL ) { pvarPortNumber->bVal = m_csa.PortNumber; pvarPortNumber->vt = VT_UI1; _hr = S_OK; } return _hr; } //*** CClusScsiAddress::get_PortNumber() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusScsiAddress::get_PathId // // Description: // Get the disk's path id. // // Arguments: // pvarPathId [OUT] - catches the path id. // // Return Value: // S_OK if successful, or E_POINTER // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusScsiAddress::get_PathId( OUT VARIANT * pvarPathId ) { //ASSERT( pvarPathId != NULL ); HRESULT _hr = E_POINTER; if ( pvarPathId != NULL ) { pvarPathId->bVal = m_csa.PathId; pvarPathId->vt = VT_UI1; _hr = S_OK; } return _hr; } //*** CClusScsiAddress::get_PathId() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusScsiAddress::get_TargetId // // Description: // Get the disk's target id. // // Arguments: // pvarTargetId [OUT] - catches the target id. // // Return Value: // S_OK if successful, or E_POINTER // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusScsiAddress::get_TargetId( OUT VARIANT * pvarTargetId ) { //ASSERT( pvarTargetId != NULL ); HRESULT _hr = E_POINTER; if ( pvarTargetId != NULL ) { pvarTargetId->bVal = m_csa.TargetId; pvarTargetId->vt = VT_UI1; _hr = S_OK; } return _hr; } //*** CClusScsiAddress::get_TargetId() ///////////////////////////////////////////////////////////////////////////// //++ // // CClusScsiAddress::get_Lun // // Description: // Get the disk's Lun. // // Arguments: // pvarLun [OUT] - catches the Lun. // // Return Value: // S_OK if successful, or E_POINTER // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CClusScsiAddress::get_Lun( OUT VARIANT * pvarLun ) { //ASSERT( pvarLun != NULL ); HRESULT _hr = E_POINTER; if ( pvarLun != NULL ) { pvarLun->bVal = m_csa.Lun; pvarLun->vt = VT_UI1; _hr = S_OK; } return _hr; } //*** CClusScsiAddress::get_Lun()