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.

1526 lines
45 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1996-2000 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // Cluster.cpp
  7. //
  8. // Abstract:
  9. // Implementation of the CCluster class.
  10. //
  11. // Author:
  12. // David Potter (davidp) May 13, 1996
  13. //
  14. // Revision History:
  15. //
  16. // Notes:
  17. //
  18. /////////////////////////////////////////////////////////////////////////////
  19. #include "stdafx.h"
  20. #include "CluAdmin.h"
  21. #include "ConstDef.h"
  22. #include "Cluster.h"
  23. #include "CASvc.h"
  24. #include "ClusDoc.h"
  25. #include "ClusProp.h"
  26. #include "ExcOper.h"
  27. #include "ClusItem.inl"
  28. #include "resource.h"
  29. #ifdef _DEBUG
  30. #define new DEBUG_NEW
  31. #undef THIS_FILE
  32. static char THIS_FILE[] = __FILE__;
  33. #endif
  34. /////////////////////////////////////////////////////////////////////////////
  35. // Global Variables
  36. /////////////////////////////////////////////////////////////////////////////
  37. #ifdef _DEBUG
  38. CTraceTag g_tagCluster( _T("Document"), _T("CLUSTER"), 0 );
  39. #endif
  40. /////////////////////////////////////////////////////////////////////////////
  41. // CCluster
  42. /////////////////////////////////////////////////////////////////////////////
  43. IMPLEMENT_DYNCREATE( CCluster, CClusterItem )
  44. /////////////////////////////////////////////////////////////////////////////
  45. // Message Maps
  46. /////////////////////////////////////////////////////////////////////////////
  47. BEGIN_MESSAGE_MAP( CCluster, CClusterItem )
  48. //{{AFX_MSG_MAP(CCluster)
  49. ON_UPDATE_COMMAND_UI(ID_FILE_PROPERTIES, OnUpdateProperties)
  50. //}}AFX_MSG_MAP
  51. END_MESSAGE_MAP()
  52. /////////////////////////////////////////////////////////////////////////////
  53. //++
  54. //
  55. // CCluster::CCluster
  56. //
  57. // Routine Description:
  58. // Default construtor.
  59. //
  60. // Arguments:
  61. // None.
  62. //
  63. // Return Value:
  64. // None.
  65. //
  66. //--
  67. /////////////////////////////////////////////////////////////////////////////
  68. CCluster::CCluster( void ) : CClusterItem( NULL, IDS_ITEMTYPE_CLUSTER )
  69. {
  70. m_idmPopupMenu = IDM_CLUSTER_POPUP;
  71. ZeroMemory( &m_cvi, sizeof( m_cvi ) );
  72. m_nMaxQuorumLogSize = 0;
  73. m_plpciNetworkPriority = NULL;
  74. // Set the object type and state images.
  75. m_iimgObjectType = GetClusterAdminApp()->Iimg( IMGLI_CLUSTER );
  76. m_iimgState = m_iimgObjectType;
  77. // Setup the property array.
  78. {
  79. m_rgProps[epropDefaultNetworkRole].Set(CLUSREG_NAME_CLUS_DEFAULT_NETWORK_ROLE, m_nDefaultNetworkRole, m_nDefaultNetworkRole);
  80. m_rgProps[epropDescription].Set(CLUSREG_NAME_CLUS_DESC, m_strDescription, m_strDescription);
  81. m_rgProps[epropEnableEventLogReplication].Set(CLUSREG_NAME_CLUS_EVTLOG_PROPAGATION, m_bEnableEventLogReplication, m_bEnableEventLogReplication);
  82. m_rgProps[epropQuorumArbitrationTimeMax].Set(CLUSREG_NAME_QUORUM_ARBITRATION_TIMEOUT, m_nQuorumArbitrationTimeMax, m_nQuorumArbitrationTimeMax);
  83. m_rgProps[epropQuorumArbitrationTimeMin].Set(CLUSREG_NAME_QUORUM_ARBITRATION_EQUALIZER, m_nQuorumArbitrationTimeMin, m_nQuorumArbitrationTimeMin);
  84. } // Setup the property array
  85. } //*** CCluster::CCluster()
  86. /////////////////////////////////////////////////////////////////////////////
  87. //++
  88. //
  89. // CCluster::~CCluster
  90. //
  91. // Routine Description:
  92. // Destructor.
  93. //
  94. // Arguments:
  95. // None.
  96. //
  97. // Return Value:
  98. // None.
  99. //
  100. //--
  101. /////////////////////////////////////////////////////////////////////////////
  102. CCluster::~CCluster( void )
  103. {
  104. Cleanup();
  105. } //*** CCluster::~CCluster()
  106. /////////////////////////////////////////////////////////////////////////////
  107. //++
  108. //
  109. // CCluster::Cleanup
  110. //
  111. // Routine Description:
  112. // Cleanup the item.
  113. //
  114. // Arguments:
  115. // None.
  116. //
  117. // Return Value:
  118. // None.
  119. //
  120. // Exceptions Thrown:
  121. // None.
  122. //
  123. //--
  124. /////////////////////////////////////////////////////////////////////////////
  125. void CCluster::Cleanup( void )
  126. {
  127. // Delete the NetworkPriority list.
  128. if ( m_plpciNetworkPriority != NULL )
  129. {
  130. m_plpciNetworkPriority->RemoveAll();
  131. delete m_plpciNetworkPriority;
  132. m_plpciNetworkPriority = NULL;
  133. } // if: NetworkPriority list exists
  134. m_hkey = NULL;
  135. } //*** CCluster::Cleanup()
  136. /////////////////////////////////////////////////////////////////////////////
  137. //++
  138. //
  139. // CCluster::Init
  140. //
  141. // Routine Description:
  142. // Initialize the item.
  143. //
  144. // Arguments:
  145. // pdoc [IN OUT] Document to which this item belongs.
  146. // lpszName [IN] Name of the item.
  147. // hOpenedCluster [IN] Handle to cluster to use that is already open.
  148. //
  149. // Return Value:
  150. // None.
  151. //
  152. // Exceptions Thrown:
  153. // CNTException Errors from OpenCluster(), GetClusterKey(), or
  154. // CreateClusterNotifyPort().
  155. // Any exceptions thrown by CCluster::ReadClusterInfo().
  156. //--
  157. /////////////////////////////////////////////////////////////////////////////
  158. void CCluster::Init(
  159. IN OUT CClusterDoc * pdoc,
  160. IN LPCTSTR lpszName,
  161. IN HCLUSTER hOpenedCluster // = NULL
  162. )
  163. {
  164. CWaitCursor wc;
  165. TCHAR szClusterName[ MAX_PATH ];
  166. ASSERT( Hkey() == NULL );
  167. ASSERT( lstrlen( lpszName ) < sizeof( szClusterName ) / sizeof( TCHAR ) );
  168. try
  169. {
  170. // If connecting the local machine, get its name.
  171. if ( lstrcmp( lpszName, _T(".") ) == 0 )
  172. {
  173. DWORD nSize = sizeof( szClusterName ) / sizeof( TCHAR );
  174. GetComputerName( szClusterName, &nSize );
  175. } // if: connecting to the local machine
  176. else
  177. {
  178. lstrcpy( szClusterName, lpszName );
  179. } // else: not connecting to the local machine
  180. // Open the cluster.
  181. if ( hOpenedCluster == NULL )
  182. {
  183. pdoc->m_hcluster = HOpenCluster( lpszName );
  184. if ( pdoc->m_hcluster == NULL )
  185. {
  186. ThrowStaticException( GetLastError(), IDS_OPEN_CLUSTER_ERROR, szClusterName );
  187. } // if: error opening the cluster
  188. } // if: no opened cluster passed in
  189. else
  190. {
  191. pdoc->m_hcluster = hOpenedCluster;
  192. } // if: cluster already opened
  193. // Get the cluster registry key.
  194. pdoc->m_hkeyCluster = GetClusterKey( pdoc->m_hcluster, MAXIMUM_ALLOWED );
  195. if ( pdoc->m_hkeyCluster == NULL )
  196. {
  197. ThrowStaticException( GetLastError(), IDS_GET_CLUSTER_KEY_ERROR, szClusterName );
  198. } // if: error opening the cluster key
  199. // Call the base class method. We can use Hcluster() after calling this.
  200. CClusterItem::Init( pdoc, szClusterName );
  201. // Get the cluster registry key.
  202. m_hkey = pdoc->m_hkeyCluster;
  203. // Register this cluster with the notification port.
  204. {
  205. HCHANGE hchange;
  206. // We want these notifications to go to the document, not us.
  207. ASSERT( Pcnk() != NULL );
  208. m_pcnk->m_cnkt = cnktDoc;
  209. m_pcnk->m_pdoc = pdoc;
  210. Trace( g_tagClusItemNotify, _T("CCluster::Init() - Registering for cluster notifications (%08.8x)"), Pcnk() );
  211. // Create the notification port.
  212. hchange = CreateClusterNotifyPort(
  213. GetClusterAdminApp()->HchangeNotifyPort(),
  214. Hcluster(),
  215. (CLUSTER_CHANGE_NODE_ADDED
  216. | CLUSTER_CHANGE_GROUP_ADDED
  217. | CLUSTER_CHANGE_RESOURCE_ADDED
  218. | CLUSTER_CHANGE_RESOURCE_TYPE_ADDED
  219. | CLUSTER_CHANGE_RESOURCE_TYPE_DELETED
  220. | CLUSTER_CHANGE_RESOURCE_TYPE_PROPERTY
  221. | CLUSTER_CHANGE_NETWORK_ADDED
  222. | CLUSTER_CHANGE_NETINTERFACE_ADDED
  223. | CLUSTER_CHANGE_QUORUM_STATE
  224. | CLUSTER_CHANGE_CLUSTER_STATE
  225. | CLUSTER_CHANGE_CLUSTER_PROPERTY
  226. | CLUSTER_CHANGE_REGISTRY_NAME
  227. | CLUSTER_CHANGE_REGISTRY_ATTRIBUTES
  228. | CLUSTER_CHANGE_REGISTRY_VALUE
  229. | CLUSTER_CHANGE_REGISTRY_SUBTREE),
  230. (DWORD_PTR) Pcnk()
  231. );
  232. if ( hchange == NULL )
  233. {
  234. ThrowStaticException( GetLastError(), IDS_CLUSTER_NOTIF_REG_ERROR, szClusterName );
  235. } // if: error creating the notify port
  236. ASSERT( hchange == GetClusterAdminApp()->HchangeNotifyPort() );
  237. } // Register this cluster with the notification port
  238. // Get the name of the cluster as recorded by the cluster.
  239. ReadClusterInfo();
  240. // Allocate lists.
  241. m_plpciNetworkPriority = new CNetworkList;
  242. if ( m_plpciNetworkPriority == NULL )
  243. {
  244. AfxThrowMemoryException();
  245. } // if: error allocating the network list
  246. // Read the initial state.
  247. UpdateState();
  248. } // try
  249. catch ( CException * )
  250. {
  251. if ( pdoc->m_hkeyCluster != NULL )
  252. {
  253. ClusterRegCloseKey( pdoc->m_hkeyCluster );
  254. pdoc->m_hkeyCluster = NULL;
  255. m_hkey = NULL;
  256. } // if: registry key opened
  257. if ( ( pdoc->m_hcluster != NULL ) && ( pdoc->m_hcluster != hOpenedCluster ) )
  258. {
  259. CloseCluster( Hcluster() );
  260. pdoc->m_hcluster = NULL;
  261. } // if: group opened
  262. m_bReadOnly = TRUE;
  263. throw;
  264. } // catch: CException
  265. } //*** CCluster::Init()
  266. /////////////////////////////////////////////////////////////////////////////
  267. //++
  268. //
  269. // CCluster::ReadItem
  270. //
  271. // Routine Description:
  272. // Read the item parameters from the cluster database.
  273. //
  274. // Arguments:
  275. // None.
  276. //
  277. // Return Value:
  278. // None.
  279. //
  280. // Exceptions Thrown:
  281. // CNTException Errors from CClusterItem::DwReadValue() or
  282. // CClusterItem::ReadItem().
  283. // Any exceptions thrown by CCluster::ReadExtensions().
  284. //
  285. //--
  286. /////////////////////////////////////////////////////////////////////////////
  287. void CCluster::ReadItem( void )
  288. {
  289. DWORD dwStatus;
  290. DWORD dwRetStatus = ERROR_SUCCESS;
  291. CWaitCursor wc;
  292. ASSERT( Hcluster() != NULL );
  293. ASSERT( Hkey() != NULL );
  294. if ( Hcluster() != NULL )
  295. {
  296. m_rgProps[epropDefaultNetworkRole].m_value.pdw = &m_nDefaultNetworkRole;
  297. m_rgProps[epropDescription].m_value.pstr = &m_strDescription;
  298. m_rgProps[epropEnableEventLogReplication].m_value.pb = &m_bEnableEventLogReplication;
  299. m_rgProps[epropQuorumArbitrationTimeMax].m_value.pdw = &m_nQuorumArbitrationTimeMax;
  300. m_rgProps[epropQuorumArbitrationTimeMin].m_value.pdw = &m_nQuorumArbitrationTimeMin;
  301. // Call the base class method.
  302. try
  303. {
  304. CClusterItem::ReadItem();
  305. } // try
  306. catch ( CNTException * pnte )
  307. {
  308. dwRetStatus = pnte->Sc();
  309. pnte->Delete();
  310. } // catch: CNTException
  311. // Get the name of the cluster as recorded by the cluster.
  312. ReadClusterInfo();
  313. // Read and parse the common properties.
  314. {
  315. CClusPropList cpl;
  316. Trace( g_tagCluster, _T("(%x) - CCluster::ReadItem() - Getting common properties"), this );
  317. dwStatus = cpl.ScGetClusterProperties(
  318. Hcluster(),
  319. CLUSCTL_CLUSTER_GET_COMMON_PROPERTIES
  320. );
  321. if (dwStatus == ERROR_SUCCESS)
  322. {
  323. Trace( g_tagCluster, _T("(%x) - CCluster::ReadItem() - Parsing common properties"), this );
  324. dwStatus = DwParseProperties(cpl);
  325. } // if: properties read successfully
  326. if (dwStatus != ERROR_SUCCESS)
  327. {
  328. Trace( g_tagError, _T("(%x) - CCluster::ReadItem() - Error 0x%08.8x getting or parsing common properties"), this, dwStatus );
  329. // PROCNUM_OUT_OF_RANGE occurs when the server side
  330. // (clussvc.exe) doesn't support the ClusterControl( )
  331. // API. In this case, read the data using the cluster
  332. // registry APIs.
  333. if ( dwStatus == RPC_S_PROCNUM_OUT_OF_RANGE )
  334. {
  335. if ( Hkey() != NULL )
  336. {
  337. // Read the Description
  338. dwStatus = DwReadValue( CLUSREG_NAME_CLUS_DESC, m_strDescription );
  339. if ( ( dwStatus != ERROR_SUCCESS )
  340. && ( dwStatus != ERROR_FILE_NOT_FOUND ) )
  341. {
  342. dwRetStatus = dwStatus;
  343. } // if: error reading the value
  344. } // if: key is available
  345. } // if: must be talking to an NT4 node
  346. else
  347. {
  348. dwRetStatus = dwStatus;
  349. } // else: not talking to an NT4 node
  350. } // if: error reading or parsing properties
  351. } // Read and parse the common properties
  352. // Get quorum resource information.
  353. {
  354. LPWSTR pwszQResName = NULL;
  355. LPWSTR pwszQuorumPath = NULL;
  356. DWORD cchQResName;
  357. DWORD cchQuorumPath;
  358. // Get the size of the resource name.
  359. cchQResName = 0;
  360. cchQuorumPath = 0;
  361. dwStatus = GetClusterQuorumResource(
  362. Hcluster(),
  363. NULL,
  364. &cchQResName,
  365. NULL,
  366. &cchQuorumPath,
  367. &m_nMaxQuorumLogSize
  368. );
  369. if ( ( dwStatus == ERROR_SUCCESS ) || ( dwStatus == ERROR_MORE_DATA ) )
  370. {
  371. // Allocate enough space for the data.
  372. cchQResName++; // Don't forget the final null-terminator.
  373. pwszQResName = new WCHAR[ cchQResName ];
  374. cchQuorumPath++;
  375. pwszQuorumPath = new WCHAR[ cchQuorumPath ];
  376. ASSERT( pwszQResName != NULL && pwszQuorumPath != NULL );
  377. // Read the resource name.
  378. dwStatus = GetClusterQuorumResource(
  379. Hcluster(),
  380. pwszQResName,
  381. &cchQResName,
  382. pwszQuorumPath,
  383. &cchQuorumPath,
  384. &m_nMaxQuorumLogSize
  385. );
  386. } // if: got the size successfully
  387. if ( dwStatus != ERROR_SUCCESS )
  388. {
  389. dwRetStatus = dwStatus;
  390. } // if: error occurred
  391. else
  392. {
  393. m_strQuorumResource = pwszQResName;
  394. m_strQuorumPath = pwszQuorumPath;
  395. ASSERT( m_strQuorumPath[ m_strQuorumPath.GetLength() - 1 ] == _T('\\') );
  396. } // else: quorum resource info retrieved successfully
  397. delete [] pwszQResName;
  398. delete [] pwszQuorumPath;
  399. } // Get the quorum resource name
  400. // Read the FQDN for the cluster.
  401. {
  402. DWORD cbReturned;
  403. DWORD cbFQDN;
  404. LPWSTR pszFQDN = NULL;
  405. pszFQDN = m_strFQDN.GetBuffer( 256 );
  406. cbFQDN = 256 * sizeof( WCHAR );
  407. dwStatus = ClusterControl(
  408. Hcluster(),
  409. NULL,
  410. CLUSCTL_CLUSTER_GET_FQDN,
  411. NULL,
  412. NULL,
  413. pszFQDN,
  414. cbFQDN,
  415. &cbReturned
  416. );
  417. if ( dwStatus == ERROR_MORE_DATA )
  418. {
  419. cbFQDN = cbReturned + sizeof( WCHAR );
  420. pszFQDN = m_strFQDN.GetBuffer( ( cbReturned / sizeof( WCHAR ) ) + 1 );
  421. dwStatus = ClusterControl(
  422. Hcluster(),
  423. NULL,
  424. CLUSCTL_CLUSTER_GET_FQDN,
  425. NULL,
  426. NULL,
  427. pszFQDN,
  428. cbFQDN,
  429. &cbReturned
  430. );
  431. } // if: buffer not large enough
  432. if ( dwStatus != ERROR_SUCCESS )
  433. {
  434. // Handle the case where the API doesn't exist (e.g. NT4).
  435. // also
  436. // Handle the case where the control code is not known (e.g. Win2K)
  437. if ( ( dwStatus == RPC_S_PROCNUM_OUT_OF_RANGE )
  438. || ( dwStatus == ERROR_INVALID_FUNCTION ) )
  439. {
  440. lstrcpy( pszFQDN, StrName() );
  441. m_strFQDN.ReleaseBuffer();
  442. }
  443. else
  444. {
  445. dwRetStatus = dwStatus;
  446. }
  447. }
  448. else
  449. {
  450. m_strFQDN.ReleaseBuffer();
  451. } // else: data retrieved successfully
  452. } // if: no error yet
  453. } // if: cluster is available
  454. // If any errors occurred, throw an exception.
  455. if ( dwRetStatus != ERROR_SUCCESS )
  456. {
  457. ThrowStaticException( dwRetStatus, IDS_READ_CLUSTER_PROPS_ERROR, StrName() );
  458. } // if: error occurred
  459. // Read extension lists.
  460. ReadClusterExtensions();
  461. ReadNodeExtensions();
  462. ReadGroupExtensions();
  463. ReadResourceExtensions();
  464. ReadResTypeExtensions();
  465. ReadNetworkExtensions();
  466. ReadNetInterfaceExtensions();
  467. // Read the initial state.
  468. UpdateState();
  469. MarkAsChanged( FALSE );
  470. } //*** CCluster::ReadItem()
  471. /////////////////////////////////////////////////////////////////////////////
  472. //++
  473. //
  474. // CCluster::PlstrExtensions
  475. //
  476. // Routine Description:
  477. // Return the list of admin extensions.
  478. //
  479. // Arguments:
  480. // None.
  481. //
  482. // Return Value:
  483. // plstr List of extensions.
  484. // NULL No extension associated with this object.
  485. //
  486. // Exceptions Thrown:
  487. // None.
  488. //
  489. //--
  490. /////////////////////////////////////////////////////////////////////////////
  491. const CStringList * CCluster::PlstrExtensions( void ) const
  492. {
  493. return &LstrClusterExtensions();
  494. } //*** CCluster::PlstrExtensions()
  495. /////////////////////////////////////////////////////////////////////////////
  496. //++
  497. //
  498. // CCluster::ReadClusterInfo
  499. //
  500. // Routine Description:
  501. // Get the name of the cluster as recorded by the cluster and the
  502. // version of the cluster software.
  503. //
  504. // Arguments:
  505. // None.
  506. //
  507. // Return Value:
  508. // None.
  509. //
  510. // Exceptions Thrown:
  511. // Any exceptions thrown by new.
  512. //
  513. //--
  514. /////////////////////////////////////////////////////////////////////////////
  515. void CCluster::ReadClusterInfo( void )
  516. {
  517. DWORD dwStatus;
  518. LPWSTR pwszName = NULL;
  519. DWORD cchName = 128;
  520. CWaitCursor wc;
  521. try
  522. {
  523. pwszName = new WCHAR[ cchName ];
  524. if ( pwszName == NULL )
  525. {
  526. AfxThrowMemoryException();
  527. } // if: error allocating the name buffer
  528. m_cvi.dwVersionInfoSize = sizeof( m_cvi );
  529. dwStatus = GetClusterInformation( Hcluster(), pwszName, &cchName, &m_cvi );
  530. if ( dwStatus == ERROR_MORE_DATA )
  531. {
  532. delete [] pwszName;
  533. cchName++;
  534. pwszName = new WCHAR[ cchName ];
  535. if ( pwszName == NULL )
  536. {
  537. AfxThrowMemoryException();
  538. } // if: error allocating the name buffer
  539. dwStatus = GetClusterInformation( Hcluster(), pwszName, &cchName, &m_cvi );
  540. } // if: buffer is too small
  541. if ( dwStatus == ERROR_SUCCESS )
  542. {
  543. Pdoc()->m_strName = pwszName;
  544. } // if: error occurred
  545. else
  546. {
  547. TraceError( _T("CCluster::Init() calling GetClusterInformation"), dwStatus );
  548. } // else: no error occurred
  549. m_strName = pwszName;
  550. delete [] pwszName;
  551. } // try
  552. catch (CException *)
  553. {
  554. delete [] pwszName;
  555. throw;
  556. } // catch: CException
  557. } //*** CCluster::ReadClusterInfo()
  558. /////////////////////////////////////////////////////////////////////////////
  559. //++
  560. //
  561. // CCluster::ReadClusterExtensions
  562. //
  563. // Routine Description:
  564. // Read the extension list for the cluster object.
  565. //
  566. // Arguments:
  567. // None.
  568. //
  569. // Return Value:
  570. // None.
  571. //
  572. // Exceptions Thrown:
  573. // CNTException Errors from CClusterItem::DwReadValue().
  574. //
  575. //--
  576. /////////////////////////////////////////////////////////////////////////////
  577. void CCluster::ReadClusterExtensions( void )
  578. {
  579. DWORD dwStatus;
  580. CWaitCursor wc;
  581. ASSERT( Hkey() != NULL );
  582. if ( Hkey() != NULL )
  583. {
  584. // Read the Cluster extension string.
  585. dwStatus = DwReadValue( CLUSREG_NAME_ADMIN_EXT, m_lstrClusterExtensions );
  586. if ( ( dwStatus != ERROR_SUCCESS )
  587. && ( dwStatus != ERROR_FILE_NOT_FOUND ) )
  588. {
  589. ThrowStaticException( dwStatus );
  590. } // if: error reading the value
  591. } // if: key is available
  592. else
  593. {
  594. m_lstrClusterExtensions.RemoveAll();
  595. } // else: key is not available
  596. } //*** CCluster::ReadClusterExtensions()
  597. /////////////////////////////////////////////////////////////////////////////
  598. //++
  599. //
  600. // CCluster::ReadNodeExtensions
  601. //
  602. // Routine Description:
  603. // Read the extension list for all nodes.
  604. //
  605. // Arguments:
  606. // None.
  607. //
  608. // Return Value:
  609. // None.
  610. //
  611. // Exceptions Thrown:
  612. // CNTException Errors from CClusterItem::DwReadValue().
  613. //
  614. //--
  615. /////////////////////////////////////////////////////////////////////////////
  616. void CCluster::ReadNodeExtensions( void )
  617. {
  618. DWORD dwStatus;
  619. CWaitCursor wc;
  620. ASSERT( Hkey() != NULL );
  621. if ( Hkey() != NULL )
  622. {
  623. // Read the Nodes extension string.
  624. dwStatus = DwReadValue( CLUSREG_NAME_ADMIN_EXT, CLUSREG_KEYNAME_NODES, m_lstrNodeExtensions );
  625. if ( ( dwStatus != ERROR_SUCCESS )
  626. && ( dwStatus != ERROR_FILE_NOT_FOUND ) )
  627. {
  628. ThrowStaticException( dwStatus );
  629. } // if: error reading the value
  630. } // if: key is available
  631. else
  632. {
  633. m_lstrNodeExtensions.RemoveAll();
  634. } // else: key is not available
  635. } //*** CCluster::ReadNodeExtensions()
  636. /////////////////////////////////////////////////////////////////////////////
  637. //++
  638. //
  639. // CCluster::ReadGroupExtensions
  640. //
  641. // Routine Description:
  642. // Read the extension list for all groups.
  643. //
  644. // Arguments:
  645. // None.
  646. //
  647. // Return Value:
  648. // None.
  649. //
  650. // Exceptions Thrown:
  651. // CNTException Errors from CClusterItem::DwReadValue().
  652. //
  653. //--
  654. /////////////////////////////////////////////////////////////////////////////
  655. void CCluster::ReadGroupExtensions( void )
  656. {
  657. DWORD dwStatus;
  658. CWaitCursor wc;
  659. ASSERT( Hkey() != NULL );
  660. if ( Hkey() != NULL )
  661. {
  662. // Read the Groups extension string.
  663. dwStatus = DwReadValue( CLUSREG_NAME_ADMIN_EXT, CLUSREG_KEYNAME_GROUPS, m_lstrGroupExtensions );
  664. if ( ( dwStatus != ERROR_SUCCESS )
  665. && ( dwStatus != ERROR_FILE_NOT_FOUND ) )
  666. {
  667. ThrowStaticException( dwStatus );
  668. } // if: error reading the value
  669. } // if: key is available
  670. else
  671. {
  672. m_lstrGroupExtensions.RemoveAll();
  673. } // else: key is not available
  674. } //*** CCluster::ReadGroupExtensions()
  675. /////////////////////////////////////////////////////////////////////////////
  676. //++
  677. //
  678. // CCluster::ReadResourceExtensions
  679. //
  680. // Routine Description:
  681. // Read the extension list for all resources.
  682. //
  683. // Arguments:
  684. // None.
  685. //
  686. // Return Value:
  687. // None.
  688. //
  689. // Exceptions Thrown:
  690. // CNTException Errors from CClusterItem::DwReadValue().
  691. //
  692. //--
  693. /////////////////////////////////////////////////////////////////////////////
  694. void CCluster::ReadResourceExtensions( void )
  695. {
  696. DWORD dwStatus;
  697. CWaitCursor wc;
  698. ASSERT( Hkey() != NULL );
  699. if ( Hkey() != NULL )
  700. {
  701. // Read the Resources extension string.
  702. dwStatus = DwReadValue( CLUSREG_NAME_ADMIN_EXT, CLUSREG_KEYNAME_RESOURCES, m_lstrResourceExtensions );
  703. if ( ( dwStatus != ERROR_SUCCESS )
  704. && ( dwStatus != ERROR_FILE_NOT_FOUND ) )
  705. {
  706. ThrowStaticException( dwStatus );
  707. } // if: error reading the value
  708. } // if: key is available
  709. else
  710. {
  711. m_lstrResourceExtensions.RemoveAll();
  712. } // else: key is not available
  713. } //*** CCluster::ReadResourceExtensions()
  714. /////////////////////////////////////////////////////////////////////////////
  715. //++
  716. //
  717. // CCluster::ReadResTypeExtensions
  718. //
  719. // Routine Description:
  720. // Read the extension list for all resouce types.
  721. //
  722. // Arguments:
  723. // None.
  724. //
  725. // Return Value:
  726. // None.
  727. //
  728. // Exceptions Thrown:
  729. // CNTException Errors from CClusterItem::DwReadValue().
  730. //
  731. //--
  732. /////////////////////////////////////////////////////////////////////////////
  733. void CCluster::ReadResTypeExtensions( void )
  734. {
  735. DWORD dwStatus;
  736. CWaitCursor wc;
  737. ASSERT( Hkey() != NULL );
  738. if ( Hkey() != NULL )
  739. {
  740. // Read the Resource Types extension string.
  741. dwStatus = DwReadValue( CLUSREG_NAME_ADMIN_EXT, CLUSREG_KEYNAME_RESOURCE_TYPES, m_lstrResTypeExtensions );
  742. if ( ( dwStatus != ERROR_SUCCESS )
  743. && ( dwStatus != ERROR_FILE_NOT_FOUND ) )
  744. {
  745. ThrowStaticException( dwStatus );
  746. } // if: error reading the value
  747. } // if: key is available
  748. else
  749. {
  750. m_lstrResTypeExtensions.RemoveAll();
  751. } // else: key is not available
  752. } //*** CCluster::ReadResTypeExtensions()
  753. /////////////////////////////////////////////////////////////////////////////
  754. //++
  755. //
  756. // CCluster::ReadNetworkExtensions
  757. //
  758. // Routine Description:
  759. // Read the extension list for all networks.
  760. //
  761. // Arguments:
  762. // None.
  763. //
  764. // Return Value:
  765. // None.
  766. //
  767. // Exceptions Thrown:
  768. // CNTException Errors from CClusterItem::DwReadValue().
  769. //
  770. //--
  771. /////////////////////////////////////////////////////////////////////////////
  772. void CCluster::ReadNetworkExtensions( void )
  773. {
  774. DWORD dwStatus;
  775. CWaitCursor wc;
  776. ASSERT( Hkey() != NULL );
  777. if ( Hkey() != NULL )
  778. {
  779. // Read the Networks extension string.
  780. dwStatus = DwReadValue( CLUSREG_NAME_ADMIN_EXT, CLUSREG_KEYNAME_NETWORKS, m_lstrNetworkExtensions );
  781. if ( ( dwStatus != ERROR_SUCCESS )
  782. && ( dwStatus != ERROR_FILE_NOT_FOUND ) )
  783. {
  784. ThrowStaticException( dwStatus );
  785. } // if: error reading the value
  786. } // if: key is available
  787. else
  788. {
  789. m_lstrNetworkExtensions.RemoveAll();
  790. } // else: key is not available
  791. } //*** CCluster::ReadNetworkExtensions()
  792. /////////////////////////////////////////////////////////////////////////////
  793. //++
  794. //
  795. // CCluster::ReadNetInterfaceExtensions
  796. //
  797. // Routine Description:
  798. // Read the extension list for all network interfaces.
  799. //
  800. // Arguments:
  801. // None.
  802. //
  803. // Return Value:
  804. // None.
  805. //
  806. // Exceptions Thrown:
  807. // CNTException Errors from CClusterItem::DwReadValue().
  808. //
  809. //--
  810. /////////////////////////////////////////////////////////////////////////////
  811. void CCluster::ReadNetInterfaceExtensions( void )
  812. {
  813. DWORD dwStatus;
  814. CWaitCursor wc;
  815. ASSERT( Hkey() != NULL );
  816. if ( Hkey() != NULL )
  817. {
  818. // Read the Network Intefaces extension string.
  819. dwStatus = DwReadValue( CLUSREG_NAME_ADMIN_EXT, CLUSREG_KEYNAME_NETINTERFACES, m_lstrNetInterfaceExtensions );
  820. if ( ( dwStatus != ERROR_SUCCESS )
  821. && ( dwStatus != ERROR_FILE_NOT_FOUND ) )
  822. {
  823. ThrowStaticException( dwStatus );
  824. } // if: error reading the value
  825. } // if: key is available
  826. else
  827. {
  828. m_lstrNetInterfaceExtensions.RemoveAll();
  829. } // else: key is not available
  830. } //*** CCluster::ReadNetInterfaceExtensions()
  831. /////////////////////////////////////////////////////////////////////////////
  832. //++
  833. //
  834. // CCluster::CollecNetworkPriority
  835. //
  836. // Routine Description:
  837. // Construct the network priority list.
  838. //
  839. // Arguments:
  840. // plpci [IN OUT] List to fill.
  841. //
  842. // Return Value:
  843. // None.
  844. //
  845. // Exceptions Thrown:
  846. // CNTException Errors from ClusterOpenEnum() or ClusterEnum().
  847. // Any exceptions thrown by new or CList::AddTail().
  848. //
  849. //--
  850. /////////////////////////////////////////////////////////////////////////////
  851. void CCluster::CollectNetworkPriority( IN OUT CNetworkList * plpci )
  852. {
  853. DWORD dwStatus;
  854. HCLUSENUM hclusenum;
  855. int ienum;
  856. LPWSTR pwszName = NULL;
  857. DWORD cchName;
  858. DWORD cchmacName;
  859. DWORD dwRetType;
  860. CNetwork * pciNet;
  861. CWaitCursor wc;
  862. ASSERT_VALID( Pdoc() );
  863. ASSERT( Hcluster() != NULL );
  864. if ( plpci == NULL )
  865. {
  866. plpci = m_plpciNetworkPriority;
  867. } // if: no list specified
  868. ASSERT( plpci != NULL );
  869. // Remove the previous contents of the list.
  870. plpci->RemoveAll();
  871. if ( Hcluster() != NULL )
  872. {
  873. // Open the enumeration.
  874. hclusenum = ClusterOpenEnum( Hcluster(), (DWORD) CLUSTER_ENUM_INTERNAL_NETWORK );
  875. if ( hclusenum == NULL )
  876. {
  877. ThrowStaticException( GetLastError(), IDS_ENUM_NETWORK_PRIORITY_ERROR, StrName() );
  878. } // if: error opening the enmeration
  879. try
  880. {
  881. // Allocate a name buffer.
  882. cchmacName = 128;
  883. pwszName = new WCHAR[ cchmacName ];
  884. if ( pwszName == NULL )
  885. {
  886. AfxThrowMemoryException();
  887. } // if: error allocating the name buffer
  888. // Loop through the enumeration and add each network to the list.
  889. for ( ienum = 0 ; ; ienum++ )
  890. {
  891. // Get the next item in the enumeration.
  892. cchName = cchmacName;
  893. dwStatus = ClusterEnum( hclusenum, ienum, &dwRetType, pwszName, &cchName );
  894. if ( dwStatus == ERROR_MORE_DATA )
  895. {
  896. delete [] pwszName;
  897. cchmacName = ++cchName;
  898. pwszName = new WCHAR[ cchmacName ];
  899. if ( pwszName == NULL )
  900. {
  901. AfxThrowMemoryException();
  902. } // if: error allocating the name buffer
  903. dwStatus = ClusterEnum( hclusenum, ienum, &dwRetType, pwszName, &cchName );
  904. } // if: name buffer was too small
  905. if ( dwStatus == ERROR_NO_MORE_ITEMS )
  906. {
  907. break;
  908. } // if: done with the enumeraiton
  909. else if ( dwStatus != ERROR_SUCCESS )
  910. {
  911. ThrowStaticException( dwStatus, IDS_ENUM_NETWORK_PRIORITY_ERROR, StrName() );
  912. } // else if: error getting the next enumeration value
  913. ASSERT( dwRetType == CLUSTER_ENUM_INTERNAL_NETWORK );
  914. // Find the item in the list of networks on the document.
  915. pciNet = Pdoc()->LpciNetworks().PciNetworkFromName( pwszName );
  916. ASSERT_VALID( pciNet );
  917. // Add the network to the list.
  918. if ( pciNet != NULL )
  919. {
  920. plpci->AddTail( pciNet );
  921. } // if: found network in list
  922. } // for: each item in the group
  923. ClusterCloseEnum( hclusenum );
  924. } // try
  925. catch ( CException * )
  926. {
  927. delete [] pwszName;
  928. ClusterCloseEnum( hclusenum );
  929. throw;
  930. } // catch: any exception
  931. } // if: cluster is available
  932. delete [] pwszName;
  933. } //*** CCluster::CollecNetworkPriority()
  934. /////////////////////////////////////////////////////////////////////////////
  935. //++
  936. //
  937. // CCluster::OnUpdateProperties
  938. //
  939. // Routine Description:
  940. // Determines whether menu items corresponding to ID_FILE_PROPERTIES
  941. // should be enabled or not.
  942. //
  943. // Arguments:
  944. // pCmdUI [IN OUT] Command routing object.
  945. //
  946. // Return Value:
  947. // None.
  948. //
  949. //--
  950. /////////////////////////////////////////////////////////////////////////////
  951. void CCluster::OnUpdateProperties( CCmdUI * pCmdUI )
  952. {
  953. pCmdUI->Enable(TRUE);
  954. } //*** CCluster::OnUpdateProperties()
  955. /////////////////////////////////////////////////////////////////////////////
  956. //++
  957. //
  958. // CCluster::BDisplayProperties
  959. //
  960. // Routine Description:
  961. // Display properties for the object.
  962. //
  963. // Arguments:
  964. // bReadOnly [IN] Don't allow edits to the object properties.
  965. //
  966. // Return Value:
  967. // TRUE OK pressed.
  968. // FALSE OK not pressed.
  969. //
  970. //--
  971. /////////////////////////////////////////////////////////////////////////////
  972. BOOL CCluster::BDisplayProperties( IN BOOL bReadOnly )
  973. {
  974. BOOL bChanged = FALSE;
  975. CClusterPropSheet sht( AfxGetMainWnd() );
  976. // Do this in case this object is deleted while we are operating on it.
  977. AddRef();
  978. // If the object has changed, read it.
  979. if ( BChanged() )
  980. {
  981. ReadItem();
  982. } // if: object changed
  983. // Display the property sheet.
  984. try
  985. {
  986. sht.SetReadOnly( bReadOnly );
  987. if ( sht.BInit( this, IimgObjectType() ) )
  988. {
  989. bChanged = ( ( sht.DoModal() == IDOK ) && ! bReadOnly );
  990. } // if: initialized successfully
  991. } // try
  992. catch ( CException * pe )
  993. {
  994. pe->Delete();
  995. } // catch: CException
  996. Release();
  997. return bChanged;
  998. } //*** CCluster::BDisplayProperties()
  999. /////////////////////////////////////////////////////////////////////////////
  1000. //++
  1001. //
  1002. // CCluster::SetName
  1003. //
  1004. // Routine Description:
  1005. // Set the name of the cluster.
  1006. //
  1007. // Arguments:
  1008. // pszName [IN] New name of the cluster.
  1009. //
  1010. // Return Value:
  1011. // None.
  1012. //
  1013. // Exceptions Thrown:
  1014. // Any exceptions thrown by WriteItem().
  1015. //
  1016. //--
  1017. /////////////////////////////////////////////////////////////////////////////
  1018. void CCluster::SetName( IN LPCTSTR pszName )
  1019. {
  1020. Rename( pszName );
  1021. } //*** CCluster::SetName()
  1022. /////////////////////////////////////////////////////////////////////////////
  1023. //++
  1024. //
  1025. // CCluster::SetDescription
  1026. //
  1027. // Routine Description:
  1028. // Set the description in the cluster database.
  1029. //
  1030. // Arguments:
  1031. // pszDesc [IN] Description to set.
  1032. //
  1033. // Return Value:
  1034. // None.
  1035. //
  1036. // Exceptions Thrown:
  1037. // Any exceptions thrown by WriteItem().
  1038. //
  1039. //--
  1040. /////////////////////////////////////////////////////////////////////////////
  1041. void CCluster::SetDescription( IN LPCTSTR pszDesc )
  1042. {
  1043. ASSERT( Hkey() != NULL );
  1044. if ( ( Hkey() != NULL ) && ( m_strDescription != pszDesc ) )
  1045. {
  1046. WriteValue( CLUSREG_NAME_CLUS_DESC, NULL, pszDesc );
  1047. m_strDescription = pszDesc;
  1048. } // if: a change occured
  1049. } //*** CCluster::SetDescription()
  1050. /////////////////////////////////////////////////////////////////////////////
  1051. //++
  1052. //
  1053. // CCluster::SetQuorumResource
  1054. //
  1055. // Routine Description:
  1056. // Set the quorum resource for the cluster.
  1057. //
  1058. // Arguments:
  1059. // pszResource [IN] Name of resource to make the quorum resource.
  1060. // pszQuorumPath [IN] Path for storing cluster files.
  1061. // nMaxLogSize [IN] Maximum size of the quorum log.
  1062. //
  1063. // Return Value:
  1064. // None.
  1065. //
  1066. // Exceptions Thrown:
  1067. // CNTException IDS_SET_QUORUM_RESOURCE_ERROR - errors from
  1068. // SetClusterQuorumResource().
  1069. //--
  1070. /////////////////////////////////////////////////////////////////////////////
  1071. void CCluster::SetQuorumResource(
  1072. IN LPCTSTR pszResource,
  1073. IN LPCTSTR pszQuorumPath,
  1074. IN DWORD nMaxLogSize
  1075. )
  1076. {
  1077. DWORD dwStatus;
  1078. CResource * pciRes;
  1079. CString strRes( pszResource ); // Required if built non-Unicode
  1080. CWaitCursor wc;
  1081. ASSERT( pszResource != NULL );
  1082. if ( ( StrQuorumResource() != pszResource )
  1083. || ( StrQuorumPath() != pszQuorumPath )
  1084. || ( NMaxQuorumLogSize() != nMaxLogSize ) )
  1085. {
  1086. // Find the resource.
  1087. pciRes = Pdoc()->LpciResources().PciResFromName( pszResource );
  1088. ASSERT_VALID( pciRes );
  1089. ASSERT( pciRes->Hresource() != NULL );
  1090. if ( pciRes->Hresource() != NULL )
  1091. {
  1092. // Change the quorum resource.
  1093. dwStatus = SetClusterQuorumResource( pciRes->Hresource(), pszQuorumPath, nMaxLogSize );
  1094. if ( dwStatus != ERROR_SUCCESS )
  1095. {
  1096. ThrowStaticException( dwStatus, IDS_SET_QUORUM_RESOURCE_ERROR, pciRes->StrName() );
  1097. } // if: error setting the quorum resource
  1098. m_strQuorumResource = pszResource;
  1099. m_strQuorumPath = pszQuorumPath;
  1100. m_nMaxQuorumLogSize = nMaxLogSize;
  1101. } // if: resource is available
  1102. } // if: the quorum resource changed
  1103. } //*** CCluster::SetQuorumResource()
  1104. /////////////////////////////////////////////////////////////////////////////
  1105. //++
  1106. //
  1107. // CCluster::SetNetworkPriority
  1108. //
  1109. // Routine Description:
  1110. // Set the network priority list.
  1111. //
  1112. // Arguments:
  1113. // rlpci [IN] List of networks in priority order.
  1114. //
  1115. // Return Value:
  1116. // None.
  1117. //
  1118. // Exceptions Thrown:
  1119. // Any exceptions thrown by HNETWORK::new.
  1120. //
  1121. //--
  1122. /////////////////////////////////////////////////////////////////////////////
  1123. void CCluster::SetNetworkPriority( IN const CNetworkList & rlpci )
  1124. {
  1125. DWORD dwStatus;
  1126. CWaitCursor wc;
  1127. ASSERT( Hcluster() != NULL );
  1128. if ( Hcluster() != NULL )
  1129. {
  1130. BOOL bChanged = TRUE;
  1131. // Determine if the list has changed.
  1132. if ( rlpci.GetCount() == LpciNetworkPriority().GetCount() )
  1133. {
  1134. POSITION posOld;
  1135. POSITION posNew;
  1136. CNetwork * pciOldNet;
  1137. CNetwork * pciNewNet;
  1138. bChanged = FALSE;
  1139. posOld = LpciNetworkPriority().GetHeadPosition();
  1140. posNew = rlpci.GetHeadPosition();
  1141. while ( posOld != NULL )
  1142. {
  1143. pciOldNet = (CNetwork *) LpciNetworkPriority().GetNext( posOld );
  1144. ASSERT_VALID( pciOldNet );
  1145. ASSERT( posNew != NULL );
  1146. pciNewNet = (CNetwork *) rlpci.GetNext( posNew );
  1147. ASSERT_VALID( pciNewNet );
  1148. if ( pciOldNet->StrName() != pciNewNet->StrName() )
  1149. {
  1150. bChanged = TRUE;
  1151. break;
  1152. } // if: name is not the same
  1153. } // while: more items in the old list
  1154. } // if: same number of items in the list
  1155. if ( bChanged )
  1156. {
  1157. HNETWORK * phnetwork = NULL;
  1158. try
  1159. {
  1160. DWORD ipci;
  1161. POSITION posPci;
  1162. CNetwork * pciNet;
  1163. // Allocate an array for all the node handles.
  1164. phnetwork = new HNETWORK[ (DWORD) rlpci.GetCount() ];
  1165. if ( phnetwork == NULL )
  1166. {
  1167. ThrowStaticException( GetLastError() );
  1168. } // if: error allocating network handle array
  1169. // Copy the handle of all the networks in the networks list to the handle aray.
  1170. posPci = rlpci.GetHeadPosition();
  1171. for ( ipci = 0 ; posPci != NULL ; ipci++ )
  1172. {
  1173. pciNet = (CNetwork *) rlpci.GetNext( posPci );
  1174. ASSERT_VALID( pciNet );
  1175. phnetwork[ ipci ] = pciNet->Hnetwork();
  1176. } // while: more networks in the list
  1177. // Set the property.
  1178. dwStatus = SetClusterNetworkPriorityOrder( Hcluster(), (DWORD) rlpci.GetCount(), phnetwork );
  1179. if ( dwStatus != ERROR_SUCCESS )
  1180. {
  1181. ThrowStaticException( dwStatus, IDS_SET_NET_PRIORITY_ERROR, StrName() );
  1182. } // if: error setting network priority
  1183. // Update the PCI list.
  1184. m_plpciNetworkPriority->RemoveAll();
  1185. posPci = rlpci.GetHeadPosition();
  1186. while ( posPci != NULL )
  1187. {
  1188. pciNet = (CNetwork *) rlpci.GetNext( posPci );
  1189. m_plpciNetworkPriority->AddTail( pciNet );
  1190. } // while: more items in the list
  1191. } // try
  1192. catch ( CException * )
  1193. {
  1194. delete [] phnetwork;
  1195. throw;
  1196. } // catch: CException
  1197. delete [] phnetwork;
  1198. } // if: list changed
  1199. } // if: key is available
  1200. } //*** CCluster::SetNetworkPriority(CNetworkList*)
  1201. /////////////////////////////////////////////////////////////////////////////
  1202. //++
  1203. //
  1204. // CCluster::Rename
  1205. //
  1206. // Routine Description:
  1207. // Change the name of the cluster..
  1208. //
  1209. // Arguments:
  1210. // pszName [IN] New name to give to the cluster.
  1211. //
  1212. // Return Value:
  1213. // None.
  1214. //
  1215. // Exceptions Thrown:
  1216. // CNTException Errors returned from SetClusterName().
  1217. //
  1218. //--
  1219. /////////////////////////////////////////////////////////////////////////////
  1220. void CCluster::Rename( IN LPCTSTR pszName )
  1221. {
  1222. DWORD dwStatus;
  1223. CWaitCursor wc;
  1224. ASSERT( Hcluster() != NULL );
  1225. if ( StrName() != pszName )
  1226. {
  1227. // Set the name.
  1228. dwStatus = SetClusterName( Hcluster(), pszName );
  1229. if ( dwStatus != ERROR_SUCCESS )
  1230. {
  1231. if ( dwStatus == ERROR_RESOURCE_PROPERTIES_STORED )
  1232. {
  1233. AfxMessageBox( IDS_RESTART_CLUSTER_NAME, MB_OK | MB_ICONEXCLAMATION );
  1234. } // if: properties stored but not in use yet
  1235. else
  1236. {
  1237. ThrowStaticException( dwStatus, IDS_RENAME_CLUSTER_ERROR, StrName(), pszName );
  1238. } // else: error occurred
  1239. } // if: error occurred setting cluster name
  1240. m_strName = pszName;
  1241. } // if: the name changed
  1242. } //*** CCluster::Rename()
  1243. /////////////////////////////////////////////////////////////////////////////
  1244. //++
  1245. //
  1246. // CCluster::BIsLabelEditValueValid
  1247. //
  1248. // Routine Description:
  1249. // Validate the label edit value as a cluster name
  1250. //
  1251. // Arguments:
  1252. // pszName [IN] New name to give to the cluster.
  1253. //
  1254. // Return Value:
  1255. // TRUE name is valid
  1256. // FALSE name is invalid
  1257. //
  1258. //--
  1259. /////////////////////////////////////////////////////////////////////////////
  1260. BOOL CCluster::BIsLabelEditValueValid( IN LPCTSTR pszName )
  1261. {
  1262. BOOL bSuccess = TRUE;
  1263. if ( StrName() != pszName )
  1264. {
  1265. CLRTL_NAME_STATUS cnStatus;
  1266. UINT idsError;
  1267. // Validate the name.
  1268. if ( ! ClRtlIsNetNameValid( pszName, &cnStatus, FALSE /*CheckIfExists*/ ) )
  1269. {
  1270. switch ( cnStatus )
  1271. {
  1272. case NetNameTooLong:
  1273. idsError = IDS_INVALID_CLUSTER_NAME_TOO_LONG;
  1274. break;
  1275. case NetNameInvalidChars:
  1276. idsError = IDS_INVALID_CLUSTER_NAME_INVALID_CHARS;
  1277. break;
  1278. case NetNameInUse:
  1279. idsError = IDS_INVALID_CLUSTER_NAME_IN_USE;
  1280. break;
  1281. case NetNameDNSNonRFCChars:
  1282. idsError = IDS_INVALID_CLUSTER_NAME_INVALID_DNS_CHARS;
  1283. break;
  1284. case NetNameSystemError:
  1285. {
  1286. DWORD scError = GetLastError();
  1287. ThrowStaticException( scError, IDS_ERROR_VALIDATING_NETWORK_NAME, pszName );
  1288. }
  1289. default:
  1290. idsError = IDS_INVALID_CLUSTER_NAME;
  1291. break;
  1292. } // switch: cnStatus
  1293. if ( idsError == IDS_INVALID_CLUSTER_NAME_INVALID_DNS_CHARS )
  1294. {
  1295. int id = AfxMessageBox(IDS_INVALID_CLUSTER_NAME_INVALID_DNS_CHARS, MB_YESNO | MB_DEFBUTTON2 | MB_ICONEXCLAMATION );
  1296. if ( id == IDNO )
  1297. {
  1298. bSuccess = FALSE;
  1299. }
  1300. }
  1301. else
  1302. {
  1303. bSuccess = FALSE;
  1304. }
  1305. } // if: error validating the name
  1306. } // if: the name changed
  1307. return bSuccess;
  1308. } //*** CCluster::BIsLabelEditValueValid()
  1309. /////////////////////////////////////////////////////////////////////////////
  1310. //++
  1311. //
  1312. // CCluster::OnBeginLabelEdit
  1313. //
  1314. // Routine Description:
  1315. // Prepare an edit control in a view for editing the cluster name.
  1316. //
  1317. // Arguments:
  1318. // pedit [IN OUT] Edit control to prepare.
  1319. //
  1320. // Return Value:
  1321. // None.
  1322. //
  1323. //--
  1324. /////////////////////////////////////////////////////////////////////////////
  1325. void CCluster::OnBeginLabelEdit( IN OUT CEdit * pedit )
  1326. {
  1327. ASSERT_VALID(pedit);
  1328. pedit->SetLimitText( MAX_CLUSTERNAME_LENGTH );
  1329. pedit->ModifyStyle( 0 /*dwRemove*/, ES_UPPERCASE | ES_OEMCONVERT /*dwAdd*/ );
  1330. } //*** CCluster::OnBeginLabelEdit()
  1331. /////////////////////////////////////////////////////////////////////////////
  1332. //++
  1333. //
  1334. // CCluster::UpdateState
  1335. //
  1336. // Routine Description:
  1337. // Update the current state of the item.
  1338. //
  1339. // Arguments:
  1340. // None.
  1341. //
  1342. // Return Value:
  1343. // None.
  1344. //
  1345. //--
  1346. /////////////////////////////////////////////////////////////////////////////
  1347. void CCluster::UpdateState( void )
  1348. {
  1349. // NOTENOTE: not referneced
  1350. //CClusterAdminApp * papp = GetClusterAdminApp();
  1351. CString strTitle;
  1352. GetClusterAdminApp();
  1353. Trace( g_tagCluster, _T("(%s) - Updating state"), StrName() );
  1354. // Update the title of the document.
  1355. ASSERT_VALID( Pdoc() );
  1356. try
  1357. {
  1358. Pdoc()->UpdateTitle();
  1359. } // try
  1360. catch ( CException * pe )
  1361. {
  1362. pe->Delete();
  1363. } // catch: CException
  1364. // Call the base class method.
  1365. CClusterItem::UpdateState();
  1366. } //*** CCluster::UpdateState()