///////////////////////////////////////////////////////////////////////////// // // Copyright (c ) 1996-2000 Microsoft Corporation // // Module Name: // ClusItem.cpp // // Description: // Implementation of the CClusterItem class. // // Maintained By: // David Potter (davidp ) May 6, 1996 // // Revision History: // // Modified to fix bugs associated with open/close state of m_hkey. // m_hkey will be closed upon destruction of CClusterItem. // Roderick Sharper March 23, 1997. // // Notes: // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "CluAdmin.h" #include "ConstDef.h" #include "ClusItem.h" #include "ClusDoc.h" #include "ExcOper.h" #include "TraceTag.h" #include "TreeItem.inl" #include "PropList.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // Global Variables ///////////////////////////////////////////////////////////////////////////// #ifdef _DEBUG CTraceTag g_tagClusItemCreate( _T("Create"), _T("CLUSTER ITEM CREATE"), 0 ); CTraceTag g_tagClusItemDelete( _T("Delete"), _T("CLUSTER ITEM DELETE"), 0 ); CTraceTag g_tagClusItemNotify( _T("Notify"), _T("CLUSTER ITEM NOTIFY"), 0 ); #endif ///////////////////////////////////////////////////////////////////////////// // CClusterItemList ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItemList::PciFromName // // Routine Description: // Find a cluster item in the list by its name. // // Arguments: // pszName [IN] Name of item to look for. // ppos [OUT] Position of the item in the list. // // Return Value: // pci Cluster item corresponding the the specified name. // //-- ///////////////////////////////////////////////////////////////////////////// CClusterItem * CClusterItemList::PciFromName( IN LPCTSTR pszName, OUT POSITION * ppos // = NULL ) { POSITION posPci; POSITION posCurPci; CClusterItem * pci = NULL; ASSERT( pszName != NULL ); posPci = GetHeadPosition( ); while ( posPci != NULL ) { posCurPci = posPci; pci = GetNext( posPci ); ASSERT_VALID( pci ); if ( pci->StrName( ).CompareNoCase( pszName ) == 0 ) { if ( ppos != NULL ) { *ppos = posCurPci; } // if break; } // if: found a match pci = NULL; } // while: more resources in the list return pci; } //*** CClusterItemList::PciFromName( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItemList::RemoveAll // // Routine Description: // Remove all items from the list, decrementing the reference count // on each one first. // // Arguments: // None. // // Return Value: // None. // // Note: // This routine is not virtual, so calls to the base class will // not go through this routine. Also, it does not call the base // class method. // //-- ///////////////////////////////////////////////////////////////////////////// #ifdef NEVER void CClusterItemList::RemoveAll( void ) { ASSERT_VALID( this ); // destroy elements CNode * pNode; for ( pNode = m_pNodeHead ; pNode != NULL ; pNode = pNode->pNext ) { // ((CClusterItem *) pNode->data)->Release( ); DestructElements( (CClusterItem**) &pNode->data, 1 ); } // for: each node in the list // Call the base class method. CObList::RemoveAll( ); } //*** CClusterItemList::RemoveAll( ) #endif //*************************************************************************** ///////////////////////////////////////////////////////////////////////////// // CClusterItem ///////////////////////////////////////////////////////////////////////////// IMPLEMENT_DYNCREATE( CClusterItem, CBaseCmdTarget ) ///////////////////////////////////////////////////////////////////////////// // Message Maps BEGIN_MESSAGE_MAP( CClusterItem, CBaseCmdTarget ) //{{AFX_MSG_MAP(CClusterItem) ON_UPDATE_COMMAND_UI(ID_FILE_RENAME, OnUpdateRename) ON_UPDATE_COMMAND_UI(ID_FILE_PROPERTIES, OnUpdateProperties) ON_COMMAND(ID_FILE_PROPERTIES, OnCmdProperties) //}}AFX_MSG_MAP END_MESSAGE_MAP( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::CClusterItem // // Routine Description: // Default constructor. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// CClusterItem::CClusterItem( void ) { CommonConstruct( ); } //*** CClusterItem::CClusterItem( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::CClusterItem // // Routine Description: // Constructor. // // Arguments: // pstrName [IN] Name of the item. // idsType [IN] Type ID of the item. // pstrDescription [IN] Description of the item. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// CClusterItem::CClusterItem( IN const CString * pstrName, IN IDS idsType, IN const CString * pstrDescription ) { CommonConstruct( ); if ( pstrName != NULL ) { m_strName = *pstrName; } // if if ( idsType == 0 ) { idsType = IDS_ITEMTYPE_CONTAINER; } // if m_idsType = idsType; m_strType.LoadString( IdsType( ) ); if ( pstrDescription != NULL ) { m_strDescription = *pstrDescription; } // if Trace( g_tagClusItemCreate, _T("CClusterItem( ) - Creating '%s' (%s )"), m_strName, m_strType ); } //*** CClusterItem::CClusterItem( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::CommonConstruct // // Routine Description: // Common construction. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CClusterItem::CommonConstruct( void ) { m_hkey = NULL; m_idsType = IDS_ITEMTYPE_CONTAINER; m_strType.LoadString( IDS_ITEMTYPE_CONTAINER ); m_iimgObjectType = 0; m_iimgState = GetClusterAdminApp( )->Iimg( IMGLI_FOLDER ); m_pdoc = NULL; m_idmPopupMenu = 0; m_bDocObj = TRUE; m_bChanged = FALSE; m_bReadOnly = FALSE; m_pcnk = NULL; } //*** CClusterItem::CommonConstruct( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::~CClusterItem // // Routine Description: // Destructor. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// CClusterItem::~CClusterItem( void ) { Trace( g_tagClusItemDelete, _T("~CClusterItem( ) - Deleting cluster item '%s'"), StrName( ) ); // Empty the lists. DeleteAllItemData( LptiBackPointers( ) ); DeleteAllItemData( LpliBackPointers( ) ); LptiBackPointers( ).RemoveAll( ); LpliBackPointers( ).RemoveAll( ); // Close the registry key. if ( Hkey( ) != NULL ) { ClusterRegCloseKey( Hkey( ) ); m_hkey = NULL; } // if // Remove the notification key and delete it. if ( BDocObj( ) ) { POSITION pos; pos = GetClusterAdminApp( )->Cnkl( ).Find( m_pcnk ); if ( pos != NULL ) { GetClusterAdminApp( )->Cnkl( ).RemoveAt( pos ); } // if Trace( g_tagClusItemNotify, _T("~CClusterItem( ) - Deleting notification key (%08.8x ) for '%s'"), m_pcnk, StrName( ) ); delete m_pcnk; m_pcnk = NULL; } // if: object resides in the document Trace( g_tagClusItemDelete, _T("~CClusterItem( ) - Done deleting cluster item '%s'"), StrName( ) ); } //*** CClusterItem::~CClusterItem( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::Delete // // Routine Description: // Delete the item. If the item still has references, add it to the // document's pending delete list. // // Arguments: // None. // // Return Value: // None. // // Exceptions Thrown: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CClusterItem::Delete( void ) { // Add a reference so that we don't delete ourselves while // still doing cleanup. AddRef( ); // Cleanup this object. Cleanup( ); // Remove the item from all lists and views. CClusterItem::RemoveItem( ); // If there are still references to this object, add it to the delete // pending list. Check for greater than 1 because we added a reference // at the beginning of this method. if ( ( Pdoc( ) != NULL ) && ( NReferenceCount( ) > 1 ) ) { if ( Pdoc( )->LpciToBeDeleted( ).Find( this ) == NULL ) { Pdoc( )->LpciToBeDeleted( ).AddTail( this ); } // if } // if: object still has references to it // Release the reference we added at the beginning. This will // cause the object to be deleted if we were the last reference. Release( ); } //*** CClusterItem::Delete( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::Init // // Routine Description: // Initialize the item. // // Arguments: // pdoc [IN OUT] Document to which this item belongs. // lpszName [IN] Name of the item. // // Return Value: // None. // // Exceptions Thrown: // Any exceptions thrown by CNotifyKey::new( ) or // CNotifyKeyList::AddTail( ). // //-- ///////////////////////////////////////////////////////////////////////////// void CClusterItem::Init( IN OUT CClusterDoc * pdoc, IN LPCTSTR lpszName ) { ASSERT_VALID( pdoc ); ASSERT( lpszName != NULL ); // Save parameters. m_pdoc = pdoc; m_strName = lpszName; Trace( g_tagClusItemCreate, _T("Init( ) - Initializing '%s' (%s )"), m_strName, m_strType ); // Find the notification key for this item in the document's list. // If one is not found, allocate one. if ( BDocObj( ) ) { POSITION pos; CClusterNotifyKey * pcnk = NULL; pos = GetClusterAdminApp( )->Cnkl( ).GetHeadPosition( ); while ( pos != NULL ) { pcnk = GetClusterAdminApp( )->Cnkl( ).GetNext( pos ); if ( ( pcnk->m_cnkt == cnktClusterItem ) && ( pcnk->m_pci == this ) ) break; pcnk = NULL; } // while: more items in the list // If a key was not found, allocate a new one. if ( pcnk == NULL ) { pcnk = new CClusterNotifyKey( this, lpszName ); if ( pcnk == NULL ) { ThrowStaticException( GetLastError( ) ); } // if: error allocating the notify key try { GetClusterAdminApp( )->Cnkl( ).AddTail( pcnk ); Trace( g_tagClusItemNotify, _T("Init( ) - Creating notification key (%08.8x ) for '%s'"), pcnk, StrName( ) ); } // try catch ( ... ) { delete pcnk; throw; } // catch: anything } // if: key wasn't found m_pcnk = pcnk; } // if: object resides in the document } //*** CClusterItem::Init( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::PlstrExtensions // // Routine Description: // Return the list of admin extensions. // // Arguments: // None. // // Return Value: // plstr List of extensions. // NULL No extension associated with this object. // // Exceptions Thrown: // None. // //-- ///////////////////////////////////////////////////////////////////////////// const CStringList * CClusterItem::PlstrExtensions( void ) const { return NULL; } //*** CClusterItem::PlstrExtensions( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::RemoveItem // // Routine Description: // Remove the item from all lists and views. // // Arguments: // None. // // Return Value: // None. // // Exceptions Thrown: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CClusterItem::RemoveItem( void ) { // Remove the item from each tree item. { POSITION posPti; CTreeItem * pti; posPti = LptiBackPointers( ).GetHeadPosition( ); while ( posPti != NULL ) { pti = LptiBackPointers( ).GetNext( posPti ); ASSERT_VALID( pti ); ASSERT_VALID( pti->PtiParent( ) ); Trace( g_tagClusItemDelete, _T("RemoveItem( ) - Deleting tree item backptr from '%s' in '%s' - %d left"), StrName( ), pti->PtiParent( )->StrName( ), LptiBackPointers( ).GetCount( ) - 1 ); pti->RemoveItem( ); } // while: more items in the list } // Remove the item from each tree item // Remove the item from each list item. { POSITION posPli; CListItem * pli; posPli = LpliBackPointers( ).GetHeadPosition( ); while ( posPli != NULL ) { pli = LpliBackPointers( ).GetNext( posPli ); ASSERT_VALID( pli ); ASSERT_VALID( pli->PtiParent( ) ); Trace( g_tagClusItemDelete, _T("RemoveItem( ) - Deleting list item backptr from '%s' in '%s' - %d left"), StrName( ), pli->PtiParent( )->StrName( ), LpliBackPointers( ).GetCount( ) - 1 ); pli->PtiParent( )->RemoveChild( pli->Pci( ) ); } // while: more items in the list } // Remove the item from each tree item } //*** CClusterItem::RemoveItem( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::WriteItem // // Routine Description: // Write the item parameters to the cluster database. // // Arguments: // None. // // Return Value: // None. // // Exceptions Thrown: // Any exceptions thrown by WriteItem( ). // //-- ///////////////////////////////////////////////////////////////////////////// void CClusterItem::WriteItem( void ) { } //*** CClusterItem::WriteItem( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::DwParseProperties // // Routine Description: // Parse the properties of the resource. This is in a separate function // from BInit so that the optimizer can do a better job. // // Arguments: // rcpl [IN] Cluster property list to parse. // // Return Value: // ERROR_SUCCESS Properties were parsed successfully. // // Exceptions Thrown: // Any exceptions from CString::operator=( ). // //-- ///////////////////////////////////////////////////////////////////////////// DWORD CClusterItem::DwParseProperties( IN const CClusPropList & rcpl ) { DWORD cProps; DWORD cprop; DWORD cbProps; const CObjectProperty * pprop; CLUSPROP_BUFFER_HELPER props; CLUSPROP_PROPERTY_NAME const * pName; ASSERT( rcpl.PbPropList( ) != NULL ); props.pb = rcpl.PbPropList( ); cbProps = rcpl.CbPropList( ); // Loop through each property. for ( cProps = *(props.pdw++ ) ; cProps > 0 ; cProps-- ) { pName = props.pName; ASSERT( pName->Syntax.dw == CLUSPROP_SYNTAX_NAME ); props.pb += sizeof( *pName ) + ALIGN_CLUSPROP( pName->cbLength ); // Decrement the counter by the size of the name. ASSERT( cbProps > sizeof( *pName ) + ALIGN_CLUSPROP( pName->cbLength ) ); cbProps -= sizeof( *pName ) + ALIGN_CLUSPROP( pName->cbLength ); ASSERT( cbProps > sizeof( *props.pValue ) + ALIGN_CLUSPROP( props.pValue->cbLength ) ); // Parse known properties. for ( pprop = Pprops( ), cprop = Cprops( ) ; cprop > 0 ; pprop++, cprop-- ) { if ( lstrcmpiW( pName->sz, pprop->m_pwszName ) == 0 ) { ASSERT( props.pSyntax->wFormat == pprop->m_propFormat ); switch ( pprop->m_propFormat ) { case CLUSPROP_FORMAT_SZ: ASSERT( ( props.pValue->cbLength == ( lstrlenW( props.pStringValue->sz ) + 1 ) * sizeof( WCHAR ) ) || ( (props.pValue->cbLength == 0 ) && ( props.pStringValue->sz[ 0 ] == L'\0' ) ) ); *pprop->m_valuePrev.pstr = props.pStringValue->sz; break; case CLUSPROP_FORMAT_DWORD: case CLUSPROP_FORMAT_LONG: ASSERT( props.pValue->cbLength == sizeof( DWORD ) ); *pprop->m_valuePrev.pdw = props.pDwordValue->dw; break; case CLUSPROP_FORMAT_BINARY: case CLUSPROP_FORMAT_MULTI_SZ: *pprop->m_valuePrev.ppb = props.pBinaryValue->rgb; *pprop->m_valuePrev.pcb = props.pBinaryValue->cbLength; break; default: ASSERT( 0 ); // don't know how to deal with this type } // switch: property format // Exit the loop since we found the parameter. break; } // if: found a match } // for: each property // If the property wasn't known, ask the derived class to parse it. if ( cprop == 0 ) { DWORD dwStatus; dwStatus = DwParseUnknownProperty( pName->sz, props, cbProps ); if ( dwStatus != ERROR_SUCCESS ) { return dwStatus; } // if } // if: property not parsed // Advance the buffer pointer past the value in the value list. while ( ( props.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK ) && ( cbProps > 0 ) ) { ASSERT( cbProps > sizeof( *props.pValue ) + ALIGN_CLUSPROP( props.pValue->cbLength ) ); cbProps -= sizeof( *props.pValue ) + ALIGN_CLUSPROP( props.pValue->cbLength ); props.pb += sizeof( *props.pValue ) + ALIGN_CLUSPROP( props.pValue->cbLength ); } // while: more values in the list // Advance the buffer pointer past the value list endmark. ASSERT( cbProps >= sizeof( *props.pSyntax ) ); cbProps -= sizeof( *props.pSyntax ); props.pb += sizeof( *props.pSyntax ); // endmark } // for: each property return ERROR_SUCCESS; } //*** CClusterItem::DwParseProperties( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::SetCommonProperties // // Routine Description: // Set the common properties for this object in the cluster database. // // Arguments: // bValidateOnly [IN] Only validate the data. // // Return Value: // None. // // Exceptions Thrown: // Any exceptions thrown by WriteItem( ). // //-- ///////////////////////////////////////////////////////////////////////////// void CClusterItem::SetCommonProperties( IN BOOL bValidateOnly ) { DWORD dwStatus = ERROR_SUCCESS; CClusPropList cpl; CWaitCursor wc; // Save data. { // Build the property list and set the data. try { BuildPropList( cpl ); dwStatus = DwSetCommonProperties( cpl, bValidateOnly ); } // try catch ( CMemoryException * pme ) { pme->Delete( ); dwStatus = ERROR_NOT_ENOUGH_MEMORY; } // catch: CMemoryException // Handle errors. if ( dwStatus != ERROR_SUCCESS ) { if ( dwStatus != ERROR_RESOURCE_PROPERTIES_STORED ) { ThrowStaticException( dwStatus, IDS_APPLY_PARAM_CHANGES_ERROR ); } // if } // if: error setting properties if ( ! bValidateOnly && ( dwStatus == ERROR_SUCCESS ) ) { DWORD cprop; const CObjectProperty * pprop; // Save new values as previous values. for ( pprop = Pprops( ), cprop = Cprops( ) ; cprop > 0 ; pprop++, cprop-- ) { switch ( pprop->m_propFormat ) { case CLUSPROP_FORMAT_SZ: ASSERT( pprop->m_value.pstr != NULL ); ASSERT( pprop->m_valuePrev.pstr != NULL ); *pprop->m_valuePrev.pstr = *pprop->m_value.pstr; break; case CLUSPROP_FORMAT_DWORD: ASSERT( pprop->m_value.pdw != NULL ); ASSERT( pprop->m_valuePrev.pdw != NULL ); *pprop->m_valuePrev.pdw = *pprop->m_value.pdw; break; case CLUSPROP_FORMAT_BINARY: case CLUSPROP_FORMAT_MULTI_SZ: ASSERT( pprop->m_value.ppb != NULL ); ASSERT( *pprop->m_value.ppb != NULL ); ASSERT( pprop->m_value.pcb != NULL ); ASSERT( pprop->m_valuePrev.ppb != NULL ); ASSERT( *pprop->m_valuePrev.ppb != NULL ); ASSERT( pprop->m_valuePrev.pcb != NULL ); delete [] *pprop->m_valuePrev.ppb; *pprop->m_valuePrev.ppb = new BYTE[ *pprop->m_value.pcb ]; if ( *pprop->m_valuePrev.ppb == NULL ) { ThrowStaticException( GetLastError( ) ); } // if: error allocating data buffer CopyMemory( *pprop->m_valuePrev.ppb, *pprop->m_value.ppb, *pprop->m_value.pcb ); *pprop->m_valuePrev.pcb = *pprop->m_value.pcb; break; default: ASSERT( 0 ); // don't know how to deal with this type } // switch: property format } // for: each property } // if: not just validating and properties set successfully if ( dwStatus == ERROR_RESOURCE_PROPERTIES_STORED ) { ThrowStaticException( dwStatus ); } // if } // Save data } //*** CClusterItem::SetCommonProperties( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::BuildPropList // // Routine Description: // Build the property list. // // Arguments: // rcpl [IN OUT] Cluster property list. // // Return Value: // None. // // Exceptions Thrown: // Any exceptions thrown by CClusPropList::ScAddProp( ). // //-- ///////////////////////////////////////////////////////////////////////////// void CClusterItem::BuildPropList( IN OUT CClusPropList & rcpl ) { DWORD cprop; const CObjectProperty * pprop; for ( pprop = Pprops( ), cprop = Cprops( ) ; cprop > 0 ; pprop++, cprop-- ) { switch ( pprop->m_propFormat ) { case CLUSPROP_FORMAT_SZ: rcpl.ScAddProp( pprop->m_pwszName, *pprop->m_value.pstr, *pprop->m_valuePrev.pstr ); break; case CLUSPROP_FORMAT_DWORD: rcpl.ScAddProp( pprop->m_pwszName, *pprop->m_value.pdw, *pprop->m_valuePrev.pdw ); break; case CLUSPROP_FORMAT_BINARY: case CLUSPROP_FORMAT_MULTI_SZ: rcpl.ScAddProp( pprop->m_pwszName, *pprop->m_value.ppb, *pprop->m_value.pcb, *pprop->m_valuePrev.ppb, *pprop->m_valuePrev.pcb ); break; default: ASSERT( 0 ); // don't know how to deal with this type return; } // switch: property format } // for: each property } //*** CClusterItem::BuildPropList( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::UpdateState // // Routine Description: // Update the current state of the item. // Default implementation. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CClusterItem::UpdateState( void ) { // Update the state of all the tree items pointing to us. { POSITION pos; CTreeItem * pti; pos = LptiBackPointers( ).GetHeadPosition( ); while ( pos != NULL ) { pti = LptiBackPointers( ).GetNext( pos ); ASSERT_VALID( pti ); pti->UpdateUIState( ); } // while: more items in the list } // Update the state of all the tree items pointing to us // Update the state of all the list items pointing to us. { POSITION pos; CListItem * pli; pos = LpliBackPointers( ).GetHeadPosition( ); while ( pos != NULL ) { pli = LpliBackPointers( ).GetNext( pos ); ASSERT_VALID( pli ); pli->UpdateUIState( ); } // while: more items in the list } // Update the state of all the tree items pointing to us } //*** CClusterItem::UpdateState( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::DwReadValue // // Routine Description: // Read a REG_SZ value for this item. // // Arguments: // pszValueName [IN] Name of the value to read. // pszKeyName [IN] Name of the key where the value resides. // rstrValue [OUT] String in which to return the value. // // Return Value: // dwStatus ERROR_SUCCESS = success, !0 = failure // //-- ///////////////////////////////////////////////////////////////////////////// DWORD CClusterItem::DwReadValue( IN LPCTSTR pszValueName, IN LPCTSTR pszKeyName, OUT CString & rstrValue ) { DWORD dwStatus; LPWSTR pwszValue = NULL; DWORD dwValueLen; DWORD dwValueType; HKEY hkey = NULL; CWaitCursor wc; ASSERT( pszValueName != NULL ); ASSERT( Hkey( ) != NULL ); rstrValue.Empty( ); try { // Open a new key if needed. if ( pszKeyName != NULL ) { dwStatus = ClusterRegOpenKey( Hkey( ), pszKeyName, KEY_READ, &hkey ); if ( dwStatus != ERROR_SUCCESS ) { return dwStatus; } // if } // if: need to open a subkey else { hkey = Hkey( ); } // else // Get the size of the value. dwValueLen = 0; dwStatus = ClusterRegQueryValue( hkey, pszValueName, &dwValueType, NULL, &dwValueLen ); if ( ( dwStatus == ERROR_SUCCESS ) || ( dwStatus == ERROR_MORE_DATA ) ) { ASSERT( dwValueType == REG_SZ ); // Allocate enough space for the data. pwszValue = rstrValue.GetBuffer( dwValueLen / sizeof( WCHAR ) ); ASSERT( pwszValue != NULL ); dwValueLen += 1 * sizeof( WCHAR ); // Don't forget the final null-terminator. // Read the value. dwStatus = ClusterRegQueryValue( hkey, pszValueName, &dwValueType, (LPBYTE ) pwszValue, &dwValueLen ); if ( dwStatus == ERROR_SUCCESS ) { ASSERT( dwValueType == REG_SZ ); } // if: value read successfully rstrValue.ReleaseBuffer( ); } // if: got the size successfully } // try catch ( CMemoryException * pme ) { pme->Delete( ); dwStatus = ERROR_NOT_ENOUGH_MEMORY; } // catch: CMemoryException if ( pszKeyName != NULL ) { ClusterRegCloseKey( hkey ); } // if return dwStatus; } //*** CClusterItem::DwReadValue( LPCTSTR, CString& ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::DwReadValue // // Routine Description: // Read a REG_MULTI_SZ value for this item. // // Arguments: // pszValueName [IN] Name of the value to read. // pszKeyName [IN] Name of the key where the value resides. // rlstrValue [OUT] String list in which to return the values. // // Return Value: // dwStatus ERROR_SUCCESS = success, !0 = failure // //-- ///////////////////////////////////////////////////////////////////////////// DWORD CClusterItem::DwReadValue( IN LPCTSTR pszValueName, IN LPCTSTR pszKeyName, OUT CStringList & rlstrValue ) { DWORD dwStatus; LPWSTR pwszValue = NULL; LPWSTR pwszCurValue; DWORD dwValueLen; DWORD dwValueType; HKEY hkey = NULL; CWaitCursor wc; ASSERT( pszValueName != NULL ); ASSERT( Hkey( ) != NULL ); rlstrValue.RemoveAll( ); try { // Open a new key if needed. if ( pszKeyName != NULL ) { dwStatus = ClusterRegOpenKey( Hkey( ), pszKeyName, KEY_READ, &hkey ); if ( dwStatus != ERROR_SUCCESS ) { return dwStatus; } // if } // if: need to open a subkey else hkey = Hkey( ); // Get the size of the value. dwValueLen = 0; dwStatus = ClusterRegQueryValue( hkey, pszValueName, &dwValueType, NULL, &dwValueLen ); if ( ( dwStatus == ERROR_SUCCESS ) || ( dwStatus == ERROR_MORE_DATA ) ) { ASSERT( dwValueType == REG_MULTI_SZ ); // Allocate enough space for the data. dwValueLen += 1 * sizeof( WCHAR ); // Don't forget the final null-terminator. pwszValue = new WCHAR[ dwValueLen / sizeof( WCHAR ) ]; if ( pwszValue == NULL ) { AfxThrowMemoryException(); } // if: error allocating the value // Read the value. dwStatus = ClusterRegQueryValue( hkey, pszValueName, &dwValueType, (LPBYTE) pwszValue, &dwValueLen ); if ( dwStatus == ERROR_SUCCESS ) { ASSERT( dwValueType == REG_MULTI_SZ ); // Add each string from the value into the string list. for ( pwszCurValue = pwszValue ; *pwszCurValue != L'\0' ; pwszCurValue += lstrlenW( pwszCurValue ) + 1 ) { rlstrValue.AddTail( pwszCurValue ); } // for } // if: read the value successfully } // if: got the size successfully } // try catch ( CMemoryException * pme ) { pme->Delete( ); dwStatus = ERROR_NOT_ENOUGH_MEMORY; } // catch: CMemoryException delete [] pwszValue; if ( pszKeyName != NULL ) { ClusterRegCloseKey( hkey ); } // if return dwStatus; } //*** CClusterItem::DwReadValue( LPCTSTR, CStringList& ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::DwReadValue // // Routine Description: // Read a REG_DWORD value for this item. // // Arguments: // pszValueName [IN] Name of the value to read. // pszKeyName [IN] Name of the key where the value resides. // pdwValue [OUT] DWORD in which to return the value. // // Return Value: // dwStatus ERROR_SUCCESS = success, !0 = failure // //-- ///////////////////////////////////////////////////////////////////////////// DWORD CClusterItem::DwReadValue( IN LPCTSTR pszValueName, IN LPCTSTR pszKeyName, OUT DWORD * pdwValue ) { DWORD dwStatus; DWORD dwValue; DWORD dwValueLen; DWORD dwValueType; HKEY hkey; CWaitCursor wc; ASSERT( pszValueName != NULL ); ASSERT( pdwValue != NULL ); ASSERT( Hkey( ) != NULL ); // Open a new key if needed. if ( pszKeyName != NULL ) { dwStatus = ClusterRegOpenKey( Hkey( ), pszKeyName, KEY_READ, &hkey ); if ( dwStatus != ERROR_SUCCESS ) { return dwStatus; } // if } // if: need to open a subkey else { hkey = Hkey( ); } // else // Read the value. dwValueLen = sizeof( dwValue ); dwStatus = ClusterRegQueryValue( hkey, pszValueName, &dwValueType, (LPBYTE) &dwValue, &dwValueLen ); if ( dwStatus == ERROR_SUCCESS ) { ASSERT( dwValueType == REG_DWORD ); ASSERT( dwValueLen == sizeof( dwValue ) ); *pdwValue = dwValue; } // if: value read successfully if ( pszKeyName != NULL ) { ClusterRegCloseKey( hkey ); } // if return dwStatus; } //*** CClusterItem::DwReadValue( LPCTSTR, DWORD* ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::DwReadValue // // Routine Description: // Read a REG_DWORD value for this item. // // Arguments: // pszValueName [IN] Name of the value to read. // pszKeyName [IN] Name of the key where the value resides. // pdwValue [OUT] DWORD in which to return the value. // dwDefault [IN] Default value if parameter not set. // // Return Value: // dwStatus ERROR_SUCCESS = success, !0 = failure // //-- ///////////////////////////////////////////////////////////////////////////// DWORD CClusterItem::DwReadValue( IN LPCTSTR pszValueName, IN LPCTSTR pszKeyName, OUT DWORD * pdwValue, IN DWORD dwDefault ) { DWORD dwStatus; CWaitCursor wc; // Read the value. dwStatus = DwReadValue( pszValueName, pszKeyName, pdwValue ); if ( dwStatus == ERROR_FILE_NOT_FOUND ) { *pdwValue = dwDefault; dwStatus = ERROR_SUCCESS; } // if: value not set return dwStatus; } //*** CClusterItem::DwReadValue( LPCTSTR, DWORD*, DWORD ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::DwReadValue // // Routine Description: // Read a REG_BINARY value for this item. // // Arguments: // pszValueName [IN] Name of the value to read. // pszKeyName [IN] Name of the key where the value resides. // ppbValue [OUT] Pointer in which to return the data. Caller // is responsible for deallocating the data. // // Return Value: // dwStatus ERROR_SUCCESS = success, !0 = failure // //-- ///////////////////////////////////////////////////////////////////////////// DWORD CClusterItem::DwReadValue( IN LPCTSTR pszValueName, IN LPCTSTR pszKeyName, OUT LPBYTE * ppbValue ) { DWORD dwStatus; DWORD dwValueLen; DWORD dwValueType; LPBYTE pbValue = NULL; HKEY hkey; CWaitCursor wc; ASSERT( pszValueName != NULL ); ASSERT( ppbValue != NULL ); ASSERT( Hkey( ) != NULL ); delete [] *ppbValue; *ppbValue = NULL; // Open a new key if needed. if ( pszKeyName != NULL ) { dwStatus = ClusterRegOpenKey( Hkey( ), pszKeyName, KEY_READ, &hkey ); if ( dwStatus != ERROR_SUCCESS ) { return dwStatus; } // if } // if: need to open a subkey else { hkey = Hkey( ); } // else // Get the length of the value. dwValueLen = 0; dwStatus = ClusterRegQueryValue( hkey, pszValueName, &dwValueType, NULL, &dwValueLen ); if ( ( dwStatus != ERROR_SUCCESS ) && ( dwStatus != ERROR_MORE_DATA ) ) { if ( pszKeyName != NULL ) { ClusterRegCloseKey( hkey ); } // if return dwStatus; } // if: error getting the length ASSERT( dwValueType == REG_BINARY ); // Allocate a buffer, try { pbValue = new BYTE[ dwValueLen ]; if ( pbValue == NULL ) { AfxThrowMemoryException(); } // if: error allocating the buffer } // try catch ( CMemoryException * ) { if ( pszKeyName != NULL ) { ClusterRegCloseKey( hkey ); } // if dwStatus = ERROR_NOT_ENOUGH_MEMORY; return dwStatus; } // catch: CMemoryException // Read the value. dwStatus = ClusterRegQueryValue( hkey, pszValueName, &dwValueType, pbValue, &dwValueLen ); if ( dwStatus == ERROR_SUCCESS ) { *ppbValue = pbValue; } // if else { delete [] pbValue; } // else if ( pszKeyName != NULL ) { ClusterRegCloseKey( hkey ); } // if return dwStatus; } //*** CClusterItem::DwReadValue( LPCTSTR, LPBYTE* ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::WriteValue // // Routine Description: // Write a REG_SZ value for this item. // // Arguments: // pszValueName [IN] Name of the value to write. // pszKeyName [IN] Name of the key where the value resides. // rstrValue [IN] Value data. // // Return Value: // None. // // Exceptions Thrown: // CNTException( dwStatus ) // //-- ///////////////////////////////////////////////////////////////////////////// void CClusterItem::WriteValue( IN LPCTSTR pszValueName, IN LPCTSTR pszKeyName, IN const CString & rstrValue ) { DWORD dwStatus; HKEY hkey; CWaitCursor wc; ASSERT( pszValueName != NULL ); ASSERT( Hkey( ) != NULL ); // Open a new key if needed. if ( pszKeyName != NULL ) { dwStatus = ClusterRegOpenKey( Hkey( ), pszKeyName, KEY_ALL_ACCESS, &hkey ); if ( dwStatus != ERROR_SUCCESS ) { ThrowStaticException( dwStatus ); } // if } // if: need to open a subkey else { hkey = Hkey( ); } // else // Write the value. dwStatus = ClusterRegSetValue( hkey, pszValueName, REG_SZ, (CONST BYTE *) (LPCTSTR) rstrValue, ( rstrValue.GetLength( ) + 1 ) * sizeof( WCHAR ) ); if ( pszKeyName != NULL ) { ClusterRegCloseKey( hkey ); } // if if ( dwStatus != ERROR_SUCCESS ) { ThrowStaticException( dwStatus ); } // if } //*** CClusterItem::WriteValue( LPCTSTR, CString& ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::WriteValue // // Routine Description: // Write a REG_MULTI_SZ value for this item. // // Arguments: // pszValueName [IN] Name of the value to write. // pszKeyName [IN] Name of the key where the value resides. // rlstrValue [IN] Value data. // // Return Value: // None. // // Exceptions Thrown: // CNTException( dwStatus ) // Any exceptions thrown by new. // //-- ///////////////////////////////////////////////////////////////////////////// void CClusterItem::WriteValue( IN LPCTSTR pszValueName, IN LPCTSTR pszKeyName, IN const CStringList & rlstrValue ) { DWORD dwStatus; LPWSTR pwszValue = NULL; LPWSTR pwszCurValue; POSITION posStr; DWORD cbValueLen; HKEY hkey; CWaitCursor wc; ASSERT( pszValueName != NULL ); ASSERT( Hkey( ) != NULL ); // Get the size of the value. posStr = rlstrValue.GetHeadPosition( ); cbValueLen = 0; while ( posStr != NULL ) { cbValueLen += ( rlstrValue.GetNext( posStr ).GetLength( ) + 1 ) * sizeof( TCHAR ); } // while: more items in the list cbValueLen += 1 * sizeof( WCHAR ); // Extra NULL at the end. // Allocate the value buffer. pwszValue = new WCHAR[cbValueLen / sizeof( WCHAR )]; if ( pwszValue == NULL ) { ThrowStaticException( GetLastError( ) ); } // if // Copy the strings to the values. posStr = rlstrValue.GetHeadPosition( ); for ( pwszCurValue = pwszValue ; posStr != NULL ; pwszCurValue += lstrlenW( pwszCurValue ) + 1 ) { lstrcpyW( pwszCurValue, rlstrValue.GetNext( posStr ) ); } // for: each item in the list pwszCurValue[0] = L'\0'; // Open a new key if needed. if ( pszKeyName != NULL ) { dwStatus = ClusterRegOpenKey( Hkey( ), pszKeyName, KEY_ALL_ACCESS, &hkey ); if ( dwStatus != ERROR_SUCCESS ) { delete [] pwszValue; ThrowStaticException( dwStatus ); } // if: error opening the key } // if: need to open a subkey else { hkey = Hkey( ); } // else // Write the value. dwStatus = ClusterRegSetValue( hkey, pszValueName, REG_MULTI_SZ, (CONST BYTE *) pwszValue, cbValueLen - ( 1 * sizeof( WCHAR ) ) ); delete [] pwszValue; if ( pszKeyName != NULL ) { ClusterRegCloseKey( hkey ); } // if if ( dwStatus != ERROR_SUCCESS ) { ThrowStaticException( dwStatus ); } // if } //*** CClusterItem::WriteValue( LPCTSTR, CStringList& ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::WriteValue // // Routine Description: // Write a REG_DWORD value for this item. // // Arguments: // pszValueName [IN] Name of the value to write. // pszKeyName [IN] Name of the key where the value resides. // dwValue [IN] Value data. // // Return Value: // None. // // Exceptions Thrown: // CNTException( dwStatus ) // //-- ///////////////////////////////////////////////////////////////////////////// void CClusterItem::WriteValue( IN LPCTSTR pszValueName, IN LPCTSTR pszKeyName, IN DWORD dwValue ) { DWORD dwStatus; HKEY hkey; CWaitCursor wc; ASSERT( pszValueName != NULL ); ASSERT( Hkey( ) != NULL ); // Open a new key if needed. if ( pszKeyName != NULL ) { dwStatus = ClusterRegOpenKey( Hkey( ), pszKeyName, KEY_ALL_ACCESS, &hkey ); if ( dwStatus != ERROR_SUCCESS ) { ThrowStaticException( dwStatus ); } // if } // if: need to open a subkey else hkey = Hkey( ); // Write the value. dwStatus = ClusterRegSetValue( hkey, pszValueName, REG_DWORD, (CONST BYTE *) &dwValue, sizeof( dwValue ) ); if ( pszKeyName != NULL ) { ClusterRegCloseKey( hkey ); } // if if ( dwStatus != ERROR_SUCCESS ) { ThrowStaticException( dwStatus ); } // if } //*** CClusterItem::WriteValue( LPCTSTR, DWORD ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::WriteValue // // Routine Description: // Write a REG_BINARY value for this item if it hasn't changed. // // Arguments: // pszValueName [IN] Name of the value to write. // pszKeyName [IN] Name of the key where the value resides. // pbValue [IN] Value data. // cbValue [IN] Size of value data. // ppbPrevValue [IN OUT] Previous value. // cbPrevValue [IN] Size of the previous data. // // Return Value: // None. // // Exceptions Thrown: // CNTException( dwStatus ) // //-- ///////////////////////////////////////////////////////////////////////////// void CClusterItem::WriteValue( IN LPCTSTR pszValueName, IN LPCTSTR pszKeyName, IN const LPBYTE pbValue, IN DWORD cbValue, IN OUT LPBYTE * ppbPrevValue, IN DWORD cbPrevValue ) { DWORD dwStatus; LPBYTE pbPrevValue = NULL; HKEY hkey; CWaitCursor wc; ASSERT( pszValueName != NULL ); ASSERT( pbValue != NULL ); ASSERT( ppbPrevValue != NULL ); ASSERT( cbValue > 0 ); ASSERT( Hkey( ) != NULL ); // See if the data has changed. if ( cbValue == cbPrevValue ) { DWORD ib; for ( ib = 0 ; ib < cbValue ; ib++ ) { if ( pbValue[ ib ] != (*ppbPrevValue )[ ib ] ) { break; } // if } // for: each byte in the value if ( ib == cbValue ) { return; } // if } // if: lengths are the same // Allocate a new buffer for the previous data pointer. pbPrevValue = new BYTE[ cbValue ]; if ( pbPrevValue == NULL ) { ThrowStaticException( GetLastError( ) ); } // if: error allocating previous data buffer CopyMemory( pbPrevValue, pbValue, cbValue ); // Open a new key if needed. if ( pszKeyName != NULL ) { dwStatus = ClusterRegOpenKey( Hkey( ), pszKeyName, KEY_ALL_ACCESS, &hkey ); if ( dwStatus != ERROR_SUCCESS ) { delete [] pbPrevValue; ThrowStaticException( dwStatus ); } // if: error opening the key } // if: need to open a subkey else { hkey = Hkey( ); } // else // Write the value if it hasn't changed. dwStatus = ClusterRegSetValue( hkey, pszValueName, REG_BINARY, pbValue, cbValue ); if ( pszKeyName != NULL ) { ClusterRegCloseKey( hkey ); } // if if ( dwStatus == ERROR_SUCCESS ) { delete [] *ppbPrevValue; *ppbPrevValue = pbPrevValue; } // if: set was successful else { delete [] pbPrevValue; ThrowStaticException( dwStatus ); } // else: error setting the value } //*** CClusterItem::WriteValue( LPCTSTR, const LPBYTE ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::DeleteValue // // Routine Description: // Delete the value for this item. // // Arguments: // pszValueName [IN] Name of the value to delete. // pszKeyName [IN] Name of the key where the value resides. // rstrValue [IN] Value data. // // Return Value: // None. // // Exceptions Thrown: // CNTException( dwStatus ) // //-- ///////////////////////////////////////////////////////////////////////////// void CClusterItem::DeleteValue( IN LPCTSTR pszValueName, IN LPCTSTR pszKeyName ) { DWORD dwStatus; HKEY hkey; CWaitCursor wc; ASSERT( pszValueName != NULL ); ASSERT( Hkey( ) != NULL ); // Open a new key if needed. if ( pszKeyName != NULL ) { dwStatus = ClusterRegOpenKey( Hkey( ), pszKeyName, KEY_ALL_ACCESS, &hkey ); if ( dwStatus != ERROR_SUCCESS ) { ThrowStaticException( dwStatus ); } // if } // if: need to open a subkey else { hkey = Hkey( ); } // else // Delete the value. dwStatus = ClusterRegDeleteValue( hkey, pszValueName ); if ( pszKeyName != NULL ) { ClusterRegCloseKey( hkey ); } // if if ( dwStatus != ERROR_SUCCESS ) { ThrowStaticException( dwStatus ); } // if } //*** CClusterItem::DeleteValue( LPCTSTR ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::BDifferent // // Routine Description: // Compare two string lists. // // Arguments: // rlstr1 [IN] First string list. // rlstr2 [IN] Second string list. // // Return Value: // TRUE Lists are different. // FALSE Lists are the same. // //-- ///////////////////////////////////////////////////////////////////////////// BOOL CClusterItem::BDifferent( IN const CStringList & rlstr1, IN const CStringList & rlstr2 ) { BOOL bDifferent; if ( rlstr1.GetCount( ) == rlstr2.GetCount( ) ) { POSITION posStr; bDifferent = FALSE; posStr = rlstr1.GetHeadPosition( ); while ( posStr != NULL ) { if ( rlstr2.Find( rlstr1.GetNext( posStr ) ) == 0 ) { bDifferent = TRUE; break; } // if: string wasn't found } // while: more items in the list } // if: lists are the same size else { bDifferent = TRUE; } // else return bDifferent; } //*** CClusterItem::BDifferent( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::BDifferentOrdered // // Routine Description: // Compare two string lists. // // Arguments: // rlstr1 [IN] First string list. // rlstr2 [IN] Second string list. // // Return Value: // TRUE Lists are different. // FALSE Lists are the same. // //-- ///////////////////////////////////////////////////////////////////////////// BOOL CClusterItem::BDifferentOrdered( IN const CStringList & rlstr1, IN const CStringList & rlstr2 ) { BOOL bDifferent; if ( rlstr1.GetCount( ) == rlstr2.GetCount( ) ) { POSITION posStr1; POSITION posStr2; bDifferent = FALSE; posStr1 = rlstr1.GetHeadPosition( ); posStr2 = rlstr2.GetHeadPosition( ); while ( posStr1 != NULL ) { if ( posStr2 == NULL ) { bDifferent = TRUE; break; } // if: fewer strings in second list if ( rlstr1.GetNext( posStr1 ) != rlstr2.GetNext( posStr2 ) ) { bDifferent = TRUE; break; } // if: strings are different } // while: more items in the list if ( posStr2 != NULL ) { bDifferent = TRUE; } // if } // if: lists are the same size else { bDifferent = TRUE; } // else return bDifferent; } //*** CClusterItem::BDifferentOrdered( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::BGetColumnData // // Routine Description: // Returns a string with the column data for a // // Arguments: // colid [IN] Column ID. // rstrText [OUT] String in which to return the text for the column. // // Return Value: // TRUE Column data returned. // FALSE Column ID not recognized. // //-- ///////////////////////////////////////////////////////////////////////////// BOOL CClusterItem::BGetColumnData( IN COLID colid, OUT CString & rstrText ) { BOOL bSuccess; switch ( colid ) { case IDS_COLTEXT_NAME: rstrText = StrName( ); bSuccess = TRUE; break; case IDS_COLTEXT_TYPE: rstrText = StrType( ); bSuccess = TRUE; break; case IDS_COLTEXT_DESCRIPTION: rstrText = StrDescription( ); bSuccess = TRUE; break; default: bSuccess = FALSE; rstrText = _T(""); break; } // switch: colid return bSuccess; } //*** CClusterItem::BGetColumnData( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::GetTreeName // // Routine Description: // Returns a string to be used in a tree control. // // Arguments: // rstrName [OUT] String in which to return the name. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// #ifdef _DISPLAY_STATE_TEXT_IN_TREE void CClusterItem::GetTreeName( OUT CString & rstrName ) const { rstrName = StrName( ); } //*** CClusterItem::GetTreeName( ) #endif ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::PmenuPopup // // Routine Description: // Returns a popup menu. // // Arguments: // None. // // Return Value: // pmenu A popup menu for the item. // //-- ///////////////////////////////////////////////////////////////////////////// CMenu * CClusterItem::PmenuPopup( void ) { CMenu * pmenu = NULL; if ( IdmPopupMenu( ) != NULL ) { // Update the state of the item before we construct its menu. UpdateState( ); // Load the menu. pmenu = new CMenu; if ( pmenu == NULL ) { return NULL; } // if if ( ! pmenu->LoadMenu( IdmPopupMenu( ) ) ) { delete pmenu; pmenu = NULL; } // if: error loading the menu } // if: there is a menu for this item return pmenu; } //*** CClusterItem::PmenuPopup( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::AddTreeItem // // Routine Description: // Add a tree item to the list item back pointer list. // // Arguments: // pti [IN] Tree item to add. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CClusterItem::AddTreeItem( CTreeItem * pti ) { POSITION pos; ASSERT_VALID( pti ); // Find the item in the list. pos = LptiBackPointers( ).Find( pti ); // If it wasn't found, add it. if ( pos == NULL ) { LptiBackPointers( ).AddTail( pti ); Trace( g_tagClusItemCreate, _T("AddTreeItem( ) - Adding tree item backptr from '%s' in '%s' - %d in list"), StrName( ), ( pti->PtiParent( ) == NULL ? _T("") : pti->PtiParent( )->StrName( ) ), LptiBackPointers( ).GetCount( ) ); } // if: item found in list } //*** CClusterItem::AddTreeItem( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::AddListItem // // Routine Description: // Add a list item to the list item back pointer list. // // Arguments: // pli [IN] List item to add. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CClusterItem::AddListItem( CListItem * pli ) { POSITION pos; ASSERT_VALID( pli ); // Find the item in the list. pos = LpliBackPointers( ).Find( pli ); // If it wasn't found, add it. if ( pos == NULL ) { LpliBackPointers( ).AddTail( pli ); Trace( g_tagClusItemCreate, _T("AddListItem( ) - Adding list item backptr from '%s' in '%s' - %d in list"), StrName( ), ( pli->PtiParent( ) == NULL ? _T("") : pli->PtiParent( )->StrName( ) ), LpliBackPointers( ).GetCount( ) ); } // if: item found in list } //*** CClusterItem::AddListItem( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::RemoveTreeItem // // Routine Description: // Remove a tree item from the tree item back pointer list. // // Arguments: // pti [IN] Tree item to remove. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CClusterItem::RemoveTreeItem( CTreeItem * pti ) { POSITION pos; ASSERT_VALID( pti ); // Find the item in the list. pos = LptiBackPointers( ).Find( pti ); // If it was found, remove it. if ( pos != NULL ) { LptiBackPointers( ).RemoveAt( pos ); Trace( g_tagClusItemDelete, _T("RemoveTreeItem( ) - Deleting tree item backptr from '%s' in '%s' - %d left"), StrName( ), ( pti->PtiParent( ) == NULL ? _T("") : pti->PtiParent( )->StrName( ) ), LptiBackPointers( ).GetCount( ) ); } // if: item found in list } //*** CClusterItem::RemoveTreeItem( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::RemoveListItem // // Routine Description: // Remove a list item from the list item back pointer list. // // Arguments: // pli [IN] List item to remove. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CClusterItem::RemoveListItem( CListItem * pli ) { POSITION pos; ASSERT_VALID( pli ); // Find the item in the list. pos = LpliBackPointers( ).Find( pli ); // If it was found, remove it. if ( pos != NULL ) { LpliBackPointers( ).RemoveAt( pos ); Trace( g_tagClusItemDelete, _T("RemoveListItem( ) - Deleting list item backptr from '%s' in '%s' - %d left"), StrName( ), ( pli->PtiParent( ) == NULL ? _T("") : pli->PtiParent( )->StrName( ) ), LpliBackPointers( ).GetCount( ) ); } // if: item found in list } //*** CClusterItem::RemoveListItem( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CResource::CClusterItem // // Routine Description: // Determines whether menu items corresponding to ID_FILE_RENAME // should be enabled or not. // // Arguments: // pCmdUI [IN OUT] Command routing object. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CClusterItem::OnUpdateRename( CCmdUI * pCmdUI ) { pCmdUI->Enable( BCanBeEdited( ) ); } //*** CClusterItem::OnUpdateRename( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::OnUpdateProperties // // Routine Description: // Determines whether menu items corresponding to ID_FILE_PROPERTIES // should be enabled or not. // // Arguments: // pCmdUI [IN OUT] Command routing object. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CClusterItem::OnUpdateProperties( CCmdUI * pCmdUI ) { pCmdUI->Enable( FALSE ); } //*** CClusterItem::OnUpdateProperties( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::OnCmdProperties // // Routine Description: // Processes the ID_FILE_PROPERTIES menu command. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void CClusterItem::OnCmdProperties( void ) { BDisplayProperties( ); } //*** CClusterItem::OnCmdProperties( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::BDisplayProperties // // Routine Description: // Display properties for the object. // // Arguments: // bReadOnly [IN] Don't allow edits to the object properties. // // Return Value: // TRUE OK pressed. // FALSE OK not pressed. // //-- ///////////////////////////////////////////////////////////////////////////// BOOL CClusterItem::BDisplayProperties( IN BOOL bReadOnly ) { AfxMessageBox( TEXT("Properties are not available."), MB_OK | MB_ICONWARNING ); return FALSE; } //*** CClusterItem::BDisplayProperties( ) ///////////////////////////////////////////////////////////////////////////// //++ // // CClusterItem::OnClusterNotify // // Routine Description: // Handler for the WM_CAM_CLUSTER_NOTIFY message. // Processes cluster notifications for this object. // // Arguments: // pnotify [IN OUT] Object describing the notification. // // Return Value: // Value returned from the application method. // //-- ///////////////////////////////////////////////////////////////////////////// LRESULT CClusterItem::OnClusterNotify( IN OUT CClusterNotify * pnotify ) { return 0; } //*** CClusterItem::OnClusterNotify( ) //*************************************************************************// ///////////////////////////////////////////////////////////////////////////// // Global Functions ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// //++ // // DestructElements // // Routine Description: // Destroys CClusterItem* elements. // // Arguments: // pElements Array of pointers to elements to destruct. // nCount Number of elements to destruct. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// extern void AFXAPI DestructElements( CClusterItem ** pElements, int nCount ) { ASSERT( nCount == 0 || AfxIsValidAddress( pElements, nCount * sizeof( CClusterItem * ) ) ); // call the destructor(s ) for ( ; nCount--; pElements++ ) { ASSERT_VALID( *pElements ); (*pElements)->Release( ); } // for: each item in the array } //*** DestructElements( CClusterItem** ) ///////////////////////////////////////////////////////////////////////////// //++ // // DeleteAllItemData // // Routine Description: // Deletes all item data in a CList. // // Arguments: // rlp [IN OUT] List whose data is to be deleted. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// void DeleteAllItemData( IN OUT CClusterItemList & rlp ) { POSITION pos; CClusterItem * pci; // Delete all the items in the Contained list. pos = rlp.GetHeadPosition( ); while ( pos != NULL ) { pci = rlp.GetNext( pos ); ASSERT_VALID( pci ); // Trace( g_tagClusItemDelete, _T("DeleteAllItemData(rlpci ) - Deleting cluster item '%s'"), pci->StrName( ) ); pci->Delete( ); } // while: more items in the list } //*** DeleteAllItemData( )