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.

2256 lines
62 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c ) 1996-2000 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // ClusItem.cpp
  7. //
  8. // Description:
  9. // Implementation of the CClusterItem class.
  10. //
  11. // Maintained By:
  12. // David Potter (davidp ) May 6, 1996
  13. //
  14. // Revision History:
  15. //
  16. // Modified to fix bugs associated with open/close state of m_hkey.
  17. // m_hkey will be closed upon destruction of CClusterItem.
  18. // Roderick Sharper March 23, 1997.
  19. //
  20. // Notes:
  21. //
  22. /////////////////////////////////////////////////////////////////////////////
  23. #include "stdafx.h"
  24. #include "CluAdmin.h"
  25. #include "ConstDef.h"
  26. #include "ClusItem.h"
  27. #include "ClusDoc.h"
  28. #include "ExcOper.h"
  29. #include "TraceTag.h"
  30. #include "TreeItem.inl"
  31. #include "PropList.h"
  32. #ifdef _DEBUG
  33. #define new DEBUG_NEW
  34. #undef THIS_FILE
  35. static char THIS_FILE[] = __FILE__;
  36. #endif
  37. /////////////////////////////////////////////////////////////////////////////
  38. // Global Variables
  39. /////////////////////////////////////////////////////////////////////////////
  40. #ifdef _DEBUG
  41. CTraceTag g_tagClusItemCreate( _T("Create"), _T("CLUSTER ITEM CREATE"), 0 );
  42. CTraceTag g_tagClusItemDelete( _T("Delete"), _T("CLUSTER ITEM DELETE"), 0 );
  43. CTraceTag g_tagClusItemNotify( _T("Notify"), _T("CLUSTER ITEM NOTIFY"), 0 );
  44. #endif
  45. /////////////////////////////////////////////////////////////////////////////
  46. // CClusterItemList
  47. /////////////////////////////////////////////////////////////////////////////
  48. /////////////////////////////////////////////////////////////////////////////
  49. //++
  50. //
  51. // CClusterItemList::PciFromName
  52. //
  53. // Routine Description:
  54. // Find a cluster item in the list by its name.
  55. //
  56. // Arguments:
  57. // pszName [IN] Name of item to look for.
  58. // ppos [OUT] Position of the item in the list.
  59. //
  60. // Return Value:
  61. // pci Cluster item corresponding the the specified name.
  62. //
  63. //--
  64. /////////////////////////////////////////////////////////////////////////////
  65. CClusterItem * CClusterItemList::PciFromName(
  66. IN LPCTSTR pszName,
  67. OUT POSITION * ppos // = NULL
  68. )
  69. {
  70. POSITION posPci;
  71. POSITION posCurPci;
  72. CClusterItem * pci = NULL;
  73. ASSERT( pszName != NULL );
  74. posPci = GetHeadPosition( );
  75. while ( posPci != NULL )
  76. {
  77. posCurPci = posPci;
  78. pci = GetNext( posPci );
  79. ASSERT_VALID( pci );
  80. if ( pci->StrName( ).CompareNoCase( pszName ) == 0 )
  81. {
  82. if ( ppos != NULL )
  83. {
  84. *ppos = posCurPci;
  85. } // if
  86. break;
  87. } // if: found a match
  88. pci = NULL;
  89. } // while: more resources in the list
  90. return pci;
  91. } //*** CClusterItemList::PciFromName( )
  92. /////////////////////////////////////////////////////////////////////////////
  93. //++
  94. //
  95. // CClusterItemList::RemoveAll
  96. //
  97. // Routine Description:
  98. // Remove all items from the list, decrementing the reference count
  99. // on each one first.
  100. //
  101. // Arguments:
  102. // None.
  103. //
  104. // Return Value:
  105. // None.
  106. //
  107. // Note:
  108. // This routine is not virtual, so calls to the base class will
  109. // not go through this routine. Also, it does not call the base
  110. // class method.
  111. //
  112. //--
  113. /////////////////////////////////////////////////////////////////////////////
  114. #ifdef NEVER
  115. void CClusterItemList::RemoveAll( void )
  116. {
  117. ASSERT_VALID( this );
  118. // destroy elements
  119. CNode * pNode;
  120. for ( pNode = m_pNodeHead ; pNode != NULL ; pNode = pNode->pNext )
  121. {
  122. // ((CClusterItem *) pNode->data)->Release( );
  123. DestructElements( (CClusterItem**) &pNode->data, 1 );
  124. } // for: each node in the list
  125. // Call the base class method.
  126. CObList::RemoveAll( );
  127. } //*** CClusterItemList::RemoveAll( )
  128. #endif
  129. //***************************************************************************
  130. /////////////////////////////////////////////////////////////////////////////
  131. // CClusterItem
  132. /////////////////////////////////////////////////////////////////////////////
  133. IMPLEMENT_DYNCREATE( CClusterItem, CBaseCmdTarget )
  134. /////////////////////////////////////////////////////////////////////////////
  135. // Message Maps
  136. BEGIN_MESSAGE_MAP( CClusterItem, CBaseCmdTarget )
  137. //{{AFX_MSG_MAP(CClusterItem)
  138. ON_UPDATE_COMMAND_UI(ID_FILE_RENAME, OnUpdateRename)
  139. ON_UPDATE_COMMAND_UI(ID_FILE_PROPERTIES, OnUpdateProperties)
  140. ON_COMMAND(ID_FILE_PROPERTIES, OnCmdProperties)
  141. //}}AFX_MSG_MAP
  142. END_MESSAGE_MAP( )
  143. /////////////////////////////////////////////////////////////////////////////
  144. //++
  145. //
  146. // CClusterItem::CClusterItem
  147. //
  148. // Routine Description:
  149. // Default constructor.
  150. //
  151. // Arguments:
  152. // None.
  153. //
  154. // Return Value:
  155. // None.
  156. //
  157. //--
  158. /////////////////////////////////////////////////////////////////////////////
  159. CClusterItem::CClusterItem( void )
  160. {
  161. CommonConstruct( );
  162. } //*** CClusterItem::CClusterItem( )
  163. /////////////////////////////////////////////////////////////////////////////
  164. //++
  165. //
  166. // CClusterItem::CClusterItem
  167. //
  168. // Routine Description:
  169. // Constructor.
  170. //
  171. // Arguments:
  172. // pstrName [IN] Name of the item.
  173. // idsType [IN] Type ID of the item.
  174. // pstrDescription [IN] Description of the item.
  175. //
  176. // Return Value:
  177. // None.
  178. //
  179. //--
  180. /////////////////////////////////////////////////////////////////////////////
  181. CClusterItem::CClusterItem(
  182. IN const CString * pstrName,
  183. IN IDS idsType,
  184. IN const CString * pstrDescription
  185. )
  186. {
  187. CommonConstruct( );
  188. if ( pstrName != NULL )
  189. {
  190. m_strName = *pstrName;
  191. } // if
  192. if ( idsType == 0 )
  193. {
  194. idsType = IDS_ITEMTYPE_CONTAINER;
  195. } // if
  196. m_idsType = idsType;
  197. m_strType.LoadString( IdsType( ) );
  198. if ( pstrDescription != NULL )
  199. {
  200. m_strDescription = *pstrDescription;
  201. } // if
  202. Trace( g_tagClusItemCreate, _T("CClusterItem( ) - Creating '%s' (%s )"), m_strName, m_strType );
  203. } //*** CClusterItem::CClusterItem( )
  204. /////////////////////////////////////////////////////////////////////////////
  205. //++
  206. //
  207. // CClusterItem::CommonConstruct
  208. //
  209. // Routine Description:
  210. // Common construction.
  211. //
  212. // Arguments:
  213. // None.
  214. //
  215. // Return Value:
  216. // None.
  217. //
  218. //--
  219. /////////////////////////////////////////////////////////////////////////////
  220. void CClusterItem::CommonConstruct( void )
  221. {
  222. m_hkey = NULL;
  223. m_idsType = IDS_ITEMTYPE_CONTAINER;
  224. m_strType.LoadString( IDS_ITEMTYPE_CONTAINER );
  225. m_iimgObjectType = 0;
  226. m_iimgState = GetClusterAdminApp( )->Iimg( IMGLI_FOLDER );
  227. m_pdoc = NULL;
  228. m_idmPopupMenu = 0;
  229. m_bDocObj = TRUE;
  230. m_bChanged = FALSE;
  231. m_bReadOnly = FALSE;
  232. m_pcnk = NULL;
  233. } //*** CClusterItem::CommonConstruct( )
  234. /////////////////////////////////////////////////////////////////////////////
  235. //++
  236. //
  237. // CClusterItem::~CClusterItem
  238. //
  239. // Routine Description:
  240. // Destructor.
  241. //
  242. // Arguments:
  243. // None.
  244. //
  245. // Return Value:
  246. // None.
  247. //
  248. //--
  249. /////////////////////////////////////////////////////////////////////////////
  250. CClusterItem::~CClusterItem( void )
  251. {
  252. Trace( g_tagClusItemDelete, _T("~CClusterItem( ) - Deleting cluster item '%s'"), StrName( ) );
  253. // Empty the lists.
  254. DeleteAllItemData( LptiBackPointers( ) );
  255. DeleteAllItemData( LpliBackPointers( ) );
  256. LptiBackPointers( ).RemoveAll( );
  257. LpliBackPointers( ).RemoveAll( );
  258. // Close the registry key.
  259. if ( Hkey( ) != NULL )
  260. {
  261. ClusterRegCloseKey( Hkey( ) );
  262. m_hkey = NULL;
  263. } // if
  264. // Remove the notification key and delete it.
  265. if ( BDocObj( ) )
  266. {
  267. POSITION pos;
  268. pos = GetClusterAdminApp( )->Cnkl( ).Find( m_pcnk );
  269. if ( pos != NULL )
  270. {
  271. GetClusterAdminApp( )->Cnkl( ).RemoveAt( pos );
  272. } // if
  273. Trace( g_tagClusItemNotify, _T("~CClusterItem( ) - Deleting notification key (%08.8x ) for '%s'"), m_pcnk, StrName( ) );
  274. delete m_pcnk;
  275. m_pcnk = NULL;
  276. } // if: object resides in the document
  277. Trace( g_tagClusItemDelete, _T("~CClusterItem( ) - Done deleting cluster item '%s'"), StrName( ) );
  278. } //*** CClusterItem::~CClusterItem( )
  279. /////////////////////////////////////////////////////////////////////////////
  280. //++
  281. //
  282. // CClusterItem::Delete
  283. //
  284. // Routine Description:
  285. // Delete the item. If the item still has references, add it to the
  286. // document's pending delete list.
  287. //
  288. // Arguments:
  289. // None.
  290. //
  291. // Return Value:
  292. // None.
  293. //
  294. // Exceptions Thrown:
  295. // None.
  296. //
  297. //--
  298. /////////////////////////////////////////////////////////////////////////////
  299. void CClusterItem::Delete( void )
  300. {
  301. // Add a reference so that we don't delete ourselves while
  302. // still doing cleanup.
  303. AddRef( );
  304. // Cleanup this object.
  305. Cleanup( );
  306. // Remove the item from all lists and views.
  307. CClusterItem::RemoveItem( );
  308. // If there are still references to this object, add it to the delete
  309. // pending list. Check for greater than 1 because we added a reference
  310. // at the beginning of this method.
  311. if ( ( Pdoc( ) != NULL ) && ( NReferenceCount( ) > 1 ) )
  312. {
  313. if ( Pdoc( )->LpciToBeDeleted( ).Find( this ) == NULL )
  314. {
  315. Pdoc( )->LpciToBeDeleted( ).AddTail( this );
  316. } // if
  317. } // if: object still has references to it
  318. // Release the reference we added at the beginning. This will
  319. // cause the object to be deleted if we were the last reference.
  320. Release( );
  321. } //*** CClusterItem::Delete( )
  322. /////////////////////////////////////////////////////////////////////////////
  323. //++
  324. //
  325. // CClusterItem::Init
  326. //
  327. // Routine Description:
  328. // Initialize the item.
  329. //
  330. // Arguments:
  331. // pdoc [IN OUT] Document to which this item belongs.
  332. // lpszName [IN] Name of the item.
  333. //
  334. // Return Value:
  335. // None.
  336. //
  337. // Exceptions Thrown:
  338. // Any exceptions thrown by CNotifyKey::new( ) or
  339. // CNotifyKeyList::AddTail( ).
  340. //
  341. //--
  342. /////////////////////////////////////////////////////////////////////////////
  343. void CClusterItem::Init( IN OUT CClusterDoc * pdoc, IN LPCTSTR lpszName )
  344. {
  345. ASSERT_VALID( pdoc );
  346. ASSERT( lpszName != NULL );
  347. // Save parameters.
  348. m_pdoc = pdoc;
  349. m_strName = lpszName;
  350. Trace( g_tagClusItemCreate, _T("Init( ) - Initializing '%s' (%s )"), m_strName, m_strType );
  351. // Find the notification key for this item in the document's list.
  352. // If one is not found, allocate one.
  353. if ( BDocObj( ) )
  354. {
  355. POSITION pos;
  356. CClusterNotifyKey * pcnk = NULL;
  357. pos = GetClusterAdminApp( )->Cnkl( ).GetHeadPosition( );
  358. while ( pos != NULL )
  359. {
  360. pcnk = GetClusterAdminApp( )->Cnkl( ).GetNext( pos );
  361. if ( ( pcnk->m_cnkt == cnktClusterItem )
  362. && ( pcnk->m_pci == this )
  363. )
  364. break;
  365. pcnk = NULL;
  366. } // while: more items in the list
  367. // If a key was not found, allocate a new one.
  368. if ( pcnk == NULL )
  369. {
  370. pcnk = new CClusterNotifyKey( this, lpszName );
  371. if ( pcnk == NULL )
  372. {
  373. ThrowStaticException( GetLastError( ) );
  374. } // if: error allocating the notify key
  375. try
  376. {
  377. GetClusterAdminApp( )->Cnkl( ).AddTail( pcnk );
  378. Trace( g_tagClusItemNotify, _T("Init( ) - Creating notification key (%08.8x ) for '%s'"), pcnk, StrName( ) );
  379. } // try
  380. catch ( ... )
  381. {
  382. delete pcnk;
  383. throw;
  384. } // catch: anything
  385. } // if: key wasn't found
  386. m_pcnk = pcnk;
  387. } // if: object resides in the document
  388. } //*** CClusterItem::Init( )
  389. /////////////////////////////////////////////////////////////////////////////
  390. //++
  391. //
  392. // CClusterItem::PlstrExtensions
  393. //
  394. // Routine Description:
  395. // Return the list of admin extensions.
  396. //
  397. // Arguments:
  398. // None.
  399. //
  400. // Return Value:
  401. // plstr List of extensions.
  402. // NULL No extension associated with this object.
  403. //
  404. // Exceptions Thrown:
  405. // None.
  406. //
  407. //--
  408. /////////////////////////////////////////////////////////////////////////////
  409. const CStringList * CClusterItem::PlstrExtensions( void ) const
  410. {
  411. return NULL;
  412. } //*** CClusterItem::PlstrExtensions( )
  413. /////////////////////////////////////////////////////////////////////////////
  414. //++
  415. //
  416. // CClusterItem::RemoveItem
  417. //
  418. // Routine Description:
  419. // Remove the item from all lists and views.
  420. //
  421. // Arguments:
  422. // None.
  423. //
  424. // Return Value:
  425. // None.
  426. //
  427. // Exceptions Thrown:
  428. // None.
  429. //
  430. //--
  431. /////////////////////////////////////////////////////////////////////////////
  432. void CClusterItem::RemoveItem( void )
  433. {
  434. // Remove the item from each tree item.
  435. {
  436. POSITION posPti;
  437. CTreeItem * pti;
  438. posPti = LptiBackPointers( ).GetHeadPosition( );
  439. while ( posPti != NULL )
  440. {
  441. pti = LptiBackPointers( ).GetNext( posPti );
  442. ASSERT_VALID( pti );
  443. ASSERT_VALID( pti->PtiParent( ) );
  444. Trace( g_tagClusItemDelete, _T("RemoveItem( ) - Deleting tree item backptr from '%s' in '%s' - %d left"), StrName( ), pti->PtiParent( )->StrName( ), LptiBackPointers( ).GetCount( ) - 1 );
  445. pti->RemoveItem( );
  446. } // while: more items in the list
  447. } // Remove the item from each tree item
  448. // Remove the item from each list item.
  449. {
  450. POSITION posPli;
  451. CListItem * pli;
  452. posPli = LpliBackPointers( ).GetHeadPosition( );
  453. while ( posPli != NULL )
  454. {
  455. pli = LpliBackPointers( ).GetNext( posPli );
  456. ASSERT_VALID( pli );
  457. ASSERT_VALID( pli->PtiParent( ) );
  458. Trace( g_tagClusItemDelete, _T("RemoveItem( ) - Deleting list item backptr from '%s' in '%s' - %d left"), StrName( ), pli->PtiParent( )->StrName( ), LpliBackPointers( ).GetCount( ) - 1 );
  459. pli->PtiParent( )->RemoveChild( pli->Pci( ) );
  460. } // while: more items in the list
  461. } // Remove the item from each tree item
  462. } //*** CClusterItem::RemoveItem( )
  463. /////////////////////////////////////////////////////////////////////////////
  464. //++
  465. //
  466. // CClusterItem::WriteItem
  467. //
  468. // Routine Description:
  469. // Write the item parameters to the cluster database.
  470. //
  471. // Arguments:
  472. // None.
  473. //
  474. // Return Value:
  475. // None.
  476. //
  477. // Exceptions Thrown:
  478. // Any exceptions thrown by WriteItem( ).
  479. //
  480. //--
  481. /////////////////////////////////////////////////////////////////////////////
  482. void CClusterItem::WriteItem( void )
  483. {
  484. } //*** CClusterItem::WriteItem( )
  485. /////////////////////////////////////////////////////////////////////////////
  486. //++
  487. //
  488. // CClusterItem::DwParseProperties
  489. //
  490. // Routine Description:
  491. // Parse the properties of the resource. This is in a separate function
  492. // from BInit so that the optimizer can do a better job.
  493. //
  494. // Arguments:
  495. // rcpl [IN] Cluster property list to parse.
  496. //
  497. // Return Value:
  498. // ERROR_SUCCESS Properties were parsed successfully.
  499. //
  500. // Exceptions Thrown:
  501. // Any exceptions from CString::operator=( ).
  502. //
  503. //--
  504. /////////////////////////////////////////////////////////////////////////////
  505. DWORD CClusterItem::DwParseProperties( IN const CClusPropList & rcpl )
  506. {
  507. DWORD cProps;
  508. DWORD cprop;
  509. DWORD cbProps;
  510. const CObjectProperty * pprop;
  511. CLUSPROP_BUFFER_HELPER props;
  512. CLUSPROP_PROPERTY_NAME const * pName;
  513. ASSERT( rcpl.PbPropList( ) != NULL );
  514. props.pb = rcpl.PbPropList( );
  515. cbProps = rcpl.CbPropList( );
  516. // Loop through each property.
  517. for ( cProps = *(props.pdw++ ) ; cProps > 0 ; cProps-- )
  518. {
  519. pName = props.pName;
  520. ASSERT( pName->Syntax.dw == CLUSPROP_SYNTAX_NAME );
  521. props.pb += sizeof( *pName ) + ALIGN_CLUSPROP( pName->cbLength );
  522. // Decrement the counter by the size of the name.
  523. ASSERT( cbProps > sizeof( *pName ) + ALIGN_CLUSPROP( pName->cbLength ) );
  524. cbProps -= sizeof( *pName ) + ALIGN_CLUSPROP( pName->cbLength );
  525. ASSERT( cbProps > sizeof( *props.pValue ) + ALIGN_CLUSPROP( props.pValue->cbLength ) );
  526. // Parse known properties.
  527. for ( pprop = Pprops( ), cprop = Cprops( ) ; cprop > 0 ; pprop++, cprop-- )
  528. {
  529. if ( lstrcmpiW( pName->sz, pprop->m_pwszName ) == 0 )
  530. {
  531. ASSERT( props.pSyntax->wFormat == pprop->m_propFormat );
  532. switch ( pprop->m_propFormat )
  533. {
  534. case CLUSPROP_FORMAT_SZ:
  535. ASSERT( ( props.pValue->cbLength == ( lstrlenW( props.pStringValue->sz ) + 1 ) * sizeof( WCHAR ) )
  536. || ( (props.pValue->cbLength == 0 ) && ( props.pStringValue->sz[ 0 ] == L'\0' ) ) );
  537. *pprop->m_valuePrev.pstr = props.pStringValue->sz;
  538. break;
  539. case CLUSPROP_FORMAT_DWORD:
  540. case CLUSPROP_FORMAT_LONG:
  541. ASSERT( props.pValue->cbLength == sizeof( DWORD ) );
  542. *pprop->m_valuePrev.pdw = props.pDwordValue->dw;
  543. break;
  544. case CLUSPROP_FORMAT_BINARY:
  545. case CLUSPROP_FORMAT_MULTI_SZ:
  546. *pprop->m_valuePrev.ppb = props.pBinaryValue->rgb;
  547. *pprop->m_valuePrev.pcb = props.pBinaryValue->cbLength;
  548. break;
  549. default:
  550. ASSERT( 0 ); // don't know how to deal with this type
  551. } // switch: property format
  552. // Exit the loop since we found the parameter.
  553. break;
  554. } // if: found a match
  555. } // for: each property
  556. // If the property wasn't known, ask the derived class to parse it.
  557. if ( cprop == 0 )
  558. {
  559. DWORD dwStatus;
  560. dwStatus = DwParseUnknownProperty( pName->sz, props, cbProps );
  561. if ( dwStatus != ERROR_SUCCESS )
  562. {
  563. return dwStatus;
  564. } // if
  565. } // if: property not parsed
  566. // Advance the buffer pointer past the value in the value list.
  567. while ( ( props.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK )
  568. && ( cbProps > 0 ) )
  569. {
  570. ASSERT( cbProps > sizeof( *props.pValue ) + ALIGN_CLUSPROP( props.pValue->cbLength ) );
  571. cbProps -= sizeof( *props.pValue ) + ALIGN_CLUSPROP( props.pValue->cbLength );
  572. props.pb += sizeof( *props.pValue ) + ALIGN_CLUSPROP( props.pValue->cbLength );
  573. } // while: more values in the list
  574. // Advance the buffer pointer past the value list endmark.
  575. ASSERT( cbProps >= sizeof( *props.pSyntax ) );
  576. cbProps -= sizeof( *props.pSyntax );
  577. props.pb += sizeof( *props.pSyntax ); // endmark
  578. } // for: each property
  579. return ERROR_SUCCESS;
  580. } //*** CClusterItem::DwParseProperties( )
  581. /////////////////////////////////////////////////////////////////////////////
  582. //++
  583. //
  584. // CClusterItem::SetCommonProperties
  585. //
  586. // Routine Description:
  587. // Set the common properties for this object in the cluster database.
  588. //
  589. // Arguments:
  590. // bValidateOnly [IN] Only validate the data.
  591. //
  592. // Return Value:
  593. // None.
  594. //
  595. // Exceptions Thrown:
  596. // Any exceptions thrown by WriteItem( ).
  597. //
  598. //--
  599. /////////////////////////////////////////////////////////////////////////////
  600. void CClusterItem::SetCommonProperties( IN BOOL bValidateOnly )
  601. {
  602. DWORD dwStatus = ERROR_SUCCESS;
  603. CClusPropList cpl;
  604. CWaitCursor wc;
  605. // Save data.
  606. {
  607. // Build the property list and set the data.
  608. try
  609. {
  610. BuildPropList( cpl );
  611. dwStatus = DwSetCommonProperties( cpl, bValidateOnly );
  612. } // try
  613. catch ( CMemoryException * pme )
  614. {
  615. pme->Delete( );
  616. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  617. } // catch: CMemoryException
  618. // Handle errors.
  619. if ( dwStatus != ERROR_SUCCESS )
  620. {
  621. if ( dwStatus != ERROR_RESOURCE_PROPERTIES_STORED )
  622. {
  623. ThrowStaticException( dwStatus, IDS_APPLY_PARAM_CHANGES_ERROR );
  624. } // if
  625. } // if: error setting properties
  626. if ( ! bValidateOnly && ( dwStatus == ERROR_SUCCESS ) )
  627. {
  628. DWORD cprop;
  629. const CObjectProperty * pprop;
  630. // Save new values as previous values.
  631. for ( pprop = Pprops( ), cprop = Cprops( ) ; cprop > 0 ; pprop++, cprop-- )
  632. {
  633. switch ( pprop->m_propFormat )
  634. {
  635. case CLUSPROP_FORMAT_SZ:
  636. ASSERT( pprop->m_value.pstr != NULL );
  637. ASSERT( pprop->m_valuePrev.pstr != NULL );
  638. *pprop->m_valuePrev.pstr = *pprop->m_value.pstr;
  639. break;
  640. case CLUSPROP_FORMAT_DWORD:
  641. ASSERT( pprop->m_value.pdw != NULL );
  642. ASSERT( pprop->m_valuePrev.pdw != NULL );
  643. *pprop->m_valuePrev.pdw = *pprop->m_value.pdw;
  644. break;
  645. case CLUSPROP_FORMAT_BINARY:
  646. case CLUSPROP_FORMAT_MULTI_SZ:
  647. ASSERT( pprop->m_value.ppb != NULL );
  648. ASSERT( *pprop->m_value.ppb != NULL );
  649. ASSERT( pprop->m_value.pcb != NULL );
  650. ASSERT( pprop->m_valuePrev.ppb != NULL );
  651. ASSERT( *pprop->m_valuePrev.ppb != NULL );
  652. ASSERT( pprop->m_valuePrev.pcb != NULL );
  653. delete [] *pprop->m_valuePrev.ppb;
  654. *pprop->m_valuePrev.ppb = new BYTE[ *pprop->m_value.pcb ];
  655. if ( *pprop->m_valuePrev.ppb == NULL )
  656. {
  657. ThrowStaticException( GetLastError( ) );
  658. } // if: error allocating data buffer
  659. CopyMemory( *pprop->m_valuePrev.ppb, *pprop->m_value.ppb, *pprop->m_value.pcb );
  660. *pprop->m_valuePrev.pcb = *pprop->m_value.pcb;
  661. break;
  662. default:
  663. ASSERT( 0 ); // don't know how to deal with this type
  664. } // switch: property format
  665. } // for: each property
  666. } // if: not just validating and properties set successfully
  667. if ( dwStatus == ERROR_RESOURCE_PROPERTIES_STORED )
  668. {
  669. ThrowStaticException( dwStatus );
  670. } // if
  671. } // Save data
  672. } //*** CClusterItem::SetCommonProperties( )
  673. /////////////////////////////////////////////////////////////////////////////
  674. //++
  675. //
  676. // CClusterItem::BuildPropList
  677. //
  678. // Routine Description:
  679. // Build the property list.
  680. //
  681. // Arguments:
  682. // rcpl [IN OUT] Cluster property list.
  683. //
  684. // Return Value:
  685. // None.
  686. //
  687. // Exceptions Thrown:
  688. // Any exceptions thrown by CClusPropList::ScAddProp( ).
  689. //
  690. //--
  691. /////////////////////////////////////////////////////////////////////////////
  692. void CClusterItem::BuildPropList(
  693. IN OUT CClusPropList & rcpl
  694. )
  695. {
  696. DWORD cprop;
  697. const CObjectProperty * pprop;
  698. for ( pprop = Pprops( ), cprop = Cprops( ) ; cprop > 0 ; pprop++, cprop-- )
  699. {
  700. switch ( pprop->m_propFormat )
  701. {
  702. case CLUSPROP_FORMAT_SZ:
  703. rcpl.ScAddProp(
  704. pprop->m_pwszName,
  705. *pprop->m_value.pstr,
  706. *pprop->m_valuePrev.pstr
  707. );
  708. break;
  709. case CLUSPROP_FORMAT_DWORD:
  710. rcpl.ScAddProp(
  711. pprop->m_pwszName,
  712. *pprop->m_value.pdw,
  713. *pprop->m_valuePrev.pdw
  714. );
  715. break;
  716. case CLUSPROP_FORMAT_BINARY:
  717. case CLUSPROP_FORMAT_MULTI_SZ:
  718. rcpl.ScAddProp(
  719. pprop->m_pwszName,
  720. *pprop->m_value.ppb,
  721. *pprop->m_value.pcb,
  722. *pprop->m_valuePrev.ppb,
  723. *pprop->m_valuePrev.pcb
  724. );
  725. break;
  726. default:
  727. ASSERT( 0 ); // don't know how to deal with this type
  728. return;
  729. } // switch: property format
  730. } // for: each property
  731. } //*** CClusterItem::BuildPropList( )
  732. /////////////////////////////////////////////////////////////////////////////
  733. //++
  734. //
  735. // CClusterItem::UpdateState
  736. //
  737. // Routine Description:
  738. // Update the current state of the item.
  739. // Default implementation.
  740. //
  741. // Arguments:
  742. // None.
  743. //
  744. // Return Value:
  745. // None.
  746. //
  747. //--
  748. /////////////////////////////////////////////////////////////////////////////
  749. void CClusterItem::UpdateState( void )
  750. {
  751. // Update the state of all the tree items pointing to us.
  752. {
  753. POSITION pos;
  754. CTreeItem * pti;
  755. pos = LptiBackPointers( ).GetHeadPosition( );
  756. while ( pos != NULL )
  757. {
  758. pti = LptiBackPointers( ).GetNext( pos );
  759. ASSERT_VALID( pti );
  760. pti->UpdateUIState( );
  761. } // while: more items in the list
  762. } // Update the state of all the tree items pointing to us
  763. // Update the state of all the list items pointing to us.
  764. {
  765. POSITION pos;
  766. CListItem * pli;
  767. pos = LpliBackPointers( ).GetHeadPosition( );
  768. while ( pos != NULL )
  769. {
  770. pli = LpliBackPointers( ).GetNext( pos );
  771. ASSERT_VALID( pli );
  772. pli->UpdateUIState( );
  773. } // while: more items in the list
  774. } // Update the state of all the tree items pointing to us
  775. } //*** CClusterItem::UpdateState( )
  776. /////////////////////////////////////////////////////////////////////////////
  777. //++
  778. //
  779. // CClusterItem::DwReadValue
  780. //
  781. // Routine Description:
  782. // Read a REG_SZ value for this item.
  783. //
  784. // Arguments:
  785. // pszValueName [IN] Name of the value to read.
  786. // pszKeyName [IN] Name of the key where the value resides.
  787. // rstrValue [OUT] String in which to return the value.
  788. //
  789. // Return Value:
  790. // dwStatus ERROR_SUCCESS = success, !0 = failure
  791. //
  792. //--
  793. /////////////////////////////////////////////////////////////////////////////
  794. DWORD CClusterItem::DwReadValue(
  795. IN LPCTSTR pszValueName,
  796. IN LPCTSTR pszKeyName,
  797. OUT CString & rstrValue
  798. )
  799. {
  800. DWORD dwStatus;
  801. LPWSTR pwszValue = NULL;
  802. DWORD dwValueLen;
  803. DWORD dwValueType;
  804. HKEY hkey = NULL;
  805. CWaitCursor wc;
  806. ASSERT( pszValueName != NULL );
  807. ASSERT( Hkey( ) != NULL );
  808. rstrValue.Empty( );
  809. try
  810. {
  811. // Open a new key if needed.
  812. if ( pszKeyName != NULL )
  813. {
  814. dwStatus = ClusterRegOpenKey( Hkey( ), pszKeyName, KEY_READ, &hkey );
  815. if ( dwStatus != ERROR_SUCCESS )
  816. {
  817. return dwStatus;
  818. } // if
  819. } // if: need to open a subkey
  820. else
  821. {
  822. hkey = Hkey( );
  823. } // else
  824. // Get the size of the value.
  825. dwValueLen = 0;
  826. dwStatus = ClusterRegQueryValue(
  827. hkey,
  828. pszValueName,
  829. &dwValueType,
  830. NULL,
  831. &dwValueLen
  832. );
  833. if ( ( dwStatus == ERROR_SUCCESS ) || ( dwStatus == ERROR_MORE_DATA ) )
  834. {
  835. ASSERT( dwValueType == REG_SZ );
  836. // Allocate enough space for the data.
  837. pwszValue = rstrValue.GetBuffer( dwValueLen / sizeof( WCHAR ) );
  838. ASSERT( pwszValue != NULL );
  839. dwValueLen += 1 * sizeof( WCHAR ); // Don't forget the final null-terminator.
  840. // Read the value.
  841. dwStatus = ClusterRegQueryValue(
  842. hkey,
  843. pszValueName,
  844. &dwValueType,
  845. (LPBYTE ) pwszValue,
  846. &dwValueLen
  847. );
  848. if ( dwStatus == ERROR_SUCCESS )
  849. {
  850. ASSERT( dwValueType == REG_SZ );
  851. } // if: value read successfully
  852. rstrValue.ReleaseBuffer( );
  853. } // if: got the size successfully
  854. } // try
  855. catch ( CMemoryException * pme )
  856. {
  857. pme->Delete( );
  858. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  859. } // catch: CMemoryException
  860. if ( pszKeyName != NULL )
  861. {
  862. ClusterRegCloseKey( hkey );
  863. } // if
  864. return dwStatus;
  865. } //*** CClusterItem::DwReadValue( LPCTSTR, CString& )
  866. /////////////////////////////////////////////////////////////////////////////
  867. //++
  868. //
  869. // CClusterItem::DwReadValue
  870. //
  871. // Routine Description:
  872. // Read a REG_MULTI_SZ value for this item.
  873. //
  874. // Arguments:
  875. // pszValueName [IN] Name of the value to read.
  876. // pszKeyName [IN] Name of the key where the value resides.
  877. // rlstrValue [OUT] String list in which to return the values.
  878. //
  879. // Return Value:
  880. // dwStatus ERROR_SUCCESS = success, !0 = failure
  881. //
  882. //--
  883. /////////////////////////////////////////////////////////////////////////////
  884. DWORD CClusterItem::DwReadValue(
  885. IN LPCTSTR pszValueName,
  886. IN LPCTSTR pszKeyName,
  887. OUT CStringList & rlstrValue
  888. )
  889. {
  890. DWORD dwStatus;
  891. LPWSTR pwszValue = NULL;
  892. LPWSTR pwszCurValue;
  893. DWORD dwValueLen;
  894. DWORD dwValueType;
  895. HKEY hkey = NULL;
  896. CWaitCursor wc;
  897. ASSERT( pszValueName != NULL );
  898. ASSERT( Hkey( ) != NULL );
  899. rlstrValue.RemoveAll( );
  900. try
  901. {
  902. // Open a new key if needed.
  903. if ( pszKeyName != NULL )
  904. {
  905. dwStatus = ClusterRegOpenKey( Hkey( ), pszKeyName, KEY_READ, &hkey );
  906. if ( dwStatus != ERROR_SUCCESS )
  907. {
  908. return dwStatus;
  909. } // if
  910. } // if: need to open a subkey
  911. else
  912. hkey = Hkey( );
  913. // Get the size of the value.
  914. dwValueLen = 0;
  915. dwStatus = ClusterRegQueryValue(
  916. hkey,
  917. pszValueName,
  918. &dwValueType,
  919. NULL,
  920. &dwValueLen
  921. );
  922. if ( ( dwStatus == ERROR_SUCCESS ) || ( dwStatus == ERROR_MORE_DATA ) )
  923. {
  924. ASSERT( dwValueType == REG_MULTI_SZ );
  925. // Allocate enough space for the data.
  926. dwValueLen += 1 * sizeof( WCHAR ); // Don't forget the final null-terminator.
  927. pwszValue = new WCHAR[ dwValueLen / sizeof( WCHAR ) ];
  928. if ( pwszValue == NULL )
  929. {
  930. AfxThrowMemoryException();
  931. } // if: error allocating the value
  932. // Read the value.
  933. dwStatus = ClusterRegQueryValue(
  934. hkey,
  935. pszValueName,
  936. &dwValueType,
  937. (LPBYTE) pwszValue,
  938. &dwValueLen
  939. );
  940. if ( dwStatus == ERROR_SUCCESS )
  941. {
  942. ASSERT( dwValueType == REG_MULTI_SZ );
  943. // Add each string from the value into the string list.
  944. for ( pwszCurValue = pwszValue
  945. ; *pwszCurValue != L'\0'
  946. ; pwszCurValue += lstrlenW( pwszCurValue ) + 1
  947. )
  948. {
  949. rlstrValue.AddTail( pwszCurValue );
  950. } // for
  951. } // if: read the value successfully
  952. } // if: got the size successfully
  953. } // try
  954. catch ( CMemoryException * pme )
  955. {
  956. pme->Delete( );
  957. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  958. } // catch: CMemoryException
  959. delete [] pwszValue;
  960. if ( pszKeyName != NULL )
  961. {
  962. ClusterRegCloseKey( hkey );
  963. } // if
  964. return dwStatus;
  965. } //*** CClusterItem::DwReadValue( LPCTSTR, CStringList& )
  966. /////////////////////////////////////////////////////////////////////////////
  967. //++
  968. //
  969. // CClusterItem::DwReadValue
  970. //
  971. // Routine Description:
  972. // Read a REG_DWORD value for this item.
  973. //
  974. // Arguments:
  975. // pszValueName [IN] Name of the value to read.
  976. // pszKeyName [IN] Name of the key where the value resides.
  977. // pdwValue [OUT] DWORD in which to return the value.
  978. //
  979. // Return Value:
  980. // dwStatus ERROR_SUCCESS = success, !0 = failure
  981. //
  982. //--
  983. /////////////////////////////////////////////////////////////////////////////
  984. DWORD CClusterItem::DwReadValue(
  985. IN LPCTSTR pszValueName,
  986. IN LPCTSTR pszKeyName,
  987. OUT DWORD * pdwValue
  988. )
  989. {
  990. DWORD dwStatus;
  991. DWORD dwValue;
  992. DWORD dwValueLen;
  993. DWORD dwValueType;
  994. HKEY hkey;
  995. CWaitCursor wc;
  996. ASSERT( pszValueName != NULL );
  997. ASSERT( pdwValue != NULL );
  998. ASSERT( Hkey( ) != NULL );
  999. // Open a new key if needed.
  1000. if ( pszKeyName != NULL )
  1001. {
  1002. dwStatus = ClusterRegOpenKey( Hkey( ), pszKeyName, KEY_READ, &hkey );
  1003. if ( dwStatus != ERROR_SUCCESS )
  1004. {
  1005. return dwStatus;
  1006. } // if
  1007. } // if: need to open a subkey
  1008. else
  1009. {
  1010. hkey = Hkey( );
  1011. } // else
  1012. // Read the value.
  1013. dwValueLen = sizeof( dwValue );
  1014. dwStatus = ClusterRegQueryValue(
  1015. hkey,
  1016. pszValueName,
  1017. &dwValueType,
  1018. (LPBYTE) &dwValue,
  1019. &dwValueLen
  1020. );
  1021. if ( dwStatus == ERROR_SUCCESS )
  1022. {
  1023. ASSERT( dwValueType == REG_DWORD );
  1024. ASSERT( dwValueLen == sizeof( dwValue ) );
  1025. *pdwValue = dwValue;
  1026. } // if: value read successfully
  1027. if ( pszKeyName != NULL )
  1028. {
  1029. ClusterRegCloseKey( hkey );
  1030. } // if
  1031. return dwStatus;
  1032. } //*** CClusterItem::DwReadValue( LPCTSTR, DWORD* )
  1033. /////////////////////////////////////////////////////////////////////////////
  1034. //++
  1035. //
  1036. // CClusterItem::DwReadValue
  1037. //
  1038. // Routine Description:
  1039. // Read a REG_DWORD value for this item.
  1040. //
  1041. // Arguments:
  1042. // pszValueName [IN] Name of the value to read.
  1043. // pszKeyName [IN] Name of the key where the value resides.
  1044. // pdwValue [OUT] DWORD in which to return the value.
  1045. // dwDefault [IN] Default value if parameter not set.
  1046. //
  1047. // Return Value:
  1048. // dwStatus ERROR_SUCCESS = success, !0 = failure
  1049. //
  1050. //--
  1051. /////////////////////////////////////////////////////////////////////////////
  1052. DWORD CClusterItem::DwReadValue(
  1053. IN LPCTSTR pszValueName,
  1054. IN LPCTSTR pszKeyName,
  1055. OUT DWORD * pdwValue,
  1056. IN DWORD dwDefault
  1057. )
  1058. {
  1059. DWORD dwStatus;
  1060. CWaitCursor wc;
  1061. // Read the value.
  1062. dwStatus = DwReadValue( pszValueName, pszKeyName, pdwValue );
  1063. if ( dwStatus == ERROR_FILE_NOT_FOUND )
  1064. {
  1065. *pdwValue = dwDefault;
  1066. dwStatus = ERROR_SUCCESS;
  1067. } // if: value not set
  1068. return dwStatus;
  1069. } //*** CClusterItem::DwReadValue( LPCTSTR, DWORD*, DWORD )
  1070. /////////////////////////////////////////////////////////////////////////////
  1071. //++
  1072. //
  1073. // CClusterItem::DwReadValue
  1074. //
  1075. // Routine Description:
  1076. // Read a REG_BINARY value for this item.
  1077. //
  1078. // Arguments:
  1079. // pszValueName [IN] Name of the value to read.
  1080. // pszKeyName [IN] Name of the key where the value resides.
  1081. // ppbValue [OUT] Pointer in which to return the data. Caller
  1082. // is responsible for deallocating the data.
  1083. //
  1084. // Return Value:
  1085. // dwStatus ERROR_SUCCESS = success, !0 = failure
  1086. //
  1087. //--
  1088. /////////////////////////////////////////////////////////////////////////////
  1089. DWORD CClusterItem::DwReadValue(
  1090. IN LPCTSTR pszValueName,
  1091. IN LPCTSTR pszKeyName,
  1092. OUT LPBYTE * ppbValue
  1093. )
  1094. {
  1095. DWORD dwStatus;
  1096. DWORD dwValueLen;
  1097. DWORD dwValueType;
  1098. LPBYTE pbValue = NULL;
  1099. HKEY hkey;
  1100. CWaitCursor wc;
  1101. ASSERT( pszValueName != NULL );
  1102. ASSERT( ppbValue != NULL );
  1103. ASSERT( Hkey( ) != NULL );
  1104. delete [] *ppbValue;
  1105. *ppbValue = NULL;
  1106. // Open a new key if needed.
  1107. if ( pszKeyName != NULL )
  1108. {
  1109. dwStatus = ClusterRegOpenKey( Hkey( ), pszKeyName, KEY_READ, &hkey );
  1110. if ( dwStatus != ERROR_SUCCESS )
  1111. {
  1112. return dwStatus;
  1113. } // if
  1114. } // if: need to open a subkey
  1115. else
  1116. {
  1117. hkey = Hkey( );
  1118. } // else
  1119. // Get the length of the value.
  1120. dwValueLen = 0;
  1121. dwStatus = ClusterRegQueryValue(
  1122. hkey,
  1123. pszValueName,
  1124. &dwValueType,
  1125. NULL,
  1126. &dwValueLen
  1127. );
  1128. if ( ( dwStatus != ERROR_SUCCESS )
  1129. && ( dwStatus != ERROR_MORE_DATA ) )
  1130. {
  1131. if ( pszKeyName != NULL )
  1132. {
  1133. ClusterRegCloseKey( hkey );
  1134. } // if
  1135. return dwStatus;
  1136. } // if: error getting the length
  1137. ASSERT( dwValueType == REG_BINARY );
  1138. // Allocate a buffer,
  1139. try
  1140. {
  1141. pbValue = new BYTE[ dwValueLen ];
  1142. if ( pbValue == NULL )
  1143. {
  1144. AfxThrowMemoryException();
  1145. } // if: error allocating the buffer
  1146. } // try
  1147. catch ( CMemoryException * )
  1148. {
  1149. if ( pszKeyName != NULL )
  1150. {
  1151. ClusterRegCloseKey( hkey );
  1152. } // if
  1153. dwStatus = ERROR_NOT_ENOUGH_MEMORY;
  1154. return dwStatus;
  1155. } // catch: CMemoryException
  1156. // Read the value.
  1157. dwStatus = ClusterRegQueryValue(
  1158. hkey,
  1159. pszValueName,
  1160. &dwValueType,
  1161. pbValue,
  1162. &dwValueLen
  1163. );
  1164. if ( dwStatus == ERROR_SUCCESS )
  1165. {
  1166. *ppbValue = pbValue;
  1167. } // if
  1168. else
  1169. {
  1170. delete [] pbValue;
  1171. } // else
  1172. if ( pszKeyName != NULL )
  1173. {
  1174. ClusterRegCloseKey( hkey );
  1175. } // if
  1176. return dwStatus;
  1177. } //*** CClusterItem::DwReadValue( LPCTSTR, LPBYTE* )
  1178. /////////////////////////////////////////////////////////////////////////////
  1179. //++
  1180. //
  1181. // CClusterItem::WriteValue
  1182. //
  1183. // Routine Description:
  1184. // Write a REG_SZ value for this item.
  1185. //
  1186. // Arguments:
  1187. // pszValueName [IN] Name of the value to write.
  1188. // pszKeyName [IN] Name of the key where the value resides.
  1189. // rstrValue [IN] Value data.
  1190. //
  1191. // Return Value:
  1192. // None.
  1193. //
  1194. // Exceptions Thrown:
  1195. // CNTException( dwStatus )
  1196. //
  1197. //--
  1198. /////////////////////////////////////////////////////////////////////////////
  1199. void CClusterItem::WriteValue(
  1200. IN LPCTSTR pszValueName,
  1201. IN LPCTSTR pszKeyName,
  1202. IN const CString & rstrValue
  1203. )
  1204. {
  1205. DWORD dwStatus;
  1206. HKEY hkey;
  1207. CWaitCursor wc;
  1208. ASSERT( pszValueName != NULL );
  1209. ASSERT( Hkey( ) != NULL );
  1210. // Open a new key if needed.
  1211. if ( pszKeyName != NULL )
  1212. {
  1213. dwStatus = ClusterRegOpenKey( Hkey( ), pszKeyName, KEY_ALL_ACCESS, &hkey );
  1214. if ( dwStatus != ERROR_SUCCESS )
  1215. {
  1216. ThrowStaticException( dwStatus );
  1217. } // if
  1218. } // if: need to open a subkey
  1219. else
  1220. {
  1221. hkey = Hkey( );
  1222. } // else
  1223. // Write the value.
  1224. dwStatus = ClusterRegSetValue(
  1225. hkey,
  1226. pszValueName,
  1227. REG_SZ,
  1228. (CONST BYTE *) (LPCTSTR) rstrValue,
  1229. ( rstrValue.GetLength( ) + 1 ) * sizeof( WCHAR )
  1230. );
  1231. if ( pszKeyName != NULL )
  1232. {
  1233. ClusterRegCloseKey( hkey );
  1234. } // if
  1235. if ( dwStatus != ERROR_SUCCESS )
  1236. {
  1237. ThrowStaticException( dwStatus );
  1238. } // if
  1239. } //*** CClusterItem::WriteValue( LPCTSTR, CString& )
  1240. /////////////////////////////////////////////////////////////////////////////
  1241. //++
  1242. //
  1243. // CClusterItem::WriteValue
  1244. //
  1245. // Routine Description:
  1246. // Write a REG_MULTI_SZ value for this item.
  1247. //
  1248. // Arguments:
  1249. // pszValueName [IN] Name of the value to write.
  1250. // pszKeyName [IN] Name of the key where the value resides.
  1251. // rlstrValue [IN] Value data.
  1252. //
  1253. // Return Value:
  1254. // None.
  1255. //
  1256. // Exceptions Thrown:
  1257. // CNTException( dwStatus )
  1258. // Any exceptions thrown by new.
  1259. //
  1260. //--
  1261. /////////////////////////////////////////////////////////////////////////////
  1262. void CClusterItem::WriteValue(
  1263. IN LPCTSTR pszValueName,
  1264. IN LPCTSTR pszKeyName,
  1265. IN const CStringList & rlstrValue
  1266. )
  1267. {
  1268. DWORD dwStatus;
  1269. LPWSTR pwszValue = NULL;
  1270. LPWSTR pwszCurValue;
  1271. POSITION posStr;
  1272. DWORD cbValueLen;
  1273. HKEY hkey;
  1274. CWaitCursor wc;
  1275. ASSERT( pszValueName != NULL );
  1276. ASSERT( Hkey( ) != NULL );
  1277. // Get the size of the value.
  1278. posStr = rlstrValue.GetHeadPosition( );
  1279. cbValueLen = 0;
  1280. while ( posStr != NULL )
  1281. {
  1282. cbValueLen += ( rlstrValue.GetNext( posStr ).GetLength( ) + 1 ) * sizeof( TCHAR );
  1283. } // while: more items in the list
  1284. cbValueLen += 1 * sizeof( WCHAR ); // Extra NULL at the end.
  1285. // Allocate the value buffer.
  1286. pwszValue = new WCHAR[cbValueLen / sizeof( WCHAR )];
  1287. if ( pwszValue == NULL )
  1288. {
  1289. ThrowStaticException( GetLastError( ) );
  1290. } // if
  1291. // Copy the strings to the values.
  1292. posStr = rlstrValue.GetHeadPosition( );
  1293. for ( pwszCurValue = pwszValue ; posStr != NULL ; pwszCurValue += lstrlenW( pwszCurValue ) + 1 )
  1294. {
  1295. lstrcpyW( pwszCurValue, rlstrValue.GetNext( posStr ) );
  1296. } // for: each item in the list
  1297. pwszCurValue[0] = L'\0';
  1298. // Open a new key if needed.
  1299. if ( pszKeyName != NULL )
  1300. {
  1301. dwStatus = ClusterRegOpenKey( Hkey( ), pszKeyName, KEY_ALL_ACCESS, &hkey );
  1302. if ( dwStatus != ERROR_SUCCESS )
  1303. {
  1304. delete [] pwszValue;
  1305. ThrowStaticException( dwStatus );
  1306. } // if: error opening the key
  1307. } // if: need to open a subkey
  1308. else
  1309. {
  1310. hkey = Hkey( );
  1311. } // else
  1312. // Write the value.
  1313. dwStatus = ClusterRegSetValue(
  1314. hkey,
  1315. pszValueName,
  1316. REG_MULTI_SZ,
  1317. (CONST BYTE *) pwszValue,
  1318. cbValueLen - ( 1 * sizeof( WCHAR ) )
  1319. );
  1320. delete [] pwszValue;
  1321. if ( pszKeyName != NULL )
  1322. {
  1323. ClusterRegCloseKey( hkey );
  1324. } // if
  1325. if ( dwStatus != ERROR_SUCCESS )
  1326. {
  1327. ThrowStaticException( dwStatus );
  1328. } // if
  1329. } //*** CClusterItem::WriteValue( LPCTSTR, CStringList& )
  1330. /////////////////////////////////////////////////////////////////////////////
  1331. //++
  1332. //
  1333. // CClusterItem::WriteValue
  1334. //
  1335. // Routine Description:
  1336. // Write a REG_DWORD value for this item.
  1337. //
  1338. // Arguments:
  1339. // pszValueName [IN] Name of the value to write.
  1340. // pszKeyName [IN] Name of the key where the value resides.
  1341. // dwValue [IN] Value data.
  1342. //
  1343. // Return Value:
  1344. // None.
  1345. //
  1346. // Exceptions Thrown:
  1347. // CNTException( dwStatus )
  1348. //
  1349. //--
  1350. /////////////////////////////////////////////////////////////////////////////
  1351. void CClusterItem::WriteValue(
  1352. IN LPCTSTR pszValueName,
  1353. IN LPCTSTR pszKeyName,
  1354. IN DWORD dwValue
  1355. )
  1356. {
  1357. DWORD dwStatus;
  1358. HKEY hkey;
  1359. CWaitCursor wc;
  1360. ASSERT( pszValueName != NULL );
  1361. ASSERT( Hkey( ) != NULL );
  1362. // Open a new key if needed.
  1363. if ( pszKeyName != NULL )
  1364. {
  1365. dwStatus = ClusterRegOpenKey( Hkey( ), pszKeyName, KEY_ALL_ACCESS, &hkey );
  1366. if ( dwStatus != ERROR_SUCCESS )
  1367. {
  1368. ThrowStaticException( dwStatus );
  1369. } // if
  1370. } // if: need to open a subkey
  1371. else
  1372. hkey = Hkey( );
  1373. // Write the value.
  1374. dwStatus = ClusterRegSetValue(
  1375. hkey,
  1376. pszValueName,
  1377. REG_DWORD,
  1378. (CONST BYTE *) &dwValue,
  1379. sizeof( dwValue )
  1380. );
  1381. if ( pszKeyName != NULL )
  1382. {
  1383. ClusterRegCloseKey( hkey );
  1384. } // if
  1385. if ( dwStatus != ERROR_SUCCESS )
  1386. {
  1387. ThrowStaticException( dwStatus );
  1388. } // if
  1389. } //*** CClusterItem::WriteValue( LPCTSTR, DWORD )
  1390. /////////////////////////////////////////////////////////////////////////////
  1391. //++
  1392. //
  1393. // CClusterItem::WriteValue
  1394. //
  1395. // Routine Description:
  1396. // Write a REG_BINARY value for this item if it hasn't changed.
  1397. //
  1398. // Arguments:
  1399. // pszValueName [IN] Name of the value to write.
  1400. // pszKeyName [IN] Name of the key where the value resides.
  1401. // pbValue [IN] Value data.
  1402. // cbValue [IN] Size of value data.
  1403. // ppbPrevValue [IN OUT] Previous value.
  1404. // cbPrevValue [IN] Size of the previous data.
  1405. //
  1406. // Return Value:
  1407. // None.
  1408. //
  1409. // Exceptions Thrown:
  1410. // CNTException( dwStatus )
  1411. //
  1412. //--
  1413. /////////////////////////////////////////////////////////////////////////////
  1414. void CClusterItem::WriteValue(
  1415. IN LPCTSTR pszValueName,
  1416. IN LPCTSTR pszKeyName,
  1417. IN const LPBYTE pbValue,
  1418. IN DWORD cbValue,
  1419. IN OUT LPBYTE * ppbPrevValue,
  1420. IN DWORD cbPrevValue
  1421. )
  1422. {
  1423. DWORD dwStatus;
  1424. LPBYTE pbPrevValue = NULL;
  1425. HKEY hkey;
  1426. CWaitCursor wc;
  1427. ASSERT( pszValueName != NULL );
  1428. ASSERT( pbValue != NULL );
  1429. ASSERT( ppbPrevValue != NULL );
  1430. ASSERT( cbValue > 0 );
  1431. ASSERT( Hkey( ) != NULL );
  1432. // See if the data has changed.
  1433. if ( cbValue == cbPrevValue )
  1434. {
  1435. DWORD ib;
  1436. for ( ib = 0 ; ib < cbValue ; ib++ )
  1437. {
  1438. if ( pbValue[ ib ] != (*ppbPrevValue )[ ib ] )
  1439. {
  1440. break;
  1441. } // if
  1442. } // for: each byte in the value
  1443. if ( ib == cbValue )
  1444. {
  1445. return;
  1446. } // if
  1447. } // if: lengths are the same
  1448. // Allocate a new buffer for the previous data pointer.
  1449. pbPrevValue = new BYTE[ cbValue ];
  1450. if ( pbPrevValue == NULL )
  1451. {
  1452. ThrowStaticException( GetLastError( ) );
  1453. } // if: error allocating previous data buffer
  1454. CopyMemory( pbPrevValue, pbValue, cbValue );
  1455. // Open a new key if needed.
  1456. if ( pszKeyName != NULL )
  1457. {
  1458. dwStatus = ClusterRegOpenKey( Hkey( ), pszKeyName, KEY_ALL_ACCESS, &hkey );
  1459. if ( dwStatus != ERROR_SUCCESS )
  1460. {
  1461. delete [] pbPrevValue;
  1462. ThrowStaticException( dwStatus );
  1463. } // if: error opening the key
  1464. } // if: need to open a subkey
  1465. else
  1466. {
  1467. hkey = Hkey( );
  1468. } // else
  1469. // Write the value if it hasn't changed.
  1470. dwStatus = ClusterRegSetValue(
  1471. hkey,
  1472. pszValueName,
  1473. REG_BINARY,
  1474. pbValue,
  1475. cbValue
  1476. );
  1477. if ( pszKeyName != NULL )
  1478. {
  1479. ClusterRegCloseKey( hkey );
  1480. } // if
  1481. if ( dwStatus == ERROR_SUCCESS )
  1482. {
  1483. delete [] *ppbPrevValue;
  1484. *ppbPrevValue = pbPrevValue;
  1485. } // if: set was successful
  1486. else
  1487. {
  1488. delete [] pbPrevValue;
  1489. ThrowStaticException( dwStatus );
  1490. } // else: error setting the value
  1491. } //*** CClusterItem::WriteValue( LPCTSTR, const LPBYTE )
  1492. /////////////////////////////////////////////////////////////////////////////
  1493. //++
  1494. //
  1495. // CClusterItem::DeleteValue
  1496. //
  1497. // Routine Description:
  1498. // Delete the value for this item.
  1499. //
  1500. // Arguments:
  1501. // pszValueName [IN] Name of the value to delete.
  1502. // pszKeyName [IN] Name of the key where the value resides.
  1503. // rstrValue [IN] Value data.
  1504. //
  1505. // Return Value:
  1506. // None.
  1507. //
  1508. // Exceptions Thrown:
  1509. // CNTException( dwStatus )
  1510. //
  1511. //--
  1512. /////////////////////////////////////////////////////////////////////////////
  1513. void CClusterItem::DeleteValue(
  1514. IN LPCTSTR pszValueName,
  1515. IN LPCTSTR pszKeyName
  1516. )
  1517. {
  1518. DWORD dwStatus;
  1519. HKEY hkey;
  1520. CWaitCursor wc;
  1521. ASSERT( pszValueName != NULL );
  1522. ASSERT( Hkey( ) != NULL );
  1523. // Open a new key if needed.
  1524. if ( pszKeyName != NULL )
  1525. {
  1526. dwStatus = ClusterRegOpenKey( Hkey( ), pszKeyName, KEY_ALL_ACCESS, &hkey );
  1527. if ( dwStatus != ERROR_SUCCESS )
  1528. {
  1529. ThrowStaticException( dwStatus );
  1530. } // if
  1531. } // if: need to open a subkey
  1532. else
  1533. {
  1534. hkey = Hkey( );
  1535. } // else
  1536. // Delete the value.
  1537. dwStatus = ClusterRegDeleteValue( hkey, pszValueName );
  1538. if ( pszKeyName != NULL )
  1539. {
  1540. ClusterRegCloseKey( hkey );
  1541. } // if
  1542. if ( dwStatus != ERROR_SUCCESS )
  1543. {
  1544. ThrowStaticException( dwStatus );
  1545. } // if
  1546. } //*** CClusterItem::DeleteValue( LPCTSTR )
  1547. /////////////////////////////////////////////////////////////////////////////
  1548. //++
  1549. //
  1550. // CClusterItem::BDifferent
  1551. //
  1552. // Routine Description:
  1553. // Compare two string lists.
  1554. //
  1555. // Arguments:
  1556. // rlstr1 [IN] First string list.
  1557. // rlstr2 [IN] Second string list.
  1558. //
  1559. // Return Value:
  1560. // TRUE Lists are different.
  1561. // FALSE Lists are the same.
  1562. //
  1563. //--
  1564. /////////////////////////////////////////////////////////////////////////////
  1565. BOOL CClusterItem::BDifferent(
  1566. IN const CStringList & rlstr1,
  1567. IN const CStringList & rlstr2
  1568. )
  1569. {
  1570. BOOL bDifferent;
  1571. if ( rlstr1.GetCount( ) == rlstr2.GetCount( ) )
  1572. {
  1573. POSITION posStr;
  1574. bDifferent = FALSE;
  1575. posStr = rlstr1.GetHeadPosition( );
  1576. while ( posStr != NULL )
  1577. {
  1578. if ( rlstr2.Find( rlstr1.GetNext( posStr ) ) == 0 )
  1579. {
  1580. bDifferent = TRUE;
  1581. break;
  1582. } // if: string wasn't found
  1583. } // while: more items in the list
  1584. } // if: lists are the same size
  1585. else
  1586. {
  1587. bDifferent = TRUE;
  1588. } // else
  1589. return bDifferent;
  1590. } //*** CClusterItem::BDifferent( )
  1591. /////////////////////////////////////////////////////////////////////////////
  1592. //++
  1593. //
  1594. // CClusterItem::BDifferentOrdered
  1595. //
  1596. // Routine Description:
  1597. // Compare two string lists.
  1598. //
  1599. // Arguments:
  1600. // rlstr1 [IN] First string list.
  1601. // rlstr2 [IN] Second string list.
  1602. //
  1603. // Return Value:
  1604. // TRUE Lists are different.
  1605. // FALSE Lists are the same.
  1606. //
  1607. //--
  1608. /////////////////////////////////////////////////////////////////////////////
  1609. BOOL CClusterItem::BDifferentOrdered(
  1610. IN const CStringList & rlstr1,
  1611. IN const CStringList & rlstr2
  1612. )
  1613. {
  1614. BOOL bDifferent;
  1615. if ( rlstr1.GetCount( ) == rlstr2.GetCount( ) )
  1616. {
  1617. POSITION posStr1;
  1618. POSITION posStr2;
  1619. bDifferent = FALSE;
  1620. posStr1 = rlstr1.GetHeadPosition( );
  1621. posStr2 = rlstr2.GetHeadPosition( );
  1622. while ( posStr1 != NULL )
  1623. {
  1624. if ( posStr2 == NULL )
  1625. {
  1626. bDifferent = TRUE;
  1627. break;
  1628. } // if: fewer strings in second list
  1629. if ( rlstr1.GetNext( posStr1 ) != rlstr2.GetNext( posStr2 ) )
  1630. {
  1631. bDifferent = TRUE;
  1632. break;
  1633. } // if: strings are different
  1634. } // while: more items in the list
  1635. if ( posStr2 != NULL )
  1636. {
  1637. bDifferent = TRUE;
  1638. } // if
  1639. } // if: lists are the same size
  1640. else
  1641. {
  1642. bDifferent = TRUE;
  1643. } // else
  1644. return bDifferent;
  1645. } //*** CClusterItem::BDifferentOrdered( )
  1646. /////////////////////////////////////////////////////////////////////////////
  1647. //++
  1648. //
  1649. // CClusterItem::BGetColumnData
  1650. //
  1651. // Routine Description:
  1652. // Returns a string with the column data for a
  1653. //
  1654. // Arguments:
  1655. // colid [IN] Column ID.
  1656. // rstrText [OUT] String in which to return the text for the column.
  1657. //
  1658. // Return Value:
  1659. // TRUE Column data returned.
  1660. // FALSE Column ID not recognized.
  1661. //
  1662. //--
  1663. /////////////////////////////////////////////////////////////////////////////
  1664. BOOL CClusterItem::BGetColumnData( IN COLID colid, OUT CString & rstrText )
  1665. {
  1666. BOOL bSuccess;
  1667. switch ( colid )
  1668. {
  1669. case IDS_COLTEXT_NAME:
  1670. rstrText = StrName( );
  1671. bSuccess = TRUE;
  1672. break;
  1673. case IDS_COLTEXT_TYPE:
  1674. rstrText = StrType( );
  1675. bSuccess = TRUE;
  1676. break;
  1677. case IDS_COLTEXT_DESCRIPTION:
  1678. rstrText = StrDescription( );
  1679. bSuccess = TRUE;
  1680. break;
  1681. default:
  1682. bSuccess = FALSE;
  1683. rstrText = _T("");
  1684. break;
  1685. } // switch: colid
  1686. return bSuccess;
  1687. } //*** CClusterItem::BGetColumnData( )
  1688. /////////////////////////////////////////////////////////////////////////////
  1689. //++
  1690. //
  1691. // CClusterItem::GetTreeName
  1692. //
  1693. // Routine Description:
  1694. // Returns a string to be used in a tree control.
  1695. //
  1696. // Arguments:
  1697. // rstrName [OUT] String in which to return the name.
  1698. //
  1699. // Return Value:
  1700. // None.
  1701. //
  1702. //--
  1703. /////////////////////////////////////////////////////////////////////////////
  1704. #ifdef _DISPLAY_STATE_TEXT_IN_TREE
  1705. void CClusterItem::GetTreeName( OUT CString & rstrName ) const
  1706. {
  1707. rstrName = StrName( );
  1708. } //*** CClusterItem::GetTreeName( )
  1709. #endif
  1710. /////////////////////////////////////////////////////////////////////////////
  1711. //++
  1712. //
  1713. // CClusterItem::PmenuPopup
  1714. //
  1715. // Routine Description:
  1716. // Returns a popup menu.
  1717. //
  1718. // Arguments:
  1719. // None.
  1720. //
  1721. // Return Value:
  1722. // pmenu A popup menu for the item.
  1723. //
  1724. //--
  1725. /////////////////////////////////////////////////////////////////////////////
  1726. CMenu * CClusterItem::PmenuPopup( void )
  1727. {
  1728. CMenu * pmenu = NULL;
  1729. if ( IdmPopupMenu( ) != NULL )
  1730. {
  1731. // Update the state of the item before we construct its menu.
  1732. UpdateState( );
  1733. // Load the menu.
  1734. pmenu = new CMenu;
  1735. if ( pmenu == NULL )
  1736. {
  1737. return NULL;
  1738. } // if
  1739. if ( ! pmenu->LoadMenu( IdmPopupMenu( ) ) )
  1740. {
  1741. delete pmenu;
  1742. pmenu = NULL;
  1743. } // if: error loading the menu
  1744. } // if: there is a menu for this item
  1745. return pmenu;
  1746. } //*** CClusterItem::PmenuPopup( )
  1747. /////////////////////////////////////////////////////////////////////////////
  1748. //++
  1749. //
  1750. // CClusterItem::AddTreeItem
  1751. //
  1752. // Routine Description:
  1753. // Add a tree item to the list item back pointer list.
  1754. //
  1755. // Arguments:
  1756. // pti [IN] Tree item to add.
  1757. //
  1758. // Return Value:
  1759. // None.
  1760. //
  1761. //--
  1762. /////////////////////////////////////////////////////////////////////////////
  1763. void CClusterItem::AddTreeItem( CTreeItem * pti )
  1764. {
  1765. POSITION pos;
  1766. ASSERT_VALID( pti );
  1767. // Find the item in the list.
  1768. pos = LptiBackPointers( ).Find( pti );
  1769. // If it wasn't found, add it.
  1770. if ( pos == NULL )
  1771. {
  1772. LptiBackPointers( ).AddTail( pti );
  1773. Trace( g_tagClusItemCreate, _T("AddTreeItem( ) - Adding tree item backptr from '%s' in '%s' - %d in list"), StrName( ), ( pti->PtiParent( ) == NULL ? _T("<ROOT>") : pti->PtiParent( )->StrName( ) ), LptiBackPointers( ).GetCount( ) );
  1774. } // if: item found in list
  1775. } //*** CClusterItem::AddTreeItem( )
  1776. /////////////////////////////////////////////////////////////////////////////
  1777. //++
  1778. //
  1779. // CClusterItem::AddListItem
  1780. //
  1781. // Routine Description:
  1782. // Add a list item to the list item back pointer list.
  1783. //
  1784. // Arguments:
  1785. // pli [IN] List item to add.
  1786. //
  1787. // Return Value:
  1788. // None.
  1789. //
  1790. //--
  1791. /////////////////////////////////////////////////////////////////////////////
  1792. void CClusterItem::AddListItem( CListItem * pli )
  1793. {
  1794. POSITION pos;
  1795. ASSERT_VALID( pli );
  1796. // Find the item in the list.
  1797. pos = LpliBackPointers( ).Find( pli );
  1798. // If it wasn't found, add it.
  1799. if ( pos == NULL )
  1800. {
  1801. LpliBackPointers( ).AddTail( pli );
  1802. Trace( g_tagClusItemCreate, _T("AddListItem( ) - Adding list item backptr from '%s' in '%s' - %d in list"), StrName( ), ( pli->PtiParent( ) == NULL ? _T("<ROOT>") : pli->PtiParent( )->StrName( ) ), LpliBackPointers( ).GetCount( ) );
  1803. } // if: item found in list
  1804. } //*** CClusterItem::AddListItem( )
  1805. /////////////////////////////////////////////////////////////////////////////
  1806. //++
  1807. //
  1808. // CClusterItem::RemoveTreeItem
  1809. //
  1810. // Routine Description:
  1811. // Remove a tree item from the tree item back pointer list.
  1812. //
  1813. // Arguments:
  1814. // pti [IN] Tree item to remove.
  1815. //
  1816. // Return Value:
  1817. // None.
  1818. //
  1819. //--
  1820. /////////////////////////////////////////////////////////////////////////////
  1821. void CClusterItem::RemoveTreeItem( CTreeItem * pti )
  1822. {
  1823. POSITION pos;
  1824. ASSERT_VALID( pti );
  1825. // Find the item in the list.
  1826. pos = LptiBackPointers( ).Find( pti );
  1827. // If it was found, remove it.
  1828. if ( pos != NULL )
  1829. {
  1830. LptiBackPointers( ).RemoveAt( pos );
  1831. Trace( g_tagClusItemDelete, _T("RemoveTreeItem( ) - Deleting tree item backptr from '%s' in '%s' - %d left"), StrName( ), ( pti->PtiParent( ) == NULL ? _T("<ROOT>") : pti->PtiParent( )->StrName( ) ), LptiBackPointers( ).GetCount( ) );
  1832. } // if: item found in list
  1833. } //*** CClusterItem::RemoveTreeItem( )
  1834. /////////////////////////////////////////////////////////////////////////////
  1835. //++
  1836. //
  1837. // CClusterItem::RemoveListItem
  1838. //
  1839. // Routine Description:
  1840. // Remove a list item from the list item back pointer list.
  1841. //
  1842. // Arguments:
  1843. // pli [IN] List item to remove.
  1844. //
  1845. // Return Value:
  1846. // None.
  1847. //
  1848. //--
  1849. /////////////////////////////////////////////////////////////////////////////
  1850. void CClusterItem::RemoveListItem( CListItem * pli )
  1851. {
  1852. POSITION pos;
  1853. ASSERT_VALID( pli );
  1854. // Find the item in the list.
  1855. pos = LpliBackPointers( ).Find( pli );
  1856. // If it was found, remove it.
  1857. if ( pos != NULL )
  1858. {
  1859. LpliBackPointers( ).RemoveAt( pos );
  1860. Trace( g_tagClusItemDelete, _T("RemoveListItem( ) - Deleting list item backptr from '%s' in '%s' - %d left"), StrName( ), ( pli->PtiParent( ) == NULL ? _T("<ROOT>") : pli->PtiParent( )->StrName( ) ), LpliBackPointers( ).GetCount( ) );
  1861. } // if: item found in list
  1862. } //*** CClusterItem::RemoveListItem( )
  1863. /////////////////////////////////////////////////////////////////////////////
  1864. //++
  1865. //
  1866. // CResource::CClusterItem
  1867. //
  1868. // Routine Description:
  1869. // Determines whether menu items corresponding to ID_FILE_RENAME
  1870. // should be enabled or not.
  1871. //
  1872. // Arguments:
  1873. // pCmdUI [IN OUT] Command routing object.
  1874. //
  1875. // Return Value:
  1876. // None.
  1877. //
  1878. //--
  1879. /////////////////////////////////////////////////////////////////////////////
  1880. void CClusterItem::OnUpdateRename( CCmdUI * pCmdUI )
  1881. {
  1882. pCmdUI->Enable( BCanBeEdited( ) );
  1883. } //*** CClusterItem::OnUpdateRename( )
  1884. /////////////////////////////////////////////////////////////////////////////
  1885. //++
  1886. //
  1887. // CClusterItem::OnUpdateProperties
  1888. //
  1889. // Routine Description:
  1890. // Determines whether menu items corresponding to ID_FILE_PROPERTIES
  1891. // should be enabled or not.
  1892. //
  1893. // Arguments:
  1894. // pCmdUI [IN OUT] Command routing object.
  1895. //
  1896. // Return Value:
  1897. // None.
  1898. //
  1899. //--
  1900. /////////////////////////////////////////////////////////////////////////////
  1901. void CClusterItem::OnUpdateProperties( CCmdUI * pCmdUI )
  1902. {
  1903. pCmdUI->Enable( FALSE );
  1904. } //*** CClusterItem::OnUpdateProperties( )
  1905. /////////////////////////////////////////////////////////////////////////////
  1906. //++
  1907. //
  1908. // CClusterItem::OnCmdProperties
  1909. //
  1910. // Routine Description:
  1911. // Processes the ID_FILE_PROPERTIES menu command.
  1912. //
  1913. // Arguments:
  1914. // None.
  1915. //
  1916. // Return Value:
  1917. // None.
  1918. //
  1919. //--
  1920. /////////////////////////////////////////////////////////////////////////////
  1921. void CClusterItem::OnCmdProperties( void )
  1922. {
  1923. BDisplayProperties( );
  1924. } //*** CClusterItem::OnCmdProperties( )
  1925. /////////////////////////////////////////////////////////////////////////////
  1926. //++
  1927. //
  1928. // CClusterItem::BDisplayProperties
  1929. //
  1930. // Routine Description:
  1931. // Display properties for the object.
  1932. //
  1933. // Arguments:
  1934. // bReadOnly [IN] Don't allow edits to the object properties.
  1935. //
  1936. // Return Value:
  1937. // TRUE OK pressed.
  1938. // FALSE OK not pressed.
  1939. //
  1940. //--
  1941. /////////////////////////////////////////////////////////////////////////////
  1942. BOOL CClusterItem::BDisplayProperties( IN BOOL bReadOnly )
  1943. {
  1944. AfxMessageBox( TEXT("Properties are not available."), MB_OK | MB_ICONWARNING );
  1945. return FALSE;
  1946. } //*** CClusterItem::BDisplayProperties( )
  1947. /////////////////////////////////////////////////////////////////////////////
  1948. //++
  1949. //
  1950. // CClusterItem::OnClusterNotify
  1951. //
  1952. // Routine Description:
  1953. // Handler for the WM_CAM_CLUSTER_NOTIFY message.
  1954. // Processes cluster notifications for this object.
  1955. //
  1956. // Arguments:
  1957. // pnotify [IN OUT] Object describing the notification.
  1958. //
  1959. // Return Value:
  1960. // Value returned from the application method.
  1961. //
  1962. //--
  1963. /////////////////////////////////////////////////////////////////////////////
  1964. LRESULT CClusterItem::OnClusterNotify( IN OUT CClusterNotify * pnotify )
  1965. {
  1966. return 0;
  1967. } //*** CClusterItem::OnClusterNotify( )
  1968. //*************************************************************************//
  1969. /////////////////////////////////////////////////////////////////////////////
  1970. // Global Functions
  1971. /////////////////////////////////////////////////////////////////////////////
  1972. /////////////////////////////////////////////////////////////////////////////
  1973. //++
  1974. //
  1975. // DestructElements
  1976. //
  1977. // Routine Description:
  1978. // Destroys CClusterItem* elements.
  1979. //
  1980. // Arguments:
  1981. // pElements Array of pointers to elements to destruct.
  1982. // nCount Number of elements to destruct.
  1983. //
  1984. // Return Value:
  1985. // None.
  1986. //
  1987. //--
  1988. /////////////////////////////////////////////////////////////////////////////
  1989. extern void AFXAPI DestructElements( CClusterItem ** pElements, int nCount )
  1990. {
  1991. ASSERT( nCount == 0
  1992. || AfxIsValidAddress( pElements, nCount * sizeof( CClusterItem * ) ) );
  1993. // call the destructor(s )
  1994. for ( ; nCount--; pElements++ )
  1995. {
  1996. ASSERT_VALID( *pElements );
  1997. (*pElements)->Release( );
  1998. } // for: each item in the array
  1999. } //*** DestructElements( CClusterItem** )
  2000. /////////////////////////////////////////////////////////////////////////////
  2001. //++
  2002. //
  2003. // DeleteAllItemData
  2004. //
  2005. // Routine Description:
  2006. // Deletes all item data in a CList.
  2007. //
  2008. // Arguments:
  2009. // rlp [IN OUT] List whose data is to be deleted.
  2010. //
  2011. // Return Value:
  2012. // None.
  2013. //
  2014. //--
  2015. /////////////////////////////////////////////////////////////////////////////
  2016. void DeleteAllItemData( IN OUT CClusterItemList & rlp )
  2017. {
  2018. POSITION pos;
  2019. CClusterItem * pci;
  2020. // Delete all the items in the Contained list.
  2021. pos = rlp.GetHeadPosition( );
  2022. while ( pos != NULL )
  2023. {
  2024. pci = rlp.GetNext( pos );
  2025. ASSERT_VALID( pci );
  2026. // Trace( g_tagClusItemDelete, _T("DeleteAllItemData(rlpci ) - Deleting cluster item '%s'"), pci->StrName( ) );
  2027. pci->Delete( );
  2028. } // while: more items in the list
  2029. } //*** DeleteAllItemData( )